go mod tidy and go mod vendor

Signed-off-by: Kazuyoshi Kato <katokazu@amazon.com>
This commit is contained in:
Kazuyoshi Kato 2022-04-21 13:49:01 +00:00
parent f616dd471e
commit aefd1849b6
75 changed files with 2087 additions and 22162 deletions

5
go.mod
View File

@ -28,8 +28,8 @@ require (
github.com/docker/go-units v0.4.0
github.com/emicklei/go-restful/v3 v3.7.3
github.com/fsnotify/fsnotify v1.5.1
github.com/gogo/googleapis v1.4.1
github.com/gogo/protobuf v1.3.2
github.com/golang/protobuf v1.5.2
github.com/google/go-cmp v0.5.6
github.com/google/uuid v1.2.0
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
@ -65,6 +65,7 @@ require (
go.opentelemetry.io/otel/trace v1.3.0
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa
google.golang.org/grpc v1.43.0
google.golang.org/protobuf v1.27.1
k8s.io/api v0.22.5
@ -91,7 +92,6 @@ require (
github.com/go-logr/stdr v1.2.2 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
@ -127,7 +127,6 @@ require (
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.5.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

2
go.sum
View File

@ -419,8 +419,6 @@ github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=

View File

@ -32,9 +32,9 @@ require (
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/godbus/dbus/v5 v5.0.6 // indirect
github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -73,6 +73,8 @@ replace (
// resolution if newer.
github.com/containerd/containerd => ../../
github.com/containerd/typeurl => github.com/kzys/typeurl v1.0.3-0.20220421192127-bac36d33562a
// Replace rules below must be kept in sync with the main go.mod file at the
// root, because that's the actual version expected by the "containerd/containerd"
// dependency above.

View File

@ -154,10 +154,6 @@ github.com/containerd/ttrpc v1.0.2/go.mod h1:UAxOpgT9ziI0gJrmKvgcZivgxOp8iFPSk8h
github.com/containerd/ttrpc v1.1.0/go.mod h1:XX4ZTnoOId4HklF4edwc4DcqskFZuvXB1Evzy5KFQpQ=
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3 h1:BhCp66ofL8oYcdelc3CBXc2/Pfvvgx+s+mrp9TvNgn8=
github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3/go.mod h1:YYyNVhZrTMiaf51Vj6WhAJqJw+vl/nzABhj8pWrzle4=
github.com/containerd/typeurl v1.0.1/go.mod h1:TB1hUtrpaiO88KEK56ijojHS1+NeF0izUACaJW2mdXg=
github.com/containerd/typeurl v1.0.2/go.mod h1:9trJWW2sRlGub4wZJRTW83VtbOLS6hwcDZXTn6oPz9s=
github.com/containerd/typeurl v1.0.3-0.20220324183432-6193a0e03259 h1:bJv9qgjarrsdd4XIIczeRdYXON88Fgn3GdXVfnQjcSo=
github.com/containerd/typeurl v1.0.3-0.20220324183432-6193a0e03259/go.mod h1:HDkcKOXRnX6yKnXv3P0QrogFi0DoiauK/LpQi961f0A=
github.com/containerd/zfs v1.0.0/go.mod h1:m+m51S1DvAP6r3FcmYCp54bQ34pyOwTieQDNRIRHsFY=
github.com/containernetworking/cni v1.0.1/go.mod h1:AKuhXbN5EzmD4yTNtfSsX3tPcmtrBI6QcRV0NiNt15Y=
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
@ -264,8 +260,6 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.6 h1:mkgN1ofwASrYnJ5W6U/BxG15eXXXjirgZc7CLqkcaro=
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0=
github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
@ -426,6 +420,8 @@ github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kzys/typeurl v1.0.3-0.20220421192127-bac36d33562a h1:89QixI2ur9quae3eryx/xYEcV6PgT/RXYgUkaeI1wls=
github.com/kzys/typeurl v1.0.3-0.20220421192127-bac36d33562a/go.mod h1:HDkcKOXRnX6yKnXv3P0QrogFi0DoiauK/LpQi961f0A=
github.com/linuxkit/virtsock v0.0.0-20201010232012-f8cee7dfc7a3/go.mod h1:3r6x7q95whyfWQpmGZTu3gk3v2YkMi05HEzl7Tf7YEo=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=

1
vendor/github.com/containerd/ttrpc/.gitattributes generated vendored Normal file
View File

@ -0,0 +1 @@
*.go text eol=lf

View File

@ -1,4 +1,5 @@
# Binaries for programs and plugins
/bin/
*.exe
*.dll
*.so
@ -9,3 +10,4 @@
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage.txt

54
vendor/github.com/containerd/ttrpc/.golangci.yml generated vendored Normal file
View File

@ -0,0 +1,54 @@
linters:
enable:
- structcheck
- varcheck
- staticcheck
- unconvert
- gofmt
- goimports
- revive
- ineffassign
- vet
- unused
- misspell
disable:
- errcheck
linters-settings:
revive:
ignore-generated-headers: true
rules:
- name: blank-imports
- name: context-as-argument
- name: context-keys-type
- name: dot-imports
- name: error-return
- name: error-strings
- name: error-naming
- name: exported
- name: if-return
- name: increment-decrement
- name: var-naming
arguments: [["UID", "GID"], []]
- name: var-declaration
- name: package-comments
- name: range
- name: receiver-naming
- name: time-naming
- name: unexported-return
- name: indent-error-flow
- name: errorf
- name: empty-block
- name: superfluous-else
- name: unused-parameter
- name: unreachable-code
- name: redefines-builtin-id
issues:
include:
- EXC0002
run:
timeout: 8m
skip-dirs:
- example

180
vendor/github.com/containerd/ttrpc/Makefile generated vendored Normal file
View File

@ -0,0 +1,180 @@
# Copyright The containerd Authors.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Go command to use for build
GO ?= go
INSTALL ?= install
# Root directory of the project (absolute path).
ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST))))
WHALE = "🇩"
ONI = "👹"
# Project binaries.
COMMANDS=protoc-gen-go-ttrpc protoc-gen-gogottrpc
ifdef BUILDTAGS
GO_BUILDTAGS = ${BUILDTAGS}
endif
GO_BUILDTAGS ?=
GO_TAGS=$(if $(GO_BUILDTAGS),-tags "$(strip $(GO_BUILDTAGS))",)
# Project packages.
PACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /example)
TESTPACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /cmd | grep -v /integration | grep -v /example)
BINPACKAGES=$(addprefix ./cmd/,$(COMMANDS))
#Replaces ":" (*nix), ";" (windows) with newline for easy parsing
GOPATHS=$(shell echo ${GOPATH} | tr ":" "\n" | tr ";" "\n")
TESTFLAGS_RACE=
GO_BUILD_FLAGS=
# See Golang issue re: '-trimpath': https://github.com/golang/go/issues/13809
GO_GCFLAGS=$(shell \
set -- ${GOPATHS}; \
echo "-gcflags=-trimpath=$${1}/src"; \
)
BINARIES=$(addprefix bin/,$(COMMANDS))
# Flags passed to `go test`
TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS)
TESTFLAGS_PARALLEL ?= 8
# Use this to replace `go test` with, for instance, `gotestsum`
GOTEST ?= $(GO) test
.PHONY: clean all AUTHORS build binaries test integration generate protos checkprotos coverage ci check help install vendor install-protobuf install-protobuild
.DEFAULT: default
# Forcibly set the default goal to all, in case an include above brought in a rule definition.
.DEFAULT_GOAL := all
all: binaries
check: proto-fmt ## run all linters
@echo "$(WHALE) $@"
GOGC=75 golangci-lint run
ci: check binaries checkprotos coverage # coverage-integration ## to be used by the CI
AUTHORS: .mailmap .git/HEAD
git log --format='%aN <%aE>' | sort -fu > $@
generate: protos
@echo "$(WHALE) $@"
@PATH="${ROOTDIR}/bin:${PATH}" $(GO) generate -x ${PACKAGES}
protos: bin/protoc-gen-gogottrpc bin/protoc-gen-go-ttrpc ## generate protobuf
@echo "$(WHALE) $@"
@(PATH="${ROOTDIR}/bin:${PATH}" protobuild --quiet ${PACKAGES})
check-protos: protos ## check if protobufs needs to be generated again
@echo "$(WHALE) $@"
@test -z "$$(git status --short | grep ".pb.go" | tee /dev/stderr)" || \
((git diff | cat) && \
(echo "$(ONI) please run 'make protos' when making changes to proto files" && false))
check-api-descriptors: protos ## check that protobuf changes aren't present.
@echo "$(WHALE) $@"
@test -z "$$(git status --short | grep ".pb.txt" | tee /dev/stderr)" || \
((git diff $$(find . -name '*.pb.txt') | cat) && \
(echo "$(ONI) please run 'make protos' when making changes to proto files and check-in the generated descriptor file changes" && false))
proto-fmt: ## check format of proto files
@echo "$(WHALE) $@"
@test -z "$$(find . -name '*.proto' -type f -exec grep -Hn -e "^ " {} \; | tee /dev/stderr)" || \
(echo "$(ONI) please indent proto files with tabs only" && false)
@test -z "$$(find . -name '*.proto' -type f -exec grep -Hn "Meta meta = " {} \; | grep -v '(gogoproto.nullable) = false' | tee /dev/stderr)" || \
(echo "$(ONI) meta fields in proto files must have option (gogoproto.nullable) = false" && false)
build: ## build the go packages
@echo "$(WHALE) $@"
@$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${EXTRA_FLAGS} ${PACKAGES}
test: ## run tests, except integration tests and tests that require root
@echo "$(WHALE) $@"
@$(GOTEST) ${TESTFLAGS} ${TESTPACKAGES}
integration: ## run integration tests
@echo "$(WHALE) $@"
@cd "${ROOTDIR}/integration" && $(GOTEST) -v ${TESTFLAGS} -parallel ${TESTFLAGS_PARALLEL} .
benchmark: ## run benchmarks tests
@echo "$(WHALE) $@"
@$(GO) test ${TESTFLAGS} -bench . -run Benchmark
FORCE:
define BUILD_BINARY
@echo "$(WHALE) $@"
@$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_TAGS} ./$<
endef
# Build a binary from a cmd.
bin/%: cmd/% FORCE
$(call BUILD_BINARY)
binaries: $(BINARIES) ## build binaries
@echo "$(WHALE) $@"
clean: ## clean up binaries
@echo "$(WHALE) $@"
@rm -f $(BINARIES)
install: ## install binaries
@echo "$(WHALE) $@ $(BINPACKAGES)"
@$(GO) install $(BINPACKAGES)
install-protobuf:
@echo "$(WHALE) $@"
@script/install-protobuf
install-protobuild:
@echo "$(WHALE) $@"
@$(GO) install google.golang.org/protobuf/cmd/protoc-gen-go@v1.27.1
@$(GO) install github.com/containerd/protobuild@7e5ee24bc1f70e9e289fef15e2631eb3491320bf
coverage: ## generate coverprofiles from the unit tests, except tests that require root
@echo "$(WHALE) $@"
@rm -f coverage.txt
@$(GO) test -i ${TESTFLAGS} ${TESTPACKAGES} 2> /dev/null
@( for pkg in ${PACKAGES}; do \
$(GO) test ${TESTFLAGS} \
-cover \
-coverprofile=profile.out \
-covermode=atomic $$pkg || exit; \
if [ -f profile.out ]; then \
cat profile.out >> coverage.txt; \
rm profile.out; \
fi; \
done )
vendor: ## ensure all the go.mod/go.sum files are up-to-date
@echo "$(WHALE) $@"
@$(GO) mod tidy
@$(GO) mod verify
verify-vendor: ## verify if all the go.mod/go.sum files are up-to-date
@echo "$(WHALE) $@"
@$(GO) mod tidy
@$(GO) mod verify
@test -z "$$(git status --short | grep "go.sum" | tee /dev/stderr)" || \
((git diff | cat) && \
(echo "$(ONI) make sure to checkin changes after go mod tidy" && false))
help: ## this help
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort

240
vendor/github.com/containerd/ttrpc/PROTOCOL.md generated vendored Normal file
View File

@ -0,0 +1,240 @@
# Protocol Specification
The ttrpc protocol is client/server protocol to support multiple request streams
over a single connection with lightweight framing. The client represents the
process which initiated the underlying connection and the server is the process
which accepted the connection. The protocol is currently defined as
asymmetrical, with clients sending requests and servers sending responses. Both
clients and servers are able to send stream data. The roles are also used in
determining the stream identifiers, with client initiated streams using odd
number identifiers and server initiated using even number. The protocol may be
extended in the future to support server initiated streams, that is not
supported in the latest version.
## Purpose
The ttrpc protocol is designed to be lightweight and optimized for low latency
and reliable connections between processes on the same host. The protocol does
not include features for handling unreliable connections such as handshakes,
resets, pings, or flow control. The protocol is designed to make low-overhead
implementations as simple as possible. It is not intended as a suitable
replacement for HTTP2/3 over the network.
## Message Frame
Each Message Frame consists of a 10-byte message header followed
by message data. The data length and stream ID are both big-endian
4-byte unsigned integers. The message type is an unsigned 1-byte
integer. The flags are also an unsigned 1-byte integer and
use is defined by the message type.
+---------------------------------------------------------------+
| Data Length (32) |
+---------------------------------------------------------------+
| Stream ID (32) |
+---------------+-----------------------------------------------+
| Msg Type (8) |
+---------------+
| Flags (8) |
+---------------+-----------------------------------------------+
| Data (*) |
+---------------------------------------------------------------+
The Data Length field represents the number of bytes in the Data field. The
total frame size will always be Data Length + 10 bytes. The maximum data length
is 4MB and any larger size should be rejected. Due to the maximum data size
being less than 16MB, the first frame byte should always be zero. This first
byte should be considered reserved for future use.
The Stream ID must be odd for client initiated streams and even for server
initiated streams. Server initiated streams are not currently supported.
## Mesage Types
| Message Type | Name | Description |
|--------------|----------|----------------------------------|
| 0x01 | Request | Initiates stream |
| 0x02 | Response | Final stream data and terminates |
| 0x03 | Data | Stream data |
### Request
The request message is used to initiate stream and send along request data for
properly routing and handling the stream. The stream may indicate unary without
any inbound or outbound stream data with only a response is expected on the
stream. The request may also indicate the stream is still open for more data and
no response is expected until data is finished. If the remote indicates the
stream is closed, the request may be considered non-unary but without anymore
stream data sent. In the case of `remote closed`, the remote still expects to
receive a response or stream data. For compatibility with non streaming clients,
a request with empty flags indicates a unary request.
#### Request Flags
| Flag | Name | Description |
|------|-----------------|--------------------------------------------------|
| 0x01 | `remote closed` | Non-unary, but no more data expected from remote |
| 0x02 | `remote open` | Non-unary, remote is still sending data |
### Response
The response message is used to end a stream with data, an empty response, or
an error. A response message is the only expected message after a unary request.
A non-unary request does not require a response message if the server is sending
back stream data. A non-unary stream may return a single response message but no
other stream data may follow.
#### Response Flags
No response flags are defined at this time, flags should be empty.
### Data
The data message is used to send data on an already initialized stream. Either
client or server may send data. A data message is not allowed on a unary stream.
A data message should not be sent after indicating `remote closed` to the peer.
The last data message on a stream must set the `remote closed` flag.
The `no data` flag is used to indicate that the data message does not include
any data. This is normally used with the `remote closed` flag to indicate the
stream is now closed without transmitting any data. Since ttrpc normally
transmits a single object per message, a zero length data message may be
interpreted as an empty object. For example, transmitting the number zero as a
protobuf message ends up with a data length of zero, but the message is still
considered data and should be processed.
#### Data Flags
| Flag | Name | Description |
|------|-----------------|-----------------------------------|
| 0x01 | `remote closed` | No more data expected from remote |
| 0x04 | `no data` | This message does not have data |
## Streaming
All ttrpc requests use streams to transfer data. Unary streams will only have
two messages sent per stream, a request from a client and a response from the
server. Non-unary streams, however, may send any numbers of messages from the
client and the server. This makes stream management more complicated than unary
streams since both client and server need to track additional state. To keep
this management as simple as possible, ttrpc minimizes the number of states and
uses two flags instead of control frames. Each stream has two states while a
stream is still alive: `local closed` and `remote closed`. Each peer considers
local and remote from their own perspective and sets flags from the other peer's
perspective. For example, if a client sends a data frame with the
`remote closed` flag, that is indicating that the client is now `local closed`
and the server will be `remote closed`. A unary operation does not need to send
these flags since each received message always indicates `remote closed`. Once a
peer is both `local closed` and `remote closed`, the stream is considered
finished and may be cleaned up.
Due to the asymmetric nature of the current protocol, a client should
always be in the `local closed` state before `remote closed` and a server should
always be in the `remote closed` state before `local closed`. This happens
because the client is always initiating requests and a client always expects a
final response back from a server to indicate the initiated request has been
fulfilled. This may mean server sends a final empty response to finish a stream
even after it has already completed sending data before the client.
### Unary State Diagram
+--------+ +--------+
| Client | | Server |
+---+----+ +----+---+
| +---------+ |
local >---------------+ Request +--------------------> remote
closed | +---------+ | closed
| |
| +----------+ |
finished <--------------+ Response +--------------------< finished
| +----------+ |
| |
### Non-Unary State Diagrams
RC: `remote closed` flag
RO: `remote open` flag
+--------+ +--------+
| Client | | Server |
+---+----+ +----+---+
| +--------------+ |
>-------------+ Request [RO] +----------------->
| +--------------+ |
| |
| +------+ |
>-----------------+ Data +--------------------->
| +------+ |
| |
| +-----------+ |
local >---------------+ Data [RC] +------------------> remote
closed | +-----------+ | closed
| |
| +----------+ |
finished <--------------+ Response +--------------------< finished
| +----------+ |
| |
+--------+ +--------+
| Client | | Server |
+---+----+ +----+---+
| +--------------+ |
local >-------------+ Request [RC] +-----------------> remote
closed | +--------------+ | closed
| |
| +------+ |
<-----------------+ Data +---------------------<
| +------+ |
| |
| +-----------+ |
finished <---------------+ Data [RC] +------------------< finished
| +-----------+ |
| |
+--------+ +--------+
| Client | | Server |
+---+----+ +----+---+
| +--------------+ |
>-------------+ Request [RO] +----------------->
| +--------------+ |
| |
| +------+ |
>-----------------+ Data +--------------------->
| +------+ |
| |
| +------+ |
<-----------------+ Data +---------------------<
| +------+ |
| |
| +------+ |
>-----------------+ Data +--------------------->
| +------+ |
| |
| +-----------+ |
local >---------------+ Data [RC] +------------------> remote
closed | +-----------+ | closed
| |
| +------+ |
<-----------------+ Data +---------------------<
| +------+ |
| |
| +-----------+ |
finished <---------------+ Data [RC] +------------------< finished
| +-----------+ |
| |
## RPC
While this protocol is defined primarily to support Remote Procedure Calls, the
protocol does not define the request and response types beyond the messages
defined in the protocol. The implementation provides a default protobuf
definition of request and response which may be used for cross language rpc.
All implementations should at least define a request type which support
routing by procedure name and a response type which supports call status.
## Version History
| Version | Features |
|---------|---------------------|
| 1.0 | Unary requests only |
| 1.2 | Streaming support |

25
vendor/github.com/containerd/ttrpc/Protobuild.toml generated vendored Normal file
View File

@ -0,0 +1,25 @@
version = "2"
generators = ["go"]
# Control protoc include paths. Below are usually some good defaults, but feel
# free to try it without them if it works for your project.
[includes]
# Include paths that will be added before all others. Typically, you want to
# treat the root of the project as an include, but this may not be necessary.
before = ["."]
# Paths that will be added untouched to the end of the includes. We use
# `/usr/local/include` to pickup the common install location of protobuf.
# This is the default.
after = ["/usr/local/include"]
# This section maps protobuf imports to Go packages. These will become
# `-M` directives in the call to the go protobuf generator.
[packages]
"google/protobuf/any.proto" = "github.com/gogo/protobuf/types"
"proto/status.proto" = "google.golang.org/genproto/googleapis/rpc/status"
[[overrides]]
# enable ttrpc and disable fieldpath and grpc for the shim
prefixes = ["github.com/containerd/ttrpc/integration/streaming"]
generators = ["go", "go-ttrpc"]

View File

@ -20,6 +20,10 @@ Please note that while this project supports generating either end of the
protocol, the generated service definitions will be incompatible with regular
GRPC services, as they do not speak the same protocol.
# Protocol
See the [protocol specification](./PROTOCOL.md).
# Usage
Create a gogo vanity binary (see
@ -43,7 +47,6 @@ directly, if required.
TODO:
- [ ] Document protocol layout
- [ ] Add testing under concurrent load to ensure
- [ ] Verify connection error handling

View File

@ -38,6 +38,26 @@ type messageType uint8
const (
messageTypeRequest messageType = 0x1
messageTypeResponse messageType = 0x2
messageTypeData messageType = 0x3
)
func (mt messageType) String() string {
switch mt {
case messageTypeRequest:
return "request"
case messageTypeResponse:
return "response"
case messageTypeData:
return "data"
default:
return "unknown"
}
}
const (
flagRemoteClosed uint8 = 0x1
flagRemoteOpen uint8 = 0x2
flagNoData uint8 = 0x4
)
// messageHeader represents the fixed-length message header of 10 bytes sent
@ -46,7 +66,7 @@ type messageHeader struct {
Length uint32 // length excluding this header. b[:4]
StreamID uint32 // identifies which request stream message is a part of. b[4:8]
Type messageType // message type b[8]
Flags uint8 // reserved b[9]
Flags uint8 // type specific flags b[9]
}
func readMessageHeader(p []byte, r io.Reader) (messageHeader, error) {
@ -111,23 +131,32 @@ func (ch *channel) recv() (messageHeader, []byte, error) {
return mh, nil, status.Errorf(codes.ResourceExhausted, "message length %v exceed maximum message size of %v", mh.Length, messageLengthMax)
}
p := ch.getmbuf(int(mh.Length))
var p []byte
if mh.Length > 0 {
p = ch.getmbuf(int(mh.Length))
if _, err := io.ReadFull(ch.br, p); err != nil {
return messageHeader{}, nil, fmt.Errorf("failed reading message: %w", err)
}
}
return mh, p, nil
}
func (ch *channel) send(streamID uint32, t messageType, p []byte) error {
if err := writeMessageHeader(ch.bw, ch.hwbuf[:], messageHeader{Length: uint32(len(p)), StreamID: streamID, Type: t}); err != nil {
func (ch *channel) send(streamID uint32, t messageType, flags uint8, p []byte) error {
// TODO: Error on send rather than on recv
//if len(p) > messageLengthMax {
// return status.Errorf(codes.InvalidArgument, "refusing to send, message length %v exceed maximum message size of %v", len(p), messageLengthMax)
//}
if err := writeMessageHeader(ch.bw, ch.hwbuf[:], messageHeader{Length: uint32(len(p)), StreamID: streamID, Type: t, Flags: flags}); err != nil {
return err
}
if len(p) > 0 {
_, err := ch.bw.Write(p)
if err != nil {
return err
}
}
return ch.bw.Flush()
}

View File

@ -19,30 +19,30 @@ package ttrpc
import (
"context"
"errors"
"fmt"
"io"
"net"
"os"
"strings"
"sync"
"syscall"
"time"
"github.com/gogo/protobuf/proto"
"github.com/sirupsen/logrus"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// ErrClosed is returned by client methods when the underlying connection is
// closed.
var ErrClosed = errors.New("ttrpc: closed")
// Client for a ttrpc server
type Client struct {
codec codec
conn net.Conn
channel *channel
calls chan *callRequest
streamLock sync.RWMutex
streams map[streamID]*stream
nextStreamID streamID
sendLock sync.Mutex
ctx context.Context
closed func()
@ -51,8 +51,6 @@ type Client struct {
userCloseFunc func()
userCloseWaitCh chan struct{}
errOnce sync.Once
err error
interceptor UnaryClientInterceptor
}
@ -73,13 +71,16 @@ func WithUnaryClientInterceptor(i UnaryClientInterceptor) ClientOpts {
}
}
// NewClient creates a new ttrpc client using the given connection
func NewClient(conn net.Conn, opts ...ClientOpts) *Client {
ctx, cancel := context.WithCancel(context.Background())
channel := newChannel(conn)
c := &Client{
codec: codec{},
conn: conn,
channel: newChannel(conn),
calls: make(chan *callRequest),
channel: channel,
streams: make(map[streamID]*stream),
nextStreamID: 1,
closed: cancel,
ctx: ctx,
userCloseFunc: func() {},
@ -95,13 +96,13 @@ func NewClient(conn net.Conn, opts ...ClientOpts) *Client {
return c
}
type callRequest struct {
ctx context.Context
req *Request
resp *Response // response will be written back here
errs chan error // error written here on completion
func (c *Client) send(sid uint32, mt messageType, flags uint8, b []byte) error {
c.sendLock.Lock()
defer c.sendLock.Unlock()
return c.channel.send(sid, mt, flags, b)
}
// Call makes a unary request and returns with response
func (c *Client) Call(ctx context.Context, service, method string, req, resp interface{}) error {
payload, err := c.codec.Marshal(req)
if err != nil {
@ -113,6 +114,7 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
Service: service,
Method: method,
Payload: payload,
// TODO: metadata from context
}
cresp = &Response{}
@ -123,7 +125,7 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
}
if dl, ok := ctx.Deadline(); ok {
creq.TimeoutNano = dl.Sub(time.Now()).Nanoseconds()
creq.TimeoutNano = time.Until(dl).Nanoseconds()
}
info := &UnaryClientInfo{
@ -143,36 +145,137 @@ func (c *Client) Call(ctx context.Context, service, method string, req, resp int
return nil
}
func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) error {
errs := make(chan error, 1)
call := &callRequest{
ctx: ctx,
req: req,
resp: resp,
errs: errs,
}
// StreamDesc describes the stream properties, whether the stream has
// a streaming client, a streaming server, or both
type StreamDesc struct {
StreamingClient bool
StreamingServer bool
}
select {
case <-ctx.Done():
return ctx.Err()
case c.calls <- call:
case <-c.ctx.Done():
return c.error()
}
// ClientStream is used to send or recv messages on the underlying stream
type ClientStream interface {
CloseSend() error
SendMsg(m interface{}) error
RecvMsg(m interface{}) error
}
select {
case <-ctx.Done():
return ctx.Err()
case err := <-errs:
type clientStream struct {
ctx context.Context
s *stream
c *Client
desc *StreamDesc
localClosed bool
remoteClosed bool
}
func (cs *clientStream) CloseSend() error {
if !cs.desc.StreamingClient {
return fmt.Errorf("%w: cannot close non-streaming client", ErrProtocol)
}
if cs.localClosed {
return ErrStreamClosed
}
err := cs.s.send(messageTypeData, flagRemoteClosed|flagNoData, nil)
if err != nil {
return filterCloseErr(err)
case <-c.ctx.Done():
return c.error()
}
cs.localClosed = true
return nil
}
func (cs *clientStream) SendMsg(m interface{}) error {
if !cs.desc.StreamingClient {
return fmt.Errorf("%w: cannot send data from non-streaming client", ErrProtocol)
}
if cs.localClosed {
return ErrStreamClosed
}
var (
payload []byte
err error
)
if m != nil {
payload, err = cs.c.codec.Marshal(m)
if err != nil {
return err
}
}
err = cs.s.send(messageTypeData, 0, payload)
if err != nil {
return filterCloseErr(err)
}
return nil
}
func (cs *clientStream) RecvMsg(m interface{}) error {
if cs.remoteClosed {
return io.EOF
}
select {
case <-cs.ctx.Done():
return cs.ctx.Err()
case msg, ok := <-cs.s.recv:
if !ok {
return cs.s.recvErr
}
if msg.header.Type == messageTypeResponse {
resp := &Response{}
err := proto.Unmarshal(msg.payload[:msg.header.Length], resp)
// return the payload buffer for reuse
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
if err := cs.c.codec.Unmarshal(resp.Payload, m); err != nil {
return err
}
if resp.Status != nil && resp.Status.Code != int32(codes.OK) {
return status.ErrorProto(resp.Status)
}
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return nil
} else if msg.header.Type == messageTypeData {
if !cs.desc.StreamingServer {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
return fmt.Errorf("received data from non-streaming server: %w", ErrProtocol)
}
if msg.header.Flags&flagRemoteClosed == flagRemoteClosed {
cs.c.deleteStream(cs.s)
cs.remoteClosed = true
if msg.header.Flags&flagNoData == flagNoData {
return io.EOF
}
}
err := cs.c.codec.Unmarshal(msg.payload[:msg.header.Length], m)
cs.c.channel.putmbuf(msg.payload)
if err != nil {
return err
}
return nil
}
return fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
}
}
// Close closes the ttrpc connection and underlying connection
func (c *Client) Close() error {
c.closeOnce.Do(func() {
c.closed()
c.conn.Close()
})
return nil
}
@ -188,194 +291,105 @@ func (c *Client) UserOnCloseWait(ctx context.Context) error {
}
}
type message struct {
messageHeader
p []byte
err error
}
// callMap provides access to a map of active calls, guarded by a mutex.
type callMap struct {
m sync.Mutex
activeCalls map[uint32]*callRequest
closeErr error
}
// newCallMap returns a new callMap with an empty set of active calls.
func newCallMap() *callMap {
return &callMap{
activeCalls: make(map[uint32]*callRequest),
}
}
// set adds a call entry to the map with the given streamID key.
func (cm *callMap) set(streamID uint32, cr *callRequest) error {
cm.m.Lock()
defer cm.m.Unlock()
if cm.closeErr != nil {
return cm.closeErr
}
cm.activeCalls[streamID] = cr
return nil
}
// get looks up the call entry for the given streamID key, then removes it
// from the map and returns it.
func (cm *callMap) get(streamID uint32) (cr *callRequest, ok bool, err error) {
cm.m.Lock()
defer cm.m.Unlock()
if cm.closeErr != nil {
return nil, false, cm.closeErr
}
cr, ok = cm.activeCalls[streamID]
if ok {
delete(cm.activeCalls, streamID)
}
return
}
// abort sends the given error to each active call, and clears the map.
// Once abort has been called, any subsequent calls to the callMap will return the error passed to abort.
func (cm *callMap) abort(err error) error {
cm.m.Lock()
defer cm.m.Unlock()
if cm.closeErr != nil {
return cm.closeErr
}
for streamID, call := range cm.activeCalls {
call.errs <- err
delete(cm.activeCalls, streamID)
}
cm.closeErr = err
return nil
}
func (c *Client) run() {
err := c.receiveLoop()
c.Close()
c.cleanupStreams(err)
c.userCloseFunc()
close(c.userCloseWaitCh)
}
func (c *Client) receiveLoop() error {
for {
select {
case <-c.ctx.Done():
return ErrClosed
default:
var (
waiters = newCallMap()
receiverDone = make(chan struct{})
msg = &streamMessage{}
err error
)
// Sender goroutine
// Receives calls from dispatch, adds them to the set of active calls, and sends them
// to the server.
go func() {
var streamID uint32 = 1
for {
select {
case <-c.ctx.Done():
return
case call := <-c.calls:
id := streamID
streamID += 2 // enforce odd client initiated request ids
if err := waiters.set(id, call); err != nil {
call.errs <- err // errs is buffered so should not block.
continue
}
if err := c.send(id, messageTypeRequest, call.req); err != nil {
call.errs <- err // errs is buffered so should not block.
waiters.get(id) // remove from waiters set
}
}
}
}()
// Receiver goroutine
// Receives responses from the server, looks up the call info in the set of active calls,
// and notifies the caller of the response.
go func() {
defer close(receiverDone)
for {
select {
case <-c.ctx.Done():
c.setError(c.ctx.Err())
return
default:
mh, p, err := c.channel.recv()
msg.header, msg.payload, err = c.channel.recv()
if err != nil {
_, ok := status.FromError(err)
if !ok {
// treat all errors that are not an rpc status as terminal.
// all others poison the connection.
c.setError(filterCloseErr(err))
return
return filterCloseErr(err)
}
}
msg := &message{
messageHeader: mh,
p: p[:mh.Length],
err: err,
sid := streamID(msg.header.StreamID)
s := c.getStream(sid)
if s == nil {
logrus.WithField("stream", sid).Errorf("ttrpc: received message on inactive stream")
continue
}
call, ok, err := waiters.get(mh.StreamID)
if err != nil {
logrus.Errorf("ttrpc: failed to look up active call: %s", err)
continue
}
if !ok {
logrus.Errorf("ttrpc: received message for unknown channel %v", mh.StreamID)
continue
}
call.errs <- c.recv(call.resp, msg)
s.closeWithError(err)
} else {
if err := s.receive(c.ctx, msg); err != nil {
logrus.WithError(err).WithField("stream", sid).Errorf("ttrpc: failed to handle message")
}
}
}()
}
}
}
defer func() {
c.conn.Close()
c.userCloseFunc()
close(c.userCloseWaitCh)
}()
// createStream creates a new stream and registers it with the client
// Introduce stream types for multiple or single response
func (c *Client) createStream(flags uint8, b []byte) (*stream, error) {
c.streamLock.Lock()
for {
// Check if closed since lock acquired to prevent adding
// anything after cleanup completes
select {
case <-receiverDone:
// The receiver has exited.
// don't return out, let the close of the context trigger the abort of waiters
c.Close()
case <-c.ctx.Done():
// Abort all active calls. This will also prevent any new calls from being added
// to waiters.
waiters.abort(c.error())
return
c.streamLock.Unlock()
return nil, ErrClosed
default:
}
// Stream ID should be allocated at same time
s := newStream(c.nextStreamID, c)
c.streams[s.id] = s
c.nextStreamID = c.nextStreamID + 2
c.sendLock.Lock()
defer c.sendLock.Unlock()
c.streamLock.Unlock()
if err := c.channel.send(uint32(s.id), messageTypeRequest, flags, b); err != nil {
return s, filterCloseErr(err)
}
return s, nil
}
func (c *Client) error() error {
c.errOnce.Do(func() {
if c.err == nil {
c.err = ErrClosed
}
})
return c.err
func (c *Client) deleteStream(s *stream) {
c.streamLock.Lock()
delete(c.streams, s.id)
c.streamLock.Unlock()
s.closeWithError(nil)
}
func (c *Client) setError(err error) {
c.errOnce.Do(func() {
c.err = err
})
func (c *Client) getStream(sid streamID) *stream {
c.streamLock.RLock()
s := c.streams[sid]
c.streamLock.RUnlock()
return s
}
func (c *Client) send(streamID uint32, mtype messageType, msg interface{}) error {
p, err := c.codec.Marshal(msg)
if err != nil {
return err
func (c *Client) cleanupStreams(err error) {
c.streamLock.Lock()
defer c.streamLock.Unlock()
for sid, s := range c.streams {
s.closeWithError(err)
delete(c.streams, sid)
}
return c.channel.send(streamID, mtype, p)
}
func (c *Client) recv(resp *Response, msg *message) error {
if msg.err != nil {
return msg.err
}
if msg.Type != messageTypeResponse {
return errors.New("unknown message type received")
}
defer c.channel.putmbuf(msg.p)
return proto.Unmarshal(msg.p, resp)
}
// filterCloseErr rewrites EOF and EPIPE errors to ErrClosed. Use when
@ -388,6 +402,8 @@ func filterCloseErr(err error) error {
return nil
case err == io.EOF:
return ErrClosed
case errors.Is(err, io.ErrClosedPipe):
return ErrClosed
case errors.Is(err, io.EOF):
return ErrClosed
case strings.Contains(err.Error(), "use of closed network connection"):
@ -395,11 +411,9 @@ func filterCloseErr(err error) error {
default:
// if we have an epipe on a write or econnreset on a read , we cast to errclosed
var oerr *net.OpError
if errors.As(err, &oerr) && (oerr.Op == "write" || oerr.Op == "read") {
serr, sok := oerr.Err.(*os.SyscallError)
if sok && ((serr.Err == syscall.EPIPE && oerr.Op == "write") ||
(serr.Err == syscall.ECONNRESET && oerr.Op == "read")) {
if errors.As(err, &oerr) {
if (oerr.Op == "write" && errors.Is(err, syscall.EPIPE)) ||
(oerr.Op == "read" && errors.Is(err, syscall.ECONNRESET)) {
return ErrClosed
}
}
@ -407,3 +421,81 @@ func filterCloseErr(err error) error {
return err
}
// NewStream creates a new stream with the given stream descriptor to the
// specified service and method. If not a streaming client, the request object
// may be provided.
func (c *Client) NewStream(ctx context.Context, desc *StreamDesc, service, method string, req interface{}) (ClientStream, error) {
var payload []byte
if req != nil {
var err error
payload, err = c.codec.Marshal(req)
if err != nil {
return nil, err
}
}
request := &Request{
Service: service,
Method: method,
Payload: payload,
// TODO: metadata from context
}
p, err := c.codec.Marshal(request)
if err != nil {
return nil, err
}
var flags uint8
if desc.StreamingClient {
flags = flagRemoteOpen
} else {
flags = flagRemoteClosed
}
s, err := c.createStream(flags, p)
if err != nil {
return nil, err
}
return &clientStream{
ctx: ctx,
s: s,
c: c,
desc: desc,
}, nil
}
func (c *Client) dispatch(ctx context.Context, req *Request, resp *Response) error {
p, err := c.codec.Marshal(req)
if err != nil {
return err
}
s, err := c.createStream(0, p)
if err != nil {
return err
}
defer c.deleteStream(s)
select {
case <-ctx.Done():
return ctx.Err()
case <-c.ctx.Done():
return ErrClosed
case msg, ok := <-s.recv:
if !ok {
return s.recvErr
}
if msg.header.Type == messageTypeResponse {
err = proto.Unmarshal(msg.payload[:msg.header.Length], resp)
} else {
err = fmt.Errorf("unexpected %q message received: %w", msg.header.Type, ErrProtocol)
}
// return the payload buffer for reuse
c.channel.putmbuf(msg.payload)
return err
}
}

View File

@ -19,7 +19,7 @@ package ttrpc
import (
"fmt"
"github.com/gogo/protobuf/proto"
"google.golang.org/protobuf/proto"
)
type codec struct{}

23
vendor/github.com/containerd/ttrpc/doc.go generated vendored Normal file
View File

@ -0,0 +1,23 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
package ttrpc defines and implements a low level simple transfer protocol
optimized for low latency and reliable connections between processes on the same
host. The protocol uses simple framing for sending requests, responses, and data
using multiple streams.
*/
package ttrpc

34
vendor/github.com/containerd/ttrpc/errors.go generated vendored Normal file
View File

@ -0,0 +1,34 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ttrpc
import "errors"
var (
// ErrProtocol is a general error in the handling the protocol.
ErrProtocol = errors.New("protocol error")
// ErrClosed is returned by client methods when the underlying connection is
// closed.
ErrClosed = errors.New("ttrpc: closed")
// ErrServerClosed is returned when the Server has closed its connection.
ErrServerClosed = errors.New("ttrpc: server closed")
// ErrStreamClosed is when the streaming connection is closed.
ErrStreamClosed = errors.New("ttrpc: stream closed")
)

View File

@ -45,6 +45,6 @@ func (fn handshakerFunc) Handshake(ctx context.Context, conn net.Conn) (net.Conn
return fn(ctx, conn)
}
func noopHandshake(ctx context.Context, conn net.Conn) (net.Conn, interface{}, error) {
func noopHandshake(_ context.Context, conn net.Conn) (net.Conn, interface{}, error) {
return conn, nil, nil
}

View File

@ -28,6 +28,13 @@ type UnaryClientInfo struct {
FullMethod string
}
// StreamServerInfo provides information about the server request
type StreamServerInfo struct {
FullMethod string
StreamingClient bool
StreamingServer bool
}
// Unmarshaler contains the server request data and allows it to be unmarshaled
// into a concrete type
type Unmarshaler func(interface{}) error
@ -41,10 +48,18 @@ type UnaryServerInterceptor func(context.Context, Unmarshaler, *UnaryServerInfo,
// UnaryClientInterceptor specifies the interceptor function for client request/response
type UnaryClientInterceptor func(context.Context, *Request, *Response, *UnaryClientInfo, Invoker) error
func defaultServerInterceptor(ctx context.Context, unmarshal Unmarshaler, info *UnaryServerInfo, method Method) (interface{}, error) {
func defaultServerInterceptor(ctx context.Context, unmarshal Unmarshaler, _ *UnaryServerInfo, method Method) (interface{}, error) {
return method(ctx, unmarshal)
}
func defaultClientInterceptor(ctx context.Context, req *Request, resp *Response, _ *UnaryClientInfo, invoker Invoker) error {
return invoker(ctx, req, resp)
}
type StreamServerInterceptor func(context.Context, StreamServer, *StreamServerInfo, StreamHandler) (interface{}, error)
func defaultStreamServerInterceptor(ctx context.Context, ss StreamServer, _ *StreamServerInfo, stream StreamHandler) (interface{}, error) {
return stream(ctx, ss)
}
type StreamClientInterceptor func(context.Context)

View File

@ -1,147 +0,0 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package plugin
import (
"strings"
"github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type ttrpcGenerator struct {
*generator.Generator
generator.PluginImports
typeurlPkg generator.Single
ttrpcPkg generator.Single
contextPkg generator.Single
}
func init() {
generator.RegisterPlugin(new(ttrpcGenerator))
}
func (p *ttrpcGenerator) Name() string {
return "ttrpc"
}
func (p *ttrpcGenerator) Init(g *generator.Generator) {
p.Generator = g
}
func (p *ttrpcGenerator) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.contextPkg = p.NewImport("context")
p.typeurlPkg = p.NewImport("github.com/containerd/typeurl")
p.ttrpcPkg = p.NewImport("github.com/containerd/ttrpc")
for _, service := range file.GetService() {
serviceName := service.GetName()
if pkg := file.GetPackage(); pkg != "" {
serviceName = pkg + "." + serviceName
}
p.genService(serviceName, service)
}
}
func (p *ttrpcGenerator) genService(fullName string, service *descriptor.ServiceDescriptorProto) {
serviceName := service.GetName() + "Service"
p.P()
p.P("type ", serviceName, " interface{")
p.In()
for _, method := range service.Method {
p.P(method.GetName(),
"(ctx ", p.contextPkg.Use(), ".Context, ",
"req *", p.typeName(method.GetInputType()), ") ",
"(*", p.typeName(method.GetOutputType()), ", error)")
}
p.Out()
p.P("}")
p.P()
// registration method
p.P("func Register", serviceName, "(srv *", p.ttrpcPkg.Use(), ".Server, svc ", serviceName, ") {")
p.In()
p.P(`srv.Register("`, fullName, `", map[string]`, p.ttrpcPkg.Use(), ".Method{")
p.In()
for _, method := range service.Method {
p.P(`"`, method.GetName(), `": `, `func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error) {`)
p.In()
p.P("var req ", p.typeName(method.GetInputType()))
p.P(`if err := unmarshal(&req); err != nil {`)
p.In()
p.P(`return nil, err`)
p.Out()
p.P(`}`)
p.P("return svc.", method.GetName(), "(ctx, &req)")
p.Out()
p.P("},")
}
p.Out()
p.P("})")
p.Out()
p.P("}")
clientType := service.GetName() + "Client"
clientStructType := strings.ToLower(clientType[:1]) + clientType[1:]
p.P()
p.P("type ", clientStructType, " struct{")
p.In()
p.P("client *", p.ttrpcPkg.Use(), ".Client")
p.Out()
p.P("}")
p.P()
p.P("func New", clientType, "(client *", p.ttrpcPkg.Use(), ".Client)", serviceName, "{")
p.In()
p.P("return &", clientStructType, "{")
p.In()
p.P("client: client,")
p.Out()
p.P("}")
p.Out()
p.P("}")
p.P()
for _, method := range service.Method {
p.P()
p.P("func (c *", clientStructType, ") ", method.GetName(),
"(ctx ", p.contextPkg.Use(), ".Context, ",
"req *", p.typeName(method.GetInputType()), ") ",
"(*", p.typeName(method.GetOutputType()), ", error) {")
p.In()
p.P("var resp ", p.typeName(method.GetOutputType()))
p.P("if err := c.client.Call(ctx, ", `"`+fullName+`", `, `"`+method.GetName()+`"`, ", req, &resp); err != nil {")
p.In()
p.P("return nil, err")
p.Out()
p.P("}")
p.P("return &resp, nil")
p.Out()
p.P("}")
}
}
func (p *ttrpcGenerator) objectNamed(name string) generator.Object {
p.Generator.RecordTypeUse(name)
return p.Generator.ObjectNamed(name)
}
func (p *ttrpcGenerator) typeName(str string) string {
return p.Generator.TypeName(p.objectNamed(str))
}

396
vendor/github.com/containerd/ttrpc/request.pb.go generated vendored Normal file
View File

@ -0,0 +1,396 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.27.1
// protoc v3.11.4
// source: github.com/containerd/ttrpc/request.proto
package ttrpc
import (
status "google.golang.org/genproto/googleapis/rpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Request struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Service string `protobuf:"bytes,1,opt,name=service,proto3" json:"service,omitempty"`
Method string `protobuf:"bytes,2,opt,name=method,proto3" json:"method,omitempty"`
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
TimeoutNano int64 `protobuf:"varint,4,opt,name=timeout_nano,json=timeoutNano,proto3" json:"timeout_nano,omitempty"`
Metadata []*KeyValue `protobuf:"bytes,5,rep,name=metadata,proto3" json:"metadata,omitempty"`
}
func (x *Request) Reset() {
*x = Request{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Request) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Request) ProtoMessage() {}
func (x *Request) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Request.ProtoReflect.Descriptor instead.
func (*Request) Descriptor() ([]byte, []int) {
return file_github_com_containerd_ttrpc_request_proto_rawDescGZIP(), []int{0}
}
func (x *Request) GetService() string {
if x != nil {
return x.Service
}
return ""
}
func (x *Request) GetMethod() string {
if x != nil {
return x.Method
}
return ""
}
func (x *Request) GetPayload() []byte {
if x != nil {
return x.Payload
}
return nil
}
func (x *Request) GetTimeoutNano() int64 {
if x != nil {
return x.TimeoutNano
}
return 0
}
func (x *Request) GetMetadata() []*KeyValue {
if x != nil {
return x.Metadata
}
return nil
}
type Response struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Status *status.Status `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3" json:"payload,omitempty"`
}
func (x *Response) Reset() {
*x = Response{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Response) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Response) ProtoMessage() {}
func (x *Response) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Response.ProtoReflect.Descriptor instead.
func (*Response) Descriptor() ([]byte, []int) {
return file_github_com_containerd_ttrpc_request_proto_rawDescGZIP(), []int{1}
}
func (x *Response) GetStatus() *status.Status {
if x != nil {
return x.Status
}
return nil
}
func (x *Response) GetPayload() []byte {
if x != nil {
return x.Payload
}
return nil
}
type StringList struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
List []string `protobuf:"bytes,1,rep,name=list,proto3" json:"list,omitempty"`
}
func (x *StringList) Reset() {
*x = StringList{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *StringList) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*StringList) ProtoMessage() {}
func (x *StringList) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use StringList.ProtoReflect.Descriptor instead.
func (*StringList) Descriptor() ([]byte, []int) {
return file_github_com_containerd_ttrpc_request_proto_rawDescGZIP(), []int{2}
}
func (x *StringList) GetList() []string {
if x != nil {
return x.List
}
return nil
}
type KeyValue struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"`
Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
}
func (x *KeyValue) Reset() {
*x = KeyValue{}
if protoimpl.UnsafeEnabled {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *KeyValue) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*KeyValue) ProtoMessage() {}
func (x *KeyValue) ProtoReflect() protoreflect.Message {
mi := &file_github_com_containerd_ttrpc_request_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use KeyValue.ProtoReflect.Descriptor instead.
func (*KeyValue) Descriptor() ([]byte, []int) {
return file_github_com_containerd_ttrpc_request_proto_rawDescGZIP(), []int{3}
}
func (x *KeyValue) GetKey() string {
if x != nil {
return x.Key
}
return ""
}
func (x *KeyValue) GetValue() string {
if x != nil {
return x.Value
}
return ""
}
var File_github_com_containerd_ttrpc_request_proto protoreflect.FileDescriptor
var file_github_com_containerd_ttrpc_request_proto_rawDesc = []byte{
0x0a, 0x29, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e,
0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x74, 0x74, 0x72, 0x70, 0x63, 0x2f, 0x72, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x74, 0x74, 0x72,
0x70, 0x63, 0x1a, 0x12, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa5, 0x01, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x16, 0x0a, 0x06,
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6d, 0x65,
0x74, 0x68, 0x6f, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x21,
0x0a, 0x0c, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x5f, 0x6e, 0x61, 0x6e, 0x6f, 0x18, 0x04,
0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x4e, 0x61, 0x6e,
0x6f, 0x12, 0x2b, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x05, 0x20,
0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x74, 0x72, 0x70, 0x63, 0x2e, 0x4b, 0x65, 0x79, 0x56,
0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0x45,
0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x06, 0x73, 0x74,
0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x07, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x70,
0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x70, 0x61,
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x22, 0x20, 0x0a, 0x0a, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x4c,
0x69, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x01, 0x20, 0x03, 0x28,
0x09, 0x52, 0x04, 0x6c, 0x69, 0x73, 0x74, 0x22, 0x32, 0x0a, 0x08, 0x4b, 0x65, 0x79, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x1d, 0x5a, 0x1b, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69,
0x6e, 0x65, 0x72, 0x64, 0x2f, 0x74, 0x74, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
}
var (
file_github_com_containerd_ttrpc_request_proto_rawDescOnce sync.Once
file_github_com_containerd_ttrpc_request_proto_rawDescData = file_github_com_containerd_ttrpc_request_proto_rawDesc
)
func file_github_com_containerd_ttrpc_request_proto_rawDescGZIP() []byte {
file_github_com_containerd_ttrpc_request_proto_rawDescOnce.Do(func() {
file_github_com_containerd_ttrpc_request_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_ttrpc_request_proto_rawDescData)
})
return file_github_com_containerd_ttrpc_request_proto_rawDescData
}
var file_github_com_containerd_ttrpc_request_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_github_com_containerd_ttrpc_request_proto_goTypes = []interface{}{
(*Request)(nil), // 0: ttrpc.Request
(*Response)(nil), // 1: ttrpc.Response
(*StringList)(nil), // 2: ttrpc.StringList
(*KeyValue)(nil), // 3: ttrpc.KeyValue
(*status.Status)(nil), // 4: Status
}
var file_github_com_containerd_ttrpc_request_proto_depIdxs = []int32{
3, // 0: ttrpc.Request.metadata:type_name -> ttrpc.KeyValue
4, // 1: ttrpc.Response.status:type_name -> Status
2, // [2:2] is the sub-list for method output_type
2, // [2:2] is the sub-list for method input_type
2, // [2:2] is the sub-list for extension type_name
2, // [2:2] is the sub-list for extension extendee
0, // [0:2] is the sub-list for field type_name
}
func init() { file_github_com_containerd_ttrpc_request_proto_init() }
func file_github_com_containerd_ttrpc_request_proto_init() {
if File_github_com_containerd_ttrpc_request_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_github_com_containerd_ttrpc_request_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Request); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_ttrpc_request_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Response); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_ttrpc_request_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*StringList); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_github_com_containerd_ttrpc_request_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*KeyValue); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_github_com_containerd_ttrpc_request_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_github_com_containerd_ttrpc_request_proto_goTypes,
DependencyIndexes: file_github_com_containerd_ttrpc_request_proto_depIdxs,
MessageInfos: file_github_com_containerd_ttrpc_request_proto_msgTypes,
}.Build()
File_github_com_containerd_ttrpc_request_proto = out.File
file_github_com_containerd_ttrpc_request_proto_rawDesc = nil
file_github_com_containerd_ttrpc_request_proto_goTypes = nil
file_github_com_containerd_ttrpc_request_proto_depIdxs = nil
}

29
vendor/github.com/containerd/ttrpc/request.proto generated vendored Normal file
View File

@ -0,0 +1,29 @@
syntax = "proto3";
package ttrpc;
import "proto/status.proto";
option go_package = "github.com/containerd/ttrpc";
message Request {
string service = 1;
string method = 2;
bytes payload = 3;
int64 timeout_nano = 4;
repeated KeyValue metadata = 5;
}
message Response {
Status status = 1;
bytes payload = 2;
}
message StringList {
repeated string list = 1;
}
message KeyValue {
string key = 1;
string value = 2;
}

View File

@ -18,7 +18,6 @@ package ttrpc
import (
"context"
"errors"
"io"
"math/rand"
"net"
@ -31,10 +30,6 @@ import (
"google.golang.org/grpc/status"
)
var (
ErrServerClosed = errors.New("ttrpc: server closed")
)
type Server struct {
config *serverConfig
services *serviceSet
@ -66,8 +61,14 @@ func NewServer(opts ...ServerOpt) (*Server, error) {
}, nil
}
// Register registers a map of methods to method handlers
// TODO: Remove in 2.0, does not support streams
func (s *Server) Register(name string, methods map[string]Method) {
s.services.register(name, methods)
s.services.register(name, &ServiceDesc{Methods: methods})
}
func (s *Server) RegisterService(name string, desc *ServiceDesc) {
s.services.register(name, desc)
}
func (s *Server) Serve(ctx context.Context, l net.Listener) error {
@ -301,27 +302,24 @@ func (c *serverConn) close() error {
func (c *serverConn) run(sctx context.Context) {
type (
request struct {
id uint32
req *Request
}
response struct {
id uint32
resp *Response
status *status.Status
data []byte
closeStream bool
streaming bool
}
)
var (
ch = newChannel(c.conn)
ctx, cancel = context.WithCancel(sctx)
active int
state connState = connStateIdle
responses = make(chan response)
requests = make(chan request)
recvErr = make(chan error, 1)
shutdown = c.shutdown
done = make(chan struct{})
active int32
lastStreamID uint32
)
defer c.conn.Close()
@ -329,18 +327,15 @@ func (c *serverConn) run(sctx context.Context) {
defer close(done)
defer c.server.delConnection(c)
go func(recvErr chan error) {
defer close(recvErr)
sendImmediate := func(id uint32, st *status.Status) bool {
sendStatus := func(id uint32, st *status.Status) bool {
select {
case responses <- response{
// even though we've had an invalid stream id, we send it
// back on the same stream id so the client knows which
// stream id was bad.
id: id,
resp: &Response{
Status: st.Proto(),
},
status: st,
closeStream: true,
}:
return true
case <-c.shutdown:
@ -350,6 +345,9 @@ func (c *serverConn) run(sctx context.Context) {
}
}
go func(recvErr chan error) {
defer close(recvErr)
streams := map[uint32]*streamHandler{}
for {
select {
case <-c.shutdown:
@ -369,99 +367,159 @@ func (c *serverConn) run(sctx context.Context) {
// in this case, we send an error for that particular message
// when the status is defined.
if !sendImmediate(mh.StreamID, status) {
if !sendStatus(mh.StreamID, status) {
return
}
continue
}
if mh.Type != messageTypeRequest {
// we must ignore this for future compat.
continue
}
var req Request
if err := c.server.codec.Unmarshal(p, &req); err != nil {
ch.putmbuf(p)
if !sendImmediate(mh.StreamID, status.Newf(codes.InvalidArgument, "unmarshal request error: %v", err)) {
return
}
continue
}
ch.putmbuf(p)
if mh.StreamID%2 != 1 {
// enforce odd client initiated identifiers.
if !sendImmediate(mh.StreamID, status.Newf(codes.InvalidArgument, "StreamID must be odd for client initiated streams")) {
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "StreamID must be odd for client initiated streams")) {
return
}
continue
}
// Forward the request to the main loop. We don't wait on s.done
// because we have already accepted the client request.
select {
case requests <- request{
id: mh.StreamID,
req: &req,
}:
case <-done:
if mh.Type == messageTypeData {
sh, ok := streams[mh.StreamID]
if !ok {
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "StreamID is no longer active")) {
return
}
}
if mh.Flags&flagNoData != flagNoData {
unmarshal := func(obj interface{}) error {
err := protoUnmarshal(p, obj)
ch.putmbuf(p)
return err
}
if err := sh.data(unmarshal); err != nil {
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "data handling error: %v", err)) {
return
}
}
}
if mh.Flags&flagRemoteClosed == flagRemoteClosed {
sh.closeSend()
if len(p) > 0 {
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "data close message cannot include data")) {
return
}
}
}
} else if mh.Type == messageTypeRequest {
if mh.StreamID <= lastStreamID {
// enforce odd client initiated identifiers.
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "StreamID cannot be re-used and must increment")) {
return
}
continue
}
lastStreamID = mh.StreamID
// TODO: Make request type configurable
// Unmarshaller which takes in a byte array and returns an interface?
var req Request
if err := c.server.codec.Unmarshal(p, &req); err != nil {
ch.putmbuf(p)
if !sendStatus(mh.StreamID, status.Newf(codes.InvalidArgument, "unmarshal request error: %v", err)) {
return
}
continue
}
ch.putmbuf(p)
id := mh.StreamID
respond := func(status *status.Status, data []byte, streaming, closeStream bool) error {
select {
case responses <- response{
id: id,
status: status,
data: data,
closeStream: closeStream,
streaming: streaming,
}:
case <-done:
return ErrClosed
}
return nil
}
sh, err := c.server.services.handle(ctx, &req, respond)
if err != nil {
status, _ := status.FromError(err)
if !sendStatus(mh.StreamID, status) {
return
}
continue
}
streams[id] = sh
atomic.AddInt32(&active, 1)
}
// TODO: else we must ignore this for future compat. log this?
}
}(recvErr)
for {
newstate := state
switch {
case active > 0:
var (
newstate connState
shutdown chan struct{}
)
activeN := atomic.LoadInt32(&active)
if activeN > 0 {
newstate = connStateActive
shutdown = nil
case active == 0:
} else {
newstate = connStateIdle
shutdown = c.shutdown // only enable this branch in idle mode
}
if newstate != state {
c.setState(newstate)
state = newstate
}
select {
case request := <-requests:
active++
go func(id uint32) {
ctx, cancel := getRequestContext(ctx, request.req)
defer cancel()
p, status := c.server.services.call(ctx, request.req.Service, request.req.Method, request.req.Payload)
resp := &Response{
Status: status.Proto(),
Payload: p,
}
select {
case responses <- response{
id: id,
resp: resp,
}:
case <-done:
}
}(request.id)
case response := <-responses:
p, err := c.server.codec.Marshal(response.resp)
if !response.streaming || response.status.Code() != codes.OK {
p, err := c.server.codec.Marshal(&Response{
Status: response.status.Proto(),
Payload: response.data,
})
if err != nil {
logrus.WithError(err).Error("failed marshaling response")
return
}
if err := ch.send(response.id, messageTypeResponse, p); err != nil {
if err := ch.send(response.id, messageTypeResponse, 0, p); err != nil {
logrus.WithError(err).Error("failed sending message on channel")
return
}
} else {
var flags uint8
if response.closeStream {
flags = flagRemoteClosed
}
if response.data == nil {
flags = flags | flagNoData
}
if err := ch.send(response.id, messageTypeData, flags, response.data); err != nil {
logrus.WithError(err).Error("failed sending message on channel")
return
}
}
active--
if response.closeStream {
// The ttrpc protocol currently does not support the case where
// the server is localClosed but not remoteClosed. Once the server
// is closing, the whole stream may be considered finished
atomic.AddInt32(&active, -1)
}
case err := <-recvErr:
// TODO(stevvooe): Not wildly clear what we should do in this
// branch. Basically, it means that we are no longer receiving
@ -475,6 +533,7 @@ func (c *serverConn) run(sctx context.Context) {
if err != nil {
logrus.WithError(err).Error("error receiving message")
}
// else, initiate shutdown
case <-shutdown:
return
}

View File

@ -25,43 +25,62 @@ import (
"path"
"unsafe"
"github.com/gogo/protobuf/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
type Method func(ctx context.Context, unmarshal func(interface{}) error) (interface{}, error)
type StreamHandler func(context.Context, StreamServer) (interface{}, error)
type Stream struct {
Handler StreamHandler
StreamingClient bool
StreamingServer bool
}
type ServiceDesc struct {
Methods map[string]Method
// TODO(stevvooe): Add stream support.
Streams map[string]Stream
}
type serviceSet struct {
services map[string]ServiceDesc
interceptor UnaryServerInterceptor
services map[string]*ServiceDesc
unaryInterceptor UnaryServerInterceptor
streamInterceptor StreamServerInterceptor
}
func newServiceSet(interceptor UnaryServerInterceptor) *serviceSet {
return &serviceSet{
services: make(map[string]ServiceDesc),
interceptor: interceptor,
services: make(map[string]*ServiceDesc),
unaryInterceptor: interceptor,
streamInterceptor: defaultStreamServerInterceptor,
}
}
func (s *serviceSet) register(name string, methods map[string]Method) {
func (s *serviceSet) register(name string, desc *ServiceDesc) {
if _, ok := s.services[name]; ok {
panic(fmt.Errorf("duplicate service %v registered", name))
}
s.services[name] = ServiceDesc{
Methods: methods,
}
s.services[name] = desc
}
func (s *serviceSet) call(ctx context.Context, serviceName, methodName string, p []byte) ([]byte, *status.Status) {
p, err := s.dispatch(ctx, serviceName, methodName, p)
func (s *serviceSet) unaryCall(ctx context.Context, method Method, info *UnaryServerInfo, data []byte) (p []byte, st *status.Status) {
unmarshal := func(obj interface{}) error {
return protoUnmarshal(data, obj)
}
resp, err := s.unaryInterceptor(ctx, unmarshal, info, method)
if err == nil {
if isNil(resp) {
err = errors.New("ttrpc: marshal called with nil")
} else {
p, err = protoMarshal(resp)
}
}
st, ok := status.FromError(err)
if !ok {
st = status.New(convertCode(err), err.Error())
@ -70,13 +89,125 @@ func (s *serviceSet) call(ctx context.Context, serviceName, methodName string, p
return p, st
}
func (s *serviceSet) dispatch(ctx context.Context, serviceName, methodName string, p []byte) ([]byte, error) {
method, err := s.resolve(serviceName, methodName)
if err != nil {
return nil, err
func (s *serviceSet) streamCall(ctx context.Context, stream StreamHandler, info *StreamServerInfo, ss StreamServer) (p []byte, st *status.Status) {
resp, err := s.streamInterceptor(ctx, ss, info, stream)
if err == nil {
p, err = protoMarshal(resp)
}
st, ok := status.FromError(err)
if !ok {
st = status.New(convertCode(err), err.Error())
}
return
}
func (s *serviceSet) handle(ctx context.Context, req *Request, respond func(*status.Status, []byte, bool, bool) error) (*streamHandler, error) {
srv, ok := s.services[req.Service]
if !ok {
return nil, status.Errorf(codes.Unimplemented, "service %v", req.Service)
}
if method, ok := srv.Methods[req.Method]; ok {
go func() {
ctx, cancel := getRequestContext(ctx, req)
defer cancel()
info := &UnaryServerInfo{
FullMethod: fullPath(req.Service, req.Method),
}
p, st := s.unaryCall(ctx, method, info, req.Payload)
respond(st, p, false, true)
}()
return nil, nil
}
if stream, ok := srv.Streams[req.Method]; ok {
ctx, cancel := getRequestContext(ctx, req)
info := &StreamServerInfo{
FullMethod: fullPath(req.Service, req.Method),
StreamingClient: stream.StreamingClient,
StreamingServer: stream.StreamingServer,
}
sh := &streamHandler{
ctx: ctx,
respond: respond,
recv: make(chan Unmarshaler, 5),
info: info,
}
go func() {
defer cancel()
p, st := s.streamCall(ctx, stream.Handler, info, sh)
respond(st, p, stream.StreamingServer, true)
}()
if req.Payload != nil {
unmarshal := func(obj interface{}) error {
return protoUnmarshal(req.Payload, obj)
}
if err := sh.data(unmarshal); err != nil {
return nil, err
}
}
return sh, nil
}
return nil, status.Errorf(codes.Unimplemented, "method %v", req.Method)
}
type streamHandler struct {
ctx context.Context
respond func(*status.Status, []byte, bool, bool) error
recv chan Unmarshaler
info *StreamServerInfo
remoteClosed bool
localClosed bool
}
func (s *streamHandler) closeSend() {
if !s.remoteClosed {
s.remoteClosed = true
close(s.recv)
}
}
func (s *streamHandler) data(unmarshal Unmarshaler) error {
if s.remoteClosed {
return ErrStreamClosed
}
select {
case s.recv <- unmarshal:
return nil
case <-s.ctx.Done():
return s.ctx.Err()
}
}
func (s *streamHandler) SendMsg(m interface{}) error {
if s.localClosed {
return ErrStreamClosed
}
p, err := protoMarshal(m)
if err != nil {
return err
}
return s.respond(nil, p, true, false)
}
func (s *streamHandler) RecvMsg(m interface{}) error {
select {
case unmarshal, ok := <-s.recv:
if !ok {
return io.EOF
}
return unmarshal(m)
case <-s.ctx.Done():
return s.ctx.Err()
}
}
func protoUnmarshal(p []byte, obj interface{}) error {
switch v := obj.(type) {
case proto.Message:
if err := proto.Unmarshal(p, v); err != nil {
@ -86,22 +217,14 @@ func (s *serviceSet) dispatch(ctx context.Context, serviceName, methodName strin
return status.Errorf(codes.Internal, "ttrpc: error unsupported request type: %T", v)
}
return nil
}
func protoMarshal(obj interface{}) ([]byte, error) {
if obj == nil {
return nil, nil
}
info := &UnaryServerInfo{
FullMethod: fullPath(serviceName, methodName),
}
resp, err := s.interceptor(ctx, unmarshal, info, method)
if err != nil {
return nil, err
}
if isNil(resp) {
return nil, errors.New("ttrpc: marshal called with nil")
}
switch v := resp.(type) {
switch v := obj.(type) {
case proto.Message:
r, err := proto.Marshal(v)
if err != nil {
@ -114,20 +237,6 @@ func (s *serviceSet) dispatch(ctx context.Context, serviceName, methodName strin
}
}
func (s *serviceSet) resolve(service, method string) (Method, error) {
srv, ok := s.services[service]
if !ok {
return nil, status.Errorf(codes.Unimplemented, "service %v", service)
}
mthd, ok := srv.Methods[method]
if !ok {
return nil, status.Errorf(codes.Unimplemented, "method %v", method)
}
return mthd, nil
}
// convertCode maps stdlib go errors into grpc space.
//
// This is ripped from the grpc-go code base.

81
vendor/github.com/containerd/ttrpc/stream.go generated vendored Normal file
View File

@ -0,0 +1,81 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ttrpc
import (
"context"
"sync"
)
type streamID uint32
type streamMessage struct {
header messageHeader
payload []byte
}
type stream struct {
id streamID
sender sender
recv chan *streamMessage
closeOnce sync.Once
recvErr error
}
func newStream(id streamID, send sender) *stream {
return &stream{
id: id,
sender: send,
recv: make(chan *streamMessage, 1),
}
}
func (s *stream) closeWithError(err error) error {
s.closeOnce.Do(func() {
if s.recv != nil {
close(s.recv)
if err != nil {
s.recvErr = err
} else {
s.recvErr = ErrClosed
}
}
})
return nil
}
func (s *stream) send(mt messageType, flags uint8, b []byte) error {
return s.sender.send(uint32(s.id), mt, flags, b)
}
func (s *stream) receive(ctx context.Context, msg *streamMessage) error {
if s.recvErr != nil {
return s.recvErr
}
select {
case s.recv <- msg:
return nil
case <-ctx.Done():
return ctx.Err()
}
}
type sender interface {
send(uint32, messageType, uint8, []byte) error
}

22
vendor/github.com/containerd/ttrpc/stream_server.go generated vendored Normal file
View File

@ -0,0 +1,22 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ttrpc
type StreamServer interface {
SendMsg(m interface{}) error
RecvMsg(m interface{}) error
}

16
vendor/github.com/containerd/ttrpc/test.proto generated vendored Normal file
View File

@ -0,0 +1,16 @@
syntax = "proto3";
package ttrpc;
option go_package = "github.com/containerd/ttrpc/internal";
message TestPayload {
string foo = 1;
int64 deadline = 2;
string metadata = 3;
}
message EchoPayload {
int64 seq = 1;
string msg = 2;
}

View File

@ -1,63 +0,0 @@
/*
Copyright The containerd Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ttrpc
import (
"fmt"
spb "google.golang.org/genproto/googleapis/rpc/status"
)
type Request struct {
Service string `protobuf:"bytes,1,opt,name=service,proto3"`
Method string `protobuf:"bytes,2,opt,name=method,proto3"`
Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3"`
TimeoutNano int64 `protobuf:"varint,4,opt,name=timeout_nano,proto3"`
Metadata []*KeyValue `protobuf:"bytes,5,rep,name=metadata,proto3"`
}
func (r *Request) Reset() { *r = Request{} }
func (r *Request) String() string { return fmt.Sprintf("%+#v", r) }
func (r *Request) ProtoMessage() {}
type Response struct {
Status *spb.Status `protobuf:"bytes,1,opt,name=status,proto3"`
Payload []byte `protobuf:"bytes,2,opt,name=payload,proto3"`
}
func (r *Response) Reset() { *r = Response{} }
func (r *Response) String() string { return fmt.Sprintf("%+#v", r) }
func (r *Response) ProtoMessage() {}
type StringList struct {
List []string `protobuf:"bytes,1,rep,name=list,proto3"`
}
func (r *StringList) Reset() { *r = StringList{} }
func (r *StringList) String() string { return fmt.Sprintf("%+#v", r) }
func (r *StringList) ProtoMessage() {}
func makeStringList(item ...string) StringList { return StringList{List: item} }
type KeyValue struct {
Key string `protobuf:"bytes,1,opt,name=key,proto3"`
Value string `protobuf:"bytes,2,opt,name=value,proto3"`
}
func (m *KeyValue) Reset() { *m = KeyValue{} }
func (*KeyValue) ProtoMessage() {}
func (m *KeyValue) String() string { return fmt.Sprintf("%+#v", m) }

View File

@ -29,7 +29,7 @@ import (
type UnixCredentialsFunc func(*unix.Ucred) error
func (fn UnixCredentialsFunc) Handshake(ctx context.Context, conn net.Conn) (net.Conn, interface{}, error) {
func (fn UnixCredentialsFunc) Handshake(_ context.Context, conn net.Conn) (net.Conn, interface{}, error) {
uc, err := requireUnixSocket(conn)
if err != nil {
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: require unix socket: %w", err)
@ -50,7 +50,7 @@ func (fn UnixCredentialsFunc) Handshake(ctx context.Context, conn net.Conn) (net
}
if ucredErr != nil {
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: failed to retrieve socket peer credentials: %w", err)
return nil, nil, fmt.Errorf("ttrpc.UnixCredentialsFunc: failed to retrieve socket peer credentials: %w", ucredErr)
}
if err := fn(ucred); err != nil {
@ -88,10 +88,6 @@ func UnixSocketRequireSameUser() UnixCredentialsFunc {
return UnixSocketRequireUidGid(euid, egid)
}
func requireRoot(ucred *unix.Ucred) error {
return requireUidGid(ucred, 0, 0)
}
func requireUidGid(ucred *unix.Ucred, uid, gid int) error {
if (uid != -1 && uint32(uid) != ucred.Uid) || (gid != -1 && uint32(gid) != ucred.Gid) {
return fmt.Errorf("ttrpc: invalid credentials: %v", syscall.EPERM)

View File

@ -26,6 +26,7 @@ import (
gogoproto "github.com/gogo/protobuf/proto"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoregistry"
)
var (
@ -242,7 +243,12 @@ func getTypeByUrl(url string) (urlType, error) {
isProto: true,
}, nil
}
mt, err := protoregistry.GlobalTypes.FindMessageByURL(url)
if err != nil {
return urlType{}, fmt.Errorf("type with url %s: %w", url, ErrNotFound)
}
empty := mt.New().Interface()
return urlType{t: reflect.TypeOf(empty).Elem(), isProto: true}, nil
}
func tryDereference(v interface{}) reflect.Type {

View File

@ -1,203 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015, Google Inc
Copyright 2018, GoGo Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,186 +0,0 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package google.rpc;
option go_package = "rpc";
option java_multiple_files = true;
option java_outer_classname = "CodeProto";
option java_package = "com.google.rpc";
option objc_class_prefix = "RPC";
// The canonical error codes for gRPC APIs.
//
//
// Sometimes multiple error codes may apply. Services should return
// the most specific error code that applies. For example, prefer
// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
enum Code {
// Not an error; returned on success
//
// HTTP Mapping: 200 OK
OK = 0;
// The operation was cancelled, typically by the caller.
//
// HTTP Mapping: 499 Client Closed Request
CANCELLED = 1;
// Unknown error. For example, this error may be returned when
// a `Status` value received from another address space belongs to
// an error space that is not known in this address space. Also
// errors raised by APIs that do not return enough error information
// may be converted to this error.
//
// HTTP Mapping: 500 Internal Server Error
UNKNOWN = 2;
// The client specified an invalid argument. Note that this differs
// from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
// that are problematic regardless of the state of the system
// (e.g., a malformed file name).
//
// HTTP Mapping: 400 Bad Request
INVALID_ARGUMENT = 3;
// The deadline expired before the operation could complete. For operations
// that change the state of the system, this error may be returned
// even if the operation has completed successfully. For example, a
// successful response from a server could have been delayed long
// enough for the deadline to expire.
//
// HTTP Mapping: 504 Gateway Timeout
DEADLINE_EXCEEDED = 4;
// Some requested entity (e.g., file or directory) was not found.
//
// Note to server developers: if a request is denied for an entire class
// of users, such as gradual feature rollout or undocumented whitelist,
// `NOT_FOUND` may be used. If a request is denied for some users within
// a class of users, such as user-based access control, `PERMISSION_DENIED`
// must be used.
//
// HTTP Mapping: 404 Not Found
NOT_FOUND = 5;
// The entity that a client attempted to create (e.g., file or directory)
// already exists.
//
// HTTP Mapping: 409 Conflict
ALREADY_EXISTS = 6;
// The caller does not have permission to execute the specified
// operation. `PERMISSION_DENIED` must not be used for rejections
// caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
// instead for those errors). `PERMISSION_DENIED` must not be
// used if the caller can not be identified (use `UNAUTHENTICATED`
// instead for those errors). This error code does not imply the
// request is valid or the requested entity exists or satisfies
// other pre-conditions.
//
// HTTP Mapping: 403 Forbidden
PERMISSION_DENIED = 7;
// The request does not have valid authentication credentials for the
// operation.
//
// HTTP Mapping: 401 Unauthorized
UNAUTHENTICATED = 16;
// Some resource has been exhausted, perhaps a per-user quota, or
// perhaps the entire file system is out of space.
//
// HTTP Mapping: 429 Too Many Requests
RESOURCE_EXHAUSTED = 8;
// The operation was rejected because the system is not in a state
// required for the operation's execution. For example, the directory
// to be deleted is non-empty, an rmdir operation is applied to
// a non-directory, etc.
//
// Service implementors can use the following guidelines to decide
// between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`:
// (a) Use `UNAVAILABLE` if the client can retry just the failing call.
// (b) Use `ABORTED` if the client should retry at a higher level
// (e.g., when a client-specified test-and-set fails, indicating the
// client should restart a read-modify-write sequence).
// (c) Use `FAILED_PRECONDITION` if the client should not retry until
// the system state has been explicitly fixed. E.g., if an "rmdir"
// fails because the directory is non-empty, `FAILED_PRECONDITION`
// should be returned since the client should not retry unless
// the files are deleted from the directory.
//
// HTTP Mapping: 400 Bad Request
FAILED_PRECONDITION = 9;
// The operation was aborted, typically due to a concurrency issue such as
// a sequencer check failure or transaction abort.
//
// See the guidelines above for deciding between `FAILED_PRECONDITION`,
// `ABORTED`, and `UNAVAILABLE`.
//
// HTTP Mapping: 409 Conflict
ABORTED = 10;
// The operation was attempted past the valid range. E.g., seeking or
// reading past end-of-file.
//
// Unlike `INVALID_ARGUMENT`, this error indicates a problem that may
// be fixed if the system state changes. For example, a 32-bit file
// system will generate `INVALID_ARGUMENT` if asked to read at an
// offset that is not in the range [0,2^32-1], but it will generate
// `OUT_OF_RANGE` if asked to read from an offset past the current
// file size.
//
// There is a fair bit of overlap between `FAILED_PRECONDITION` and
// `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific
// error) when it applies so that callers who are iterating through
// a space can easily look for an `OUT_OF_RANGE` error to detect when
// they are done.
//
// HTTP Mapping: 400 Bad Request
OUT_OF_RANGE = 11;
// The operation is not implemented or is not supported/enabled in this
// service.
//
// HTTP Mapping: 501 Not Implemented
UNIMPLEMENTED = 12;
// Internal errors. This means that some invariants expected by the
// underlying system have been broken. This error code is reserved
// for serious errors.
//
// HTTP Mapping: 500 Internal Server Error
INTERNAL = 13;
// The service is currently unavailable. This is most likely a
// transient condition, which can be corrected by retrying with
// a backoff. Note that it is not always safe to retry
// non-idempotent operations.
//
// See the guidelines above for deciding between `FAILED_PRECONDITION`,
// `ABORTED`, and `UNAVAILABLE`.
//
// HTTP Mapping: 503 Service Unavailable
UNAVAILABLE = 14;
// Unrecoverable data loss or corruption.
//
// HTTP Mapping: 500 Internal Server Error
DATA_LOSS = 15;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,249 +0,0 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package google.rpc;
import "google/protobuf/duration.proto";
option go_package = "rpc";
option java_multiple_files = true;
option java_outer_classname = "ErrorDetailsProto";
option java_package = "com.google.rpc";
option objc_class_prefix = "RPC";
// Describes when the clients can retry a failed request. Clients could ignore
// the recommendation here or retry when this information is missing from error
// responses.
//
// It's always recommended that clients should use exponential backoff when
// retrying.
//
// Clients should wait until `retry_delay` amount of time has passed since
// receiving the error response before retrying. If retrying requests also
// fail, clients should use an exponential backoff scheme to gradually increase
// the delay between retries based on `retry_delay`, until either a maximum
// number of retries have been reached or a maximum retry delay cap has been
// reached.
message RetryInfo {
// Clients should wait at least this long between retrying the same request.
google.protobuf.Duration retry_delay = 1;
}
// Describes additional debugging info.
message DebugInfo {
// The stack trace entries indicating where the error occurred.
repeated string stack_entries = 1;
// Additional debugging information provided by the server.
string detail = 2;
}
// Describes how a quota check failed.
//
// For example if a daily limit was exceeded for the calling project,
// a service could respond with a QuotaFailure detail containing the project
// id and the description of the quota limit that was exceeded. If the
// calling project hasn't enabled the service in the developer console, then
// a service could respond with the project id and set `service_disabled`
// to true.
//
// Also see RetryInfo and Help types for other details about handling a
// quota failure.
message QuotaFailure {
// A message type used to describe a single quota violation. For example, a
// daily quota or a custom quota that was exceeded.
message Violation {
// The subject on which the quota check failed.
// For example, "clientip:<ip address of client>" or "project:<Google
// developer project id>".
string subject = 1;
// A description of how the quota check failed. Clients can use this
// description to find more about the quota configuration in the service's
// public documentation, or find the relevant quota limit to adjust through
// developer console.
//
// For example: "Service disabled" or "Daily Limit for read operations
// exceeded".
string description = 2;
}
// Describes all quota violations.
repeated Violation violations = 1;
}
// Describes the cause of the error with structured details.
//
// Example of an error when contacting the "pubsub.googleapis.com" API when it
// is not enabled:
//
// { "reason": "API_DISABLED"
// "domain": "googleapis.com"
// "metadata": {
// "resource": "projects/123",
// "service": "pubsub.googleapis.com"
// }
// }
//
// This response indicates that the pubsub.googleapis.com API is not enabled.
//
// Example of an error that is returned when attempting to create a Spanner
// instance in a region that is out of stock:
//
// { "reason": "STOCKOUT"
// "domain": "spanner.googleapis.com",
// "metadata": {
// "availableRegions": "us-central1,us-east2"
// }
// }
message ErrorInfo {
// The reason of the error. This is a constant value that identifies the
// proximate cause of the error. Error reasons are unique within a particular
// domain of errors. This should be at most 63 characters and match
// /[A-Z0-9_]+/.
string reason = 1;
// The logical grouping to which the "reason" belongs. The error domain
// is typically the registered service name of the tool or product that
// generates the error. Example: "pubsub.googleapis.com". If the error is
// generated by some common infrastructure, the error domain must be a
// globally unique value that identifies the infrastructure. For Google API
// infrastructure, the error domain is "googleapis.com".
string domain = 2;
// Additional structured details about this error.
//
// Keys should match /[a-zA-Z0-9-_]/ and be limited to 64 characters in
// length. When identifying the current value of an exceeded limit, the units
// should be contained in the key, not the value. For example, rather than
// {"instanceLimit": "100/request"}, should be returned as,
// {"instanceLimitPerRequest": "100"}, if the client exceeds the number of
// instances that can be created in a single (batch) request.
map<string, string> metadata = 3;
}
// Describes what preconditions have failed.
//
// For example, if an RPC failed because it required the Terms of Service to be
// acknowledged, it could list the terms of service violation in the
// PreconditionFailure message.
message PreconditionFailure {
// A message type used to describe a single precondition failure.
message Violation {
// The type of PreconditionFailure. We recommend using a service-specific
// enum type to define the supported precondition violation subjects. For
// example, "TOS" for "Terms of Service violation".
string type = 1;
// The subject, relative to the type, that failed.
// For example, "google.com/cloud" relative to the "TOS" type would indicate
// which terms of service is being referenced.
string subject = 2;
// A description of how the precondition failed. Developers can use this
// description to understand how to fix the failure.
//
// For example: "Terms of service not accepted".
string description = 3;
}
// Describes all precondition violations.
repeated Violation violations = 1;
}
// Describes violations in a client request. This error type focuses on the
// syntactic aspects of the request.
message BadRequest {
// A message type used to describe a single bad request field.
message FieldViolation {
// A path leading to a field in the request body. The value will be a
// sequence of dot-separated identifiers that identify a protocol buffer
// field. E.g., "field_violations.field" would identify this field.
string field = 1;
// A description of why the request element is bad.
string description = 2;
}
// Describes all violations in a client request.
repeated FieldViolation field_violations = 1;
}
// Contains metadata about the request that clients can attach when filing a bug
// or providing other forms of feedback.
message RequestInfo {
// An opaque string that should only be interpreted by the service generating
// it. For example, it can be used to identify requests in the service's logs.
string request_id = 1;
// Any data that was used to serve this request. For example, an encrypted
// stack trace that can be sent back to the service provider for debugging.
string serving_data = 2;
}
// Describes the resource that is being accessed.
message ResourceInfo {
// A name for the type of resource being accessed, e.g. "sql table",
// "cloud storage bucket", "file", "Google calendar"; or the type URL
// of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic".
string resource_type = 1;
// The name of the resource being accessed. For example, a shared calendar
// name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
// error is [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
string resource_name = 2;
// The owner of the resource (optional).
// For example, "user:<owner email>" or "project:<Google developer project
// id>".
string owner = 3;
// Describes what error is encountered when accessing this resource.
// For example, updating a cloud project may require the `writer` permission
// on the developer console project.
string description = 4;
}
// Provides links to documentation or for performing an out of band action.
//
// For example, if a quota check failed with an error indicating the calling
// project hasn't enabled the accessed service, this can contain a URL pointing
// directly to the right place in the developer console to flip the bit.
message Help {
// Describes a URL link.
message Link {
// Describes what the link offers.
string description = 1;
// The URL of the link.
string url = 2;
}
// URL(s) pointing to additional information on handling the current error.
repeated Link links = 1;
}
// Provides a localized error message that is safe to return to the user
// which can be attached to an RPC error.
message LocalizedMessage {
// The locale used following the specification defined at
// http://www.rfc-editor.org/rfc/bcp/bcp47.txt.
// Examples are: "en-US", "fr-CH", "es-MX"
string locale = 1;
// The localized error message in the above locale.
string message = 2;
}

View File

@ -1,680 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: google/rpc/status.proto
package rpc
import (
bytes "bytes"
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
types "github.com/gogo/protobuf/types"
io "io"
math "math"
math_bits "math/bits"
reflect "reflect"
strings "strings"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs. It is
// used by [gRPC](https://github.com/grpc). Each `Status` message contains
// three pieces of data: error code, error message, and error details.
//
// You can find out more about this error model and how to work with it in the
// [API Design Guide](https://cloud.google.com/apis/design/errors).
type Status struct {
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
Code int32 `protobuf:"varint,1,opt,name=code,proto3" json:"code,omitempty"`
// A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
Message string `protobuf:"bytes,2,opt,name=message,proto3" json:"message,omitempty"`
// A list of messages that carry the error details. There is a common set of
// message types for APIs to use.
Details []*types.Any `protobuf:"bytes,3,rep,name=details,proto3" json:"details,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Status) Reset() { *m = Status{} }
func (*Status) ProtoMessage() {}
func (*Status) Descriptor() ([]byte, []int) {
return fileDescriptor_24d244abaf643bfe, []int{0}
}
func (m *Status) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
}
func (m *Status) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
if deterministic {
return xxx_messageInfo_Status.Marshal(b, m, deterministic)
} else {
b = b[:cap(b)]
n, err := m.MarshalToSizedBuffer(b)
if err != nil {
return nil, err
}
return b[:n], nil
}
}
func (m *Status) XXX_Merge(src proto.Message) {
xxx_messageInfo_Status.Merge(m, src)
}
func (m *Status) XXX_Size() int {
return m.Size()
}
func (m *Status) XXX_DiscardUnknown() {
xxx_messageInfo_Status.DiscardUnknown(m)
}
var xxx_messageInfo_Status proto.InternalMessageInfo
func (m *Status) GetCode() int32 {
if m != nil {
return m.Code
}
return 0
}
func (m *Status) GetMessage() string {
if m != nil {
return m.Message
}
return ""
}
func (m *Status) GetDetails() []*types.Any {
if m != nil {
return m.Details
}
return nil
}
func (*Status) XXX_MessageName() string {
return "google.rpc.Status"
}
func init() {
proto.RegisterType((*Status)(nil), "google.rpc.Status")
}
func init() { proto.RegisterFile("google/rpc/status.proto", fileDescriptor_24d244abaf643bfe) }
var fileDescriptor_24d244abaf643bfe = []byte{
// 238 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4f, 0xcf, 0xcf, 0x4f,
0xcf, 0x49, 0xd5, 0x2f, 0x2a, 0x48, 0xd6, 0x2f, 0x2e, 0x49, 0x2c, 0x29, 0x2d, 0xd6, 0x2b, 0x28,
0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x82, 0x48, 0xe8, 0x15, 0x15, 0x24, 0x4b, 0x49, 0x42, 0x15, 0x81,
0x65, 0x92, 0x4a, 0xd3, 0xf4, 0x13, 0xf3, 0x2a, 0x21, 0xca, 0x94, 0xd2, 0xb8, 0xd8, 0x82, 0xc1,
0xda, 0x84, 0x84, 0xb8, 0x58, 0x92, 0xf3, 0x53, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83,
0xc0, 0x6c, 0x21, 0x09, 0x2e, 0xf6, 0xdc, 0xd4, 0xe2, 0xe2, 0xc4, 0xf4, 0x54, 0x09, 0x26, 0x05,
0x46, 0x0d, 0xce, 0x20, 0x18, 0x57, 0x48, 0x8f, 0x8b, 0x3d, 0x25, 0xb5, 0x24, 0x31, 0x33, 0xa7,
0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x44, 0x0f, 0x6a, 0x21, 0xcc, 0x12, 0x3d, 0xc7,
0xbc, 0xca, 0x20, 0x98, 0x22, 0xa7, 0xc4, 0x0b, 0x0f, 0xe5, 0x18, 0x6e, 0x3c, 0x94, 0x63, 0xf8,
0xf0, 0x50, 0x8e, 0xf1, 0xc7, 0x43, 0x39, 0xc6, 0x86, 0x47, 0x72, 0x8c, 0x2b, 0x1e, 0xc9, 0x31,
0x9e, 0x78, 0x24, 0xc7, 0x78, 0xe1, 0x91, 0x1c, 0xe3, 0x83, 0x47, 0x72, 0x8c, 0x2f, 0x1e, 0xc9,
0x31, 0x7c, 0x00, 0x89, 0x3f, 0x96, 0x63, 0x3c, 0xf1, 0x58, 0x8e, 0x91, 0x8b, 0x2f, 0x39, 0x3f,
0x57, 0x0f, 0xe1, 0x11, 0x27, 0x6e, 0x88, 0x5b, 0x03, 0x40, 0x56, 0x04, 0x30, 0x46, 0x31, 0x17,
0x15, 0x24, 0xff, 0x60, 0x64, 0x5c, 0xc4, 0xc4, 0x1c, 0x14, 0xe0, 0x9c, 0xc4, 0x06, 0xb6, 0xd9,
0x18, 0x10, 0x00, 0x00, 0xff, 0xff, 0x16, 0xcd, 0x7b, 0x60, 0x13, 0x01, 0x00, 0x00,
}
func (this *Status) Compare(that interface{}) int {
if that == nil {
if this == nil {
return 0
}
return 1
}
that1, ok := that.(*Status)
if !ok {
that2, ok := that.(Status)
if ok {
that1 = &that2
} else {
return 1
}
}
if that1 == nil {
if this == nil {
return 0
}
return 1
} else if this == nil {
return -1
}
if this.Code != that1.Code {
if this.Code < that1.Code {
return -1
}
return 1
}
if this.Message != that1.Message {
if this.Message < that1.Message {
return -1
}
return 1
}
if len(this.Details) != len(that1.Details) {
if len(this.Details) < len(that1.Details) {
return -1
}
return 1
}
for i := range this.Details {
if c := this.Details[i].Compare(that1.Details[i]); c != 0 {
return c
}
}
if c := bytes.Compare(this.XXX_unrecognized, that1.XXX_unrecognized); c != 0 {
return c
}
return 0
}
func (this *Status) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*Status)
if !ok {
that2, ok := that.(Status)
if ok {
that1 = &that2
} else {
return false
}
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if this.Code != that1.Code {
return false
}
if this.Message != that1.Message {
return false
}
if len(this.Details) != len(that1.Details) {
return false
}
for i := range this.Details {
if !this.Details[i].Equal(that1.Details[i]) {
return false
}
}
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
return true
}
func (this *Status) GoString() string {
if this == nil {
return "nil"
}
s := make([]string, 0, 7)
s = append(s, "&rpc.Status{")
s = append(s, "Code: "+fmt.Sprintf("%#v", this.Code)+",\n")
s = append(s, "Message: "+fmt.Sprintf("%#v", this.Message)+",\n")
if this.Details != nil {
s = append(s, "Details: "+fmt.Sprintf("%#v", this.Details)+",\n")
}
if this.XXX_unrecognized != nil {
s = append(s, "XXX_unrecognized:"+fmt.Sprintf("%#v", this.XXX_unrecognized)+",\n")
}
s = append(s, "}")
return strings.Join(s, "")
}
func valueToGoStringStatus(v interface{}, typ string) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)
}
func (m *Status) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalToSizedBuffer(dAtA[:size])
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *Status) MarshalTo(dAtA []byte) (int, error) {
size := m.Size()
return m.MarshalToSizedBuffer(dAtA[:size])
}
func (m *Status) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i := len(dAtA)
_ = i
var l int
_ = l
if m.XXX_unrecognized != nil {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Details) > 0 {
for iNdEx := len(m.Details) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Details[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintStatus(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x1a
}
}
if len(m.Message) > 0 {
i -= len(m.Message)
copy(dAtA[i:], m.Message)
i = encodeVarintStatus(dAtA, i, uint64(len(m.Message)))
i--
dAtA[i] = 0x12
}
if m.Code != 0 {
i = encodeVarintStatus(dAtA, i, uint64(m.Code))
i--
dAtA[i] = 0x8
}
return len(dAtA) - i, nil
}
func encodeVarintStatus(dAtA []byte, offset int, v uint64) int {
offset -= sovStatus(v)
base := offset
for v >= 1<<7 {
dAtA[offset] = uint8(v&0x7f | 0x80)
v >>= 7
offset++
}
dAtA[offset] = uint8(v)
return base
}
func NewPopulatedStatus(r randyStatus, easy bool) *Status {
this := &Status{}
this.Code = int32(r.Int31())
if r.Intn(2) == 0 {
this.Code *= -1
}
this.Message = string(randStringStatus(r))
if r.Intn(5) != 0 {
v1 := r.Intn(5)
this.Details = make([]*types.Any, v1)
for i := 0; i < v1; i++ {
this.Details[i] = types.NewPopulatedAny(r, easy)
}
}
if !easy && r.Intn(10) != 0 {
this.XXX_unrecognized = randUnrecognizedStatus(r, 4)
}
return this
}
type randyStatus interface {
Float32() float32
Float64() float64
Int63() int64
Int31() int32
Uint32() uint32
Intn(n int) int
}
func randUTF8RuneStatus(r randyStatus) rune {
ru := r.Intn(62)
if ru < 10 {
return rune(ru + 48)
} else if ru < 36 {
return rune(ru + 55)
}
return rune(ru + 61)
}
func randStringStatus(r randyStatus) string {
v2 := r.Intn(100)
tmps := make([]rune, v2)
for i := 0; i < v2; i++ {
tmps[i] = randUTF8RuneStatus(r)
}
return string(tmps)
}
func randUnrecognizedStatus(r randyStatus, maxFieldNumber int) (dAtA []byte) {
l := r.Intn(5)
for i := 0; i < l; i++ {
wire := r.Intn(4)
if wire == 3 {
wire = 5
}
fieldNumber := maxFieldNumber + r.Intn(100)
dAtA = randFieldStatus(dAtA, r, fieldNumber, wire)
}
return dAtA
}
func randFieldStatus(dAtA []byte, r randyStatus, fieldNumber int, wire int) []byte {
key := uint32(fieldNumber)<<3 | uint32(wire)
switch wire {
case 0:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
v3 := r.Int63()
if r.Intn(2) == 0 {
v3 *= -1
}
dAtA = encodeVarintPopulateStatus(dAtA, uint64(v3))
case 1:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
case 2:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
ll := r.Intn(100)
dAtA = encodeVarintPopulateStatus(dAtA, uint64(ll))
for j := 0; j < ll; j++ {
dAtA = append(dAtA, byte(r.Intn(256)))
}
default:
dAtA = encodeVarintPopulateStatus(dAtA, uint64(key))
dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))
}
return dAtA
}
func encodeVarintPopulateStatus(dAtA []byte, v uint64) []byte {
for v >= 1<<7 {
dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))
v >>= 7
}
dAtA = append(dAtA, uint8(v))
return dAtA
}
func (m *Status) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
if m.Code != 0 {
n += 1 + sovStatus(uint64(m.Code))
}
l = len(m.Message)
if l > 0 {
n += 1 + l + sovStatus(uint64(l))
}
if len(m.Details) > 0 {
for _, e := range m.Details {
l = e.Size()
n += 1 + l + sovStatus(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
func sovStatus(x uint64) (n int) {
return (math_bits.Len64(x|1) + 6) / 7
}
func sozStatus(x uint64) (n int) {
return sovStatus(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}
func (this *Status) String() string {
if this == nil {
return "nil"
}
repeatedStringForDetails := "[]*Any{"
for _, f := range this.Details {
repeatedStringForDetails += strings.Replace(fmt.Sprintf("%v", f), "Any", "types.Any", 1) + ","
}
repeatedStringForDetails += "}"
s := strings.Join([]string{`&Status{`,
`Code:` + fmt.Sprintf("%v", this.Code) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`Details:` + repeatedStringForDetails + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`,
}, "")
return s
}
func valueToStringStatus(v interface{}) string {
rv := reflect.ValueOf(v)
if rv.IsNil() {
return "nil"
}
pv := reflect.Indirect(rv).Interface()
return fmt.Sprintf("*%v", pv)
}
func (m *Status) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStatus
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: Status: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: Status: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Code", wireType)
}
m.Code = 0
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStatus
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
m.Code |= int32(b&0x7F) << shift
if b < 0x80 {
break
}
}
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStatus
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthStatus
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Message = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Details", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowStatus
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthStatus
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthStatus
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Details = append(m.Details, &types.Any{})
if err := m.Details[len(m.Details)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipStatus(dAtA[iNdEx:])
if err != nil {
return err
}
if (skippy < 0) || (iNdEx+skippy) < 0 {
return ErrInvalidLengthStatus
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func skipStatus(dAtA []byte) (n int, err error) {
l := len(dAtA)
iNdEx := 0
depth := 0
for iNdEx < l {
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStatus
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
wireType := int(wire & 0x7)
switch wireType {
case 0:
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStatus
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
iNdEx++
if dAtA[iNdEx-1] < 0x80 {
break
}
}
case 1:
iNdEx += 8
case 2:
var length int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return 0, ErrIntOverflowStatus
}
if iNdEx >= l {
return 0, io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
length |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if length < 0 {
return 0, ErrInvalidLengthStatus
}
iNdEx += length
case 3:
depth++
case 4:
if depth == 0 {
return 0, ErrUnexpectedEndOfGroupStatus
}
depth--
case 5:
iNdEx += 4
default:
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
}
if iNdEx < 0 {
return 0, ErrInvalidLengthStatus
}
if depth == 0 {
return iNdEx, nil
}
}
return 0, io.ErrUnexpectedEOF
}
var (
ErrInvalidLengthStatus = fmt.Errorf("proto: negative length found during unmarshaling")
ErrIntOverflowStatus = fmt.Errorf("proto: integer overflow")
ErrUnexpectedEndOfGroupStatus = fmt.Errorf("proto: unexpected end of group")
)

View File

@ -1,47 +0,0 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package google.rpc;
import "google/protobuf/any.proto";
option cc_enable_arenas = true;
option go_package = "rpc";
option java_multiple_files = true;
option java_outer_classname = "StatusProto";
option java_package = "com.google.rpc";
option objc_class_prefix = "RPC";
// The `Status` type defines a logical error model that is suitable for
// different programming environments, including REST APIs and RPC APIs. It is
// used by [gRPC](https://github.com/grpc). Each `Status` message contains
// three pieces of data: error code, error message, and error details.
//
// You can find out more about this error model and how to work with it in the
// [API Design Guide](https://cloud.google.com/apis/design/errors).
message Status {
// The status code, which should be an enum value of [google.rpc.Code][google.rpc.Code].
int32 code = 1;
// A developer-facing error message, which should be in English. Any
// user-facing error message should be localized and sent in the
// [google.rpc.Status.details][google.rpc.Status.details] field, or localized by the client.
string message = 2;
// A list of messages that carry the error details. There is a common set of
// message types for APIs to use.
repeated google.protobuf.Any details = 3;
}

View File

@ -1,580 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package compare
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type plugin struct {
*generator.Generator
generator.PluginImports
fmtPkg generator.Single
bytesPkg generator.Single
sortkeysPkg generator.Single
protoPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "compare"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.fmtPkg = p.NewImport("fmt")
p.bytesPkg = p.NewImport("bytes")
p.sortkeysPkg = p.NewImport("github.com/gogo/protobuf/sortkeys")
p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
for _, msg := range file.Messages() {
if msg.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasCompare(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg)
}
}
}
func (p *plugin) generateNullableField(fieldname string) {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
p.P(`if *this.`, fieldname, ` < *that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
}
func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string) {
p.P(`if that == nil {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`that1, ok := that.(*`, ccTypeName, `)`)
p.P(`if !ok {`)
p.In()
p.P(`that2, ok := that.(`, ccTypeName, `)`)
p.P(`if ok {`)
p.In()
p.P(`that1 = &that2`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`if that1 == nil {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`} else if this == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
}
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
fieldname := p.GetOneOfFieldName(message, field)
repeated := field.IsRepeated()
ctype := gogoproto.IsCustomType(field)
nullable := gogoproto.IsNullable(field)
// oneof := field.OneofIndex != nil
if !repeated {
if ctype {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else if c := this.`, fieldname, `.Compare(*that1.`, fieldname, `); c != 0 {`)
} else {
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
} else {
p.P(`if c := this.`, fieldname, `.Compare(&that1.`, fieldname, `); c != 0 {`)
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsString() {
if nullable && !proto3 {
p.generateNullableField(fieldname)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else if field.IsBool() {
if nullable && !proto3 {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
p.P(`if !*this.`, fieldname, ` {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if !this.`, fieldname, ` {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else {
if nullable && !proto3 {
p.generateNullableField(fieldname)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
p.In()
p.P(`if this.`, fieldname, ` < that1.`, fieldname, `{`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
}
}
} else {
p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
p.In()
p.P(`if len(this.`, fieldname, `) < len(that1.`, fieldname, `) {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
p.P(`for i := range this.`, fieldname, ` {`)
p.In()
if ctype {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
if p.IsMap(field) {
m := p.GoMapType(nil, field)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
mapValue := m.ValueAliasField
if mapValue.IsMessage() || p.IsGroup(mapValue) {
if nullable && valuegoTyp == valuegoAliasTyp {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
} else {
// Compare() has a pointer receiver, but map value is a value type
a := `this.` + fieldname + `[i]`
b := `that1.` + fieldname + `[i]`
if valuegoTyp != valuegoAliasTyp {
// cast back to the type that has the generated methods on it
a = `(` + valuegoTyp + `)(` + a + `)`
b = `(` + valuegoTyp + `)(` + b + `)`
}
p.P(`a := `, a)
p.P(`b := `, b)
if nullable {
p.P(`if c := a.Compare(b); c != 0 {`)
} else {
p.P(`if c := (&a).Compare(&b); c != 0 {`)
}
}
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if mapValue.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if mapValue.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
} else if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if c := this.`, fieldname, `[i].Compare(that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else {
p.P(`if c := this.`, fieldname, `[i].Compare(&that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
} else if field.IsBytes() {
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `[i], that1.`, fieldname, `[i]); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
} else if field.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else if field.IsBool() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if !this.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
p.In()
p.P(`if this.`, fieldname, `[i] < that1.`, fieldname, `[i] {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.P(`return 1`)
p.Out()
p.P(`}`)
}
}
p.Out()
p.P(`}`)
}
}
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if oneof {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else {`)
p.In()
// Generate two type switches in order to compare the
// types of the oneofs. If they are of the same type
// call Compare, otherwise return 1 or -1.
p.P(`thisType := -1`)
p.P(`switch this.`, fieldname, `.(type) {`)
for i, subfield := range message.Field {
if *subfield.OneofIndex == *field.OneofIndex {
ccTypeName := p.OneOfTypeName(message, subfield)
p.P(`case *`, ccTypeName, `:`)
p.In()
p.P(`thisType = `, i)
p.Out()
}
}
p.P(`default:`)
p.In()
p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", this.`, fieldname, `))`)
p.Out()
p.P(`}`)
p.P(`that1Type := -1`)
p.P(`switch that1.`, fieldname, `.(type) {`)
for i, subfield := range message.Field {
if *subfield.OneofIndex == *field.OneofIndex {
ccTypeName := p.OneOfTypeName(message, subfield)
p.P(`case *`, ccTypeName, `:`)
p.In()
p.P(`that1Type = `, i)
p.Out()
}
}
p.P(`default:`)
p.In()
p.P(`panic(fmt.Sprintf("compare: unexpected type %T in oneof", that1.`, fieldname, `))`)
p.Out()
p.P(`}`)
p.P(`if thisType == that1Type {`)
p.In()
p.P(`if c := this.`, fieldname, `.Compare(that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if thisType < that1Type {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`} else if thisType > that1Type {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
p.generateField(file, message, field)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
p.P(`extkeys := make([]int32, 0, len(thismap)+len(thatmap))`)
p.P(`for k, _ := range thismap {`)
p.In()
p.P(`extkeys = append(extkeys, k)`)
p.Out()
p.P(`}`)
p.P(`for k, _ := range thatmap {`)
p.In()
p.P(`if _, ok := thismap[k]; !ok {`)
p.In()
p.P(`extkeys = append(extkeys, k)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(p.sortkeysPkg.Use(), `.Int32s(extkeys)`)
p.P(`for _, k := range extkeys {`)
p.In()
p.P(`if v, ok := thismap[k]; ok {`)
p.In()
p.P(`if v2, ok := thatmap[k]; ok {`)
p.In()
p.P(`if c := v.Compare(&v2); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return 1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
p.P(`return -1`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
fieldname := "XXX_extensions"
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_unrecognized"
p.P(`if c := `, p.bytesPkg.Use(), `.Compare(this.`, fieldname, `, that1.`, fieldname, `); c != 0 {`)
p.In()
p.P(`return c`)
p.Out()
p.P(`}`)
}
p.P(`return 0`)
p.Out()
p.P(`}`)
//Generate Compare methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, field := range m.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) Compare(that interface{}) int {`)
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName)
vanity.TurnOffNullableForNativeTypes(field)
p.generateField(file, message, field)
p.P(`return 0`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,118 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package compare
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
unsafePkg := imports.NewImport("unsafe")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasCompare(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
p.P(`func Test`, ccTypeName, `Compare(t *`, testingPkg.Use(), `.T) {`)
p.In()
if hasUnsafe {
p.P(`var bigendian uint32 = 0x01020304`)
p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
p.In()
p.P(`t.Skip("unsafe does not work on big endian architectures")`)
p.Out()
p.P(`}`)
}
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if c := p.Compare(msg); c != 0 {`)
p.In()
p.P(`t.Fatalf("%#v !Compare %#v, since %d", msg, p, c)`)
p.Out()
p.P(`}`)
p.P(`p2 := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`c := p.Compare(p2)`)
p.P(`c2 := p2.Compare(p)`)
p.P(`if c != (-1 * c2) {`)
p.In()
p.P(`t.Errorf("p.Compare(p2) = %d", c)`)
p.P(`t.Errorf("p2.Compare(p) = %d", c2)`)
p.P(`t.Errorf("p = %#v", p)`)
p.P(`t.Errorf("p2 = %#v", p2)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,133 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The defaultcheck plugin is used to check whether nullable is not used incorrectly.
For instance:
An error is caused if a nullable field:
- has a default value,
- is an enum which does not start at zero,
- is used for an extension,
- is used for a native proto3 type,
- is used for a repeated native type.
An error is also caused if a field with a default value is used in a message:
- which is a face.
- without getters.
It is enabled by the following extensions:
- nullable
For incorrect usage of nullable with tests see:
github.com/gogo/protobuf/test/nullableconflict
*/
package defaultcheck
import (
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"os"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "defaultcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
for _, msg := range file.Messages() {
getters := gogoproto.HasGoGetters(file.FileDescriptorProto, msg.DescriptorProto)
face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
for _, field := range msg.GetField() {
if len(field.GetDefaultValue()) > 0 {
if !getters {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value and not have a getter method", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if face {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot have a default value be in a face", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
}
if gogoproto.IsNullable(field) {
continue
}
if len(field.GetDefaultValue()) > 0 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and have a default value", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if !field.IsMessage() && !gogoproto.IsCustomType(field) {
if field.IsRepeated() {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a repeated non-nullable native type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
} else if proto3 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v is a native type and in proto3 syntax with nullable=false there exists conflicting implementations when encoding zero values", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if field.IsBytes() {
fmt.Fprintf(os.Stderr, "WARNING: field %v.%v is a non-nullable bytes type, nullable=false has no effect\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
}
}
if !field.IsEnum() {
continue
}
enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
if len(enum.Value) == 0 || enum.Value[0].GetNumber() != 0 {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be non-nullable and be an enum type %v which does not start with zero", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name), enum.GetName())
os.Exit(1)
}
}
}
for _, e := range file.GetExtension() {
if !gogoproto.IsNullable(e) {
fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be nullable %v", generator.CamelCase(e.GetName()), generator.CamelCase(*e.Name))
os.Exit(1)
}
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,201 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The description (experimental) plugin generates a Description method for each message.
The Description method returns a populated google_protobuf.FileDescriptorSet struct.
This contains the description of the files used to generate this message.
It is enabled by the following extensions:
- description
- description_all
The description plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message B {
option (gogoproto.description) = true;
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the description plugin, will generate the following code:
func (this *B) Description() (desc *google_protobuf.FileDescriptorSet) {
return ExampleDescription()
}
and the following test code:
func TestDescription(t *testing9.T) {
ExampleDescription()
}
The hope is to use this struct in some way instead of reflect.
This package is subject to change, since a use has not been figured out yet.
*/
package description
import (
"bytes"
"compress/gzip"
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
generator.PluginImports
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "description"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
used := false
localName := generator.FileName(file)
p.PluginImports = generator.NewPluginImports(p.Generator)
descriptorPkg := p.NewImport("github.com/gogo/protobuf/protoc-gen-gogo/descriptor")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
gzipPkg := p.NewImport("compress/gzip")
bytesPkg := p.NewImport("bytes")
ioutilPkg := p.NewImport("io/ioutil")
for _, message := range file.Messages() {
if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
p.In()
p.P(`return `, localName, `Description()`)
p.Out()
p.P(`}`)
}
if used {
p.P(`func `, localName, `Description() (desc *`, descriptorPkg.Use(), `.FileDescriptorSet) {`)
p.In()
//Don't generate SourceCodeInfo, since it will create too much code.
ss := make([]*descriptor.SourceCodeInfo, 0)
for _, f := range p.Generator.AllFiles().GetFile() {
ss = append(ss, f.SourceCodeInfo)
f.SourceCodeInfo = nil
}
b, err := proto.Marshal(p.Generator.AllFiles())
if err != nil {
panic(err)
}
for i, f := range p.Generator.AllFiles().GetFile() {
f.SourceCodeInfo = ss[i]
}
p.P(`d := &`, descriptorPkg.Use(), `.FileDescriptorSet{}`)
var buf bytes.Buffer
w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression)
w.Write(b)
w.Close()
b = buf.Bytes()
p.P("var gzipped = []byte{")
p.In()
p.P("// ", len(b), " bytes of a gzipped FileDescriptorSet")
for len(b) > 0 {
n := 16
if n > len(b) {
n = len(b)
}
s := ""
for _, c := range b[:n] {
s += fmt.Sprintf("0x%02x,", c)
}
p.P(s)
b = b[n:]
}
p.Out()
p.P("}")
p.P(`r := `, bytesPkg.Use(), `.NewReader(gzipped)`)
p.P(`gzipr, err := `, gzipPkg.Use(), `.NewReader(r)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`ungzipped, err := `, ioutilPkg.Use(), `.ReadAll(gzipr)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(ungzipped, d); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`return d`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,73 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package description
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
if !gogoproto.HasDescription(file.FileDescriptorProto, message.DescriptorProto) ||
!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
}
if used {
localName := generator.FileName(file)
p.P(`func Test`, localName, `Description(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(localName, `Description()`)
p.Out()
p.P(`}`)
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,200 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The embedcheck plugin is used to check whether embed is not used incorrectly.
For instance:
An embedded message has a generated string method, but the is a member of a message which does not.
This causes a warning.
An error is caused by a namespace conflict.
It is enabled by the following extensions:
- embed
- embed_all
For incorrect usage of embed with tests see:
github.com/gogo/protobuf/test/embedconflict
*/
package embedcheck
import (
"fmt"
"os"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "embedcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
var overwriters []map[string]gogoproto.EnableFunc = []map[string]gogoproto.EnableFunc{
{
"stringer": gogoproto.IsStringer,
},
{
"gostring": gogoproto.HasGoString,
},
{
"equal": gogoproto.HasEqual,
},
{
"verboseequal": gogoproto.HasVerboseEqual,
},
{
"size": gogoproto.IsSizer,
"protosizer": gogoproto.IsProtoSizer,
},
{
"unmarshaler": gogoproto.IsUnmarshaler,
"unsafe_unmarshaler": gogoproto.IsUnsafeUnmarshaler,
},
{
"marshaler": gogoproto.IsMarshaler,
"unsafe_marshaler": gogoproto.IsUnsafeMarshaler,
},
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
for _, msg := range file.Messages() {
for _, os := range overwriters {
possible := true
for _, overwriter := range os {
if overwriter(file.FileDescriptorProto, msg.DescriptorProto) {
possible = false
}
}
if possible {
p.checkOverwrite(msg, os)
}
}
p.checkNameSpace(msg)
for _, field := range msg.GetField() {
if gogoproto.IsEmbed(field) && gogoproto.IsCustomName(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v with custom name %v cannot be embedded", *field.Name, gogoproto.GetCustomName(field))
os.Exit(1)
}
}
p.checkRepeated(msg)
}
for _, e := range file.GetExtension() {
if gogoproto.IsEmbed(e) {
fmt.Fprintf(os.Stderr, "ERROR: extended field %v cannot be embedded", generator.CamelCase(*e.Name))
os.Exit(1)
}
}
}
func (p *plugin) checkNameSpace(message *generator.Descriptor) map[string]bool {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
names := make(map[string]bool)
for _, field := range message.Field {
fieldname := generator.CamelCase(*field.Name)
if field.IsMessage() && gogoproto.IsEmbed(field) {
desc := p.ObjectNamed(field.GetTypeName())
moreNames := p.checkNameSpace(desc.(*generator.Descriptor))
for another := range moreNames {
if names[another] {
fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
os.Exit(1)
}
names[another] = true
}
} else {
if names[fieldname] {
fmt.Fprintf(os.Stderr, "ERROR: duplicate embedded fieldname %v in type %v\n", fieldname, ccTypeName)
os.Exit(1)
}
names[fieldname] = true
}
}
return names
}
func (p *plugin) checkOverwrite(message *generator.Descriptor, enablers map[string]gogoproto.EnableFunc) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
names := []string{}
for name := range enablers {
names = append(names, name)
}
for _, field := range message.Field {
if field.IsMessage() && gogoproto.IsEmbed(field) {
fieldname := generator.CamelCase(*field.Name)
desc := p.ObjectNamed(field.GetTypeName())
msg := desc.(*generator.Descriptor)
for errStr, enabled := range enablers {
if enabled(msg.File().FileDescriptorProto, msg.DescriptorProto) {
fmt.Fprintf(os.Stderr, "WARNING: found non-%v %v with embedded %v %v\n", names, ccTypeName, errStr, fieldname)
}
}
p.checkOverwrite(msg, enablers)
}
}
}
func (p *plugin) checkRepeated(message *generator.Descriptor) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
for _, field := range message.Field {
if !gogoproto.IsEmbed(field) {
continue
}
if field.IsBytes() {
fieldname := generator.CamelCase(*field.Name)
fmt.Fprintf(os.Stderr, "ERROR: found embedded bytes field %s in message %s\n", fieldname, ccTypeName)
os.Exit(1)
}
if !field.IsRepeated() {
continue
}
fieldname := generator.CamelCase(*field.Name)
fmt.Fprintf(os.Stderr, "ERROR: found repeated embedded field %s in message %s\n", fieldname, ccTypeName)
os.Exit(1)
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,104 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The enumstringer (experimental) plugin generates a String method for each enum.
It is enabled by the following extensions:
- enum_stringer
- enum_stringer_all
This package is subject to change.
*/
package enumstringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type enumstringer struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
}
func NewEnumStringer() *enumstringer {
return &enumstringer{}
}
func (p *enumstringer) Name() string {
return "enumstringer"
}
func (p *enumstringer) Init(g *generator.Generator) {
p.Generator = g
}
func (p *enumstringer) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
strconvPkg := p.NewImport("strconv")
for _, enum := range file.Enums() {
if !gogoproto.IsEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
continue
}
if gogoproto.IsGoEnumStringer(file.FileDescriptorProto, enum.EnumDescriptorProto) {
panic("Go enum stringer conflicts with new enumstringer plugin: please use gogoproto.goproto_enum_stringer or gogoproto.goproto_enum_string_all and set it to false")
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(enum.TypeName())
p.P("func (x ", ccTypeName, ") String() string {")
p.In()
p.P(`s, ok := `, ccTypeName, `_name[int32(x)]`)
p.P(`if ok {`)
p.In()
p.P(`return s`)
p.Out()
p.P(`}`)
p.P(`return `, strconvPkg.Use(), `.Itoa(int(x))`)
p.Out()
p.P(`}`)
}
if !p.atleastOne {
return
}
}
func init() {
generator.RegisterPlugin(NewEnumStringer())
}

View File

@ -1,694 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The equal plugin generates an Equal and a VerboseEqual method for each message.
These equal methods are quite obvious.
The only difference is that VerboseEqual returns a non nil error if it is not equal.
This error contains more detail on exactly which part of the message was not equal to the other message.
The idea is that this is useful for debugging.
Equal is enabled using the following extensions:
- equal
- equal_all
While VerboseEqual is enable dusing the following extensions:
- verbose_equal
- verbose_equal_all
The equal plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.equal_all) = true;
option (gogoproto.verbose_equal_all) = true;
message B {
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the equal plugin, will generate the following code:
func (this *B) VerboseEqual(that interface{}) error {
if that == nil {
if this == nil {
return nil
}
return fmt2.Errorf("that == nil && this != nil")
}
that1, ok := that.(*B)
if !ok {
return fmt2.Errorf("that is not of type *B")
}
if that1 == nil {
if this == nil {
return nil
}
return fmt2.Errorf("that is type *B but is nil && this != nil")
} else if this == nil {
return fmt2.Errorf("that is type *B but is not nil && this == nil")
}
if !this.A.Equal(&that1.A) {
return fmt2.Errorf("A this(%v) Not Equal that(%v)", this.A, that1.A)
}
if len(this.G) != len(that1.G) {
return fmt2.Errorf("G this(%v) Not Equal that(%v)", len(this.G), len(that1.G))
}
for i := range this.G {
if !this.G[i].Equal(that1.G[i]) {
return fmt2.Errorf("G this[%v](%v) Not Equal that[%v](%v)", i, this.G[i], i, that1.G[i])
}
}
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return fmt2.Errorf("XXX_unrecognized this(%v) Not Equal that(%v)", this.XXX_unrecognized, that1.XXX_unrecognized)
}
return nil
}
func (this *B) Equal(that interface{}) bool {
if that == nil {
return this == nil
}
that1, ok := that.(*B)
if !ok {
return false
}
if that1 == nil {
return this == nil
} else if this == nil {
return false
}
if !this.A.Equal(&that1.A) {
return false
}
if len(this.G) != len(that1.G) {
return false
}
for i := range this.G {
if !this.G[i].Equal(that1.G[i]) {
return false
}
}
if !bytes.Equal(this.XXX_unrecognized, that1.XXX_unrecognized) {
return false
}
return true
}
and the following test code:
func TestBVerboseEqual(t *testing8.T) {
popr := math_rand8.New(math_rand8.NewSource(time8.Now().UnixNano()))
p := NewPopulatedB(popr, false)
dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
if err != nil {
panic(err)
}
msg := &B{}
if err := github_com_gogo_protobuf_proto2.Unmarshal(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)
}
*/
package equal
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type plugin struct {
*generator.Generator
generator.PluginImports
fmtPkg generator.Single
bytesPkg generator.Single
protoPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "equal"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.fmtPkg = p.NewImport("fmt")
p.bytesPkg = p.NewImport("bytes")
p.protoPkg = p.NewImport("github.com/gogo/protobuf/proto")
for _, msg := range file.Messages() {
if msg.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg, true)
}
if gogoproto.HasEqual(file.FileDescriptorProto, msg.DescriptorProto) {
p.generateMessage(file, msg, false)
}
}
}
func (p *plugin) generateNullableField(fieldname string, verbose bool) {
p.P(`if this.`, fieldname, ` != nil && that1.`, fieldname, ` != nil {`)
p.In()
p.P(`if *this.`, fieldname, ` != *that1.`, fieldname, `{`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", *this.`, fieldname, `, *that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that.`, fieldname, ` != nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`} else if that1.`, fieldname, ` != nil {`)
}
func (p *plugin) generateMsgNullAndTypeCheck(ccTypeName string, verbose bool) {
p.P(`if that == nil {`)
p.In()
if verbose {
p.P(`if this == nil {`)
p.In()
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that == nil && this != nil")`)
} else {
p.P(`return this == nil`)
}
p.Out()
p.P(`}`)
p.P(``)
p.P(`that1, ok := that.(*`, ccTypeName, `)`)
p.P(`if !ok {`)
p.In()
p.P(`that2, ok := that.(`, ccTypeName, `)`)
p.P(`if ok {`)
p.In()
p.P(`that1 = &that2`)
p.Out()
p.P(`} else {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is not of type *`, ccTypeName, `")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`if that1 == nil {`)
p.In()
if verbose {
p.P(`if this == nil {`)
p.In()
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is nil && this != nil")`)
} else {
p.P(`return this == nil`)
}
p.Out()
p.P(`} else if this == nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("that is type *`, ccTypeName, ` but is not nil && this == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
func (p *plugin) generateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, verbose bool) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
fieldname := p.GetOneOfFieldName(message, field)
repeated := field.IsRepeated()
ctype := gogoproto.IsCustomType(field)
nullable := gogoproto.IsNullable(field)
isNormal := (gogoproto.IsStdDuration(field) ||
gogoproto.IsStdDouble(field) ||
gogoproto.IsStdFloat(field) ||
gogoproto.IsStdInt64(field) ||
gogoproto.IsStdUInt64(field) ||
gogoproto.IsStdInt32(field) ||
gogoproto.IsStdUInt32(field) ||
gogoproto.IsStdBool(field) ||
gogoproto.IsStdString(field))
isBytes := gogoproto.IsStdBytes(field)
isTimestamp := gogoproto.IsStdTime(field)
// oneof := field.OneofIndex != nil
if !repeated {
if ctype || isTimestamp {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if !this.`, fieldname, `.Equal(*that1.`, fieldname, `) {`)
} else {
p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else if isNormal {
if nullable {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else if isBytes {
if nullable {
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `, *that1.`, fieldname, `) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else {
if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
} else {
p.P(`if !this.`, fieldname, `.Equal(&that1.`, fieldname, `) {`)
}
} else if field.IsBytes() {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
} else if field.IsString() {
if nullable && !proto3 {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
} else {
if nullable && !proto3 {
p.generateNullableField(fieldname, verbose)
} else {
p.P(`if this.`, fieldname, ` != that1.`, fieldname, `{`)
}
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
} else {
p.P(`if len(this.`, fieldname, `) != len(that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", len(this.`, fieldname, `), len(that1.`, fieldname, `))`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.P(`for i := range this.`, fieldname, ` {`)
p.In()
if ctype && !p.IsMap(field) {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else if isTimestamp {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
}
} else if isNormal {
if nullable {
p.P(`if dthis, dthat := this.`, fieldname, `[i], that1.`, fieldname, `[i]; (dthis != nil && dthat != nil && *dthis != *dthat) || (dthis != nil && dthat == nil) || (dthis == nil && dthat != nil) {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
} else if isBytes {
if nullable {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(*this.`, fieldname, `[i], *that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
}
} else {
if p.IsMap(field) {
m := p.GoMapType(nil, field)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
mapValue := m.ValueAliasField
mapValueNormal := (gogoproto.IsStdDuration(mapValue) ||
gogoproto.IsStdDouble(mapValue) ||
gogoproto.IsStdFloat(mapValue) ||
gogoproto.IsStdInt64(mapValue) ||
gogoproto.IsStdUInt64(mapValue) ||
gogoproto.IsStdInt32(mapValue) ||
gogoproto.IsStdUInt32(mapValue) ||
gogoproto.IsStdBool(mapValue) ||
gogoproto.IsStdString(mapValue))
mapValueBytes := gogoproto.IsStdBytes(mapValue)
if mapValue.IsMessage() || p.IsGroup(mapValue) {
if nullable && valuegoTyp == valuegoAliasTyp {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else {
// Equal() has a pointer receiver, but map value is a value type
a := `this.` + fieldname + `[i]`
b := `that1.` + fieldname + `[i]`
if !mapValueNormal && !mapValueBytes && valuegoTyp != valuegoAliasTyp {
// cast back to the type that has the generated methods on it
a = `(` + valuegoTyp + `)(` + a + `)`
b = `(` + valuegoTyp + `)(` + b + `)`
}
p.P(`a := `, a)
p.P(`b := `, b)
if mapValueNormal {
if nullable {
p.P(`if *a != *b {`)
} else {
p.P(`if a != b {`)
}
} else if mapValueBytes {
if nullable {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(*a, *b) {`)
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(a, b) {`)
}
} else if nullable {
p.P(`if !a.Equal(b) {`)
} else {
p.P(`if !(&a).Equal(&b) {`)
}
}
} else if mapValue.IsBytes() {
if ctype {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(*that1.`, fieldname, `[i]) { //nullable`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) { //not nullable`)
}
} else {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
}
} else if mapValue.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
} else if field.IsMessage() || p.IsGroup(field) {
if nullable {
p.P(`if !this.`, fieldname, `[i].Equal(that1.`, fieldname, `[i]) {`)
} else {
p.P(`if !this.`, fieldname, `[i].Equal(&that1.`, fieldname, `[i]) {`)
}
} else if field.IsBytes() {
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `[i], that1.`, fieldname, `[i]) {`)
} else if field.IsString() {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
} else {
p.P(`if this.`, fieldname, `[i] != that1.`, fieldname, `[i] {`)
}
}
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", i, this.`, fieldname, `[i], i, that1.`, fieldname, `[i])`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
func (p *plugin) generateMessage(file *generator.FileDescriptor, message *generator.Descriptor, verbose bool) {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if verbose {
p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
} else {
p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
}
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if oneof {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if that1.`, fieldname, ` == nil {`)
p.In()
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` != nil && that1.`, fieldname, ` == nil")`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else if this.`, fieldname, ` == nil {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("this.`, fieldname, ` == nil && that1.`, fieldname, ` != nil")`)
} else {
p.P(`return false`)
}
p.Out()
if verbose {
p.P(`} else if err := this.`, fieldname, `.VerboseEqual(that1.`, fieldname, `); err != nil {`)
} else {
p.P(`} else if !this.`, fieldname, `.Equal(that1.`, fieldname, `) {`)
}
p.In()
if verbose {
p.P(`return err`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
} else {
p.generateField(file, message, field, verbose)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_InternalExtensions"
p.P(`thismap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(this)`)
p.P(`thatmap := `, p.protoPkg.Use(), `.GetUnsafeExtensionsMap(that1)`)
p.P(`for k, v := range thismap {`)
p.In()
p.P(`if v2, ok := thatmap[k]; ok {`)
p.In()
p.P(`if !v.Equal(&v2) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this[%v](%v) Not Equal that[%v](%v)", k, thismap[k], k, thatmap[k])`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`} else {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In that", k)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`for k, _ := range thatmap {`)
p.In()
p.P(`if _, ok := thismap[k]; !ok {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, `[%v] Not In this", k)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
fieldname := "XXX_extensions"
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
fieldname := "XXX_unrecognized"
p.P(`if !`, p.bytesPkg.Use(), `.Equal(this.`, fieldname, `, that1.`, fieldname, `) {`)
p.In()
if verbose {
p.P(`return `, p.fmtPkg.Use(), `.Errorf("`, fieldname, ` this(%v) Not Equal that(%v)", this.`, fieldname, `, that1.`, fieldname, `)`)
} else {
p.P(`return false`)
}
p.Out()
p.P(`}`)
}
if verbose {
p.P(`return nil`)
} else {
p.P(`return true`)
}
p.Out()
p.P(`}`)
//Generate Equal methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, field := range m.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
if verbose {
p.P(`func (this *`, ccTypeName, `) VerboseEqual(that interface{}) error {`)
} else {
p.P(`func (this *`, ccTypeName, `) Equal(that interface{}) bool {`)
}
p.In()
p.generateMsgNullAndTypeCheck(ccTypeName, verbose)
vanity.TurnOffNullableForNativeTypes(field)
p.generateField(file, message, field, verbose)
if verbose {
p.P(`return nil`)
} else {
p.P(`return true`)
}
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,109 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package equal
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
unsafePkg := imports.NewImport("unsafe")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
hasUnsafe := gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) ||
gogoproto.IsUnsafeUnmarshaler(file.FileDescriptorProto, message.DescriptorProto)
p.P(`func Test`, ccTypeName, `VerboseEqual(t *`, testingPkg.Use(), `.T) {`)
p.In()
if hasUnsafe {
if hasUnsafe {
p.P(`var bigendian uint32 = 0x01020304`)
p.P(`if *(*byte)(`, unsafePkg.Use(), `.Pointer(&bigendian)) == 1 {`)
p.In()
p.P(`t.Skip("unsafe does not work on big endian architectures")`)
p.Out()
p.P(`}`)
}
}
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("%#v !VerboseEqual %#v, since %v", msg, p, err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,233 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The face plugin generates a function will be generated which can convert a structure which satisfies an interface (face) to the specified structure.
This interface contains getters for each of the fields in the struct.
The specified struct is also generated with the getters.
This means that getters should be turned off so as not to conflict with face getters.
This allows it to satisfy its own face.
It is enabled by the following extensions:
- face
- face_all
Turn off getters by using the following extensions:
- getters
- getters_all
The face plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message A {
option (gogoproto.face) = true;
option (gogoproto.goproto_getters) = false;
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the face plugin, will generate the following code:
type AFace interface {
Proto() github_com_gogo_protobuf_proto.Message
GetDescription() string
GetNumber() int64
GetId() github_com_gogo_protobuf_test_custom.Uuid
}
func (this *A) Proto() github_com_gogo_protobuf_proto.Message {
return this
}
func (this *A) TestProto() github_com_gogo_protobuf_proto.Message {
return NewAFromFace(this)
}
func (this *A) GetDescription() string {
return this.Description
}
func (this *A) GetNumber() int64 {
return this.Number
}
func (this *A) GetId() github_com_gogo_protobuf_test_custom.Uuid {
return this.Id
}
func NewAFromFace(that AFace) *A {
this := &A{}
this.Description = that.GetDescription()
this.Number = that.GetNumber()
this.Id = that.GetId()
return this
}
and the following test code:
func TestAFace(t *testing7.T) {
popr := math_rand7.New(math_rand7.NewSource(time7.Now().UnixNano()))
p := NewPopulatedA(popr, true)
msg := p.TestProto()
if !p.Equal(msg) {
t.Fatalf("%#v !Face Equal %#v", msg, p)
}
}
The struct A, representing the message, will also be generated just like always.
As you can see A satisfies its own Face, AFace.
Creating another struct which satisfies AFace is very easy.
Simply create all these methods specified in AFace.
Implementing The Proto method is done with the helper function NewAFromFace:
func (this *MyStruct) Proto() proto.Message {
return NewAFromFace(this)
}
just the like TestProto method which is used to test the NewAFromFace function.
*/
package face
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type plugin struct {
*generator.Generator
generator.PluginImports
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "face"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if message.DescriptorProto.HasExtension() {
panic("face does not support message with extensions")
}
if gogoproto.HasGoGetters(file.FileDescriptorProto, message.DescriptorProto) {
panic("face requires getters to be disabled please use gogoproto.getters or gogoproto.getters_all and set it to false")
}
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`type `, ccTypeName, `Face interface{`)
p.In()
p.P(`Proto() `, protoPkg.Use(), `.Message`)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
goTyp = m.GoType
}
p.P(`Get`, fieldname, `() `, goTyp)
}
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) Proto() `, protoPkg.Use(), `.Message {`)
p.In()
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) TestProto() `, protoPkg.Use(), `.Message {`)
p.In()
p.P(`return New`, ccTypeName, `FromFace(this)`)
p.Out()
p.P(`}`)
p.P(``)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
goTyp = m.GoType
}
p.P(`func (this *`, ccTypeName, `) Get`, fieldname, `() `, goTyp, `{`)
p.In()
p.P(` return this.`, fieldname)
p.Out()
p.P(`}`)
p.P(``)
}
p.P(``)
p.P(`func New`, ccTypeName, `FromFace(that `, ccTypeName, `Face) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
p.P(`this.`, fieldname, ` = that.Get`, fieldname, `()`)
}
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
}
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,82 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package face
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.IsFace(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Face(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`msg := p.TestProto()`)
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("%#v !Face Equal %#v", msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,386 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The gostring plugin generates a GoString method for each message.
The GoString method is called whenever you use a fmt.Printf as such:
fmt.Printf("%#v", mymessage)
or whenever you actually call GoString()
The output produced by the GoString method can be copied from the output into code and used to set a variable.
It is totally valid Go Code and is populated exactly as the struct that was printed out.
It is enabled by the following extensions:
- gostring
- gostring_all
The gostring plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.gostring_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the gostring plugin, will generate the following code:
func (this *A) GoString() string {
if this == nil {
return "nil"
}
s := strings1.Join([]string{`&test.A{` + `Description:` + fmt1.Sprintf("%#v", this.Description), `Number:` + fmt1.Sprintf("%#v", this.Number), `Id:` + fmt1.Sprintf("%#v", this.Id), `XXX_unrecognized:` + fmt1.Sprintf("%#v", this.XXX_unrecognized) + `}`}, ", ")
return s
}
and the following test code:
func TestAGoString(t *testing6.T) {
popr := math_rand6.New(math_rand6.NewSource(time6.Now().UnixNano()))
p := NewPopulatedA(popr, false)
s1 := p.GoString()
s2 := fmt2.Sprintf("%#v", p)
if s1 != s2 {
t.Fatalf("GoString want %v got %v", s1, s2)
}
_, err := go_parser.ParseExpr(s1)
if err != nil {
panic(err)
}
}
Typically fmt.Printf("%#v") will stop to print when it reaches a pointer and
not print their values, while the generated GoString method will always print all values, recursively.
*/
package gostring
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type gostring struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
overwrite bool
}
func NewGoString() *gostring {
return &gostring{}
}
func (p *gostring) Name() string {
return "gostring"
}
func (p *gostring) Overwrite() {
p.overwrite = true
}
func (p *gostring) Init(g *generator.Generator) {
p.Generator = g
}
func (p *gostring) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
fmtPkg := p.NewImport("fmt")
stringsPkg := p.NewImport("strings")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
sortPkg := p.NewImport("sort")
strconvPkg := p.NewImport("strconv")
reflectPkg := p.NewImport("reflect")
sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
extensionToGoStringUsed := false
for _, message := range file.Messages() {
if !p.overwrite && !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
packageName := file.GoPackageName()
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) GoString() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`s := make([]string, 0, `, strconv.Itoa(len(message.Field)+4), `)`)
p.P(`s = append(s, "&`, packageName, ".", ccTypeName, `{")`)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
fieldname := p.GetFieldName(message, field)
oneof := field.OneofIndex != nil
if oneof {
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
p.Out()
p.P(`}`)
} else if p.IsMap(field) {
m := p.GoMapType(nil, field)
mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
keysName := `keysFor` + fieldname
keygoTyp, _ := p.GoType(nil, keyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
keyCapTyp := generator.CamelCase(keygoTyp)
p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
p.P(`for k, _ := range this.`, fieldname, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(keysName, ` = append(`, keysName, `, k)`)
} else {
p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
}
p.Out()
p.P(`}`)
p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
mapName := `mapStringFor` + fieldname
p.P(mapName, ` := "`, mapgoTyp, `{"`)
p.P(`for _, k := range `, keysName, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[k])`)
} else {
p.P(mapName, ` += fmt.Sprintf("%#v: %#v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
}
p.Out()
p.P(`}`)
p.P(mapName, ` += "}"`)
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`s = append(s, "`, fieldname, `: " + `, mapName, `+ ",\n")`)
p.Out()
p.P(`}`)
} else if (field.IsMessage() && !gogoproto.IsCustomType(field) && !gogoproto.IsStdType(field)) || p.IsGroup(field) {
if nullable || repeated {
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
}
if nullable {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
} else if repeated {
if nullable {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
} else {
goTyp, _ := p.GoType(message, field)
goTyp = strings.Replace(goTyp, "[]", "", 1)
p.P("vs := make([]", goTyp, ", len(this.", fieldname, "))")
p.P("for i := range vs {")
p.In()
p.P("vs[i] = this.", fieldname, "[i]")
p.Out()
p.P("}")
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", vs) + ",\n")`)
}
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, stringsPkg.Use(), `.Replace(this.`, fieldname, `.GoString()`, ",`&`,``,1)", ` + ",\n")`)
}
if nullable || repeated {
p.Out()
p.P(`}`)
}
} else {
if !proto3 && (nullable || repeated) {
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
}
if field.IsEnum() {
if nullable && !repeated && !proto3 {
goTyp, _ := p.GoType(message, field)
p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
}
} else {
if nullable && !repeated && !proto3 {
goTyp, _ := p.GoType(message, field)
p.P(`s = append(s, "`, fieldname, `: " + valueToGoString`, p.localName, `(this.`, fieldname, `,"`, generator.GoTypeToName(goTyp), `"`, `) + ",\n")`)
} else {
p.P(`s = append(s, "`, fieldname, `: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `) + ",\n")`)
}
}
if !proto3 && (nullable || repeated) {
p.Out()
p.P(`}`)
}
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`s = append(s, "XXX_InternalExtensions: " + extensionToGoString`, p.localName, `(this) + ",\n")`)
extensionToGoStringUsed = true
} else {
p.P(`if this.XXX_extensions != nil {`)
p.In()
p.P(`s = append(s, "XXX_extensions: " + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_extensions) + ",\n")`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if this.XXX_unrecognized != nil {`)
p.In()
p.P(`s = append(s, "XXX_unrecognized:" + `, fmtPkg.Use(), `.Sprintf("%#v", this.XXX_unrecognized) + ",\n")`)
p.Out()
p.P(`}`)
}
p.P(`s = append(s, "}")`)
p.P(`return `, stringsPkg.Use(), `.Join(s, "")`)
p.Out()
p.P(`}`)
//Generate GoString methods for oneof fields
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) GoString() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
fieldname := p.GetOneOfFieldName(message, field)
outStr := strings.Join([]string{
"s := ",
stringsPkg.Use(), ".Join([]string{`&", packageName, ".", ccTypeName, "{` + \n",
"`", fieldname, ":` + ", fmtPkg.Use(), `.Sprintf("%#v", this.`, fieldname, `)`,
" + `}`",
`}`,
`,", "`,
`)`}, "")
p.P(outStr)
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`func valueToGoString`, p.localName, `(v interface{}, typ string) string {`)
p.In()
p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
p.P(`if rv.IsNil() {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
p.P(`return `, fmtPkg.Use(), `.Sprintf("func(v %v) *%v { return &v } ( %#v )", typ, typ, pv)`)
p.Out()
p.P(`}`)
if extensionToGoStringUsed {
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
fmt.Fprintf(os.Stderr, "The GoString plugin for messages with extensions requires importing gogoprotobuf. Please see file %s", file.GetName())
os.Exit(1)
}
p.P(`func extensionToGoString`, p.localName, `(m `, protoPkg.Use(), `.Message) string {`)
p.In()
p.P(`e := `, protoPkg.Use(), `.GetUnsafeExtensionsMap(m)`)
p.P(`if e == nil { return "nil" }`)
p.P(`s := "proto.NewUnsafeXXX_InternalExtensions(map[int32]proto.Extension{"`)
p.P(`keys := make([]int, 0, len(e))`)
p.P(`for k := range e {`)
p.In()
p.P(`keys = append(keys, int(k))`)
p.Out()
p.P(`}`)
p.P(sortPkg.Use(), `.Ints(keys)`)
p.P(`ss := []string{}`)
p.P(`for _, k := range keys {`)
p.In()
p.P(`ss = append(ss, `, strconvPkg.Use(), `.Itoa(k) + ": " + e[int32(k)].GoString())`)
p.Out()
p.P(`}`)
p.P(`s+=`, stringsPkg.Use(), `.Join(ss, ",") + "})"`)
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewGoString())
}

View File

@ -1,90 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package gostring
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
fmtPkg := imports.NewImport("fmt")
parserPkg := imports.NewImport("go/parser")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.HasGoString(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `GoString(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`s1 := p.GoString()`)
p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%#v", p)`)
p.P(`if s1 != s2 {`)
p.In()
p.P(`t.Fatalf("GoString want %v got %v", s1, s2)`)
p.Out()
p.P(`}`)
p.P(`_, err := `, parserPkg.Use(), `.ParseExpr(s1)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatal(err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,93 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The oneofcheck plugin is used to check whether oneof is not used incorrectly.
For instance:
An error is caused if a oneof field:
- is used in a face
- is an embedded field
*/
package oneofcheck
import (
"fmt"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"os"
)
type plugin struct {
*generator.Generator
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "oneofcheck"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
for _, msg := range file.Messages() {
face := gogoproto.IsFace(file.FileDescriptorProto, msg.DescriptorProto)
for _, field := range msg.GetField() {
if field.OneofIndex == nil {
continue
}
if face {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in a face and oneof\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if gogoproto.IsEmbed(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and an embedded field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if !gogoproto.IsNullable(field) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and a non-nullable field\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
if gogoproto.IsUnion(file.FileDescriptorProto, msg.DescriptorProto) {
fmt.Fprintf(os.Stderr, "ERROR: field %v.%v cannot be in an oneof and in an union (deprecated)\n", generator.CamelCase(*msg.Name), generator.CamelCase(*field.Name))
os.Exit(1)
}
}
}
}
func (p *plugin) GenerateImports(*generator.FileDescriptor) {}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,815 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The populate plugin generates a NewPopulated function.
This function returns a newly populated structure.
It is enabled by the following extensions:
- populate
- populate_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.populate_all) = true;
message B {
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the populate plugin, will generate code the following code:
func NewPopulatedB(r randyExample, easy bool) *B {
this := &B{}
v2 := NewPopulatedA(r, easy)
this.A = *v2
if r.Intn(10) != 0 {
v3 := r.Intn(10)
this.G = make([]github_com_gogo_protobuf_test_custom.Uint128, v3)
for i := 0; i < v3; i++ {
v4 := github_com_gogo_protobuf_test_custom.NewPopulatedUint128(r)
this.G[i] = *v4
}
}
if !easy && r.Intn(10) != 0 {
this.XXX_unrecognized = randUnrecognizedExample(r, 3)
}
return this
}
The idea that is useful for testing.
Most of the other plugins' generated test code uses it.
You will still be able to use the generated test code of other packages
if you turn off the popluate plugin and write your own custom NewPopulated function.
If the easy flag is not set the XXX_unrecognized and XXX_extensions fields are also populated.
These have caused problems with JSON marshalling and unmarshalling tests.
*/
package populate
import (
"fmt"
"math"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type VarGen interface {
Next() string
Current() string
}
type varGen struct {
index int64
}
func NewVarGen() VarGen {
return &varGen{0}
}
func (this *varGen) Next() string {
this.index++
return fmt.Sprintf("v%d", this.index)
}
func (this *varGen) Current() string {
return fmt.Sprintf("v%d", this.index)
}
type plugin struct {
*generator.Generator
generator.PluginImports
varGen VarGen
atleastOne bool
localName string
typesPkg generator.Single
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "populate"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
}
func value(typeName string, fieldType descriptor.FieldDescriptorProto_Type) string {
switch fieldType {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE:
return typeName + "(r.Float64())"
case descriptor.FieldDescriptorProto_TYPE_FLOAT:
return typeName + "(r.Float32())"
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64,
descriptor.FieldDescriptorProto_TYPE_SINT64:
return typeName + "(r.Int63())"
case descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_FIXED64:
return typeName + "(uint64(r.Uint32()))"
case descriptor.FieldDescriptorProto_TYPE_INT32,
descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32,
descriptor.FieldDescriptorProto_TYPE_ENUM:
return typeName + "(r.Int31())"
case descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_FIXED32:
return typeName + "(r.Uint32())"
case descriptor.FieldDescriptorProto_TYPE_BOOL:
return typeName + `(bool(r.Intn(2) == 0))`
case descriptor.FieldDescriptorProto_TYPE_STRING,
descriptor.FieldDescriptorProto_TYPE_GROUP,
descriptor.FieldDescriptorProto_TYPE_MESSAGE,
descriptor.FieldDescriptorProto_TYPE_BYTES:
}
panic(fmt.Errorf("unexpected type %v", typeName))
}
func negative(fieldType descriptor.FieldDescriptorProto_Type) bool {
switch fieldType {
case descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_BOOL:
return false
}
return true
}
func (p *plugin) getFuncName(goTypName string, field *descriptor.FieldDescriptorProto) string {
funcName := "NewPopulated" + goTypName
goTypNames := strings.Split(goTypName, ".")
if len(goTypNames) == 2 {
funcName = goTypNames[0] + ".NewPopulated" + goTypNames[1]
} else if len(goTypNames) != 1 {
panic(fmt.Errorf("unreachable: too many dots in %v", goTypName))
}
if field != nil {
switch {
case gogoproto.IsStdTime(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdTime"
case gogoproto.IsStdDuration(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdDuration"
case gogoproto.IsStdDouble(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdDouble"
case gogoproto.IsStdFloat(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdFloat"
case gogoproto.IsStdInt64(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdInt64"
case gogoproto.IsStdUInt64(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt64"
case gogoproto.IsStdInt32(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdInt32"
case gogoproto.IsStdUInt32(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdUInt32"
case gogoproto.IsStdBool(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdBool"
case gogoproto.IsStdString(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdString"
case gogoproto.IsStdBytes(field):
funcName = p.typesPkg.Use() + ".NewPopulatedStdBytes"
}
}
return funcName
}
func (p *plugin) getFuncCall(goTypName string, field *descriptor.FieldDescriptorProto) string {
funcName := p.getFuncName(goTypName, field)
funcCall := funcName + "(r, easy)"
return funcCall
}
func (p *plugin) getCustomFuncCall(goTypName string) string {
funcName := p.getFuncName(goTypName, nil)
funcCall := funcName + "(r)"
return funcCall
}
func (p *plugin) getEnumVal(field *descriptor.FieldDescriptorProto, goTyp string) string {
enum := p.ObjectNamed(field.GetTypeName()).(*generator.EnumDescriptor)
l := len(enum.Value)
values := make([]string, l)
for i := range enum.Value {
values[i] = strconv.Itoa(int(*enum.Value[i].Number))
}
arr := "[]int32{" + strings.Join(values, ",") + "}"
val := strings.Join([]string{generator.GoTypeToName(goTyp), `(`, arr, `[r.Intn(`, fmt.Sprintf("%d", l), `)])`}, "")
return val
}
func (p *plugin) GenerateField(file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
goTyp, _ := p.GoType(message, field)
fieldname := p.GetOneOfFieldName(message, field)
goTypName := generator.GoTypeToName(goTyp)
if p.IsMap(field) {
m := p.GoMapType(nil, field)
keygoTyp, _ := p.GoType(nil, m.KeyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, m.KeyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, _ := p.GoType(nil, m.ValueAliasField)
keytypName := generator.GoTypeToName(keygoTyp)
keygoAliasTyp = generator.GoTypeToName(keygoAliasTyp)
valuetypAliasName := generator.GoTypeToName(valuegoAliasTyp)
nullable, valuegoTyp, valuegoAliasTyp := generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, m.GoType, `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
keyval := ""
if m.KeyField.IsString() {
keyval = fmt.Sprintf("randString%v(r)", p.localName)
} else {
keyval = value(keytypName, m.KeyField.GetType())
}
if keygoAliasTyp != keygoTyp {
keyval = keygoAliasTyp + `(` + keyval + `)`
}
if m.ValueField.IsMessage() || p.IsGroup(field) ||
(m.ValueField.IsBytes() && gogoproto.IsCustomType(field)) {
s := `this.` + fieldname + `[` + keyval + `] = `
if gogoproto.IsStdType(field) {
valuegoTyp = valuegoAliasTyp
}
funcCall := p.getCustomFuncCall(goTypName)
if !gogoproto.IsCustomType(field) {
goTypName = generator.GoTypeToName(valuegoTyp)
funcCall = p.getFuncCall(goTypName, m.ValueAliasField)
}
if !nullable {
funcCall = `*` + funcCall
}
if valuegoTyp != valuegoAliasTyp {
funcCall = `(` + valuegoAliasTyp + `)(` + funcCall + `)`
}
s += funcCall
p.P(s)
} else if m.ValueField.IsEnum() {
s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + p.getEnumVal(m.ValueField, valuegoTyp)
p.P(s)
} else if m.ValueField.IsBytes() {
count := p.varGen.Next()
p.P(count, ` := r.Intn(100)`)
p.P(p.varGen.Next(), ` := `, keyval)
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = make(`, valuegoTyp, `, `, count, `)`)
p.P(`for i := 0; i < `, count, `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `][i] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
} else if m.ValueField.IsString() {
s := `this.` + fieldname + `[` + keyval + `]` + ` = ` + fmt.Sprintf("randString%v(r)", p.localName)
p.P(s)
} else {
p.P(p.varGen.Next(), ` := `, keyval)
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] = `, value(valuetypAliasName, m.ValueField.GetType()))
if negative(m.ValueField.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, `[`, p.varGen.Current(), `] *= -1`)
p.Out()
p.P(`}`)
}
}
p.Out()
p.P(`}`)
} else if gogoproto.IsCustomType(field) {
funcCall := p.getCustomFuncCall(goTypName)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
p.Out()
p.P(`}`)
} else if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, ` = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
}
} else if field.IsMessage() || p.IsGroup(field) {
funcCall := p.getFuncCall(goTypName, field)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(5)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, `[i] = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, `[i] = *`, p.varGen.Current())
}
p.Out()
p.P(`}`)
} else {
if gogoproto.IsNullable(field) {
p.P(`this.`, fieldname, ` = `, funcCall)
} else {
p.P(p.varGen.Next(), `:= `, funcCall)
p.P(`this.`, fieldname, ` = *`, p.varGen.Current())
}
}
} else {
if field.IsEnum() {
val := p.getEnumVal(field, goTyp)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, val)
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, val)
} else {
p.P(p.varGen.Next(), ` := `, val)
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
} else if field.IsBytes() {
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`this.`, fieldname, `[i] = make([]byte,`, p.varGen.Current(), `)`)
p.P(`for j := 0; j < `, p.varGen.Current(), `; j++ {`)
p.In()
p.P(`this.`, fieldname, `[i][j] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
} else {
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = byte(r.Intn(256))`)
p.Out()
p.P(`}`)
}
} else if field.IsString() {
typName := generator.GoTypeToName(goTyp)
val := fmt.Sprintf("%s(randString%v(r))", typName, p.localName)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, val)
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, val)
} else {
p.P(p.varGen.Next(), `:= `, val)
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
} else {
typName := generator.GoTypeToName(goTyp)
if field.IsRepeated() {
p.P(p.varGen.Next(), ` := r.Intn(10)`)
p.P(`this.`, fieldname, ` = make(`, goTyp, `, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`this.`, fieldname, `[i] = `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, `[i] *= -1`)
p.Out()
p.P(`}`)
}
p.Out()
p.P(`}`)
} else if !gogoproto.IsNullable(field) || proto3 {
p.P(`this.`, fieldname, ` = `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(`this.`, fieldname, ` *= -1`)
p.Out()
p.P(`}`)
}
} else {
p.P(p.varGen.Next(), ` := `, value(typName, field.GetType()))
if negative(field.GetType()) {
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(p.varGen.Current(), ` *= -1`)
p.Out()
p.P(`}`)
}
p.P(`this.`, fieldname, ` = &`, p.varGen.Current())
}
}
}
}
func (p *plugin) hasLoop(pkg string, field *descriptor.FieldDescriptorProto, visited []*generator.Descriptor, excludes []*generator.Descriptor) *generator.Descriptor {
if field.IsMessage() || p.IsGroup(field) || p.IsMap(field) {
var fieldMessage *generator.Descriptor
if p.IsMap(field) {
m := p.GoMapType(nil, field)
if !m.ValueField.IsMessage() {
return nil
}
fieldMessage = p.ObjectNamed(m.ValueField.GetTypeName()).(*generator.Descriptor)
} else {
fieldMessage = p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
}
fieldTypeName := generator.CamelCaseSlice(fieldMessage.TypeName())
for _, message := range visited {
messageTypeName := generator.CamelCaseSlice(message.TypeName())
if fieldTypeName == messageTypeName {
for _, e := range excludes {
if fieldTypeName == generator.CamelCaseSlice(e.TypeName()) {
return nil
}
}
return fieldMessage
}
}
for _, f := range fieldMessage.Field {
if strings.HasPrefix(f.GetTypeName(), "."+pkg) {
visited = append(visited, fieldMessage)
loopTo := p.hasLoop(pkg, f, visited, excludes)
if loopTo != nil {
return loopTo
}
}
}
}
return nil
}
func (p *plugin) loops(pkg string, field *descriptor.FieldDescriptorProto, message *generator.Descriptor) int {
//fmt.Fprintf(os.Stderr, "loops %v %v\n", field.GetTypeName(), generator.CamelCaseSlice(message.TypeName()))
excludes := []*generator.Descriptor{}
loops := 0
for {
visited := []*generator.Descriptor{}
loopTo := p.hasLoop(pkg, field, visited, excludes)
if loopTo == nil {
break
}
//fmt.Fprintf(os.Stderr, "loopTo %v\n", generator.CamelCaseSlice(loopTo.TypeName()))
excludes = append(excludes, loopTo)
loops++
}
return loops
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.atleastOne = false
p.PluginImports = generator.NewPluginImports(p.Generator)
p.varGen = NewVarGen()
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
p.localName = generator.FileName(file)
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
if !gogoproto.HasPopulate(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
loopLevels := make([]int, len(message.Field))
maxLoopLevel := 0
for i, field := range message.Field {
loopLevels[i] = p.loops(file.GetPackage(), field, message)
if loopLevels[i] > maxLoopLevel {
maxLoopLevel = loopLevels[i]
}
}
ranTotal := 0
for i := range loopLevels {
ranTotal += int(math.Pow10(maxLoopLevel - loopLevels[i]))
}
p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
if gogoproto.IsUnion(message.File().FileDescriptorProto, message.DescriptorProto) && len(message.Field) > 0 {
p.P(`fieldNum := r.Intn(`, fmt.Sprintf("%d", ranTotal), `)`)
p.P(`switch fieldNum {`)
k := 0
for i, field := range message.Field {
is := []string{}
ran := int(math.Pow10(maxLoopLevel - loopLevels[i]))
for j := 0; j < ran; j++ {
is = append(is, fmt.Sprintf("%d", j+k))
}
k += ran
p.P(`case `, strings.Join(is, ","), `:`)
p.In()
p.GenerateField(file, message, field)
p.Out()
}
p.P(`}`)
} else {
var maxFieldNumber int32
oneofs := make(map[string]struct{})
for fieldIndex, field := range message.Field {
if field.GetNumber() > maxFieldNumber {
maxFieldNumber = field.GetNumber()
}
oneof := field.OneofIndex != nil
if !oneof {
if field.IsRequired() || (!gogoproto.IsNullable(field) && !field.IsRepeated()) || (proto3 && !field.IsMessage()) {
p.GenerateField(file, message, field)
} else {
if loopLevels[fieldIndex] > 0 {
p.P(`if r.Intn(5) == 0 {`)
} else {
p.P(`if r.Intn(5) != 0 {`)
}
p.In()
p.GenerateField(file, message, field)
p.Out()
p.P(`}`)
}
} else {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
fieldNumbers := []int32{}
for _, f := range message.Field {
fname := p.GetFieldName(message, f)
if fname == fieldname {
fieldNumbers = append(fieldNumbers, f.GetNumber())
}
}
p.P(`oneofNumber_`, fieldname, ` := `, fmt.Sprintf("%#v", fieldNumbers), `[r.Intn(`, strconv.Itoa(len(fieldNumbers)), `)]`)
p.P(`switch oneofNumber_`, fieldname, ` {`)
for _, f := range message.Field {
fname := p.GetFieldName(message, f)
if fname != fieldname {
continue
}
p.P(`case `, strconv.Itoa(int(f.GetNumber())), `:`)
p.In()
ccTypeName := p.OneOfTypeName(message, f)
p.P(`this.`, fname, ` = NewPopulated`, ccTypeName, `(r, easy)`)
p.Out()
}
p.P(`}`)
}
}
if message.DescriptorProto.HasExtension() {
p.P(`if !easy && r.Intn(10) != 0 {`)
p.In()
p.P(`l := r.Intn(5)`)
p.P(`for i := 0; i < l; i++ {`)
p.In()
if len(message.DescriptorProto.GetExtensionRange()) > 1 {
p.P(`eIndex := r.Intn(`, strconv.Itoa(len(message.DescriptorProto.GetExtensionRange())), `)`)
p.P(`fieldNumber := 0`)
p.P(`switch eIndex {`)
for i, e := range message.DescriptorProto.GetExtensionRange() {
p.P(`case `, strconv.Itoa(i), `:`)
p.In()
p.P(`fieldNumber = r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
p.Out()
if e.GetEnd() > maxFieldNumber {
maxFieldNumber = e.GetEnd()
}
}
p.P(`}`)
} else {
e := message.DescriptorProto.GetExtensionRange()[0]
p.P(`fieldNumber := r.Intn(`, strconv.Itoa(int(e.GetEnd()-e.GetStart())), `) + `, strconv.Itoa(int(e.GetStart())))
if e.GetEnd() > maxFieldNumber {
maxFieldNumber = e.GetEnd()
}
}
p.P(`wire := r.Intn(4)`)
p.P(`if wire == 3 { wire = 5 }`)
p.P(`dAtA := randField`, p.localName, `(nil, r, fieldNumber, wire)`)
p.P(protoPkg.Use(), `.SetRawExtension(this, int32(fieldNumber), dAtA)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
if maxFieldNumber < (1 << 10) {
p.P(`if !easy && r.Intn(10) != 0 {`)
p.In()
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`this.XXX_unrecognized = randUnrecognized`, p.localName, `(r, `, strconv.Itoa(int(maxFieldNumber+1)), `)`)
}
p.Out()
p.P(`}`)
}
}
p.P(`return this`)
p.Out()
p.P(`}`)
p.P(``)
//Generate NewPopulated functions for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, f := range m.Field {
oneof := f.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, f)
p.P(`func NewPopulated`, ccTypeName, `(r randy`, p.localName, `, easy bool) *`, ccTypeName, ` {`)
p.In()
p.P(`this := &`, ccTypeName, `{}`)
vanity.TurnOffNullableForNativeTypes(f)
p.GenerateField(file, message, f)
p.P(`return this`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`type randy`, p.localName, ` interface {`)
p.In()
p.P(`Float32() float32`)
p.P(`Float64() float64`)
p.P(`Int63() int64`)
p.P(`Int31() int32`)
p.P(`Uint32() uint32`)
p.P(`Intn(n int) int`)
p.Out()
p.P(`}`)
p.P(`func randUTF8Rune`, p.localName, `(r randy`, p.localName, `) rune {`)
p.In()
p.P(`ru := r.Intn(62)`)
p.P(`if ru < 10 {`)
p.In()
p.P(`return rune(ru+48)`)
p.Out()
p.P(`} else if ru < 36 {`)
p.In()
p.P(`return rune(ru+55)`)
p.Out()
p.P(`}`)
p.P(`return rune(ru+61)`)
p.Out()
p.P(`}`)
p.P(`func randString`, p.localName, `(r randy`, p.localName, `) string {`)
p.In()
p.P(p.varGen.Next(), ` := r.Intn(100)`)
p.P(`tmps := make([]rune, `, p.varGen.Current(), `)`)
p.P(`for i := 0; i < `, p.varGen.Current(), `; i++ {`)
p.In()
p.P(`tmps[i] = randUTF8Rune`, p.localName, `(r)`)
p.Out()
p.P(`}`)
p.P(`return string(tmps)`)
p.Out()
p.P(`}`)
p.P(`func randUnrecognized`, p.localName, `(r randy`, p.localName, `, maxFieldNumber int) (dAtA []byte) {`)
p.In()
p.P(`l := r.Intn(5)`)
p.P(`for i := 0; i < l; i++ {`)
p.In()
p.P(`wire := r.Intn(4)`)
p.P(`if wire == 3 { wire = 5 }`)
p.P(`fieldNumber := maxFieldNumber + r.Intn(100)`)
p.P(`dAtA = randField`, p.localName, `(dAtA, r, fieldNumber, wire)`)
p.Out()
p.P(`}`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
p.P(`func randField`, p.localName, `(dAtA []byte, r randy`, p.localName, `, fieldNumber int, wire int) []byte {`)
p.In()
p.P(`key := uint32(fieldNumber)<<3 | uint32(wire)`)
p.P(`switch wire {`)
p.P(`case 0:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(p.varGen.Next(), ` := r.Int63()`)
p.P(`if r.Intn(2) == 0 {`)
p.In()
p.P(p.varGen.Current(), ` *= -1`)
p.Out()
p.P(`}`)
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(`, p.varGen.Current(), `))`)
p.Out()
p.P(`case 1:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
p.Out()
p.P(`case 2:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`ll := r.Intn(100)`)
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(ll))`)
p.P(`for j := 0; j < ll; j++ {`)
p.In()
p.P(`dAtA = append(dAtA, byte(r.Intn(256)))`)
p.Out()
p.P(`}`)
p.Out()
p.P(`default:`)
p.In()
p.P(`dAtA = encodeVarintPopulate`, p.localName, `(dAtA, uint64(key))`)
p.P(`dAtA = append(dAtA, byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)), byte(r.Intn(256)))`)
p.Out()
p.P(`}`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
p.P(`func encodeVarintPopulate`, p.localName, `(dAtA []byte, v uint64) []byte {`)
p.In()
p.P(`for v >= 1<<7 {`)
p.In()
p.P(`dAtA = append(dAtA, uint8(uint64(v)&0x7f|0x80))`)
p.P(`v >>= 7`)
p.Out()
p.P(`}`)
p.P(`dAtA = append(dAtA, uint8(v))`)
p.P(`return dAtA`)
p.Out()
p.P(`}`)
}
func init() {
generator.RegisterPlugin(NewPlugin())
}

View File

@ -1,696 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The size plugin generates a Size or ProtoSize method for each message.
This is useful with the MarshalTo method generated by the marshalto plugin and the
gogoproto.marshaler and gogoproto.marshaler_all extensions.
It is enabled by the following extensions:
- sizer
- sizer_all
- protosizer
- protosizer_all
The size plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
And a benchmark given it is enabled using one of the following extensions:
- benchgen
- benchgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.sizer_all) = true;
message B {
option (gogoproto.description) = true;
optional A A = 1 [(gogoproto.nullable) = false, (gogoproto.embed) = true];
repeated bytes G = 2 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uint128", (gogoproto.nullable) = false];
}
given to the size plugin, will generate the following code:
func (m *B) Size() (n int) {
if m == nil {
return 0
}
var l int
_ = l
l = m.A.Size()
n += 1 + l + sovExample(uint64(l))
if len(m.G) > 0 {
for _, e := range m.G {
l = e.Size()
n += 1 + l + sovExample(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
return n
}
and the following test code:
func TestBSize(t *testing5.T) {
popr := math_rand5.New(math_rand5.NewSource(time5.Now().UnixNano()))
p := NewPopulatedB(popr, true)
dAtA, err := github_com_gogo_protobuf_proto2.Marshal(p)
if err != nil {
panic(err)
}
size := p.Size()
if len(dAtA) != size {
t.Fatalf("size %v != marshalled size %v", size, len(dAtA))
}
}
func BenchmarkBSize(b *testing5.B) {
popr := math_rand5.New(math_rand5.NewSource(616))
total := 0
pops := make([]*B, 1000)
for i := 0; i < 1000; i++ {
pops[i] = NewPopulatedB(popr, false)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += pops[i%1000].Size()
}
b.SetBytes(int64(total / b.N))
}
The sovExample function is a size of varint function for the example.pb.go file.
*/
package size
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"github.com/gogo/protobuf/vanity"
)
type size struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
typesPkg generator.Single
bitsPkg generator.Single
}
func NewSize() *size {
return &size{}
}
func (p *size) Name() string {
return "size"
}
func (p *size) Init(g *generator.Generator) {
p.Generator = g
}
func wireToType(wire string) int {
switch wire {
case "fixed64":
return proto.WireFixed64
case "fixed32":
return proto.WireFixed32
case "varint":
return proto.WireVarint
case "bytes":
return proto.WireBytes
case "group":
return proto.WireBytes
case "zigzag32":
return proto.WireVarint
case "zigzag64":
return proto.WireVarint
}
panic("unreachable")
}
func keySize(fieldNumber int32, wireType int) int {
x := uint32(fieldNumber)<<3 | uint32(wireType)
size := 0
for size = 0; x > 127; size++ {
x >>= 7
}
size++
return size
}
func (p *size) sizeVarint() {
p.P(`
func sov`, p.localName, `(x uint64) (n int) {
return (`, p.bitsPkg.Use(), `.Len64(x | 1) + 6)/ 7
}`)
}
func (p *size) sizeZigZag() {
p.P(`func soz`, p.localName, `(x uint64) (n int) {
return sov`, p.localName, `(uint64((x << 1) ^ uint64((int64(x) >> 63))))
}`)
}
func (p *size) std(field *descriptor.FieldDescriptorProto, name string) (string, bool) {
ptr := ""
if gogoproto.IsNullable(field) {
ptr = "*"
}
if gogoproto.IsStdTime(field) {
return p.typesPkg.Use() + `.SizeOfStdTime(` + ptr + name + `)`, true
} else if gogoproto.IsStdDuration(field) {
return p.typesPkg.Use() + `.SizeOfStdDuration(` + ptr + name + `)`, true
} else if gogoproto.IsStdDouble(field) {
return p.typesPkg.Use() + `.SizeOfStdDouble(` + ptr + name + `)`, true
} else if gogoproto.IsStdFloat(field) {
return p.typesPkg.Use() + `.SizeOfStdFloat(` + ptr + name + `)`, true
} else if gogoproto.IsStdInt64(field) {
return p.typesPkg.Use() + `.SizeOfStdInt64(` + ptr + name + `)`, true
} else if gogoproto.IsStdUInt64(field) {
return p.typesPkg.Use() + `.SizeOfStdUInt64(` + ptr + name + `)`, true
} else if gogoproto.IsStdInt32(field) {
return p.typesPkg.Use() + `.SizeOfStdInt32(` + ptr + name + `)`, true
} else if gogoproto.IsStdUInt32(field) {
return p.typesPkg.Use() + `.SizeOfStdUInt32(` + ptr + name + `)`, true
} else if gogoproto.IsStdBool(field) {
return p.typesPkg.Use() + `.SizeOfStdBool(` + ptr + name + `)`, true
} else if gogoproto.IsStdString(field) {
return p.typesPkg.Use() + `.SizeOfStdString(` + ptr + name + `)`, true
} else if gogoproto.IsStdBytes(field) {
return p.typesPkg.Use() + `.SizeOfStdBytes(` + ptr + name + `)`, true
}
return "", false
}
func (p *size) generateField(proto3 bool, file *generator.FileDescriptor, message *generator.Descriptor, field *descriptor.FieldDescriptorProto, sizeName string) {
fieldname := p.GetOneOfFieldName(message, field)
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
doNilCheck := gogoproto.NeedsNilCheck(proto3, field)
if repeated {
p.P(`if len(m.`, fieldname, `) > 0 {`)
p.In()
} else if doNilCheck {
p.P(`if m.`, fieldname, ` != nil {`)
p.In()
}
packed := field.IsPacked() || (proto3 && field.IsPacked3())
_, wire := p.GoType(message, field)
wireType := wireToType(wire)
fieldNumber := field.GetNumber()
if packed {
wireType = proto.WireBytes
}
key := keySize(fieldNumber, wireType)
switch *field.Type {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*8))`, `+len(m.`, fieldname, `)*8`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+8), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+8))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+8))
} else {
p.P(`n+=`, strconv.Itoa(key+8))
}
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)*4))`, `+len(m.`, fieldname, `)*4`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+4), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+4))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+4))
} else {
p.P(`n+=`, strconv.Itoa(key+4))
}
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
if packed {
p.P(`l = 0`)
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`l+=sov`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(*m.`, fieldname, `))`)
} else {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(m.`, fieldname, `))`)
}
case descriptor.FieldDescriptorProto_TYPE_BOOL:
if packed {
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(len(m.`, fieldname, `)))`, `+len(m.`, fieldname, `)*1`)
} else if repeated {
p.P(`n+=`, strconv.Itoa(key+1), `*len(m.`, fieldname, `)`)
} else if proto3 {
p.P(`if m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key+1))
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key+1))
} else {
p.P(`n+=`, strconv.Itoa(key+1))
}
case descriptor.FieldDescriptorProto_TYPE_STRING:
if repeated {
p.P(`for _, s := range m.`, fieldname, ` { `)
p.In()
p.P(`l = len(s)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`if l > 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`l=len(*m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
} else {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
case descriptor.FieldDescriptorProto_TYPE_GROUP:
panic(fmt.Errorf("size does not support group %v", fieldname))
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
if p.IsMap(field) {
m := p.GoMapType(nil, field)
_, keywire := p.GoType(nil, m.KeyAliasField)
valuegoTyp, _ := p.GoType(nil, m.ValueField)
valuegoAliasTyp, valuewire := p.GoType(nil, m.ValueAliasField)
_, fieldwire := p.GoType(nil, field)
nullable, valuegoTyp, valuegoAliasTyp = generator.GoMapValueTypes(field, m.ValueField, valuegoTyp, valuegoAliasTyp)
fieldKeySize := keySize(field.GetNumber(), wireToType(fieldwire))
keyKeySize := keySize(1, wireToType(keywire))
valueKeySize := keySize(2, wireToType(valuewire))
p.P(`for k, v := range m.`, fieldname, ` { `)
p.In()
p.P(`_ = k`)
p.P(`_ = v`)
sum := []string{strconv.Itoa(keyKeySize)}
switch m.KeyField.GetType() {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
sum = append(sum, `8`)
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
sum = append(sum, `4`)
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
sum = append(sum, `sov`+p.localName+`(uint64(k))`)
case descriptor.FieldDescriptorProto_TYPE_BOOL:
sum = append(sum, `1`)
case descriptor.FieldDescriptorProto_TYPE_STRING,
descriptor.FieldDescriptorProto_TYPE_BYTES:
sum = append(sum, `len(k)+sov`+p.localName+`(uint64(len(k)))`)
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
sum = append(sum, `soz`+p.localName+`(uint64(k))`)
}
switch m.ValueField.GetType() {
case descriptor.FieldDescriptorProto_TYPE_DOUBLE,
descriptor.FieldDescriptorProto_TYPE_FIXED64,
descriptor.FieldDescriptorProto_TYPE_SFIXED64:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, strconv.Itoa(8))
case descriptor.FieldDescriptorProto_TYPE_FLOAT,
descriptor.FieldDescriptorProto_TYPE_FIXED32,
descriptor.FieldDescriptorProto_TYPE_SFIXED32:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, strconv.Itoa(4))
case descriptor.FieldDescriptorProto_TYPE_INT64,
descriptor.FieldDescriptorProto_TYPE_UINT64,
descriptor.FieldDescriptorProto_TYPE_UINT32,
descriptor.FieldDescriptorProto_TYPE_ENUM,
descriptor.FieldDescriptorProto_TYPE_INT32:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `sov`+p.localName+`(uint64(v))`)
case descriptor.FieldDescriptorProto_TYPE_BOOL:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `1`)
case descriptor.FieldDescriptorProto_TYPE_STRING:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `len(v)+sov`+p.localName+`(uint64(len(v)))`)
case descriptor.FieldDescriptorProto_TYPE_BYTES:
if gogoproto.IsCustomType(field) {
p.P(`l = 0`)
if nullable {
p.P(`if v != nil {`)
p.In()
}
p.P(`l = v.`, sizeName, `()`)
p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
if nullable {
p.Out()
p.P(`}`)
}
sum = append(sum, `l`)
} else {
p.P(`l = 0`)
if proto3 {
p.P(`if len(v) > 0 {`)
} else {
p.P(`if v != nil {`)
}
p.In()
p.P(`l = `, strconv.Itoa(valueKeySize), ` + len(v)+sov`+p.localName+`(uint64(len(v)))`)
p.Out()
p.P(`}`)
sum = append(sum, `l`)
}
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `soz`+p.localName+`(uint64(v))`)
case descriptor.FieldDescriptorProto_TYPE_MESSAGE:
stdSizeCall, stdOk := p.std(m.ValueAliasField, "v")
if nullable {
p.P(`l = 0`)
p.P(`if v != nil {`)
p.In()
if stdOk {
p.P(`l = `, stdSizeCall)
} else if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((`, valuegoTyp, `)(v)).`, sizeName, `()`)
} else {
p.P(`l = v.`, sizeName, `()`)
}
p.P(`l += `, strconv.Itoa(valueKeySize), ` + sov`+p.localName+`(uint64(l))`)
p.Out()
p.P(`}`)
sum = append(sum, `l`)
} else {
if stdOk {
p.P(`l = `, stdSizeCall)
} else if valuegoTyp != valuegoAliasTyp {
p.P(`l = ((*`, valuegoTyp, `)(&v)).`, sizeName, `()`)
} else {
p.P(`l = v.`, sizeName, `()`)
}
sum = append(sum, strconv.Itoa(valueKeySize))
sum = append(sum, `l+sov`+p.localName+`(uint64(l))`)
}
}
p.P(`mapEntrySize := `, strings.Join(sum, "+"))
p.P(`n+=mapEntrySize+`, fieldKeySize, `+sov`, p.localName, `(uint64(mapEntrySize))`)
p.Out()
p.P(`}`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
stdSizeCall, stdOk := p.std(field, "e")
if stdOk {
p.P(`l=`, stdSizeCall)
} else {
p.P(`l=e.`, sizeName, `()`)
}
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
stdSizeCall, stdOk := p.std(field, "m."+fieldname)
if stdOk {
p.P(`l=`, stdSizeCall)
} else {
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
}
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
case descriptor.FieldDescriptorProto_TYPE_BYTES:
if !gogoproto.IsCustomType(field) {
if repeated {
p.P(`for _, b := range m.`, fieldname, ` { `)
p.In()
p.P(`l = len(b)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`if l > 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=len(m.`, fieldname, `)`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
} else {
if repeated {
p.P(`for _, e := range m.`, fieldname, ` { `)
p.In()
p.P(`l=e.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
p.Out()
p.P(`}`)
} else {
p.P(`l=m.`, fieldname, `.`, sizeName, `()`)
p.P(`n+=`, strconv.Itoa(key), `+l+sov`, p.localName, `(uint64(l))`)
}
}
case descriptor.FieldDescriptorProto_TYPE_SINT32,
descriptor.FieldDescriptorProto_TYPE_SINT64:
if packed {
p.P(`l = 0`)
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`l+=soz`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
p.P(`n+=`, strconv.Itoa(key), `+sov`, p.localName, `(uint64(l))+l`)
} else if repeated {
p.P(`for _, e := range m.`, fieldname, ` {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(e))`)
p.Out()
p.P(`}`)
} else if proto3 {
p.P(`if m.`, fieldname, ` != 0 {`)
p.In()
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
p.Out()
p.P(`}`)
} else if nullable {
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(*m.`, fieldname, `))`)
} else {
p.P(`n+=`, strconv.Itoa(key), `+soz`, p.localName, `(uint64(m.`, fieldname, `))`)
}
default:
panic("not implemented")
}
if repeated || doNilCheck {
p.Out()
p.P(`}`)
}
}
func (p *size) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
p.typesPkg = p.NewImport("github.com/gogo/protobuf/types")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
p.bitsPkg = p.NewImport("math/bits")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = p.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) && gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
fmt.Fprintf(os.Stderr, "ERROR: message %v cannot support both sizer and protosizer plugins\n", generator.CamelCase(*message.Name))
os.Exit(1)
}
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`if m == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`var l int`)
p.P(`_ = l`)
oneofs := make(map[string]struct{})
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.generateField(proto3, file, message, field, sizeName)
} else {
fieldname := p.GetFieldName(message, field)
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P(`if m.`, fieldname, ` != nil {`)
p.In()
p.P(`n+=m.`, fieldname, `.`, sizeName, `()`)
p.Out()
p.P(`}`)
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`n += `, protoPkg.Use(), `.SizeOfInternalExtension(m)`)
} else {
p.P(`if m.XXX_extensions != nil {`)
p.In()
p.P(`n+=len(m.XXX_extensions)`)
p.Out()
p.P(`}`)
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if m.XXX_unrecognized != nil {`)
p.In()
p.P(`n+=len(m.XXX_unrecognized)`)
p.Out()
p.P(`}`)
}
p.P(`return n`)
p.Out()
p.P(`}`)
p.P()
//Generate Size methods for oneof fields
m := proto.Clone(message.DescriptorProto).(*descriptor.DescriptorProto)
for _, f := range m.Field {
oneof := f.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, f)
p.P(`func (m *`, ccTypeName, `) `, sizeName, `() (n int) {`)
p.In()
p.P(`if m == nil {`)
p.In()
p.P(`return 0`)
p.Out()
p.P(`}`)
p.P(`var l int`)
p.P(`_ = l`)
vanity.TurnOffNullableForNativeTypes(f)
p.generateField(false, file, message, f, sizeName)
p.P(`return n`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.sizeVarint()
p.sizeZigZag()
}
func init() {
generator.RegisterPlugin(NewSize())
}

View File

@ -1,134 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package size
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
sizeName := ""
if gogoproto.IsSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "Size"
} else if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
sizeName = "ProtoSize"
} else {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, sizeName, `(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`size2 := `, protoPkg.Use(), `.Size(p)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`size := p.`, sizeName, `()`)
p.P(`if len(dAtA) != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != marshalled size %v", seed, size, len(dAtA))`)
p.Out()
p.P(`}`)
p.P(`if size2 != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != before marshal proto.Size %v", seed, size, size2)`)
p.Out()
p.P(`}`)
p.P(`size3 := `, protoPkg.Use(), `.Size(p)`)
p.P(`if size3 != size {`)
p.In()
p.P(`t.Errorf("seed = %d, size %v != after marshal proto.Size %v", seed, size, size3)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Benchmark`, ccTypeName, sizeName, `(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`pops := make([]*`, ccTypeName, `, 1000)`)
p.P(`for i := 0; i < 1000; i++ {`)
p.In()
p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
p.Out()
p.P(`}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`total += pops[i%1000].`, sizeName, `()`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,347 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The stringer plugin generates a String method for each message.
It is enabled by the following extensions:
- stringer
- stringer_all
The stringer plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.goproto_stringer_all) = false;
option (gogoproto.stringer_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the stringer stringer, will generate the following code:
func (this *A) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&A{`,
`Description:` + fmt.Sprintf("%v", this.Description) + `,`,
`Number:` + fmt.Sprintf("%v", this.Number) + `,`,
`Id:` + fmt.Sprintf("%v", this.Id) + `,`,
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
`}`,
}, "")
return s
}
and the following test code:
func TestAStringer(t *testing4.T) {
popr := math_rand4.New(math_rand4.NewSource(time4.Now().UnixNano()))
p := NewPopulatedA(popr, false)
s1 := p.String()
s2 := fmt1.Sprintf("%v", p)
if s1 != s2 {
t.Fatalf("String want %v got %v", s1, s2)
}
}
Typically fmt.Printf("%v") will stop to print when it reaches a pointer and
not print their values, while the generated String method will always print all values, recursively.
*/
package stringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
"strings"
)
type stringer struct {
*generator.Generator
generator.PluginImports
atleastOne bool
localName string
}
func NewStringer() *stringer {
return &stringer{}
}
func (p *stringer) Name() string {
return "stringer"
}
func (p *stringer) Init(g *generator.Generator) {
p.Generator = g
}
func (p *stringer) Generate(file *generator.FileDescriptor) {
proto3 := gogoproto.IsProto3(file.FileDescriptorProto)
p.PluginImports = generator.NewPluginImports(p.Generator)
p.atleastOne = false
p.localName = generator.FileName(file)
fmtPkg := p.NewImport("fmt")
stringsPkg := p.NewImport("strings")
reflectPkg := p.NewImport("reflect")
sortKeysPkg := p.NewImport("github.com/gogo/protobuf/sortkeys")
protoPkg := p.NewImport("github.com/gogo/protobuf/proto")
for _, message := range file.Messages() {
if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if gogoproto.EnabledGoStringer(file.FileDescriptorProto, message.DescriptorProto) {
panic("old string method needs to be disabled, please use gogoproto.goproto_stringer or gogoproto.goproto_stringer_all and set it to false")
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
p.atleastOne = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) String() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
for _, field := range message.Field {
if p.IsMap(field) || !field.IsRepeated() {
continue
}
if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
nullable := gogoproto.IsNullable(field)
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
fieldMessageDesc := file.GetMessage(msgname)
gogoStringer := false
if fieldMessageDesc != nil {
gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
}
fieldname := p.GetFieldName(message, field)
stringfunc := fmtPkg.Use() + `.Sprintf("%v", f)`
if gogoStringer {
stringfunc = `f.String()`
}
repeatedName := `repeatedStringFor` + fieldname
if nullable {
p.P(repeatedName, ` := "[]*`, typeName, `{"`)
} else {
p.P(repeatedName, ` := "[]`, typeName, `{"`)
}
p.P(`for _, f := range `, `this.`, fieldname, ` {`)
p.In()
if nullable {
p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1)", ` + ","`)
} else if gogoStringer {
p.P(repeatedName, " += ", stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1)", ` + ","`)
} else {
p.P(repeatedName, " += ", stringfunc, ` + ","`)
}
p.Out()
p.P(`}`)
p.P(repeatedName, ` += "}"`)
}
}
for _, field := range message.Field {
if !p.IsMap(field) {
continue
}
fieldname := p.GetFieldName(message, field)
m := p.GoMapType(nil, field)
mapgoTyp, keyField, keyAliasField := m.GoType, m.KeyField, m.KeyAliasField
keysName := `keysFor` + fieldname
keygoTyp, _ := p.GoType(nil, keyField)
keygoTyp = strings.Replace(keygoTyp, "*", "", 1)
keygoAliasTyp, _ := p.GoType(nil, keyAliasField)
keygoAliasTyp = strings.Replace(keygoAliasTyp, "*", "", 1)
keyCapTyp := generator.CamelCase(keygoTyp)
p.P(keysName, ` := make([]`, keygoTyp, `, 0, len(this.`, fieldname, `))`)
p.P(`for k, _ := range this.`, fieldname, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(keysName, ` = append(`, keysName, `, k)`)
} else {
p.P(keysName, ` = append(`, keysName, `, `, keygoTyp, `(k))`)
}
p.Out()
p.P(`}`)
p.P(sortKeysPkg.Use(), `.`, keyCapTyp, `s(`, keysName, `)`)
mapName := `mapStringFor` + fieldname
p.P(mapName, ` := "`, mapgoTyp, `{"`)
p.P(`for _, k := range `, keysName, ` {`)
p.In()
if keygoAliasTyp == keygoTyp {
p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[k])`)
} else {
p.P(mapName, ` += fmt.Sprintf("%v: %v,", k, this.`, fieldname, `[`, keygoAliasTyp, `(k)])`)
}
p.Out()
p.P(`}`)
p.P(mapName, ` += "}"`)
}
p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
oneofs := make(map[string]struct{})
for _, field := range message.Field {
nullable := gogoproto.IsNullable(field)
repeated := field.IsRepeated()
fieldname := p.GetFieldName(message, field)
oneof := field.OneofIndex != nil
if oneof {
if _, ok := oneofs[fieldname]; ok {
continue
} else {
oneofs[fieldname] = struct{}{}
}
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
} else if p.IsMap(field) {
mapName := `mapStringFor` + fieldname
p.P("`", fieldname, ":`", ` + `, mapName, " + `,", "`,")
} else if (field.IsMessage() && !gogoproto.IsCustomType(field)) || p.IsGroup(field) {
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
fieldMessageDesc := file.GetMessage(msgname)
gogoStringer := false
if fieldMessageDesc != nil {
gogoStringer = gogoproto.IsStringer(file.FileDescriptorProto, fieldMessageDesc)
}
stringfunc := fmtPkg.Use() + `.Sprintf("%v", this.` + fieldname + `)`
if gogoStringer {
stringfunc = `this.` + fieldname + `.String()`
}
if nullable && !repeated {
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
} else if repeated {
repeatedName := `repeatedStringFor` + fieldname
p.P("`", fieldname, ":`", ` + `, repeatedName, " + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, stringsPkg.Use(), `.Replace(`, stringfunc, `, "`, typeName, `","`, msgname, `"`, ", 1),`&`,``,1) + `,", "`,")
}
} else {
if nullable && !repeated && !proto3 {
p.P("`", fieldname, ":`", ` + valueToString`, p.localName, `(this.`, fieldname, ") + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
}
}
}
if message.DescriptorProto.HasExtension() {
if gogoproto.HasExtensionsMap(file.FileDescriptorProto, message.DescriptorProto) {
p.P("`XXX_InternalExtensions:` + ", protoPkg.Use(), ".StringFromInternalExtension(this) + `,`,")
} else {
p.P("`XXX_extensions:` + ", protoPkg.Use(), ".StringFromExtensionsBytes(this.XXX_extensions) + `,`,")
}
}
if gogoproto.HasUnrecognized(file.FileDescriptorProto, message.DescriptorProto) {
p.P("`XXX_unrecognized:` + ", fmtPkg.Use(), `.Sprintf("%v", this.XXX_unrecognized) + `, "`,`,")
}
p.P("`}`,")
p.P(`}`, `,""`, ")")
p.P(`return s`)
p.Out()
p.P(`}`)
//Generate String methods for oneof fields
for _, field := range message.Field {
oneof := field.OneofIndex != nil
if !oneof {
continue
}
ccTypeName := p.OneOfTypeName(message, field)
p.P(`func (this *`, ccTypeName, `) String() string {`)
p.In()
p.P(`if this == nil {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P("s := ", stringsPkg.Use(), ".Join([]string{`&", ccTypeName, "{`,")
fieldname := p.GetOneOfFieldName(message, field)
if field.IsMessage() || p.IsGroup(field) {
desc := p.ObjectNamed(field.GetTypeName())
msgname := p.TypeName(desc)
msgnames := strings.Split(msgname, ".")
typeName := msgnames[len(msgnames)-1]
p.P("`", fieldname, ":`", ` + `, stringsPkg.Use(), `.Replace(`, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, `), "`, typeName, `","`, msgname, `"`, ", 1) + `,", "`,")
} else {
p.P("`", fieldname, ":`", ` + `, fmtPkg.Use(), `.Sprintf("%v", this.`, fieldname, ") + `,", "`,")
}
p.P("`}`,")
p.P(`}`, `,""`, ")")
p.P(`return s`)
p.Out()
p.P(`}`)
}
}
if !p.atleastOne {
return
}
p.P(`func valueToString`, p.localName, `(v interface{}) string {`)
p.In()
p.P(`rv := `, reflectPkg.Use(), `.ValueOf(v)`)
p.P(`if rv.IsNil() {`)
p.In()
p.P(`return "nil"`)
p.Out()
p.P(`}`)
p.P(`pv := `, reflectPkg.Use(), `.Indirect(rv).Interface()`)
p.P(`return `, fmtPkg.Use(), `.Sprintf("*%v", pv)`)
p.Out()
p.P(`}`)
}
func init() {
generator.RegisterPlugin(NewStringer())
}

View File

@ -1,83 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package stringer
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
fmtPkg := imports.NewImport("fmt")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if !gogoproto.IsStringer(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Stringer(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`s1 := p.String()`)
p.P(`s2 := `, fmtPkg.Use(), `.Sprintf("%v", p)`)
p.P(`if s1 != s2 {`)
p.In()
p.P(`t.Fatalf("String want %v got %v", s1, s2)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

View File

@ -1,608 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The testgen plugin generates Test and Benchmark functions for each message.
Tests are enabled using the following extensions:
- testgen
- testgen_all
Benchmarks are enabled using the following extensions:
- benchgen
- benchgen_all
Let us look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
option (gogoproto.testgen_all) = true;
option (gogoproto.benchgen_all) = true;
message A {
optional string Description = 1 [(gogoproto.nullable) = false];
optional int64 Number = 2 [(gogoproto.nullable) = false];
optional bytes Id = 3 [(gogoproto.customtype) = "github.com/gogo/protobuf/test/custom.Uuid", (gogoproto.nullable) = false];
}
given to the testgen plugin, will generate the following test code:
func TestAProto(t *testing.T) {
popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
p := NewPopulatedA(popr, false)
dAtA, err := github_com_gogo_protobuf_proto.Marshal(p)
if err != nil {
panic(err)
}
msg := &A{}
if err := github_com_gogo_protobuf_proto.Unmarshal(dAtA, msg); err != nil {
panic(err)
}
for i := range dAtA {
dAtA[i] = byte(popr.Intn(256))
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
func BenchmarkAProtoMarshal(b *testing.B) {
popr := math_rand.New(math_rand.NewSource(616))
total := 0
pops := make([]*A, 10000)
for i := 0; i < 10000; i++ {
pops[i] = NewPopulatedA(popr, false)
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
dAtA, err := github_com_gogo_protobuf_proto.Marshal(pops[i%10000])
if err != nil {
panic(err)
}
total += len(dAtA)
}
b.SetBytes(int64(total / b.N))
}
func BenchmarkAProtoUnmarshal(b *testing.B) {
popr := math_rand.New(math_rand.NewSource(616))
total := 0
datas := make([][]byte, 10000)
for i := 0; i < 10000; i++ {
dAtA, err := github_com_gogo_protobuf_proto.Marshal(NewPopulatedA(popr, false))
if err != nil {
panic(err)
}
datas[i] = dAtA
}
msg := &A{}
b.ResetTimer()
for i := 0; i < b.N; i++ {
total += len(datas[i%10000])
if err := github_com_gogo_protobuf_proto.Unmarshal(datas[i%10000], msg); err != nil {
panic(err)
}
}
b.SetBytes(int64(total / b.N))
}
func TestAJSON(t *testing1.T) {
popr := math_rand1.New(math_rand1.NewSource(time1.Now().UnixNano()))
p := NewPopulatedA(popr, true)
jsondata, err := encoding_json.Marshal(p)
if err != nil {
panic(err)
}
msg := &A{}
err = encoding_json.Unmarshal(jsondata, msg)
if err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Json Equal %#v", msg, p)
}
}
func TestAProtoText(t *testing2.T) {
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
p := NewPopulatedA(popr, true)
dAtA := github_com_gogo_protobuf_proto1.MarshalTextString(p)
msg := &A{}
if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
func TestAProtoCompactText(t *testing2.T) {
popr := math_rand2.New(math_rand2.NewSource(time2.Now().UnixNano()))
p := NewPopulatedA(popr, true)
dAtA := github_com_gogo_protobuf_proto1.CompactTextString(p)
msg := &A{}
if err := github_com_gogo_protobuf_proto1.UnmarshalText(dAtA, msg); err != nil {
panic(err)
}
if err := p.VerboseEqual(msg); err != nil {
t.Fatalf("%#v !VerboseProto %#v, since %v", msg, p, err)
}
if !p.Equal(msg) {
t.Fatalf("%#v !Proto %#v", msg, p)
}
}
Other registered tests are also generated.
Tests are registered to this test plugin by calling the following function.
func RegisterTestPlugin(newFunc NewTestPlugin)
where NewTestPlugin is:
type NewTestPlugin func(g *generator.Generator) TestPlugin
and TestPlugin is an interface:
type TestPlugin interface {
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
}
Plugins that use this interface include:
- populate
- gostring
- equal
- union
- and more
Please look at these plugins as examples of how to create your own.
A good idea is to let each plugin generate its own tests.
*/
package testgen
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type TestPlugin interface {
Generate(imports generator.PluginImports, file *generator.FileDescriptor) (used bool)
}
type NewTestPlugin func(g *generator.Generator) TestPlugin
var testplugins = make([]NewTestPlugin, 0)
func RegisterTestPlugin(newFunc NewTestPlugin) {
testplugins = append(testplugins, newFunc)
}
type plugin struct {
*generator.Generator
generator.PluginImports
tests []TestPlugin
}
func NewPlugin() *plugin {
return &plugin{}
}
func (p *plugin) Name() string {
return "testgen"
}
func (p *plugin) Init(g *generator.Generator) {
p.Generator = g
p.tests = make([]TestPlugin, 0, len(testplugins))
for i := range testplugins {
p.tests = append(p.tests, testplugins[i](g))
}
}
func (p *plugin) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
atLeastOne := false
for i := range p.tests {
used := p.tests[i].Generate(p.PluginImports, file)
if used {
atLeastOne = true
}
}
if atLeastOne {
p.P(`//These tests are generated by github.com/gogo/protobuf/plugin/testgen`)
}
}
type testProto struct {
*generator.Generator
}
func newProto(g *generator.Generator) TestPlugin {
return &testProto{g}
}
func (p *testProto) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `Proto(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`littlefuzz := make([]byte, len(dAtA))`)
p.P(`copy(littlefuzz, dAtA)`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.P(`if len(littlefuzz) > 0 {`)
p.In()
p.P(`fuzzamount := 100`)
p.P(`for i := 0; i < fuzzamount; i++ {`)
p.In()
p.P(`littlefuzz[popr.Intn(len(littlefuzz))] = byte(popr.Intn(256))`)
p.P(`littlefuzz = append(littlefuzz, byte(popr.Intn(256)))`)
p.Out()
p.P(`}`)
p.P(`// shouldn't panic`)
p.P(`_ = `, protoPkg.Use(), `.Unmarshal(littlefuzz, msg)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
if gogoproto.IsMarshaler(file.FileDescriptorProto, message.DescriptorProto) || gogoproto.IsUnsafeMarshaler(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`func Test`, ccTypeName, `MarshalTo(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, false)`)
if gogoproto.IsProtoSizer(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`size := p.ProtoSize()`)
} else {
p.P(`size := p.Size()`)
}
p.P(`dAtA := make([]byte, size)`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
p.P(`_, err := p.MarshalTo(dAtA)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`for i := range dAtA {`)
p.In()
p.P(`dAtA[i] = byte(popr.Intn(256))`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
}
if gogoproto.HasBenchGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Benchmark`, ccTypeName, `ProtoMarshal(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`pops := make([]*`, ccTypeName, `, 10000)`)
p.P(`for i := 0; i < 10000; i++ {`)
p.In()
p.P(`pops[i] = NewPopulated`, ccTypeName, `(popr, false)`)
p.Out()
p.P(`}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(pops[i%10000])`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`total += len(dAtA)`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
p.P(`func Benchmark`, ccTypeName, `ProtoUnmarshal(b *`, testingPkg.Use(), `.B) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(616))`)
p.P(`total := 0`)
p.P(`datas := make([][]byte, 10000)`)
p.P(`for i := 0; i < 10000; i++ {`)
p.In()
p.P(`dAtA, err := `, protoPkg.Use(), `.Marshal(NewPopulated`, ccTypeName, `(popr, false))`)
p.P(`if err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.P(`datas[i] = dAtA`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`b.ResetTimer()`)
p.P(`for i := 0; i < b.N; i++ {`)
p.In()
p.P(`total += len(datas[i%10000])`)
p.P(`if err := `, protoPkg.Use(), `.Unmarshal(datas[i%10000], msg); err != nil {`)
p.In()
p.P(`panic(err)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P(`b.SetBytes(int64(total / b.N))`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
type testJson struct {
*generator.Generator
}
func newJson(g *generator.Generator) TestPlugin {
return &testJson{g}
}
func (p *testJson) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
jsonPkg := imports.NewImport("github.com/gogo/protobuf/jsonpb")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `JSON(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`marshaler := `, jsonPkg.Use(), `.Marshaler{}`)
p.P(`jsondata, err := marshaler.MarshalToString(p)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`err = `, jsonPkg.Use(), `.UnmarshalString(jsondata, msg)`)
p.P(`if err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Json Equal %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
}
return used
}
type testText struct {
*generator.Generator
}
func newText(g *generator.Generator) TestPlugin {
return &testText{g}
}
func (p *testText) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
testingPkg := imports.NewImport("testing")
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
protoPkg := imports.NewImport("github.com/gogo/protobuf/proto")
if !gogoproto.ImportsGoGoProto(file.FileDescriptorProto) {
protoPkg = imports.NewImport("github.com/golang/protobuf/proto")
}
//fmtPkg := imports.NewImport("fmt")
for _, message := range file.Messages() {
ccTypeName := generator.CamelCaseSlice(message.TypeName())
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
if gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
used = true
p.P(`func Test`, ccTypeName, `ProtoText(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`dAtA := `, protoPkg.Use(), `.MarshalTextString(p)`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
p.P(`func Test`, ccTypeName, `ProtoCompactText(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`seed := `, timePkg.Use(), `.Now().UnixNano()`)
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(seed))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`dAtA := `, protoPkg.Use(), `.CompactTextString(p)`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if err := `, protoPkg.Use(), `.UnmarshalText(dAtA, msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, err = %v", seed, err)`)
p.Out()
p.P(`}`)
if gogoproto.HasVerboseEqual(file.FileDescriptorProto, message.DescriptorProto) {
p.P(`if err := p.VerboseEqual(msg); err != nil {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !VerboseProto %#v, since %v", seed, msg, p, err)`)
p.Out()
p.P(`}`)
}
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("seed = %d, %#v !Proto %#v", seed, msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
p.P()
}
}
return used
}
func init() {
RegisterTestPlugin(newProto)
RegisterTestPlugin(newJson)
RegisterTestPlugin(newText)
}

View File

@ -1,209 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
The onlyone plugin generates code for the onlyone extension.
All fields must be nullable and only one of the fields may be set, like a union.
Two methods are generated
GetValue() interface{}
and
SetValue(v interface{}) (set bool)
These provide easier interaction with a onlyone.
The onlyone extension is not called union as this causes compile errors in the C++ generated code.
There can only be one ;)
It is enabled by the following extensions:
- onlyone
- onlyone_all
The onlyone plugin also generates a test given it is enabled using one of the following extensions:
- testgen
- testgen_all
Lets look at:
github.com/gogo/protobuf/test/example/example.proto
Btw all the output can be seen at:
github.com/gogo/protobuf/test/example/*
The following message:
message U {
option (gogoproto.onlyone) = true;
optional A A = 1;
optional B B = 2;
}
given to the onlyone plugin, will generate code which looks a lot like this:
func (this *U) GetValue() interface{} {
if this.A != nil {
return this.A
}
if this.B != nil {
return this.B
}
return nil
}
func (this *U) SetValue(value interface{}) bool {
switch vt := value.(type) {
case *A:
this.A = vt
case *B:
this.B = vt
default:
return false
}
return true
}
and the following test code:
func TestUUnion(t *testing.T) {
popr := math_rand.New(math_rand.NewSource(time.Now().UnixNano()))
p := NewPopulatedU(popr)
v := p.GetValue()
msg := &U{}
if !msg.SetValue(v) {
t.Fatalf("Union: Could not set Value")
}
if !p.Equal(msg) {
t.Fatalf("%#v !Union Equal %#v", msg, p)
}
}
*/
package union
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type union struct {
*generator.Generator
generator.PluginImports
}
func NewUnion() *union {
return &union{}
}
func (p *union) Name() string {
return "union"
}
func (p *union) Init(g *generator.Generator) {
p.Generator = g
}
func (p *union) Generate(file *generator.FileDescriptor) {
p.PluginImports = generator.NewPluginImports(p.Generator)
for _, message := range file.Messages() {
if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.HasExtension() {
panic("onlyone does not currently support extensions")
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func (this *`, ccTypeName, `) GetValue() interface{} {`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
if fieldname == "Value" {
panic("cannot have a onlyone message " + ccTypeName + " with a field named Value")
}
p.P(`if this.`, fieldname, ` != nil {`)
p.In()
p.P(`return this.`, fieldname)
p.Out()
p.P(`}`)
}
p.P(`return nil`)
p.Out()
p.P(`}`)
p.P(``)
p.P(`func (this *`, ccTypeName, `) SetValue(value interface{}) bool {`)
p.In()
p.P(`switch vt := value.(type) {`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
goTyp, _ := p.GoType(message, field)
p.P(`case `, goTyp, `:`)
p.In()
p.P(`this.`, fieldname, ` = vt`)
p.Out()
}
p.P(`default:`)
p.In()
for _, field := range message.Field {
fieldname := p.GetFieldName(message, field)
if field.IsMessage() {
goTyp, _ := p.GoType(message, field)
obj := p.ObjectNamed(field.GetTypeName()).(*generator.Descriptor)
if gogoproto.IsUnion(obj.File().FileDescriptorProto, obj.DescriptorProto) {
p.P(`this.`, fieldname, ` = new(`, generator.GoTypeToName(goTyp), `)`)
p.P(`if set := this.`, fieldname, `.SetValue(value); set {`)
p.In()
p.P(`return true`)
p.Out()
p.P(`}`)
p.P(`this.`, fieldname, ` = nil`)
}
}
}
p.P(`return false`)
p.Out()
p.P(`}`)
p.P(`return true`)
p.Out()
p.P(`}`)
}
}
func init() {
generator.RegisterPlugin(NewUnion())
}

View File

@ -1,86 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package union
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/plugin/testgen"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
type test struct {
*generator.Generator
}
func NewTest(g *generator.Generator) testgen.TestPlugin {
return &test{g}
}
func (p *test) Generate(imports generator.PluginImports, file *generator.FileDescriptor) bool {
used := false
randPkg := imports.NewImport("math/rand")
timePkg := imports.NewImport("time")
testingPkg := imports.NewImport("testing")
for _, message := range file.Messages() {
if !gogoproto.IsUnion(file.FileDescriptorProto, message.DescriptorProto) ||
!gogoproto.HasTestGen(file.FileDescriptorProto, message.DescriptorProto) {
continue
}
if message.DescriptorProto.GetOptions().GetMapEntry() {
continue
}
used = true
ccTypeName := generator.CamelCaseSlice(message.TypeName())
p.P(`func Test`, ccTypeName, `OnlyOne(t *`, testingPkg.Use(), `.T) {`)
p.In()
p.P(`popr := `, randPkg.Use(), `.New(`, randPkg.Use(), `.NewSource(`, timePkg.Use(), `.Now().UnixNano()))`)
p.P(`p := NewPopulated`, ccTypeName, `(popr, true)`)
p.P(`v := p.GetValue()`)
p.P(`msg := &`, ccTypeName, `{}`)
p.P(`if !msg.SetValue(v) {`)
p.In()
p.P(`t.Fatalf("OnlyOne: Could not set Value")`)
p.Out()
p.P(`}`)
p.P(`if !p.Equal(msg) {`)
p.In()
p.P(`t.Fatalf("%#v !OnlyOne Equal %#v", msg, p)`)
p.Out()
p.P(`}`)
p.Out()
p.P(`}`)
}
return used
}
func init() {
testgen.RegisterTestPlugin(NewTest)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,461 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2013, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package generator
import (
"bytes"
"go/parser"
"go/printer"
"go/token"
"path"
"strings"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
)
func (d *FileDescriptor) Messages() []*Descriptor {
return d.desc
}
func (d *FileDescriptor) Enums() []*EnumDescriptor {
return d.enum
}
func (d *Descriptor) IsGroup() bool {
return d.group
}
func (g *Generator) IsGroup(field *descriptor.FieldDescriptorProto) bool {
if d, ok := g.typeNameToObject[field.GetTypeName()].(*Descriptor); ok {
return d.IsGroup()
}
return false
}
func (g *Generator) TypeNameByObject(typeName string) Object {
o, ok := g.typeNameToObject[typeName]
if !ok {
g.Fail("can't find object with type", typeName)
}
return o
}
func (g *Generator) OneOfTypeName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
typeName := message.TypeName()
ccTypeName := CamelCaseSlice(typeName)
fieldName := g.GetOneOfFieldName(message, field)
tname := ccTypeName + "_" + fieldName
// It is possible for this to collide with a message or enum
// nested in this message. Check for collisions.
ok := true
for _, desc := range message.nested {
if strings.Join(desc.TypeName(), "_") == tname {
ok = false
break
}
}
for _, enum := range message.enums {
if strings.Join(enum.TypeName(), "_") == tname {
ok = false
break
}
}
if !ok {
tname += "_"
}
return tname
}
type PluginImports interface {
NewImport(pkg string) Single
GenerateImports(file *FileDescriptor)
}
type pluginImports struct {
generator *Generator
singles []Single
}
func NewPluginImports(generator *Generator) *pluginImports {
return &pluginImports{generator, make([]Single, 0)}
}
func (this *pluginImports) NewImport(pkg string) Single {
imp := newImportedPackage(this.generator.ImportPrefix, pkg)
this.singles = append(this.singles, imp)
return imp
}
func (this *pluginImports) GenerateImports(file *FileDescriptor) {
for _, s := range this.singles {
if s.IsUsed() {
this.generator.PrintImport(GoPackageName(s.Name()), GoImportPath(s.Location()))
}
}
}
type Single interface {
Use() string
IsUsed() bool
Name() string
Location() string
}
type importedPackage struct {
used bool
pkg string
name string
importPrefix string
}
func newImportedPackage(importPrefix string, pkg string) *importedPackage {
return &importedPackage{
pkg: pkg,
importPrefix: importPrefix,
}
}
func (this *importedPackage) Use() string {
if !this.used {
this.name = string(cleanPackageName(this.pkg))
this.used = true
}
return this.name
}
func (this *importedPackage) IsUsed() bool {
return this.used
}
func (this *importedPackage) Name() string {
return this.name
}
func (this *importedPackage) Location() string {
return this.importPrefix + this.pkg
}
func (g *Generator) GetFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
goTyp, _ := g.GoType(message, field)
fieldname := CamelCase(*field.Name)
if gogoproto.IsCustomName(field) {
fieldname = gogoproto.GetCustomName(field)
}
if gogoproto.IsEmbed(field) {
fieldname = EmbedFieldName(goTyp)
}
if field.OneofIndex != nil {
fieldname = message.OneofDecl[int(*field.OneofIndex)].GetName()
fieldname = CamelCase(fieldname)
}
for _, f := range methodNames {
if f == fieldname {
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
func (g *Generator) GetOneOfFieldName(message *Descriptor, field *descriptor.FieldDescriptorProto) string {
goTyp, _ := g.GoType(message, field)
fieldname := CamelCase(*field.Name)
if gogoproto.IsCustomName(field) {
fieldname = gogoproto.GetCustomName(field)
}
if gogoproto.IsEmbed(field) {
fieldname = EmbedFieldName(goTyp)
}
for _, f := range methodNames {
if f == fieldname {
return fieldname + "_"
}
}
if !gogoproto.IsProtoSizer(message.file.FileDescriptorProto, message.DescriptorProto) {
if fieldname == "Size" {
return fieldname + "_"
}
}
return fieldname
}
func (g *Generator) IsMap(field *descriptor.FieldDescriptorProto) bool {
if !field.IsMessage() {
return false
}
byName := g.ObjectNamed(field.GetTypeName())
desc, ok := byName.(*Descriptor)
if byName == nil || !ok || !desc.GetOptions().GetMapEntry() {
return false
}
return true
}
func (g *Generator) GetMapKeyField(field, keyField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
if !gogoproto.IsCastKey(field) {
return keyField
}
keyField = proto.Clone(keyField).(*descriptor.FieldDescriptorProto)
if keyField.Options == nil {
keyField.Options = &descriptor.FieldOptions{}
}
keyType := gogoproto.GetCastKey(field)
if err := proto.SetExtension(keyField.Options, gogoproto.E_Casttype, &keyType); err != nil {
g.Fail(err.Error())
}
return keyField
}
func (g *Generator) GetMapValueField(field, valField *descriptor.FieldDescriptorProto) *descriptor.FieldDescriptorProto {
if gogoproto.IsCustomType(field) && gogoproto.IsCastValue(field) {
g.Fail("cannot have a customtype and casttype: ", field.String())
}
valField = proto.Clone(valField).(*descriptor.FieldDescriptorProto)
if valField.Options == nil {
valField.Options = &descriptor.FieldOptions{}
}
stdtime := gogoproto.IsStdTime(field)
if stdtime {
if err := proto.SetExtension(valField.Options, gogoproto.E_Stdtime, &stdtime); err != nil {
g.Fail(err.Error())
}
}
stddur := gogoproto.IsStdDuration(field)
if stddur {
if err := proto.SetExtension(valField.Options, gogoproto.E_Stdduration, &stddur); err != nil {
g.Fail(err.Error())
}
}
wktptr := gogoproto.IsWktPtr(field)
if wktptr {
if err := proto.SetExtension(valField.Options, gogoproto.E_Wktpointer, &wktptr); err != nil {
g.Fail(err.Error())
}
}
if valType := gogoproto.GetCastValue(field); len(valType) > 0 {
if err := proto.SetExtension(valField.Options, gogoproto.E_Casttype, &valType); err != nil {
g.Fail(err.Error())
}
}
if valType := gogoproto.GetCustomType(field); len(valType) > 0 {
if err := proto.SetExtension(valField.Options, gogoproto.E_Customtype, &valType); err != nil {
g.Fail(err.Error())
}
}
nullable := gogoproto.IsNullable(field)
if err := proto.SetExtension(valField.Options, gogoproto.E_Nullable, &nullable); err != nil {
g.Fail(err.Error())
}
return valField
}
// GoMapValueTypes returns the map value Go type and the alias map value Go type (for casting), taking into
// account whether the map is nullable or the value is a message.
func GoMapValueTypes(mapField, valueField *descriptor.FieldDescriptorProto, goValueType, goValueAliasType string) (nullable bool, outGoType string, outGoAliasType string) {
nullable = gogoproto.IsNullable(mapField) && (valueField.IsMessage() || gogoproto.IsCustomType(mapField))
if nullable {
// ensure the non-aliased Go value type is a pointer for consistency
if strings.HasPrefix(goValueType, "*") {
outGoType = goValueType
} else {
outGoType = "*" + goValueType
}
outGoAliasType = goValueAliasType
} else {
outGoType = strings.Replace(goValueType, "*", "", 1)
outGoAliasType = strings.Replace(goValueAliasType, "*", "", 1)
}
return
}
func GoTypeToName(goTyp string) string {
return strings.Replace(strings.Replace(goTyp, "*", "", -1), "[]", "", -1)
}
func EmbedFieldName(goTyp string) string {
goTyp = GoTypeToName(goTyp)
goTyps := strings.Split(goTyp, ".")
if len(goTyps) == 1 {
return goTyp
}
if len(goTyps) == 2 {
return goTyps[1]
}
panic("unreachable")
}
func (g *Generator) GeneratePlugin(p Plugin) {
plugins = []Plugin{p}
p.Init(g)
// Generate the output. The generator runs for every file, even the files
// that we don't generate output for, so that we can collate the full list
// of exported symbols to support public imports.
genFileMap := make(map[*FileDescriptor]bool, len(g.genFiles))
for _, file := range g.genFiles {
genFileMap[file] = true
}
for _, file := range g.allFiles {
g.Reset()
g.writeOutput = genFileMap[file]
g.generatePlugin(file, p)
if !g.writeOutput {
continue
}
g.Response.File = append(g.Response.File, &plugin.CodeGeneratorResponse_File{
Name: proto.String(file.goFileName(g.pathType)),
Content: proto.String(g.String()),
})
}
}
func (g *Generator) SetFile(filename string) {
g.file = g.fileByName(filename)
}
func (g *Generator) generatePlugin(file *FileDescriptor, p Plugin) {
g.writtenImports = make(map[string]bool)
g.usedPackages = make(map[GoImportPath]bool)
g.packageNames = make(map[GoImportPath]GoPackageName)
g.usedPackageNames = make(map[GoPackageName]bool)
g.addedImports = make(map[GoImportPath]bool)
g.file = file
// Run the plugins before the imports so we know which imports are necessary.
p.Generate(file)
// Generate header and imports last, though they appear first in the output.
rem := g.Buffer
g.Buffer = new(bytes.Buffer)
g.generateHeader()
// p.GenerateImports(g.file)
g.generateImports()
if !g.writeOutput {
return
}
g.Write(rem.Bytes())
// Reformat generated code.
contents := string(g.Buffer.Bytes())
fset := token.NewFileSet()
ast, err := parser.ParseFile(fset, "", g, parser.ParseComments)
if err != nil {
g.Fail("bad Go source code was generated:", contents, err.Error())
return
}
g.Reset()
err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(g, fset, ast)
if err != nil {
g.Fail("generated Go source code could not be reformatted:", err.Error())
}
}
func GetCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
return getCustomType(field)
}
func getCustomType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
if field.Options != nil {
var v interface{}
v, err = proto.GetExtension(field.Options, gogoproto.E_Customtype)
if err == nil && v.(*string) != nil {
ctype := *(v.(*string))
packageName, typ = splitCPackageType(ctype)
return packageName, typ, nil
}
}
return "", "", err
}
func splitCPackageType(ctype string) (packageName string, typ string) {
ss := strings.Split(ctype, ".")
if len(ss) == 1 {
return "", ctype
}
packageName = strings.Join(ss[0:len(ss)-1], ".")
typeName := ss[len(ss)-1]
importStr := strings.Map(badToUnderscore, packageName)
typ = importStr + "." + typeName
return packageName, typ
}
func getCastType(field *descriptor.FieldDescriptorProto) (packageName string, typ string, err error) {
if field.Options != nil {
var v interface{}
v, err = proto.GetExtension(field.Options, gogoproto.E_Casttype)
if err == nil && v.(*string) != nil {
ctype := *(v.(*string))
packageName, typ = splitCPackageType(ctype)
return packageName, typ, nil
}
}
return "", "", err
}
func FileName(file *FileDescriptor) string {
fname := path.Base(file.FileDescriptorProto.GetName())
fname = strings.Replace(fname, ".proto", "", -1)
fname = strings.Replace(fname, "-", "_", -1)
fname = strings.Replace(fname, ".", "_", -1)
return CamelCase(fname)
}
func (g *Generator) AllFiles() *descriptor.FileDescriptorSet {
set := &descriptor.FileDescriptorSet{}
set.File = make([]*descriptor.FileDescriptorProto, len(g.allFiles))
for i := range g.allFiles {
set.File[i] = g.allFiles[i].FileDescriptorProto
}
return set
}
func (d *Descriptor) Path() string {
return d.path
}
func (g *Generator) useTypes() string {
pkg := strings.Map(badToUnderscore, "github.com/gogo/protobuf/types")
g.customImports = append(g.customImports, "github.com/gogo/protobuf/types")
return pkg
}
func (d *FileDescriptor) GoPackageName() string {
return string(d.packageName)
}

View File

@ -1,117 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2017 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
Package remap handles tracking the locations of Go tokens in a source text
across a rewrite by the Go formatter.
*/
package remap
import (
"fmt"
"go/scanner"
"go/token"
)
// A Location represents a span of byte offsets in the source text.
type Location struct {
Pos, End int // End is exclusive
}
// A Map represents a mapping between token locations in an input source text
// and locations in the correspnding output text.
type Map map[Location]Location
// Find reports whether the specified span is recorded by m, and if so returns
// the new location it was mapped to. If the input span was not found, the
// returned location is the same as the input.
func (m Map) Find(pos, end int) (Location, bool) {
key := Location{
Pos: pos,
End: end,
}
if loc, ok := m[key]; ok {
return loc, true
}
return key, false
}
func (m Map) add(opos, oend, npos, nend int) {
m[Location{Pos: opos, End: oend}] = Location{Pos: npos, End: nend}
}
// Compute constructs a location mapping from input to output. An error is
// reported if any of the tokens of output cannot be mapped.
func Compute(input, output []byte) (Map, error) {
itok := tokenize(input)
otok := tokenize(output)
if len(itok) != len(otok) {
return nil, fmt.Errorf("wrong number of tokens, %d ≠ %d", len(itok), len(otok))
}
m := make(Map)
for i, ti := range itok {
to := otok[i]
if ti.Token != to.Token {
return nil, fmt.Errorf("token %d type mismatch: %s ≠ %s", i+1, ti, to)
}
m.add(ti.pos, ti.end, to.pos, to.end)
}
return m, nil
}
// tokinfo records the span and type of a source token.
type tokinfo struct {
pos, end int
token.Token
}
func tokenize(src []byte) []tokinfo {
fs := token.NewFileSet()
var s scanner.Scanner
s.Init(fs.AddFile("src", fs.Base(), len(src)), src, nil, scanner.ScanComments)
var info []tokinfo
for {
pos, next, lit := s.Scan()
switch next {
case token.SEMICOLON:
continue
}
info = append(info, tokinfo{
pos: int(pos - 1),
end: int(pos + token.Pos(len(lit)) - 1),
Token: next,
})
if next == token.EOF {
break
}
}
return info
}

View File

@ -1,536 +0,0 @@
// Go support for Protocol Buffers - Google's data interchange format
//
// Copyright 2015 The Go Authors. All rights reserved.
// https://github.com/golang/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Package grpc outputs gRPC service descriptions in Go code.
// It runs as a plugin for the Go protocol buffer compiler plugin.
// It is linked in to protoc-gen-go.
package grpc
import (
"fmt"
"strconv"
"strings"
pb "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
)
// generatedCodeVersion indicates a version of the generated code.
// It is incremented whenever an incompatibility between the generated code and
// the grpc package is introduced; the generated code references
// a constant, grpc.SupportPackageIsVersionN (where N is generatedCodeVersion).
const generatedCodeVersion = 4
// Paths for packages used by code generated in this file,
// relative to the import_prefix of the generator.Generator.
const (
contextPkgPath = "context"
grpcPkgPath = "google.golang.org/grpc"
codePkgPath = "google.golang.org/grpc/codes"
statusPkgPath = "google.golang.org/grpc/status"
)
func init() {
generator.RegisterPlugin(new(grpc))
}
// grpc is an implementation of the Go protocol buffer compiler's
// plugin architecture. It generates bindings for gRPC support.
type grpc struct {
gen *generator.Generator
}
// Name returns the name of this plugin, "grpc".
func (g *grpc) Name() string {
return "grpc"
}
// The names for packages imported in the generated code.
// They may vary from the final path component of the import path
// if the name is used by other packages.
var (
contextPkg string
grpcPkg string
)
// Init initializes the plugin.
func (g *grpc) Init(gen *generator.Generator) {
g.gen = gen
}
// Given a type name defined in a .proto, return its object.
// Also record that we're using it, to guarantee the associated import.
func (g *grpc) objectNamed(name string) generator.Object {
g.gen.RecordTypeUse(name)
return g.gen.ObjectNamed(name)
}
// Given a type name defined in a .proto, return its name as we will print it.
func (g *grpc) typeName(str string) string {
return g.gen.TypeName(g.objectNamed(str))
}
// P forwards to g.gen.P.
func (g *grpc) P(args ...interface{}) { g.gen.P(args...) }
// Generate generates code for the services in the given file.
func (g *grpc) Generate(file *generator.FileDescriptor) {
if len(file.FileDescriptorProto.Service) == 0 {
return
}
contextPkg = string(g.gen.AddImport(contextPkgPath))
grpcPkg = string(g.gen.AddImport(grpcPkgPath))
g.P("// Reference imports to suppress errors if they are not otherwise used.")
g.P("var _ ", contextPkg, ".Context")
g.P("var _ ", grpcPkg, ".ClientConn")
g.P()
// Assert version compatibility.
g.P("// This is a compile-time assertion to ensure that this generated file")
g.P("// is compatible with the grpc package it is being compiled against.")
g.P("const _ = ", grpcPkg, ".SupportPackageIsVersion", generatedCodeVersion)
g.P()
for i, service := range file.FileDescriptorProto.Service {
g.generateService(file, service, i)
}
}
// GenerateImports generates the import declaration for this file.
func (g *grpc) GenerateImports(file *generator.FileDescriptor) {}
// reservedClientName records whether a client name is reserved on the client side.
var reservedClientName = map[string]bool{
// TODO: do we need any in gRPC?
}
func unexport(s string) string { return strings.ToLower(s[:1]) + s[1:] }
// deprecationComment is the standard comment added to deprecated
// messages, fields, enums, and enum values.
var deprecationComment = "// Deprecated: Do not use."
// generateService generates all the code for the named service.
func (g *grpc) generateService(file *generator.FileDescriptor, service *pb.ServiceDescriptorProto, index int) {
path := fmt.Sprintf("6,%d", index) // 6 means service.
origServName := service.GetName()
fullServName := origServName
if pkg := file.GetPackage(); pkg != "" {
fullServName = pkg + "." + fullServName
}
servName := generator.CamelCase(origServName)
deprecated := service.GetOptions().GetDeprecated()
g.P()
g.P(fmt.Sprintf(`// %sClient is the client API for %s service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.`, servName, servName))
// Client interface.
if deprecated {
g.P("//")
g.P(deprecationComment)
}
g.P("type ", servName, "Client interface {")
for i, method := range service.Method {
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
g.P(g.generateClientSignature(servName, method))
}
g.P("}")
g.P()
// Client structure.
g.P("type ", unexport(servName), "Client struct {")
g.P("cc *", grpcPkg, ".ClientConn")
g.P("}")
g.P()
// NewClient factory.
if deprecated {
g.P(deprecationComment)
}
g.P("func New", servName, "Client (cc *", grpcPkg, ".ClientConn) ", servName, "Client {")
g.P("return &", unexport(servName), "Client{cc}")
g.P("}")
g.P()
var methodIndex, streamIndex int
serviceDescVar := "_" + servName + "_serviceDesc"
// Client method implementations.
for _, method := range service.Method {
var descExpr string
if !method.GetServerStreaming() && !method.GetClientStreaming() {
// Unary RPC method
descExpr = fmt.Sprintf("&%s.Methods[%d]", serviceDescVar, methodIndex)
methodIndex++
} else {
// Streaming RPC method
descExpr = fmt.Sprintf("&%s.Streams[%d]", serviceDescVar, streamIndex)
streamIndex++
}
g.generateClientMethod(servName, fullServName, serviceDescVar, method, descExpr)
}
// Server interface.
serverType := servName + "Server"
g.P("// ", serverType, " is the server API for ", servName, " service.")
if deprecated {
g.P("//")
g.P(deprecationComment)
}
g.P("type ", serverType, " interface {")
for i, method := range service.Method {
g.gen.PrintComments(fmt.Sprintf("%s,2,%d", path, i)) // 2 means method in a service.
g.P(g.generateServerSignature(servName, method))
}
g.P("}")
g.P()
// Server Unimplemented struct for forward compatability.
if deprecated {
g.P(deprecationComment)
}
g.generateUnimplementedServer(servName, service)
// Server registration.
if deprecated {
g.P(deprecationComment)
}
g.P("func Register", servName, "Server(s *", grpcPkg, ".Server, srv ", serverType, ") {")
g.P("s.RegisterService(&", serviceDescVar, `, srv)`)
g.P("}")
g.P()
// Server handler implementations.
var handlerNames []string
for _, method := range service.Method {
hname := g.generateServerMethod(servName, fullServName, method)
handlerNames = append(handlerNames, hname)
}
// Service descriptor.
g.P("var ", serviceDescVar, " = ", grpcPkg, ".ServiceDesc {")
g.P("ServiceName: ", strconv.Quote(fullServName), ",")
g.P("HandlerType: (*", serverType, ")(nil),")
g.P("Methods: []", grpcPkg, ".MethodDesc{")
for i, method := range service.Method {
if method.GetServerStreaming() || method.GetClientStreaming() {
continue
}
g.P("{")
g.P("MethodName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
g.P("},")
}
g.P("},")
g.P("Streams: []", grpcPkg, ".StreamDesc{")
for i, method := range service.Method {
if !method.GetServerStreaming() && !method.GetClientStreaming() {
continue
}
g.P("{")
g.P("StreamName: ", strconv.Quote(method.GetName()), ",")
g.P("Handler: ", handlerNames[i], ",")
if method.GetServerStreaming() {
g.P("ServerStreams: true,")
}
if method.GetClientStreaming() {
g.P("ClientStreams: true,")
}
g.P("},")
}
g.P("},")
g.P("Metadata: \"", file.GetName(), "\",")
g.P("}")
g.P()
}
// generateUnimplementedServer creates the unimplemented server struct
func (g *grpc) generateUnimplementedServer(servName string, service *pb.ServiceDescriptorProto) {
serverType := servName + "Server"
g.P("// Unimplemented", serverType, " can be embedded to have forward compatible implementations.")
g.P("type Unimplemented", serverType, " struct {")
g.P("}")
g.P()
// Unimplemented<service_name>Server's concrete methods
for _, method := range service.Method {
g.generateServerMethodConcrete(servName, method)
}
g.P()
}
// generateServerMethodConcrete returns unimplemented methods which ensure forward compatibility
func (g *grpc) generateServerMethodConcrete(servName string, method *pb.MethodDescriptorProto) {
header := g.generateServerSignatureWithParamNames(servName, method)
g.P("func (*Unimplemented", servName, "Server) ", header, " {")
var nilArg string
if !method.GetServerStreaming() && !method.GetClientStreaming() {
nilArg = "nil, "
}
methName := generator.CamelCase(method.GetName())
statusPkg := string(g.gen.AddImport(statusPkgPath))
codePkg := string(g.gen.AddImport(codePkgPath))
g.P("return ", nilArg, statusPkg, `.Errorf(`, codePkg, `.Unimplemented, "method `, methName, ` not implemented")`)
g.P("}")
}
// generateClientSignature returns the client-side signature for a method.
func (g *grpc) generateClientSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
reqArg := ", in *" + g.typeName(method.GetInputType())
if method.GetClientStreaming() {
reqArg = ""
}
respName := "*" + g.typeName(method.GetOutputType())
if method.GetServerStreaming() || method.GetClientStreaming() {
respName = servName + "_" + generator.CamelCase(origMethName) + "Client"
}
return fmt.Sprintf("%s(ctx %s.Context%s, opts ...%s.CallOption) (%s, error)", methName, contextPkg, reqArg, grpcPkg, respName)
}
func (g *grpc) generateClientMethod(servName, fullServName, serviceDescVar string, method *pb.MethodDescriptorProto, descExpr string) {
sname := fmt.Sprintf("/%s/%s", fullServName, method.GetName())
methName := generator.CamelCase(method.GetName())
inType := g.typeName(method.GetInputType())
outType := g.typeName(method.GetOutputType())
if method.GetOptions().GetDeprecated() {
g.P(deprecationComment)
}
g.P("func (c *", unexport(servName), "Client) ", g.generateClientSignature(servName, method), "{")
if !method.GetServerStreaming() && !method.GetClientStreaming() {
g.P("out := new(", outType, ")")
// TODO: Pass descExpr to Invoke.
g.P(`err := c.cc.Invoke(ctx, "`, sname, `", in, out, opts...)`)
g.P("if err != nil { return nil, err }")
g.P("return out, nil")
g.P("}")
g.P()
return
}
streamType := unexport(servName) + methName + "Client"
g.P("stream, err := c.cc.NewStream(ctx, ", descExpr, `, "`, sname, `", opts...)`)
g.P("if err != nil { return nil, err }")
g.P("x := &", streamType, "{stream}")
if !method.GetClientStreaming() {
g.P("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
}
g.P("return x, nil")
g.P("}")
g.P()
genSend := method.GetClientStreaming()
genRecv := method.GetServerStreaming()
genCloseAndRecv := !method.GetServerStreaming()
// Stream auxiliary types and methods.
g.P("type ", servName, "_", methName, "Client interface {")
if genSend {
g.P("Send(*", inType, ") error")
}
if genRecv {
g.P("Recv() (*", outType, ", error)")
}
if genCloseAndRecv {
g.P("CloseAndRecv() (*", outType, ", error)")
}
g.P(grpcPkg, ".ClientStream")
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPkg, ".ClientStream")
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", inType, ") error {")
g.P("return x.ClientStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", outType, ", error) {")
g.P("m := new(", outType, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
if genCloseAndRecv {
g.P("func (x *", streamType, ") CloseAndRecv() (*", outType, ", error) {")
g.P("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }")
g.P("m := new(", outType, ")")
g.P("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
}
// generateServerSignatureWithParamNames returns the server-side signature for a method with parameter names.
func (g *grpc) generateServerSignatureWithParamNames(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
var reqArgs []string
ret := "error"
if !method.GetServerStreaming() && !method.GetClientStreaming() {
reqArgs = append(reqArgs, "ctx "+contextPkg+".Context")
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
}
if !method.GetClientStreaming() {
reqArgs = append(reqArgs, "req *"+g.typeName(method.GetInputType()))
}
if method.GetServerStreaming() || method.GetClientStreaming() {
reqArgs = append(reqArgs, "srv "+servName+"_"+generator.CamelCase(origMethName)+"Server")
}
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
// generateServerSignature returns the server-side signature for a method.
func (g *grpc) generateServerSignature(servName string, method *pb.MethodDescriptorProto) string {
origMethName := method.GetName()
methName := generator.CamelCase(origMethName)
if reservedClientName[methName] {
methName += "_"
}
var reqArgs []string
ret := "error"
if !method.GetServerStreaming() && !method.GetClientStreaming() {
reqArgs = append(reqArgs, contextPkg+".Context")
ret = "(*" + g.typeName(method.GetOutputType()) + ", error)"
}
if !method.GetClientStreaming() {
reqArgs = append(reqArgs, "*"+g.typeName(method.GetInputType()))
}
if method.GetServerStreaming() || method.GetClientStreaming() {
reqArgs = append(reqArgs, servName+"_"+generator.CamelCase(origMethName)+"Server")
}
return methName + "(" + strings.Join(reqArgs, ", ") + ") " + ret
}
func (g *grpc) generateServerMethod(servName, fullServName string, method *pb.MethodDescriptorProto) string {
methName := generator.CamelCase(method.GetName())
hname := fmt.Sprintf("_%s_%s_Handler", servName, methName)
inType := g.typeName(method.GetInputType())
outType := g.typeName(method.GetOutputType())
if !method.GetServerStreaming() && !method.GetClientStreaming() {
g.P("func ", hname, "(srv interface{}, ctx ", contextPkg, ".Context, dec func(interface{}) error, interceptor ", grpcPkg, ".UnaryServerInterceptor) (interface{}, error) {")
g.P("in := new(", inType, ")")
g.P("if err := dec(in); err != nil { return nil, err }")
g.P("if interceptor == nil { return srv.(", servName, "Server).", methName, "(ctx, in) }")
g.P("info := &", grpcPkg, ".UnaryServerInfo{")
g.P("Server: srv,")
g.P("FullMethod: ", strconv.Quote(fmt.Sprintf("/%s/%s", fullServName, methName)), ",")
g.P("}")
g.P("handler := func(ctx ", contextPkg, ".Context, req interface{}) (interface{}, error) {")
g.P("return srv.(", servName, "Server).", methName, "(ctx, req.(*", inType, "))")
g.P("}")
g.P("return interceptor(ctx, in, info, handler)")
g.P("}")
g.P()
return hname
}
streamType := unexport(servName) + methName + "Server"
g.P("func ", hname, "(srv interface{}, stream ", grpcPkg, ".ServerStream) error {")
if !method.GetClientStreaming() {
g.P("m := new(", inType, ")")
g.P("if err := stream.RecvMsg(m); err != nil { return err }")
g.P("return srv.(", servName, "Server).", methName, "(m, &", streamType, "{stream})")
} else {
g.P("return srv.(", servName, "Server).", methName, "(&", streamType, "{stream})")
}
g.P("}")
g.P()
genSend := method.GetServerStreaming()
genSendAndClose := !method.GetServerStreaming()
genRecv := method.GetClientStreaming()
// Stream auxiliary types and methods.
g.P("type ", servName, "_", methName, "Server interface {")
if genSend {
g.P("Send(*", outType, ") error")
}
if genSendAndClose {
g.P("SendAndClose(*", outType, ") error")
}
if genRecv {
g.P("Recv() (*", inType, ", error)")
}
g.P(grpcPkg, ".ServerStream")
g.P("}")
g.P()
g.P("type ", streamType, " struct {")
g.P(grpcPkg, ".ServerStream")
g.P("}")
g.P()
if genSend {
g.P("func (x *", streamType, ") Send(m *", outType, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genSendAndClose {
g.P("func (x *", streamType, ") SendAndClose(m *", outType, ") error {")
g.P("return x.ServerStream.SendMsg(m)")
g.P("}")
g.P()
}
if genRecv {
g.P("func (x *", streamType, ") Recv() (*", inType, ", error) {")
g.P("m := new(", inType, ")")
g.P("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }")
g.P("return m, nil")
g.P("}")
g.P()
}
return hname
}

View File

@ -1,37 +0,0 @@
# Go support for Protocol Buffers - Google's data interchange format
#
# Copyright 2010 The Go Authors. All rights reserved.
# https://github.com/golang/protobuf
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Not stored here, but plugin.proto is in https://github.com/google/protobuf/
# at src/google/protobuf/compiler/plugin.proto
# Also we need to fix an import.
regenerate:
go install github.com/gogo/protobuf/protoc-gen-gogo
protoc --gogo_out=Mgoogle/protobuf/descriptor.proto=github.com/gogo/protobuf/protoc-gen-gogo/descriptor:. -I=../../protobuf/google/protobuf/compiler/:../../protobuf/ ../../protobuf/google/protobuf/compiler/plugin.proto

View File

@ -1,365 +0,0 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// source: plugin.proto
package plugin_go
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
// The version number of protocol compiler.
type Version struct {
Major *int32 `protobuf:"varint,1,opt,name=major" json:"major,omitempty"`
Minor *int32 `protobuf:"varint,2,opt,name=minor" json:"minor,omitempty"`
Patch *int32 `protobuf:"varint,3,opt,name=patch" json:"patch,omitempty"`
// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
// be empty for mainline stable releases.
Suffix *string `protobuf:"bytes,4,opt,name=suffix" json:"suffix,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{0}
}
func (m *Version) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Version.Unmarshal(m, b)
}
func (m *Version) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Version.Marshal(b, m, deterministic)
}
func (m *Version) XXX_Merge(src proto.Message) {
xxx_messageInfo_Version.Merge(m, src)
}
func (m *Version) XXX_Size() int {
return xxx_messageInfo_Version.Size(m)
}
func (m *Version) XXX_DiscardUnknown() {
xxx_messageInfo_Version.DiscardUnknown(m)
}
var xxx_messageInfo_Version proto.InternalMessageInfo
func (m *Version) GetMajor() int32 {
if m != nil && m.Major != nil {
return *m.Major
}
return 0
}
func (m *Version) GetMinor() int32 {
if m != nil && m.Minor != nil {
return *m.Minor
}
return 0
}
func (m *Version) GetPatch() int32 {
if m != nil && m.Patch != nil {
return *m.Patch
}
return 0
}
func (m *Version) GetSuffix() string {
if m != nil && m.Suffix != nil {
return *m.Suffix
}
return ""
}
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
type CodeGeneratorRequest struct {
// The .proto files that were explicitly listed on the command-line. The
// code generator should generate code only for these files. Each file's
// descriptor will be included in proto_file, below.
FileToGenerate []string `protobuf:"bytes,1,rep,name=file_to_generate,json=fileToGenerate" json:"file_to_generate,omitempty"`
// The generator parameter passed on the command-line.
Parameter *string `protobuf:"bytes,2,opt,name=parameter" json:"parameter,omitempty"`
// FileDescriptorProtos for all files in files_to_generate and everything
// they import. The files will appear in topological order, so each file
// appears before any file that imports it.
//
// protoc guarantees that all proto_files will be written after
// the fields above, even though this is not technically guaranteed by the
// protobuf wire format. This theoretically could allow a plugin to stream
// in the FileDescriptorProtos and handle them one by one rather than read
// the entire set into memory at once. However, as of this writing, this
// is not similarly optimized on protoc's end -- it will store all fields in
// memory at once before sending them to the plugin.
//
// Type names of fields and extensions in the FileDescriptorProto are always
// fully qualified.
ProtoFile []*descriptor.FileDescriptorProto `protobuf:"bytes,15,rep,name=proto_file,json=protoFile" json:"proto_file,omitempty"`
// The version number of protocol compiler.
CompilerVersion *Version `protobuf:"bytes,3,opt,name=compiler_version,json=compilerVersion" json:"compiler_version,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorRequest) Reset() { *m = CodeGeneratorRequest{} }
func (m *CodeGeneratorRequest) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorRequest) ProtoMessage() {}
func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{1}
}
func (m *CodeGeneratorRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorRequest.Unmarshal(m, b)
}
func (m *CodeGeneratorRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorRequest.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorRequest) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorRequest.Merge(m, src)
}
func (m *CodeGeneratorRequest) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorRequest.Size(m)
}
func (m *CodeGeneratorRequest) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorRequest.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorRequest proto.InternalMessageInfo
func (m *CodeGeneratorRequest) GetFileToGenerate() []string {
if m != nil {
return m.FileToGenerate
}
return nil
}
func (m *CodeGeneratorRequest) GetParameter() string {
if m != nil && m.Parameter != nil {
return *m.Parameter
}
return ""
}
func (m *CodeGeneratorRequest) GetProtoFile() []*descriptor.FileDescriptorProto {
if m != nil {
return m.ProtoFile
}
return nil
}
func (m *CodeGeneratorRequest) GetCompilerVersion() *Version {
if m != nil {
return m.CompilerVersion
}
return nil
}
// The plugin writes an encoded CodeGeneratorResponse to stdout.
type CodeGeneratorResponse struct {
// Error message. If non-empty, code generation failed. The plugin process
// should exit with status code zero even if it reports an error in this way.
//
// This should be used to indicate errors in .proto files which prevent the
// code generator from generating correct code. Errors which indicate a
// problem in protoc itself -- such as the input CodeGeneratorRequest being
// unparseable -- should be reported by writing a message to stderr and
// exiting with a non-zero status code.
Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"`
File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorResponse) Reset() { *m = CodeGeneratorResponse{} }
func (m *CodeGeneratorResponse) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorResponse) ProtoMessage() {}
func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{2}
}
func (m *CodeGeneratorResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorResponse.Unmarshal(m, b)
}
func (m *CodeGeneratorResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorResponse.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorResponse.Merge(m, src)
}
func (m *CodeGeneratorResponse) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorResponse.Size(m)
}
func (m *CodeGeneratorResponse) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorResponse.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorResponse proto.InternalMessageInfo
func (m *CodeGeneratorResponse) GetError() string {
if m != nil && m.Error != nil {
return *m.Error
}
return ""
}
func (m *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File {
if m != nil {
return m.File
}
return nil
}
// Represents a single generated file.
type CodeGeneratorResponse_File struct {
// The file name, relative to the output directory. The name must not
// contain "." or ".." components and must be relative, not be absolute (so,
// the file cannot lie outside the output directory). "/" must be used as
// the path separator, not "\".
//
// If the name is omitted, the content will be appended to the previous
// file. This allows the generator to break large files into small chunks,
// and allows the generated text to be streamed back to protoc so that large
// files need not reside completely in memory at one time. Note that as of
// this writing protoc does not optimize for this -- it will read the entire
// CodeGeneratorResponse before writing files to disk.
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
// If non-empty, indicates that the named file should already exist, and the
// content here is to be inserted into that file at a defined insertion
// point. This feature allows a code generator to extend the output
// produced by another code generator. The original generator may provide
// insertion points by placing special annotations in the file that look
// like:
// @@protoc_insertion_point(NAME)
// The annotation can have arbitrary text before and after it on the line,
// which allows it to be placed in a comment. NAME should be replaced with
// an identifier naming the point -- this is what other generators will use
// as the insertion_point. Code inserted at this point will be placed
// immediately above the line containing the insertion point (thus multiple
// insertions to the same point will come out in the order they were added).
// The double-@ is intended to make it unlikely that the generated code
// could contain things that look like insertion points by accident.
//
// For example, the C++ code generator places the following line in the
// .pb.h files that it generates:
// // @@protoc_insertion_point(namespace_scope)
// This line appears within the scope of the file's package namespace, but
// outside of any particular class. Another plugin can then specify the
// insertion_point "namespace_scope" to generate additional classes or
// other declarations that should be placed in this scope.
//
// Note that if the line containing the insertion point begins with
// whitespace, the same whitespace will be added to every line of the
// inserted text. This is useful for languages like Python, where
// indentation matters. In these languages, the insertion point comment
// should be indented the same amount as any inserted code will need to be
// in order to work correctly in that context.
//
// The code generator that generates the initial file and the one which
// inserts into it must both run as part of a single invocation of protoc.
// Code generators are executed in the order in which they appear on the
// command line.
//
// If |insertion_point| is present, |name| must also be present.
InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"`
// The file contents.
Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *CodeGeneratorResponse_File) Reset() { *m = CodeGeneratorResponse_File{} }
func (m *CodeGeneratorResponse_File) String() string { return proto.CompactTextString(m) }
func (*CodeGeneratorResponse_File) ProtoMessage() {}
func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) {
return fileDescriptor_22a625af4bc1cc87, []int{2, 0}
}
func (m *CodeGeneratorResponse_File) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_CodeGeneratorResponse_File.Unmarshal(m, b)
}
func (m *CodeGeneratorResponse_File) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_CodeGeneratorResponse_File.Marshal(b, m, deterministic)
}
func (m *CodeGeneratorResponse_File) XXX_Merge(src proto.Message) {
xxx_messageInfo_CodeGeneratorResponse_File.Merge(m, src)
}
func (m *CodeGeneratorResponse_File) XXX_Size() int {
return xxx_messageInfo_CodeGeneratorResponse_File.Size(m)
}
func (m *CodeGeneratorResponse_File) XXX_DiscardUnknown() {
xxx_messageInfo_CodeGeneratorResponse_File.DiscardUnknown(m)
}
var xxx_messageInfo_CodeGeneratorResponse_File proto.InternalMessageInfo
func (m *CodeGeneratorResponse_File) GetName() string {
if m != nil && m.Name != nil {
return *m.Name
}
return ""
}
func (m *CodeGeneratorResponse_File) GetInsertionPoint() string {
if m != nil && m.InsertionPoint != nil {
return *m.InsertionPoint
}
return ""
}
func (m *CodeGeneratorResponse_File) GetContent() string {
if m != nil && m.Content != nil {
return *m.Content
}
return ""
}
func init() {
proto.RegisterType((*Version)(nil), "google.protobuf.compiler.Version")
proto.RegisterType((*CodeGeneratorRequest)(nil), "google.protobuf.compiler.CodeGeneratorRequest")
proto.RegisterType((*CodeGeneratorResponse)(nil), "google.protobuf.compiler.CodeGeneratorResponse")
proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
}
func init() { proto.RegisterFile("plugin.proto", fileDescriptor_22a625af4bc1cc87) }
var fileDescriptor_22a625af4bc1cc87 = []byte{
// 383 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x92, 0xcd, 0x6a, 0xd5, 0x40,
0x14, 0xc7, 0x89, 0x37, 0xb5, 0xe4, 0xb4, 0x34, 0x65, 0xa8, 0x32, 0x94, 0x2e, 0xe2, 0x45, 0x30,
0xab, 0x14, 0x8a, 0xe0, 0xbe, 0x15, 0x75, 0xe1, 0xe2, 0x32, 0x88, 0x0b, 0x41, 0x42, 0x4c, 0x4f,
0xe2, 0x48, 0x32, 0x67, 0x9c, 0x99, 0x88, 0x4f, 0xea, 0x7b, 0xf8, 0x06, 0x32, 0x1f, 0xa9, 0x72,
0xf1, 0xee, 0xe6, 0xff, 0x3b, 0xf3, 0x71, 0xce, 0x8f, 0x81, 0x53, 0x3d, 0x2d, 0xa3, 0x54, 0x8d,
0x36, 0xe4, 0x88, 0xf1, 0x91, 0x68, 0x9c, 0x30, 0xa6, 0x2f, 0xcb, 0xd0, 0xf4, 0x34, 0x6b, 0x39,
0xa1, 0xb9, 0xac, 0x62, 0xe5, 0x7a, 0xad, 0x5c, 0xdf, 0xa3, 0xed, 0x8d, 0xd4, 0x8e, 0x4c, 0xdc,
0xbd, 0xed, 0xe1, 0xf8, 0x23, 0x1a, 0x2b, 0x49, 0xb1, 0x0b, 0x38, 0x9a, 0xbb, 0x6f, 0x64, 0x78,
0x56, 0x65, 0xf5, 0x91, 0x88, 0x21, 0x50, 0xa9, 0xc8, 0xf0, 0x47, 0x89, 0xfa, 0xe0, 0xa9, 0xee,
0x5c, 0xff, 0x95, 0x6f, 0x22, 0x0d, 0x81, 0x3d, 0x85, 0xc7, 0x76, 0x19, 0x06, 0xf9, 0x93, 0xe7,
0x55, 0x56, 0x17, 0x22, 0xa5, 0xed, 0xef, 0x0c, 0x2e, 0xee, 0xe8, 0x1e, 0xdf, 0xa2, 0x42, 0xd3,
0x39, 0x32, 0x02, 0xbf, 0x2f, 0x68, 0x1d, 0xab, 0xe1, 0x7c, 0x90, 0x13, 0xb6, 0x8e, 0xda, 0x31,
0xd6, 0x90, 0x67, 0xd5, 0xa6, 0x2e, 0xc4, 0x99, 0xe7, 0x1f, 0x28, 0x9d, 0x40, 0x76, 0x05, 0x85,
0xee, 0x4c, 0x37, 0xa3, 0xc3, 0xd8, 0x4a, 0x21, 0xfe, 0x02, 0x76, 0x07, 0x10, 0xc6, 0x69, 0xfd,
0x29, 0x5e, 0x56, 0x9b, 0xfa, 0xe4, 0xe6, 0x79, 0xb3, 0xaf, 0xe5, 0x8d, 0x9c, 0xf0, 0xf5, 0x83,
0x80, 0x9d, 0xc7, 0xa2, 0x08, 0x55, 0x5f, 0x61, 0xef, 0xe1, 0x7c, 0x15, 0xd7, 0xfe, 0x88, 0x4e,
0xc2, 0x78, 0x27, 0x37, 0xcf, 0x9a, 0x43, 0x86, 0x9b, 0x24, 0x4f, 0x94, 0x2b, 0x49, 0x60, 0xfb,
0x2b, 0x83, 0x27, 0x7b, 0x33, 0x5b, 0x4d, 0xca, 0xa2, 0x77, 0x87, 0xc6, 0x24, 0xcf, 0x85, 0x88,
0x81, 0xbd, 0x83, 0xfc, 0x9f, 0xe6, 0x5f, 0x1e, 0x7e, 0xf1, 0xbf, 0x97, 0x86, 0xd9, 0x44, 0xb8,
0xe1, 0xf2, 0x33, 0xe4, 0x61, 0x1e, 0x06, 0xb9, 0xea, 0x66, 0x4c, 0xcf, 0x84, 0x35, 0x7b, 0x01,
0xa5, 0x54, 0x16, 0x8d, 0x93, 0xa4, 0x5a, 0x4d, 0x52, 0xb9, 0x24, 0xf3, 0xec, 0x01, 0xef, 0x3c,
0x65, 0x1c, 0x8e, 0x7b, 0x52, 0x0e, 0x95, 0xe3, 0x65, 0xd8, 0xb0, 0xc6, 0xdb, 0x57, 0x70, 0xd5,
0xd3, 0x7c, 0xb0, 0xbf, 0xdb, 0xd3, 0x5d, 0xf8, 0x9b, 0x41, 0xaf, 0xfd, 0x54, 0xc4, 0x9f, 0xda,
0x8e, 0xf4, 0x27, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x72, 0x3d, 0x18, 0xb5, 0x02, 0x00, 0x00,
}

View File

@ -1,161 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package command
import (
"fmt"
"go/format"
"io/ioutil"
"os"
"strings"
_ "github.com/gogo/protobuf/plugin/compare"
_ "github.com/gogo/protobuf/plugin/defaultcheck"
_ "github.com/gogo/protobuf/plugin/description"
_ "github.com/gogo/protobuf/plugin/embedcheck"
_ "github.com/gogo/protobuf/plugin/enumstringer"
_ "github.com/gogo/protobuf/plugin/equal"
_ "github.com/gogo/protobuf/plugin/face"
_ "github.com/gogo/protobuf/plugin/gostring"
_ "github.com/gogo/protobuf/plugin/marshalto"
_ "github.com/gogo/protobuf/plugin/oneofcheck"
_ "github.com/gogo/protobuf/plugin/populate"
_ "github.com/gogo/protobuf/plugin/size"
_ "github.com/gogo/protobuf/plugin/stringer"
"github.com/gogo/protobuf/plugin/testgen"
_ "github.com/gogo/protobuf/plugin/union"
_ "github.com/gogo/protobuf/plugin/unmarshal"
"github.com/gogo/protobuf/proto"
"github.com/gogo/protobuf/protoc-gen-gogo/generator"
_ "github.com/gogo/protobuf/protoc-gen-gogo/grpc"
plugin "github.com/gogo/protobuf/protoc-gen-gogo/plugin"
)
func Read() *plugin.CodeGeneratorRequest {
g := generator.New()
data, err := ioutil.ReadAll(os.Stdin)
if err != nil {
g.Error(err, "reading input")
}
if err := proto.Unmarshal(data, g.Request); err != nil {
g.Error(err, "parsing input proto")
}
if len(g.Request.FileToGenerate) == 0 {
g.Fail("no files to generate")
}
return g.Request
}
// filenameSuffix replaces the .pb.go at the end of each filename.
func GeneratePlugin(req *plugin.CodeGeneratorRequest, p generator.Plugin, filenameSuffix string) *plugin.CodeGeneratorResponse {
g := generator.New()
g.Request = req
if len(g.Request.FileToGenerate) == 0 {
g.Fail("no files to generate")
}
g.CommandLineParameters(g.Request.GetParameter())
g.WrapTypes()
g.SetPackageNames()
g.BuildTypeNameMap()
g.GeneratePlugin(p)
for i := 0; i < len(g.Response.File); i++ {
g.Response.File[i].Name = proto.String(
strings.Replace(*g.Response.File[i].Name, ".pb.go", filenameSuffix, -1),
)
}
if err := goformat(g.Response); err != nil {
g.Error(err)
}
return g.Response
}
func goformat(resp *plugin.CodeGeneratorResponse) error {
for i := 0; i < len(resp.File); i++ {
formatted, err := format.Source([]byte(resp.File[i].GetContent()))
if err != nil {
return fmt.Errorf("go format error: %v", err)
}
fmts := string(formatted)
resp.File[i].Content = &fmts
}
return nil
}
func Generate(req *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse {
// Begin by allocating a generator. The request and response structures are stored there
// so we can do error handling easily - the response structure contains the field to
// report failure.
g := generator.New()
g.Request = req
g.CommandLineParameters(g.Request.GetParameter())
// Create a wrapped version of the Descriptors and EnumDescriptors that
// point to the file that defines them.
g.WrapTypes()
g.SetPackageNames()
g.BuildTypeNameMap()
g.GenerateAllFiles()
if err := goformat(g.Response); err != nil {
g.Error(err)
}
testReq := proto.Clone(req).(*plugin.CodeGeneratorRequest)
testResp := GeneratePlugin(testReq, testgen.NewPlugin(), "pb_test.go")
for i := 0; i < len(testResp.File); i++ {
if strings.Contains(*testResp.File[i].Content, `//These tests are generated by github.com/gogo/protobuf/plugin/testgen`) {
g.Response.File = append(g.Response.File, testResp.File[i])
}
}
return g.Response
}
func Write(resp *plugin.CodeGeneratorResponse) {
g := generator.New()
// Send back the results.
data, err := proto.Marshal(resp)
if err != nil {
g.Error(err, "failed to marshal output proto")
}
_, err = os.Stdout.Write(data)
if err != nil {
g.Error(err, "failed to write output proto")
}
}

View File

@ -1,78 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func EnumHasBoolExtension(enum *descriptor.EnumDescriptorProto, extension *proto.ExtensionDesc) bool {
if enum.Options == nil {
return false
}
value, err := proto.GetExtension(enum.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolEnumOption(extension *proto.ExtensionDesc, value bool) func(enum *descriptor.EnumDescriptorProto) {
return func(enum *descriptor.EnumDescriptorProto) {
if EnumHasBoolExtension(enum, extension) {
return
}
if enum.Options == nil {
enum.Options = &descriptor.EnumOptions{}
}
if err := proto.SetExtension(enum.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoEnumPrefix(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_GoprotoEnumPrefix, false)(enum)
}
func TurnOffGoEnumStringer(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_GoprotoEnumStringer, false)(enum)
}
func TurnOnEnumStringer(enum *descriptor.EnumDescriptorProto) {
SetBoolEnumOption(gogoproto.E_EnumStringer, true)(enum)
}

View File

@ -1,90 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func FieldHasBoolExtension(field *descriptor.FieldDescriptorProto, extension *proto.ExtensionDesc) bool {
if field.Options == nil {
return false
}
value, err := proto.GetExtension(field.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolFieldOption(extension *proto.ExtensionDesc, value bool) func(field *descriptor.FieldDescriptorProto) {
return func(field *descriptor.FieldDescriptorProto) {
if FieldHasBoolExtension(field, extension) {
return
}
if field.Options == nil {
field.Options = &descriptor.FieldOptions{}
}
if err := proto.SetExtension(field.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffNullable(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() && !field.IsMessage() {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}
func TurnOffNullableForNativeTypes(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() || field.IsMessage() {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}
func TurnOffNullableForNativeTypesWithoutDefaultsOnly(field *descriptor.FieldDescriptorProto) {
if field.IsRepeated() || field.IsMessage() {
return
}
if field.DefaultValue != nil {
return
}
SetBoolFieldOption(gogoproto.E_Nullable, false)(field)
}

View File

@ -1,197 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"path/filepath"
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func NotGoogleProtobufDescriptorProto(file *descriptor.FileDescriptorProto) bool {
// can not just check if file.GetName() == "google/protobuf/descriptor.proto" because we do not want to assume compile path
_, fileName := filepath.Split(file.GetName())
return !(file.GetPackage() == "google.protobuf" && fileName == "descriptor.proto")
}
func FilterFiles(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto) bool) []*descriptor.FileDescriptorProto {
filtered := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i := range files {
if !f(files[i]) {
continue
}
filtered = append(filtered, files[i])
}
return filtered
}
func FileHasBoolExtension(file *descriptor.FileDescriptorProto, extension *proto.ExtensionDesc) bool {
if file.Options == nil {
return false
}
value, err := proto.GetExtension(file.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolFileOption(extension *proto.ExtensionDesc, value bool) func(file *descriptor.FileDescriptorProto) {
return func(file *descriptor.FileDescriptorProto) {
if FileHasBoolExtension(file, extension) {
return
}
if file.Options == nil {
file.Options = &descriptor.FileOptions{}
}
if err := proto.SetExtension(file.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoGettersAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoGettersAll, false)(file)
}
func TurnOffGoEnumPrefixAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoEnumPrefixAll, false)(file)
}
func TurnOffGoStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoStringerAll, false)(file)
}
func TurnOnVerboseEqualAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_VerboseEqualAll, true)(file)
}
func TurnOnFaceAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_FaceAll, true)(file)
}
func TurnOnGoStringAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GostringAll, true)(file)
}
func TurnOnPopulateAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_PopulateAll, true)(file)
}
func TurnOnStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_StringerAll, true)(file)
}
func TurnOnEqualAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_EqualAll, true)(file)
}
func TurnOnDescriptionAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_DescriptionAll, true)(file)
}
func TurnOnTestGenAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_TestgenAll, true)(file)
}
func TurnOnBenchGenAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_BenchgenAll, true)(file)
}
func TurnOnMarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_MarshalerAll, true)(file)
}
func TurnOnUnmarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnmarshalerAll, true)(file)
}
func TurnOnStable_MarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_StableMarshalerAll, true)(file)
}
func TurnOnSizerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_SizerAll, true)(file)
}
func TurnOffGoEnumStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoEnumStringerAll, false)(file)
}
func TurnOnEnumStringerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_EnumStringerAll, true)(file)
}
func TurnOnUnsafeUnmarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnsafeUnmarshalerAll, true)(file)
}
func TurnOnUnsafeMarshalerAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_UnsafeMarshalerAll, true)(file)
}
func TurnOffGoExtensionsMapAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoExtensionsMapAll, false)(file)
}
func TurnOffGoUnrecognizedAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoUnrecognizedAll, false)(file)
}
func TurnOffGoUnkeyedAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoUnkeyedAll, false)(file)
}
func TurnOffGoSizecacheAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoSizecacheAll, false)(file)
}
func TurnOffGogoImport(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GogoprotoImport, false)(file)
}
func TurnOnCompareAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_CompareAll, true)(file)
}
func TurnOnMessageNameAll(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_MessagenameAll, true)(file)
}
func TurnOnGoRegistration(file *descriptor.FileDescriptorProto) {
SetBoolFileOption(gogoproto.E_GoprotoRegistration, true)(file)
}

View File

@ -1,125 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. All rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
func ForEachFile(files []*descriptor.FileDescriptorProto, f func(file *descriptor.FileDescriptorProto)) {
for _, file := range files {
f(file)
}
}
func OnlyProto2(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i, file := range files {
if file.GetSyntax() == "proto3" {
continue
}
outs = append(outs, files[i])
}
return outs
}
func OnlyProto3(files []*descriptor.FileDescriptorProto) []*descriptor.FileDescriptorProto {
outs := make([]*descriptor.FileDescriptorProto, 0, len(files))
for i, file := range files {
if file.GetSyntax() != "proto3" {
continue
}
outs = append(outs, files[i])
}
return outs
}
func ForEachMessageInFiles(files []*descriptor.FileDescriptorProto, f func(msg *descriptor.DescriptorProto)) {
for _, file := range files {
ForEachMessage(file.MessageType, f)
}
}
func ForEachMessage(msgs []*descriptor.DescriptorProto, f func(msg *descriptor.DescriptorProto)) {
for _, msg := range msgs {
f(msg)
ForEachMessage(msg.NestedType, f)
}
}
func ForEachFieldInFilesExcludingExtensions(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, file := range files {
ForEachFieldExcludingExtensions(file.MessageType, f)
}
}
func ForEachFieldInFiles(files []*descriptor.FileDescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, file := range files {
for _, ext := range file.Extension {
f(ext)
}
ForEachField(file.MessageType, f)
}
}
func ForEachFieldExcludingExtensions(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.Field {
f(field)
}
ForEachField(msg.NestedType, f)
}
}
func ForEachField(msgs []*descriptor.DescriptorProto, f func(field *descriptor.FieldDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.Field {
f(field)
}
for _, ext := range msg.Extension {
f(ext)
}
ForEachField(msg.NestedType, f)
}
}
func ForEachEnumInFiles(files []*descriptor.FileDescriptorProto, f func(enum *descriptor.EnumDescriptorProto)) {
for _, file := range files {
for _, enum := range file.EnumType {
f(enum)
}
}
}
func ForEachEnum(msgs []*descriptor.DescriptorProto, f func(field *descriptor.EnumDescriptorProto)) {
for _, msg := range msgs {
for _, field := range msg.EnumType {
f(field)
}
ForEachEnum(msg.NestedType, f)
}
}

View File

@ -1,154 +0,0 @@
// Protocol Buffers for Go with Gadgets
//
// Copyright (c) 2015, The GoGo Authors. rights reserved.
// http://github.com/gogo/protobuf
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package vanity
import (
"github.com/gogo/protobuf/gogoproto"
"github.com/gogo/protobuf/proto"
descriptor "github.com/gogo/protobuf/protoc-gen-gogo/descriptor"
)
func MessageHasBoolExtension(msg *descriptor.DescriptorProto, extension *proto.ExtensionDesc) bool {
if msg.Options == nil {
return false
}
value, err := proto.GetExtension(msg.Options, extension)
if err != nil {
return false
}
if value == nil {
return false
}
if value.(*bool) == nil {
return false
}
return true
}
func SetBoolMessageOption(extension *proto.ExtensionDesc, value bool) func(msg *descriptor.DescriptorProto) {
return func(msg *descriptor.DescriptorProto) {
if MessageHasBoolExtension(msg, extension) {
return
}
if msg.Options == nil {
msg.Options = &descriptor.MessageOptions{}
}
if err := proto.SetExtension(msg.Options, extension, &value); err != nil {
panic(err)
}
}
}
func TurnOffGoGetters(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoGetters, false)(msg)
}
func TurnOffGoStringer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoStringer, false)(msg)
}
func TurnOnVerboseEqual(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_VerboseEqual, true)(msg)
}
func TurnOnFace(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Face, true)(msg)
}
func TurnOnGoString(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Face, true)(msg)
}
func TurnOnPopulate(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Populate, true)(msg)
}
func TurnOnStringer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Stringer, true)(msg)
}
func TurnOnEqual(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Equal, true)(msg)
}
func TurnOnDescription(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Description, true)(msg)
}
func TurnOnTestGen(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Testgen, true)(msg)
}
func TurnOnBenchGen(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Benchgen, true)(msg)
}
func TurnOnMarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Marshaler, true)(msg)
}
func TurnOnUnmarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Unmarshaler, true)(msg)
}
func TurnOnSizer(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Sizer, true)(msg)
}
func TurnOnUnsafeUnmarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_UnsafeUnmarshaler, true)(msg)
}
func TurnOnUnsafeMarshaler(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_UnsafeMarshaler, true)(msg)
}
func TurnOffGoExtensionsMap(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoExtensionsMap, false)(msg)
}
func TurnOffGoUnrecognized(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoUnrecognized, false)(msg)
}
func TurnOffGoUnkeyed(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoUnkeyed, false)(msg)
}
func TurnOffGoSizecache(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_GoprotoSizecache, false)(msg)
}
func TurnOnCompare(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Compare, true)(msg)
}
func TurnOnMessageName(msg *descriptor.DescriptorProto) {
SetBoolMessageOption(gogoproto.E_Messagename, true)(msg)
}

View File

@ -0,0 +1,62 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: github.com/golang/protobuf/ptypes/empty/empty.proto
package empty
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
emptypb "google.golang.org/protobuf/types/known/emptypb"
reflect "reflect"
)
// Symbols defined in public import of google/protobuf/empty.proto.
type Empty = emptypb.Empty
var File_github_com_golang_protobuf_ptypes_empty_empty_proto protoreflect.FileDescriptor
var file_github_com_golang_protobuf_ptypes_empty_empty_proto_rawDesc = []byte{
0x0a, 0x33, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c,
0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x70, 0x74, 0x79,
0x70, 0x65, 0x73, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2f, 0x70, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x3b, 0x65, 0x6d,
0x70, 0x74, 0x79, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var file_github_com_golang_protobuf_ptypes_empty_empty_proto_goTypes = []interface{}{}
var file_github_com_golang_protobuf_ptypes_empty_empty_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_github_com_golang_protobuf_ptypes_empty_empty_proto_init() }
func file_github_com_golang_protobuf_ptypes_empty_empty_proto_init() {
if File_github_com_golang_protobuf_ptypes_empty_empty_proto != nil {
return
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_github_com_golang_protobuf_ptypes_empty_empty_proto_rawDesc,
NumEnums: 0,
NumMessages: 0,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_github_com_golang_protobuf_ptypes_empty_empty_proto_goTypes,
DependencyIndexes: file_github_com_golang_protobuf_ptypes_empty_empty_proto_depIdxs,
}.Build()
File_github_com_golang_protobuf_ptypes_empty_empty_proto = out.File
file_github_com_golang_protobuf_ptypes_empty_empty_proto_rawDesc = nil
file_github_com_golang_protobuf_ptypes_empty_empty_proto_goTypes = nil
file_github_com_golang_protobuf_ptypes_empty_empty_proto_depIdxs = nil
}

View File

@ -1,13 +1,13 @@
// Code generated by protoc-gen-gogo. DO NOT EDIT.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/rpc/code.proto
package rpc
package code
import (
fmt "fmt"
proto "github.com/gogo/protobuf/proto"
math "math"
strconv "strconv"
proto "github.com/golang/protobuf/proto"
)
// Reference imports to suppress errors if they are not otherwise used.
@ -19,7 +19,7 @@ var _ = math.Inf
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
// The canonical error codes for gRPC APIs.
//
@ -34,11 +34,11 @@ const (
// Not an error; returned on success
//
// HTTP Mapping: 200 OK
OK Code = 0
Code_OK Code = 0
// The operation was cancelled, typically by the caller.
//
// HTTP Mapping: 499 Client Closed Request
CANCELLED Code = 1
Code_CANCELLED Code = 1
// Unknown error. For example, this error may be returned when
// a `Status` value received from another address space belongs to
// an error space that is not known in this address space. Also
@ -46,14 +46,14 @@ const (
// may be converted to this error.
//
// HTTP Mapping: 500 Internal Server Error
UNKNOWN Code = 2
Code_UNKNOWN Code = 2
// The client specified an invalid argument. Note that this differs
// from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
// that are problematic regardless of the state of the system
// (e.g., a malformed file name).
//
// HTTP Mapping: 400 Bad Request
INVALID_ARGUMENT Code = 3
Code_INVALID_ARGUMENT Code = 3
// The deadline expired before the operation could complete. For operations
// that change the state of the system, this error may be returned
// even if the operation has completed successfully. For example, a
@ -61,7 +61,7 @@ const (
// enough for the deadline to expire.
//
// HTTP Mapping: 504 Gateway Timeout
DEADLINE_EXCEEDED Code = 4
Code_DEADLINE_EXCEEDED Code = 4
// Some requested entity (e.g., file or directory) was not found.
//
// Note to server developers: if a request is denied for an entire class
@ -71,12 +71,12 @@ const (
// must be used.
//
// HTTP Mapping: 404 Not Found
NOT_FOUND Code = 5
Code_NOT_FOUND Code = 5
// The entity that a client attempted to create (e.g., file or directory)
// already exists.
//
// HTTP Mapping: 409 Conflict
ALREADY_EXISTS Code = 6
Code_ALREADY_EXISTS Code = 6
// The caller does not have permission to execute the specified
// operation. `PERMISSION_DENIED` must not be used for rejections
// caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
@ -87,17 +87,17 @@ const (
// other pre-conditions.
//
// HTTP Mapping: 403 Forbidden
PERMISSION_DENIED Code = 7
Code_PERMISSION_DENIED Code = 7
// The request does not have valid authentication credentials for the
// operation.
//
// HTTP Mapping: 401 Unauthorized
UNAUTHENTICATED Code = 16
Code_UNAUTHENTICATED Code = 16
// Some resource has been exhausted, perhaps a per-user quota, or
// perhaps the entire file system is out of space.
//
// HTTP Mapping: 429 Too Many Requests
RESOURCE_EXHAUSTED Code = 8
Code_RESOURCE_EXHAUSTED Code = 8
// The operation was rejected because the system is not in a state
// required for the operation's execution. For example, the directory
// to be deleted is non-empty, an rmdir operation is applied to
@ -116,7 +116,7 @@ const (
// the files are deleted from the directory.
//
// HTTP Mapping: 400 Bad Request
FAILED_PRECONDITION Code = 9
Code_FAILED_PRECONDITION Code = 9
// The operation was aborted, typically due to a concurrency issue such as
// a sequencer check failure or transaction abort.
//
@ -124,7 +124,7 @@ const (
// `ABORTED`, and `UNAVAILABLE`.
//
// HTTP Mapping: 409 Conflict
ABORTED Code = 10
Code_ABORTED Code = 10
// The operation was attempted past the valid range. E.g., seeking or
// reading past end-of-file.
//
@ -142,18 +142,18 @@ const (
// they are done.
//
// HTTP Mapping: 400 Bad Request
OUT_OF_RANGE Code = 11
Code_OUT_OF_RANGE Code = 11
// The operation is not implemented or is not supported/enabled in this
// service.
//
// HTTP Mapping: 501 Not Implemented
UNIMPLEMENTED Code = 12
Code_UNIMPLEMENTED Code = 12
// Internal errors. This means that some invariants expected by the
// underlying system have been broken. This error code is reserved
// for serious errors.
//
// HTTP Mapping: 500 Internal Server Error
INTERNAL Code = 13
Code_INTERNAL Code = 13
// The service is currently unavailable. This is most likely a
// transient condition, which can be corrected by retrying with
// a backoff. Note that it is not always safe to retry
@ -163,11 +163,11 @@ const (
// `ABORTED`, and `UNAVAILABLE`.
//
// HTTP Mapping: 503 Service Unavailable
UNAVAILABLE Code = 14
Code_UNAVAILABLE Code = 14
// Unrecoverable data loss or corruption.
//
// HTTP Mapping: 500 Internal Server Error
DATA_LOSS Code = 15
Code_DATA_LOSS Code = 15
)
var Code_name = map[int32]string{
@ -210,6 +210,10 @@ var Code_value = map[string]int32{
"DATA_LOSS": 15,
}
func (x Code) String() string {
return proto.EnumName(Code_name, int32(x))
}
func (Code) EnumDescriptor() ([]byte, []int) {
return fileDescriptor_fe593a732623ccf0, []int{0}
}
@ -221,38 +225,28 @@ func init() {
func init() { proto.RegisterFile("google/rpc/code.proto", fileDescriptor_fe593a732623ccf0) }
var fileDescriptor_fe593a732623ccf0 = []byte{
// 393 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x91, 0x3d, 0x6e, 0x13, 0x41,
0x14, 0xc7, 0x3d, 0x76, 0x70, 0xe2, 0xf1, 0xd7, 0xcb, 0x84, 0x40, 0x37, 0x07, 0xa0, 0x70, 0x0a,
0x4e, 0xf0, 0xbc, 0xf3, 0x9c, 0x8c, 0x32, 0x7e, 0xb3, 0x9a, 0x9d, 0x09, 0x01, 0x21, 0xad, 0xc4,
0xc6, 0x4a, 0x03, 0x5a, 0xcb, 0xe2, 0x00, 0x9c, 0x85, 0x8a, 0x1b, 0x70, 0x85, 0x94, 0x29, 0x29,
0xf1, 0xa6, 0xa1, 0x74, 0x49, 0x89, 0x06, 0x0a, 0xda, 0x9f, 0xde, 0xc7, 0xff, 0x43, 0x9e, 0xdf,
0xb7, 0xed, 0xfd, 0xc7, 0xcd, 0xc5, 0x6e, 0xdb, 0x5c, 0x34, 0xed, 0xdd, 0x66, 0xb1, 0xdd, 0xb5,
0x9f, 0x5b, 0x25, 0xff, 0xe1, 0xc5, 0x6e, 0xdb, 0xbc, 0xfa, 0xde, 0x97, 0x47, 0x45, 0x7b, 0xb7,
0x51, 0x43, 0xd9, 0xf7, 0xd7, 0xd0, 0x53, 0x53, 0x39, 0x2a, 0x90, 0x0b, 0x72, 0x8e, 0x0c, 0x08,
0x35, 0x96, 0xc7, 0x89, 0xaf, 0xd9, 0xbf, 0x61, 0xe8, 0xab, 0xe7, 0x12, 0x2c, 0xdf, 0xa0, 0xb3,
0xa6, 0xc6, 0x70, 0x99, 0xd6, 0xc4, 0x11, 0x06, 0xea, 0x5c, 0x9e, 0x1a, 0x42, 0xe3, 0x2c, 0x53,
0x4d, 0xb7, 0x05, 0x91, 0x21, 0x03, 0x47, 0xf9, 0x10, 0xfb, 0x58, 0xaf, 0x7c, 0x62, 0x03, 0xcf,
0x94, 0x92, 0x33, 0x74, 0x81, 0xd0, 0xbc, 0xad, 0xe9, 0xd6, 0x56, 0xb1, 0x82, 0x61, 0xde, 0x2c,
0x29, 0xac, 0x6d, 0x55, 0x59, 0xcf, 0xb5, 0x21, 0xb6, 0x64, 0xe0, 0x58, 0x9d, 0xc9, 0x79, 0x62,
0x4c, 0xf1, 0x8a, 0x38, 0xda, 0x02, 0x23, 0x19, 0x00, 0xf5, 0x42, 0xaa, 0x40, 0x95, 0x4f, 0xa1,
0xc8, 0x5f, 0xae, 0x30, 0x55, 0x99, 0x9f, 0xa8, 0x97, 0xf2, 0x6c, 0x85, 0xd6, 0x91, 0xa9, 0xcb,
0x40, 0x85, 0x67, 0x63, 0xa3, 0xf5, 0x0c, 0xa3, 0xac, 0x1c, 0x97, 0x3e, 0xe4, 0x29, 0xa9, 0x40,
0x4e, 0x7c, 0x8a, 0xb5, 0x5f, 0xd5, 0x01, 0xf9, 0x92, 0x60, 0xac, 0x4e, 0xe5, 0x34, 0xb1, 0x5d,
0x97, 0x8e, 0xb2, 0x0d, 0x32, 0x30, 0x51, 0x13, 0x79, 0x62, 0x39, 0x52, 0x60, 0x74, 0x30, 0x55,
0x73, 0x39, 0x4e, 0x8c, 0x37, 0x68, 0x1d, 0x2e, 0x1d, 0xc1, 0x2c, 0x1b, 0x32, 0x18, 0xb1, 0x76,
0xbe, 0xaa, 0x60, 0xbe, 0x7c, 0xff, 0xb8, 0xd7, 0xbd, 0x1f, 0x7b, 0xdd, 0x3b, 0xec, 0xb5, 0xf8,
0xbd, 0xd7, 0xe2, 0x4b, 0xa7, 0xc5, 0xb7, 0x4e, 0x8b, 0x87, 0x4e, 0x8b, 0xc7, 0x4e, 0x8b, 0x9f,
0x9d, 0x16, 0xbf, 0x3a, 0xdd, 0x3b, 0x64, 0xfe, 0xa4, 0xc5, 0xc3, 0x93, 0x16, 0x72, 0xd6, 0xb4,
0x9f, 0x16, 0xff, 0xf3, 0x5f, 0x8e, 0x72, 0xf8, 0x65, 0xae, 0xa5, 0x14, 0xef, 0x06, 0xbb, 0x6d,
0xf3, 0xb5, 0x3f, 0x08, 0x65, 0xf1, 0x61, 0xf8, 0xb7, 0xaa, 0xd7, 0x7f, 0x02, 0x00, 0x00, 0xff,
0xff, 0x03, 0xd4, 0x27, 0xff, 0xc3, 0x01, 0x00, 0x00,
}
func (x Code) String() string {
s, ok := Code_name[int32(x)]
if ok {
return s
}
return strconv.Itoa(int(x))
// 362 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x44, 0x51, 0xcd, 0x6e, 0x93, 0x31,
0x10, 0xa4, 0x69, 0x49, 0x9b, 0xcd, 0xdf, 0xd6, 0xa5, 0xf0, 0x0e, 0x1c, 0x92, 0x43, 0x8f, 0x9c,
0x36, 0x9f, 0x37, 0xad, 0x55, 0x67, 0xfd, 0xc9, 0x3f, 0x25, 0x70, 0xb1, 0x4a, 0x1a, 0x7d, 0x42,
0x2a, 0x75, 0xf4, 0xc1, 0x13, 0xf1, 0x12, 0xbc, 0x1e, 0x72, 0x8b, 0xe8, 0xc5, 0x87, 0x99, 0xf1,
0xee, 0xce, 0x0c, 0x5c, 0x76, 0xa5, 0x74, 0x8f, 0xfb, 0x65, 0x7f, 0xd8, 0x2d, 0x77, 0xe5, 0x61,
0xbf, 0x38, 0xf4, 0xe5, 0x57, 0x51, 0xf0, 0x02, 0x2f, 0xfa, 0xc3, 0xee, 0xe3, 0x9f, 0x01, 0x9c,
0x34, 0xe5, 0x61, 0xaf, 0x86, 0x30, 0x70, 0xb7, 0xf8, 0x46, 0x4d, 0x61, 0xd4, 0x90, 0x34, 0x6c,
0x2d, 0x6b, 0x3c, 0x52, 0x63, 0x38, 0x4d, 0x72, 0x2b, 0xee, 0xb3, 0xe0, 0x40, 0xbd, 0x03, 0x34,
0x72, 0x47, 0xd6, 0xe8, 0x4c, 0xfe, 0x3a, 0x6d, 0x58, 0x22, 0x1e, 0xab, 0x4b, 0x38, 0xd7, 0x4c,
0xda, 0x1a, 0xe1, 0xcc, 0xdb, 0x86, 0x59, 0xb3, 0xc6, 0x93, 0x3a, 0x48, 0x5c, 0xcc, 0x6b, 0x97,
0x44, 0xe3, 0x5b, 0xa5, 0x60, 0x46, 0xd6, 0x33, 0xe9, 0x2f, 0x99, 0xb7, 0x26, 0xc4, 0x80, 0xc3,
0xfa, 0xb3, 0x65, 0xbf, 0x31, 0x21, 0x18, 0x27, 0x59, 0xb3, 0x18, 0xd6, 0x78, 0xaa, 0x2e, 0x60,
0x9e, 0x84, 0x52, 0xbc, 0x61, 0x89, 0xa6, 0xa1, 0xc8, 0x1a, 0x51, 0xbd, 0x07, 0xe5, 0x39, 0xb8,
0xe4, 0x9b, 0xba, 0xe5, 0x86, 0x52, 0xa8, 0xf8, 0x99, 0xfa, 0x00, 0x17, 0x6b, 0x32, 0x96, 0x75,
0x6e, 0x3d, 0x37, 0x4e, 0xb4, 0x89, 0xc6, 0x09, 0x8e, 0xea, 0xe5, 0xb4, 0x72, 0xbe, 0xaa, 0x40,
0x21, 0x4c, 0x5c, 0x8a, 0xd9, 0xad, 0xb3, 0x27, 0xb9, 0x66, 0x1c, 0xab, 0x73, 0x98, 0x26, 0x31,
0x9b, 0xd6, 0x72, 0xb5, 0xc1, 0x1a, 0x27, 0x6a, 0x02, 0x67, 0x46, 0x22, 0x7b, 0x21, 0x8b, 0x53,
0x35, 0x87, 0x71, 0x12, 0xba, 0x23, 0x63, 0x69, 0x65, 0x19, 0x67, 0xd5, 0x90, 0xa6, 0x48, 0xd9,
0xba, 0x10, 0x70, 0xbe, 0xda, 0xc2, 0x6c, 0x57, 0x7e, 0x2c, 0x5e, 0xb3, 0x5c, 0x8d, 0x6a, 0x90,
0x6d, 0x8d, 0xb8, 0x3d, 0xfa, 0x7a, 0xf5, 0x8f, 0xe8, 0xca, 0xe3, 0xfd, 0x53, 0xb7, 0x28, 0x7d,
0xb7, 0xec, 0xf6, 0x4f, 0xcf, 0x05, 0x2c, 0x5f, 0xa8, 0xfb, 0xc3, 0xf7, 0x9f, 0xff, 0xab, 0xf9,
0x54, 0x9f, 0xdf, 0x83, 0x63, 0xdf, 0x36, 0xdf, 0x86, 0xcf, 0xaa, 0xab, 0xbf, 0x01, 0x00, 0x00,
0xff, 0xff, 0x8e, 0x97, 0x77, 0xc2, 0xbf, 0x01, 0x00, 0x00,
}

View File

@ -0,0 +1,168 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: google/protobuf/empty.proto
package emptypb
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
// A generic empty message that you can re-use to avoid defining duplicated
// empty messages in your APIs. A typical example is to use it as the request
// or the response type of an API method. For instance:
//
// service Foo {
// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
// }
//
// The JSON representation for `Empty` is empty JSON object `{}`.
type Empty struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
mi := &file_google_protobuf_empty_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Empty) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_google_protobuf_empty_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
return file_google_protobuf_empty_proto_rawDescGZIP(), []int{0}
}
var File_google_protobuf_empty_proto protoreflect.FileDescriptor
var file_google_protobuf_empty_proto_rawDesc = []byte{
0x0a, 0x1b, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x07,
0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x7d, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x0a,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2e, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x6b,
0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2,
0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1e, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77,
0x6e, 0x54, 0x79, 0x70, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_google_protobuf_empty_proto_rawDescOnce sync.Once
file_google_protobuf_empty_proto_rawDescData = file_google_protobuf_empty_proto_rawDesc
)
func file_google_protobuf_empty_proto_rawDescGZIP() []byte {
file_google_protobuf_empty_proto_rawDescOnce.Do(func() {
file_google_protobuf_empty_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_empty_proto_rawDescData)
})
return file_google_protobuf_empty_proto_rawDescData
}
var file_google_protobuf_empty_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_google_protobuf_empty_proto_goTypes = []interface{}{
(*Empty)(nil), // 0: google.protobuf.Empty
}
var file_google_protobuf_empty_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_google_protobuf_empty_proto_init() }
func file_google_protobuf_empty_proto_init() {
if File_google_protobuf_empty_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_google_protobuf_empty_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_google_protobuf_empty_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_google_protobuf_empty_proto_goTypes,
DependencyIndexes: file_google_protobuf_empty_proto_depIdxs,
MessageInfos: file_google_protobuf_empty_proto_msgTypes,
}.Build()
File_google_protobuf_empty_proto = out.File
file_google_protobuf_empty_proto_rawDesc = nil
file_google_protobuf_empty_proto_goTypes = nil
file_google_protobuf_empty_proto_depIdxs = nil
}

33
vendor/modules.txt vendored
View File

@ -115,11 +115,10 @@ github.com/containerd/imgcrypt/images/encryption
## explicit; go 1.14
github.com/containerd/nri
github.com/containerd/nri/types/v1
# github.com/containerd/ttrpc v1.1.0
# github.com/containerd/ttrpc v1.1.1-0.20220420014843-944ef4a40df3
## explicit; go 1.13
github.com/containerd/ttrpc
github.com/containerd/ttrpc/plugin
# github.com/containerd/typeurl v1.0.3-0.20220324183432-6193a0e03259
# github.com/containerd/typeurl v1.0.3-0.20220422153119-7f6e6d160d67
## explicit; go 1.13
github.com/containerd/typeurl
# github.com/containerd/zfs v1.0.0
@ -197,38 +196,13 @@ github.com/go-logr/stdr
# github.com/godbus/dbus/v5 v5.0.6
## explicit; go 1.12
github.com/godbus/dbus/v5
# github.com/gogo/googleapis v1.4.1
## explicit; go 1.12
github.com/gogo/googleapis/google/rpc
# github.com/gogo/protobuf v1.3.2
## explicit; go 1.15
github.com/gogo/protobuf/gogoproto
github.com/gogo/protobuf/plugin/compare
github.com/gogo/protobuf/plugin/defaultcheck
github.com/gogo/protobuf/plugin/description
github.com/gogo/protobuf/plugin/embedcheck
github.com/gogo/protobuf/plugin/enumstringer
github.com/gogo/protobuf/plugin/equal
github.com/gogo/protobuf/plugin/face
github.com/gogo/protobuf/plugin/gostring
github.com/gogo/protobuf/plugin/marshalto
github.com/gogo/protobuf/plugin/oneofcheck
github.com/gogo/protobuf/plugin/populate
github.com/gogo/protobuf/plugin/size
github.com/gogo/protobuf/plugin/stringer
github.com/gogo/protobuf/plugin/testgen
github.com/gogo/protobuf/plugin/union
github.com/gogo/protobuf/plugin/unmarshal
github.com/gogo/protobuf/proto
github.com/gogo/protobuf/protoc-gen-gogo/descriptor
github.com/gogo/protobuf/protoc-gen-gogo/generator
github.com/gogo/protobuf/protoc-gen-gogo/generator/internal/remap
github.com/gogo/protobuf/protoc-gen-gogo/grpc
github.com/gogo/protobuf/protoc-gen-gogo/plugin
github.com/gogo/protobuf/sortkeys
github.com/gogo/protobuf/types
github.com/gogo/protobuf/vanity
github.com/gogo/protobuf/vanity/command
# github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
## explicit
github.com/golang/groupcache/lru
@ -241,6 +215,7 @@ github.com/golang/protobuf/protoc-gen-go/descriptor
github.com/golang/protobuf/ptypes
github.com/golang/protobuf/ptypes/any
github.com/golang/protobuf/ptypes/duration
github.com/golang/protobuf/ptypes/empty
github.com/golang/protobuf/ptypes/timestamp
github.com/golang/protobuf/ptypes/wrappers
# github.com/google/go-cmp v0.5.6
@ -548,6 +523,7 @@ google.golang.org/appengine/urlfetch
# google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa => google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63
## explicit; go 1.11
google.golang.org/genproto/googleapis/api/httpbody
google.golang.org/genproto/googleapis/rpc/code
google.golang.org/genproto/googleapis/rpc/errdetails
google.golang.org/genproto/googleapis/rpc/status
google.golang.org/genproto/protobuf/field_mask
@ -635,6 +611,7 @@ google.golang.org/protobuf/runtime/protoimpl
google.golang.org/protobuf/types/descriptorpb
google.golang.org/protobuf/types/known/anypb
google.golang.org/protobuf/types/known/durationpb
google.golang.org/protobuf/types/known/emptypb
google.golang.org/protobuf/types/known/timestamppb
google.golang.org/protobuf/types/known/wrapperspb
google.golang.org/protobuf/types/pluginpb