Repository: twitchtv/twirp Branch: main Commit: fb7430a3be6b Files: 528 Total size: 4.0 MB Directory structure: gitextract_m5s28tuc/ ├── .github/ │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows/ │ ├── commit-checks.yml │ └── stale.yaml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Gopkg.toml ├── LICENSE ├── Makefile ├── NOTICE ├── PROTOCOL.md ├── README.md ├── THIRD_PARTY ├── _tools/ │ ├── .gitignore │ └── src/ │ ├── github.com/ │ │ ├── kisielk/ │ │ │ ├── errcheck/ │ │ │ │ ├── LICENSE │ │ │ │ ├── README.md │ │ │ │ ├── internal/ │ │ │ │ │ └── errcheck/ │ │ │ │ │ └── errcheck.go │ │ │ │ └── main.go │ │ │ └── gotool/ │ │ │ ├── LEGAL │ │ │ ├── LICENSE │ │ │ ├── README.md │ │ │ ├── go13.go │ │ │ ├── go14-15.go │ │ │ ├── go16-18.go │ │ │ ├── internal/ │ │ │ │ └── load/ │ │ │ │ ├── path.go │ │ │ │ ├── pkg.go │ │ │ │ └── search.go │ │ │ ├── match.go │ │ │ ├── match18.go │ │ │ └── tool.go │ │ └── twitchtv/ │ │ └── retool/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── add.go │ │ ├── build.go │ │ ├── clean.go │ │ ├── do.go │ │ ├── input.go │ │ ├── main.go │ │ ├── manifest.go │ │ ├── print.go │ │ ├── remove.go │ │ ├── spec.go │ │ ├── sync.go │ │ ├── tool.go │ │ ├── tooldir.go │ │ ├── upgrade.go │ │ └── vendor/ │ │ └── github.com/ │ │ ├── Masterminds/ │ │ │ └── semver/ │ │ │ ├── LICENSE.txt │ │ │ ├── README.md │ │ │ ├── collection.go │ │ │ ├── constraints.go │ │ │ ├── doc.go │ │ │ └── version.go │ │ └── pkg/ │ │ └── errors/ │ │ ├── LICENSE │ │ ├── README.md │ │ ├── errors.go │ │ └── stack.go │ ├── golang.org/ │ │ └── x/ │ │ ├── sys/ │ │ │ └── execabs/ │ │ │ └── execabs.go │ │ └── tools/ │ │ └── go/ │ │ ├── ast/ │ │ │ └── astutil/ │ │ │ ├── enclosing.go │ │ │ ├── imports.go │ │ │ ├── rewrite.go │ │ │ └── util.go │ │ ├── buildutil/ │ │ │ ├── allpackages.go │ │ │ ├── fakecontext.go │ │ │ ├── overlay.go │ │ │ ├── tags.go │ │ │ └── util.go │ │ ├── internal/ │ │ │ └── cgo/ │ │ │ ├── cgo.go │ │ │ └── cgo_pkgconfig.go │ │ └── loader/ │ │ ├── doc.go │ │ ├── loader.go │ │ └── util.go │ └── google.golang.org/ │ └── protobuf/ │ ├── cmd/ │ │ └── protoc-gen-go/ │ │ ├── internal_gengo/ │ │ │ ├── init.go │ │ │ ├── main.go │ │ │ ├── reflect.go │ │ │ └── well_known_types.go │ │ └── main.go │ ├── compiler/ │ │ └── protogen/ │ │ └── protogen.go │ ├── encoding/ │ │ ├── prototext/ │ │ │ ├── decode.go │ │ │ ├── doc.go │ │ │ └── encode.go │ │ └── protowire/ │ │ └── wire.go │ ├── internal/ │ │ ├── descfmt/ │ │ │ └── stringer.go │ │ ├── descopts/ │ │ │ └── options.go │ │ ├── detrand/ │ │ │ └── rand.go │ │ ├── encoding/ │ │ │ ├── defval/ │ │ │ │ └── default.go │ │ │ ├── messageset/ │ │ │ │ └── messageset.go │ │ │ ├── tag/ │ │ │ │ └── tag.go │ │ │ └── text/ │ │ │ ├── decode.go │ │ │ ├── decode_number.go │ │ │ ├── decode_string.go │ │ │ ├── decode_token.go │ │ │ ├── doc.go │ │ │ └── encode.go │ │ ├── errors/ │ │ │ ├── errors.go │ │ │ ├── is_go112.go │ │ │ └── is_go113.go │ │ ├── filedesc/ │ │ │ ├── build.go │ │ │ ├── desc.go │ │ │ ├── desc_init.go │ │ │ ├── desc_lazy.go │ │ │ ├── desc_list.go │ │ │ ├── desc_list_gen.go │ │ │ └── placeholder.go │ │ ├── filetype/ │ │ │ └── build.go │ │ ├── flags/ │ │ │ ├── flags.go │ │ │ ├── proto_legacy_disable.go │ │ │ └── proto_legacy_enable.go │ │ ├── genid/ │ │ │ ├── any_gen.go │ │ │ ├── api_gen.go │ │ │ ├── descriptor_gen.go │ │ │ ├── doc.go │ │ │ ├── duration_gen.go │ │ │ ├── empty_gen.go │ │ │ ├── field_mask_gen.go │ │ │ ├── goname.go │ │ │ ├── map_entry.go │ │ │ ├── source_context_gen.go │ │ │ ├── struct_gen.go │ │ │ ├── timestamp_gen.go │ │ │ ├── type_gen.go │ │ │ ├── wrappers.go │ │ │ └── wrappers_gen.go │ │ ├── impl/ │ │ │ ├── api_export.go │ │ │ ├── checkinit.go │ │ │ ├── codec_extension.go │ │ │ ├── codec_field.go │ │ │ ├── codec_gen.go │ │ │ ├── codec_map.go │ │ │ ├── codec_map_go111.go │ │ │ ├── codec_map_go112.go │ │ │ ├── codec_message.go │ │ │ ├── codec_messageset.go │ │ │ ├── codec_reflect.go │ │ │ ├── codec_tables.go │ │ │ ├── codec_unsafe.go │ │ │ ├── convert.go │ │ │ ├── convert_list.go │ │ │ ├── convert_map.go │ │ │ ├── decode.go │ │ │ ├── encode.go │ │ │ ├── enum.go │ │ │ ├── extension.go │ │ │ ├── legacy_enum.go │ │ │ ├── legacy_export.go │ │ │ ├── legacy_extension.go │ │ │ ├── legacy_file.go │ │ │ ├── legacy_message.go │ │ │ ├── merge.go │ │ │ ├── merge_gen.go │ │ │ ├── message.go │ │ │ ├── message_reflect.go │ │ │ ├── message_reflect_field.go │ │ │ ├── message_reflect_gen.go │ │ │ ├── pointer_reflect.go │ │ │ ├── pointer_unsafe.go │ │ │ ├── validate.go │ │ │ └── weak.go │ │ ├── order/ │ │ │ ├── order.go │ │ │ └── range.go │ │ ├── pragma/ │ │ │ └── pragma.go │ │ ├── set/ │ │ │ └── ints.go │ │ ├── strs/ │ │ │ ├── strings.go │ │ │ ├── strings_pure.go │ │ │ └── strings_unsafe.go │ │ └── version/ │ │ └── version.go │ ├── proto/ │ │ ├── checkinit.go │ │ ├── decode.go │ │ ├── decode_gen.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── encode_gen.go │ │ ├── equal.go │ │ ├── extension.go │ │ ├── merge.go │ │ ├── messageset.go │ │ ├── proto.go │ │ ├── proto_methods.go │ │ ├── proto_reflect.go │ │ ├── reset.go │ │ ├── size.go │ │ ├── size_gen.go │ │ └── wrappers.go │ ├── reflect/ │ │ ├── protodesc/ │ │ │ ├── desc.go │ │ │ ├── desc_init.go │ │ │ ├── desc_resolve.go │ │ │ ├── desc_validate.go │ │ │ └── proto.go │ │ ├── protoreflect/ │ │ │ ├── methods.go │ │ │ ├── proto.go │ │ │ ├── source.go │ │ │ ├── source_gen.go │ │ │ ├── type.go │ │ │ ├── value.go │ │ │ ├── value_pure.go │ │ │ ├── value_union.go │ │ │ └── value_unsafe.go │ │ └── protoregistry/ │ │ └── registry.go │ ├── runtime/ │ │ ├── protoiface/ │ │ │ ├── legacy.go │ │ │ └── methods.go │ │ └── protoimpl/ │ │ ├── impl.go │ │ └── version.go │ └── types/ │ ├── descriptorpb/ │ │ └── descriptor.pb.go │ └── pluginpb/ │ └── plugin.pb.go ├── check_protoc_version.sh ├── client_options.go ├── client_options_test.go ├── clientcompat/ │ ├── README.md │ ├── clientcompat.go │ ├── clientcompat.proto │ ├── gen.go │ ├── gocompat/ │ │ └── gocompat.go │ ├── internal/ │ │ └── clientcompat/ │ │ ├── clientcompat.pb.go │ │ └── clientcompat.twirp.go │ ├── main.go │ └── run.go ├── context.go ├── ctxsetters/ │ └── ctxsetters.go ├── docs/ │ ├── best_practices.md │ ├── command_line.md │ ├── curl.md │ ├── errors.md │ ├── example.md │ ├── headers.md │ ├── hooks.md │ ├── install.md │ ├── intro.md │ ├── migrate_to_twirp.md │ ├── mux.md │ ├── protobuf_and_json.md │ ├── routing.md │ ├── spec_v5.md │ ├── spec_v6.md │ ├── spec_v7.md │ └── version_matrix.md ├── errors.go ├── errors_test.go ├── example/ │ ├── cmd/ │ │ ├── client/ │ │ │ └── main.go │ │ └── server/ │ │ ├── README.md │ │ ├── main.go │ │ └── statter.go │ ├── gen.go │ ├── service.pb.go │ ├── service.proto │ └── service.twirp.go ├── hooks/ │ └── statsd/ │ ├── statsd.go │ └── statsd_test.go ├── interceptors.go ├── interceptors_test.go ├── internal/ │ ├── contextkeys/ │ │ └── keys.go │ ├── descriptors/ │ │ └── descriptors.go │ ├── gen/ │ │ ├── logging.go │ │ ├── main.go │ │ ├── stringutils/ │ │ │ └── stringutils.go │ │ ├── typemap/ │ │ │ ├── testdata/ │ │ │ │ ├── fileset.pb │ │ │ │ ├── gen.go │ │ │ │ ├── importer.proto │ │ │ │ ├── public_importer.proto │ │ │ │ ├── public_reimporter.proto │ │ │ │ ├── root_pkg.proto │ │ │ │ └── service.proto │ │ │ ├── typemap.go │ │ │ └── typemap_test.go │ │ ├── version.go │ │ └── wrappers.go │ └── twirptest/ │ ├── client_1_13_test.go │ ├── client_test.go │ ├── empty_service/ │ │ ├── compile_test.go │ │ ├── empty_service.pb.go │ │ ├── empty_service.proto │ │ ├── empty_service.twirp.go │ │ └── gen.go │ ├── gen.go │ ├── google_protobuf_imports/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── service.pb.go │ │ ├── service.proto │ │ └── service.twirp.go │ ├── hatmakers.go │ ├── importable/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── importable.pb.go │ │ ├── importable.proto │ │ └── importable.twirp.go │ ├── importer/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── importer.pb.go │ │ ├── importer.proto │ │ └── importer.twirp.go │ ├── importer_local/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── importer_local.pb.go │ │ ├── importer_local.proto │ │ ├── importer_local.twirp.go │ │ ├── importer_local_msgdef.pb.go │ │ └── importer_local_msgdef.proto │ ├── importmapping/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── gen.sh │ │ ├── protoc_gen-x.sh │ │ ├── x/ │ │ │ ├── x.pb.go │ │ │ ├── x.proto │ │ │ └── x.twirp.go │ │ └── y/ │ │ ├── y.pb.go │ │ └── y.proto │ ├── json_serialization/ │ │ ├── gen.go │ │ ├── json_serialization.pb.go │ │ ├── json_serialization.proto │ │ ├── json_serialization.twirp.go │ │ └── json_serialization_test.go │ ├── multiple/ │ │ ├── gen.go │ │ ├── multiple1.pb.go │ │ ├── multiple1.proto │ │ ├── multiple1.twirp.go │ │ ├── multiple2.pb.go │ │ ├── multiple2.proto │ │ ├── multiple2.twirp.go │ │ └── multiple_test.go │ ├── no_package_name/ │ │ ├── gen.go │ │ ├── no_package_name.pb.go │ │ ├── no_package_name.proto │ │ └── no_package_name.twirp.go │ ├── no_package_name_importer/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── no_package_name_importer.pb.go │ │ ├── no_package_name_importer.proto │ │ └── no_package_name_importer.twirp.go │ ├── service.pb.go │ ├── service.proto │ ├── service.twirp.go │ ├── service_method_same_name/ │ │ ├── compile_test.go │ │ ├── gen.go │ │ ├── service_method_same_name.pb.go │ │ ├── service_method_same_name.proto │ │ └── service_method_same_name.twirp.go │ ├── service_test.go │ └── snake_case_names/ │ ├── compatibility_test.go │ ├── compile_test.go │ ├── gen.go │ ├── snake_case_names.pb.go │ ├── snake_case_names.proto │ └── snake_case_names.twirp.go ├── license_test.go ├── protoc-gen-twirp/ │ ├── command_line.go │ ├── command_line_test.go │ ├── generator.go │ ├── generator_test.go │ ├── go_naming.go │ ├── go_naming_test.go │ └── main.go ├── server_options.go ├── server_options_test.go ├── tools.json ├── vendor/ │ ├── github.com/ │ │ ├── davecgh/ │ │ │ └── go-spew/ │ │ │ ├── LICENSE │ │ │ └── spew/ │ │ │ ├── bypass.go │ │ │ ├── bypasssafe.go │ │ │ ├── common.go │ │ │ ├── config.go │ │ │ ├── doc.go │ │ │ ├── dump.go │ │ │ ├── format.go │ │ │ └── spew.go │ │ ├── pkg/ │ │ │ └── errors/ │ │ │ ├── LICENSE │ │ │ ├── errors.go │ │ │ └── stack.go │ │ ├── pmezard/ │ │ │ └── go-difflib/ │ │ │ ├── LICENSE │ │ │ └── difflib/ │ │ │ └── difflib.go │ │ └── stretchr/ │ │ └── testify/ │ │ ├── LICENSE │ │ ├── assert/ │ │ │ ├── assertion_format.go │ │ │ ├── assertion_forward.go │ │ │ ├── assertions.go │ │ │ ├── doc.go │ │ │ ├── errors.go │ │ │ ├── forward_assertions.go │ │ │ └── http_assertions.go │ │ └── require/ │ │ ├── doc.go │ │ ├── forward_requirements.go │ │ ├── require.go │ │ ├── require_forward.go │ │ └── requirements.go │ └── google.golang.org/ │ └── protobuf/ │ ├── AUTHORS │ ├── CONTRIBUTORS │ ├── LICENSE │ ├── PATENTS │ ├── encoding/ │ │ ├── protojson/ │ │ │ ├── decode.go │ │ │ ├── doc.go │ │ │ ├── encode.go │ │ │ └── well_known_types.go │ │ ├── prototext/ │ │ │ ├── decode.go │ │ │ ├── doc.go │ │ │ └── encode.go │ │ └── protowire/ │ │ └── wire.go │ ├── internal/ │ │ ├── descfmt/ │ │ │ └── stringer.go │ │ ├── descopts/ │ │ │ └── options.go │ │ ├── detrand/ │ │ │ └── rand.go │ │ ├── encoding/ │ │ │ ├── defval/ │ │ │ │ └── default.go │ │ │ ├── json/ │ │ │ │ ├── decode.go │ │ │ │ ├── decode_number.go │ │ │ │ ├── decode_string.go │ │ │ │ ├── decode_token.go │ │ │ │ └── encode.go │ │ │ ├── messageset/ │ │ │ │ └── messageset.go │ │ │ ├── tag/ │ │ │ │ └── tag.go │ │ │ └── text/ │ │ │ ├── decode.go │ │ │ ├── decode_number.go │ │ │ ├── decode_string.go │ │ │ ├── decode_token.go │ │ │ ├── doc.go │ │ │ └── encode.go │ │ ├── errors/ │ │ │ ├── errors.go │ │ │ ├── is_go112.go │ │ │ └── is_go113.go │ │ ├── filedesc/ │ │ │ ├── build.go │ │ │ ├── desc.go │ │ │ ├── desc_init.go │ │ │ ├── desc_lazy.go │ │ │ ├── desc_list.go │ │ │ ├── desc_list_gen.go │ │ │ └── placeholder.go │ │ ├── filetype/ │ │ │ └── build.go │ │ ├── flags/ │ │ │ ├── flags.go │ │ │ ├── proto_legacy_disable.go │ │ │ └── proto_legacy_enable.go │ │ ├── genid/ │ │ │ ├── any_gen.go │ │ │ ├── api_gen.go │ │ │ ├── descriptor_gen.go │ │ │ ├── doc.go │ │ │ ├── duration_gen.go │ │ │ ├── empty_gen.go │ │ │ ├── field_mask_gen.go │ │ │ ├── goname.go │ │ │ ├── map_entry.go │ │ │ ├── source_context_gen.go │ │ │ ├── struct_gen.go │ │ │ ├── timestamp_gen.go │ │ │ ├── type_gen.go │ │ │ ├── wrappers.go │ │ │ └── wrappers_gen.go │ │ ├── impl/ │ │ │ ├── api_export.go │ │ │ ├── checkinit.go │ │ │ ├── codec_extension.go │ │ │ ├── codec_field.go │ │ │ ├── codec_gen.go │ │ │ ├── codec_map.go │ │ │ ├── codec_map_go111.go │ │ │ ├── codec_map_go112.go │ │ │ ├── codec_message.go │ │ │ ├── codec_messageset.go │ │ │ ├── codec_reflect.go │ │ │ ├── codec_tables.go │ │ │ ├── codec_unsafe.go │ │ │ ├── convert.go │ │ │ ├── convert_list.go │ │ │ ├── convert_map.go │ │ │ ├── decode.go │ │ │ ├── encode.go │ │ │ ├── enum.go │ │ │ ├── extension.go │ │ │ ├── legacy_enum.go │ │ │ ├── legacy_export.go │ │ │ ├── legacy_extension.go │ │ │ ├── legacy_file.go │ │ │ ├── legacy_message.go │ │ │ ├── merge.go │ │ │ ├── merge_gen.go │ │ │ ├── message.go │ │ │ ├── message_reflect.go │ │ │ ├── message_reflect_field.go │ │ │ ├── message_reflect_gen.go │ │ │ ├── pointer_reflect.go │ │ │ ├── pointer_unsafe.go │ │ │ ├── validate.go │ │ │ └── weak.go │ │ ├── order/ │ │ │ ├── order.go │ │ │ └── range.go │ │ ├── pragma/ │ │ │ └── pragma.go │ │ ├── set/ │ │ │ └── ints.go │ │ ├── strs/ │ │ │ ├── strings.go │ │ │ ├── strings_pure.go │ │ │ └── strings_unsafe.go │ │ └── version/ │ │ └── version.go │ ├── proto/ │ │ ├── checkinit.go │ │ ├── decode.go │ │ ├── decode_gen.go │ │ ├── doc.go │ │ ├── encode.go │ │ ├── encode_gen.go │ │ ├── equal.go │ │ ├── extension.go │ │ ├── merge.go │ │ ├── messageset.go │ │ ├── proto.go │ │ ├── proto_methods.go │ │ ├── proto_reflect.go │ │ ├── reset.go │ │ ├── size.go │ │ ├── size_gen.go │ │ └── wrappers.go │ ├── reflect/ │ │ ├── protoreflect/ │ │ │ ├── methods.go │ │ │ ├── proto.go │ │ │ ├── source.go │ │ │ ├── source_gen.go │ │ │ ├── type.go │ │ │ ├── value.go │ │ │ ├── value_pure.go │ │ │ ├── value_union.go │ │ │ └── value_unsafe.go │ │ └── protoregistry/ │ │ └── registry.go │ ├── runtime/ │ │ ├── protoiface/ │ │ │ ├── legacy.go │ │ │ └── methods.go │ │ └── protoimpl/ │ │ ├── impl.go │ │ └── version.go │ └── types/ │ ├── descriptorpb/ │ │ └── descriptor.pb.go │ ├── known/ │ │ ├── emptypb/ │ │ │ └── empty.pb.go │ │ └── wrapperspb/ │ │ └── wrappers.pb.go │ └── pluginpb/ │ └── plugin.pb.go ├── vendor_test.go ├── version_constant.go └── website/ ├── .gitignore ├── core/ │ └── Footer.js ├── i18n/ │ └── en.json ├── package.json ├── pages/ │ └── en/ │ ├── help.js │ ├── index.js │ └── users.js ├── sidebars.json ├── siteConfig.js └── static/ ├── .well-known/ │ └── assetlinks.json └── css/ └── custom.css ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/PULL_REQUEST_TEMPLATE.md ================================================ *Issue #, if available:* *Description of changes:* By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license. ================================================ FILE: .github/workflows/commit-checks.yml ================================================ name: commit checks on: push: jobs: run: name: tests runs-on: ubuntu-latest strategy: matrix: go-version: ['^1.16.0', '^1.15.0', '^1.14.0'] env: GO111MODULE: 'off' GOPATH: ${{ github.workspace }}/go REPO_PATH: ${{ github.workspace }}/go/src/github.com/twitchtv/twirp steps: - uses: actions/checkout@v2 with: # Relative path under github.workspace to place the repository path: ./go/src/github.com/twitchtv/twirp - name: Install Go uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Run Go Tests run: | cd ${{ env.REPO_PATH }} go test -race ./... - name: Run clientcompat Tests run: | cd ${{ env.REPO_PATH }} GOBIN="${{env.REPO_PATH}}/bin" go install ./clientcompat GOBIN="${{env.REPO_PATH}}/bin" go install ./clientcompat/gocompat ./bin/clientcompat -client ./bin/gocompat ================================================ FILE: .github/workflows/stale.yaml ================================================ name: "Stale issue handler" on: workflow_dispatch: schedule: - cron: "0 0 * * *" # This action would run every day at midnight jobs: # Job to close stale PRs and issues. Documentation on the github action https://github.com/marketplace/actions/close-stale-issues stale: runs-on: ubuntu-latest steps: - uses: actions/stale@v3 with: repo-token: ${{ secrets.GITHUB_TOKEN }} stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label / comment or this will be closed in 5 days' stale-pr-message: 'This PR is stale because it has been open for 60 days with no activity. Remove stale label / comment or this will be closed in 5 days' days-before-stale: 60 days-before-close: 5 stale-pr-label: 'no-pr-activity' stale-issue-label: 'no-issue-activity' exempt-pr-labels: 'pending' exempt-issue-labels: 'pending' ================================================ FILE: .gitignore ================================================ *.test npm-debug.log /bin /release /build ================================================ FILE: .travis.yml ================================================ sudo: false language: go go: - 1.13.x - 1.14.x - 1.15.x - tip script: - go install ./... - go test -race ./... ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing Thanks for helping make Twirp better! This is great! ## Twirp Design Principles Contributions to Twirp should align with the project’s design principles: - Maintain backwards compatibility. Twirp has been in production at Twitch since 2016 and released to the public in January 2018. It is currently used by many companies and individuals with a variety of needs. There must be a compelling use-case and solid reasoning behind a major version upgrade. - Simple wire protocol and minimal public API. Fewer things in the core means fewer things to break. In addition, it ensures lower friction updates and easier to maintain implementations in other languages. - Avoid surprising behavior. For instance, mechanisms that can alter a program’s control flow in a surprising way (such as middleware or observability hooks) should be treated with caution. - Prefer pragmatism over bleeding-edge. Users should be able to deploy and accept updates to Twirp even if they are conservative on updating its dependencies. This includes Go, the protobuf compiler and runtime libraries, and the HTTP protocol. - Keep configuration to a minimum. For example: avoid adding flags to code generation commands, so that generated code is predictable across versions and platforms. - Limit dependencies where possible, so that they are easier to integrate and upgrade. - Prefer generated code over shared libraries between services and clients, so that it is easier to implement changes without forcing a lock-step upgrade across the ecosystem. Examples of contributions that should be addressed with high priority: - Security updates. - Performance improvements. - Supporting new versions of key dependencies such as Go and Protobuf. - Documentation. - Making Twirp easier to integrate with other tools. ## Report an Issue If you have run into a bug or want to discuss a new feature, please [file an issue](https://github.com/twitchtv/twirp/issues). If you'd rather not publicly discuss the issue, please email security@twitch.tv. ## Contributing Code with Pull Requests Twirp uses github pull requests. Fork, hack away at your changes and submit. Most pull requests will go through a few iterations before they get merged. Different contributors will sometimes have different opinions, and often patches will need to be revised before they can get merged. ### Requirements - Add tests that cover your contribution. Overall code coverage should not decrease. - Twirp officially supports the last 3 releases of Go. - Protobuf version 3.x.x to generate code with the protoc command. - For linters and other tools, we use [retool](https://github.com/twitchtv/retool). If `make setup` is not able to install it, you can install it in your path with `go get github.com/twitchtv/retool` and then install tools with `retool build`. ### Running tests Generally you want to make changes and run `make`, which will install all dependencies we know about, build the core, and run tests. A few notes: - Clone the repo on `$GOPATH/src/github.com/twitchtv/twirp` (go modules not supported yet). - Run Go unit tests with `make test`. - Most tests of the Go server are in `internal/twirptest/service_test.go`. - Integration tests running the full stack in Go are in the [clientcompat](./clientcompat) directory. ## Contributing Documentation Twirp's docs are generated with [Docusaurus](https://docusaurus.io/). You can safely edit anything inside the [docs](./docs) directory, adding new pages or editing them. You can edit the sidebar by editing [website/sidebars.json](./website/sidebars.json). To render and review your changes, run docusaurus's local server. See [Install docusaurus on your machine](https://docusaurus.io/docs/en/installation.html). 1. `cd website` 2. `npm install` 3. `npm start` 4. Navigate to http://localhost:3000/twirp to see how it looks. Publish the new docs on the `gh-pages` branch. See [this guide](https://docusaurus.io/docs/en/tutorial-publish-site) for details. ``` GIT_USER= CURRENT_BRANCH=gh-pages USE_SSH=true npm run publish-gh-pages ``` ## Making a New Release Releasing versions is the responsibility of the core maintainers. Most people can skip this section. Twirp uses GitHub releases. To make a new release: 1. Merge all changes that should be included in the release into the main branch. 2. Update the version constant in `internal/gen/version.go`. Please respect [semantic versioning](http://semver.org/): `v..`. 3. Run `make test_all` to re-generate code and run tests. Check that generated test files include the new version in the header comment. 4. Add a new commit to main with a message like "Version vX.X.X release" and push. 5. Tag the commit you just made: `git tag vX.X.X` and `git push origin --tags`. 6. Go to GitHub https://github.com/twitchtv/twirp/releases and "Draft a new release". 7. Make sure that all new functionality is properly documented, on code comments, PR description, and include links and/or upgrade instructions on the release. For example the [v7 release](https://github.com/twitchtv/twirp/releases/tag/v7.0.0). Minor releases can just include a link to the PR/PRs that were merged included into the release. ## Code of Conduct This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact opensource-codeofconduct@amazon.com with any additional questions or comments. ## Licensing See the [LICENSE](https://github.com/twitchtv/twirp/blob/main/LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. ================================================ FILE: Gopkg.toml ================================================ # The importable parts of Twirp have no external dependencies. They just use the # standard library. But both protoc-gen-twirp and Twirp's tests *do* have some # dependencies, and this manifest lists them. # # All dependencies are specified as overrides, not constraints, so that dep # doesn't get confused if someone imports Twirp. We don't want to falsely # require any particular versions of these libraries - they are *only* for # tests and building main packages. [[override]] name = "google.golang.org/protobuf" version = "1.26.0" [[override]] name = "github.com/pkg/errors" version = "0.8.0" [[override]] name = "github.com/stretchr/testify" version = "1.2.0" [prune] unused-packages = true go-tests = true non-go = true ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: Makefile ================================================ PATH := ${PWD}/_tools/bin:${PWD}/bin:${PATH} export GO111MODULE=off all: setup test_all .PHONY: setup generate test_all test test_clientcompat setup: ./check_protoc_version.sh GOPATH="$$PWD/_tools" GOBIN="$$PWD/_tools/bin" go get github.com/twitchtv/retool ./_tools/bin/retool build generate: # Recompile and install generator GOBIN="$$PWD/bin" go install -v ./protoc-gen-twirp # Generate code from go:generate comments go generate ./... test_all: setup test test_clientcompat test: generate ./_tools/bin/errcheck ./internal/twirptest go test -race ./... test_clientcompat: generate GOBIN="$$PWD/bin" go install ./clientcompat GOBIN="$$PWD/bin" go install ./clientcompat/gocompat ./bin/clientcompat -client ./bin/gocompat ================================================ FILE: NOTICE ================================================ Twirp Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. ================================================ FILE: PROTOCOL.md ================================================ # Twirp Wire Protocol This document defines the Twirp wire protocol over HTTP. The current protocol version is v7. ## Overview The Twirp wire protocol is a simple RPC protocol based on HTTP and Protocol Buffers (proto). The protocol uses HTTP URLs to specify the RPC endpoints, and sends/receives proto messages as HTTP request/response bodies. To use Twirp, developers first define their APIs using proto files, then use Twirp tools to generate the client and the server libraries. The generated libraries implement the Twirp wire protocol, using the standard HTTP library provided by the programming language runtime or the operating system. Once the client and the server are implemented, the client can communicate with the server by making RPC calls. The Twirp wire protocol supports both binary and JSON encodings of proto messages, and works with any HTTP client and any HTTP version. ### URLs In [ABNF syntax](https://tools.ietf.org/html/rfc5234), Twirp's URLs have the following format: ```abnf URL ::= Base-URL [ Prefix ] "/" [ Package "." ] Service "/" Method ``` The Twirp wire protocol uses HTTP URLs to specify the RPC endpoints on the server for sending the requests. Such direct mapping makes the request routing simple and efficient. The Twirp URLs have the following components. * **Base-URL** is the virtual location of a Twirp API server, which is typically published via API documentation or service discovery. Currently, it should only contain URL `scheme` and `authority`. For example, "https://example.com". * **Prefix** is usually "/twirp", but it could be empty "", or an arbitrary path like "/my/custom/prefix". * **Package** is the proto `package` name for an API, which is often considered as an API version. For example, `example.calendar.v1`. This component is omitted if the API definition doesn't have a package name. * **Service** is the proto `service` name for an API. For example, `CalendarService`. * **Method** is the proto `rpc` name for an API method. For example, `CreateEvent`. ### Requests Twirp always uses HTTP POST method to send requests, because it closely matches the semantics of RPC methods. The **Request-Headers** are normal HTTP headers. The Twirp wire protocol uses the following headers. * **Content-Type** header indicates the proto message encoding, which should be one of "application/protobuf", "application/json". The server uses this value to decide how to parse the request body, and encode the response body. The **Request-Body** is the encoded request message, contained in the HTTP request body. The encoding is specified by the `Content-Type` header. ### Responses The **Response-Headers** are just normal HTTP response headers. The Twirp wire protocol uses the following headers. * **Content-Type** The value should be either "application/protobuf" or "application/json" to indicate the encoding of the response message. It must match the "Content-Type" header in the request. The **Request-Body** is the encoded response message contained in the HTTP response body. The encoding is specified by the `Content-Type` header. ### Example The following example shows a simple Echo API definition and its corresponding wire payloads. The example assumes the server base URL is "https://example.com". ```proto syntax = "proto3"; package example.echoer; service Echo { rpc Hello(HelloRequest) returns (HelloResponse); } message HelloRequest { string message; } message HelloResponse { string message; } ``` **Proto Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/protobuf Content-Length: 15 ``` **JSON Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` **Proto Response** ``` HTTP/1.1 200 OK Content-Type: application/protobuf Content-Length: 15 ``` **JSON Response** ``` HTTP/1.1 200 OK Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` ## Errors Twirp error responses are always JSON-encoded, regardless of the request's Content-Type, with a corresponding `Content-Type: application/json` header. This ensures that the errors are human-readable in any setting. Twirp errors are a JSON object with the keys: * **code**: One of the Twirp error codes as a string. * **msg**: A human-readable message describing the error as a string. * **meta**: (optional) An object with string values holding arbitrary additional metadata describing the error. Example: ```json { "code": "internal", "msg": "Something went wrong" } ``` Example with metadata: ```json { "code": "permission_denied", "msg": "Thou shall not pass", "meta": { "target": "Balrog", "power": "999" } } ``` ### Error Codes Twirp errors always include an error code. This code is represented as a string and must be one of a fixed set of codes, listed in the table below. Each code has an associated HTTP Status Code. When a server responds with the given error code, it must set the corresponding HTTP Status Code for the response. | Twirp Error Code | HTTP Status | Description | ------------------- | ----------- | ----------- | canceled | 408 | The operation was cancelled. | unknown | 500 | An unknown error occurred. For example, this can be used when handling errors raised by APIs that do not return any error information. | invalid_argument | 400 | The client specified an invalid argument. This indicates arguments that are invalid regardless of the state of the system (i.e. a malformed file name, required argument, number out of range, etc.). | malformed | 400 | The client sent a message which could not be decoded. This may mean that the message was encoded improperly or that the client and server have incompatible message definitions. | deadline_exceeded | 408 | Operation expired before completion. For operations that change the state of the system, this error may be returned even if the operation has completed successfully (timeout). | not_found | 404 | Some requested entity was not found. | bad_route | 404 | The requested URL path wasn't routable to a Twirp service and method. This is returned by generated server code and should not be returned by application code (use "not_found" or "unimplemented" instead). | already_exists | 409 | An attempt to create an entity failed because one already exists. | permission_denied | 403 | The caller does not have permission to execute the specified operation. It must not be used if the caller cannot be identified (use "unauthenticated" instead). | unauthenticated | 401 | The request does not have valid authentication credentials for the operation. | resource_exhausted | 429 | Some resource has been exhausted or rate-limited, perhaps a per-user quota, or perhaps the entire file system is out of space. | failed_precondition | 412 | The operation was rejected because the system is not in a state required for the operation's execution. For example, doing an rmdir operation on a directory that is non-empty, or on a non-directory object, or when having conflicting read-modify-write on the same resource. | aborted | 409 | The operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction aborts, etc. | out_of_range | 400 | The operation was attempted past the valid range. For example, seeking or reading past end of a paginated collection. Unlike "invalid_argument", this error indicates a problem that may be fixed if the system state changes (i.e. adding more items to the collection). 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. | unimplemented | 501 | The operation is not implemented or not supported/enabled in this service. | internal | 500 | When some invariants expected by the underlying system have been broken. In other words, something bad happened in the library or backend service. Twirp specific issues like wire and serialization problems are also reported as "internal" errors. | unavailable | 503 | The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff. | data_loss | 500 | The operation resulted in unrecoverable data loss or corruption. ================================================ FILE: README.md ================================================ ![Twirp Logo](./logo.png) [![Build Status](https://travis-ci.org/twitchtv/twirp.svg?branch=main)](https://travis-ci.org/twitchtv/twirp) [![Go Report Card](https://goreportcard.com/badge/github.com/twitchtv/twirp)](https://goreportcard.com/report/github.com/twitchtv/twirp) [![GoDoc](https://godoc.org/github.com/twitchtv/twirp?status.svg)](https://godoc.org/github.com/twitchtv/twirp) --- Twirp is a framework for service-to-service communication emphasizing simplicity and minimalism. It generates routing and serialization from API definition files and lets you focus on your application's logic instead of thinking about folderol like HTTP methods and paths and JSON. Twirp is similar to [gRPC](http://www.grpc.io/), but without the custom HTTP server and transport implementations: it runs on the standard library's extremely-well-tested-and-high-performance `net/http` Server. It can run on HTTP 1.1, not just http/2, and supports JSON serialization for easy debugging. Along the way, you get autogenerated clients and a simple, smart framework for passing error messages. Nice! Read more about the motivation behind on the [announcement blog post](https://blog.twitch.tv/en/2018/01/16/twirp-a-sweet-new-rpc-framework-for-go-5f2febbf35f/). ### Documentation * [Getting Started](https://twitchtv.github.io/twirp/docs/intro.html) * [Usage Example](https://twitchtv.github.io/twirp/docs/example.html) * [Errors](https://twitchtv.github.io/twirp/docs/errors.html) * More: https://twitchtv.github.io/twirp/ ### Implementations in other languages This repo contains the generator and runtime library for the Go implementation. Here is a list of some third-party implementations in other languages. | Language | Clients | Servers | Repository | |----------------|---------|---------|------------| | **Crystal** | ✓ | ✓ | [github.com/mloughran/twirp.cr](https://github.com/mloughran/twirp.cr) | **Dart** | ✓ | | [github.com/apptreesoftware/protoc-gen-twirp_dart](https://github.com/apptreesoftware/protoc-gen-twirp_dart) | **Elixir** | ✓ | ✓ | [github.com/keathley/twirp-elixir](https://github.com/keathley/twirp-elixir) | **Java** | ✓ | ✓ | [github.com/fajran/protoc-gen-twirp_java_jaxrs](https://github.com/fajran/protoc-gen-twirp_java_jaxrs) | **Java** | | ✓ | [github.com/devork/flit](https://github.com/devork/flit) | **Java** | | ✓ | [github.com/github/flit](https://github.com/github/flit) | **JavaScript** | ✓ | | [github.com/thechriswalker/protoc-gen-twirp_js](https://github.com/thechriswalker/protoc-gen-twirp_js) | **JavaScript** | ✓ | | [github.com/Xe/twirp-codegens/cmd/protoc-gen-twirp_jsbrowser](https://github.com/Xe/twirp-codegens) | **JavaScript** | ✓ | ✓ | [github.com/tatethurston/TwirpScript](https://github.com/tatethurston/TwirpScript) | **Kotlin** | ✓ | | [github.com/collectiveidea/twirp-kmm](https://github.com/collectiveidea/twirp-kmm) | **PHP** | ✓ | ✓ | [github.com/twirphp/twirp](https://github.com/twirphp/twirp) | **Python3** | ✓ | ✓ | [github.com/verloop/twirpy](https://github.com/verloop/twirpy) | **Ruby** | ✓ | ✓ | [github.com/twitchtv/twirp-ruby](https://github.com/twitchtv/twirp-ruby) | **Rust** | ✓ | ✓ | [github.com/sourcefrog/prost-twirp](https://github.com/sourcefrog/prost-twirp) | **Scala** | ✓ | ✓ | [github.com/soundcloud/twinagle](https://github.com/soundcloud/twinagle) | **Swagger** | ✓ | ✓ | [github.com/go-bridget/twirp-swagger-gen](https://github.com/go-bridget/twirp-swagger-gen) | **Swift** | ✓ | | [github.com/CrazyHulk/protoc-gen-swiftwirp](https://github.com/CrazyHulk/protoc-gen-swiftwirp) | **Typescript** | ✓ | ✓ | [github.com/hopin-team/twirp-ts](https://github.com/hopin-team/twirp-ts) | **Typescript** | ✓ | ✓ | [github.com/tatethurston/TwirpScript](https://github.com/tatethurston/TwirpScript) | **Typescript** | ✓ | ✓ | [github.com/timostamm/protobuf-ts](https://github.com/timostamm/protobuf-ts) ### Support and Community We have a channel on the Gophers slack, [#twirp](https://gophers.slack.com/messages/twirp), which is the best place to get quick answers to your questions. You can join the Gopher slack [here](https://invite.slack.golangbridge.org/). ### Releases Twirp follows semantic versioning through git tags, and uses GitHub Releases for release notes and upgrade guides: [Twirp Releases](https://github.com/twitchtv/twirp/releases) ### Contributing Check out [CONTRIBUTING.md](./CONTRIBUTING.md) for notes on making contributions. ### License This library is licensed under the Apache 2.0 License. ================================================ FILE: THIRD_PARTY ================================================ ** Protobuf -- https://github.com/protocolbuffers/protobuf-go Copyright 2010 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: _tools/.gitignore ================================================ /bin/ /pkg/ /manifest.json ================================================ FILE: _tools/src/github.com/kisielk/errcheck/LICENSE ================================================ Copyright (c) 2013 Kamil Kisiel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: _tools/src/github.com/kisielk/errcheck/README.md ================================================ # errcheck errcheck is a program for checking for unchecked errors in go programs. [![Build Status](https://travis-ci.org/kisielk/errcheck.png?branch=master)](https://travis-ci.org/kisielk/errcheck) ## Install go get -u github.com/kisielk/errcheck errcheck requires Go 1.6 or newer and depends on the package go/loader from the golang.org/x/tools repository. ## Use For basic usage, just give the package path of interest as the first argument: errcheck github.com/kisielk/errcheck/testdata To check all packages beneath the current directory: errcheck ./... Or check all packages in your $GOPATH and $GOROOT: errcheck all errcheck also recognizes the following command-line options: The `-tags` flag takes a space-separated list of build tags, just like `go build`. If you are using any custom build tags in your code base, you may need to specify the relevant tags here. The `-asserts` flag enables checking for ignored type assertion results. It takes no arguments. The `-blank` flag enables checking for assignments of errors to the blank identifier. It takes no arguments. ## Excluding functions Use the `-exclude` flag to specify a path to a file containing a list of functions to be excluded. errcheck -exclude errcheck_excludes.txt path/to/package The file should contain one function signature per line. The format for function signatures is `package.FunctionName` while for methods it's `(package.Receiver).MethodName` for value receivers and `(*package.Receiver).MethodName` for pointer receivers. An example of an exclude file is: io/ioutil.ReadFile (*net/http.Client).Do The exclude list is combined with an internal list for functions in the Go standard library that have an error return type but are documented to never return an error. ### The deprecated method The `-ignore` flag takes a comma-separated list of pairs of the form package:regex. For each package, the regex describes which functions to ignore within that package. The package may be omitted to have the regex apply to all packages. For example, you may wish to ignore common operations like Read and Write: errcheck -ignore '[rR]ead|[wW]rite' path/to/package or you may wish to ignore common functions like the `print` variants in `fmt`: errcheck -ignore 'fmt:[FS]?[Pp]rint*' path/to/package The `-ignorepkg` flag takes a comma-separated list of package import paths to ignore: errcheck -ignorepkg 'fmt,encoding/binary' path/to/package Note that this is equivalent to: errcheck -ignore 'fmt:.*,encoding/binary:.*' path/to/package If a regex is provided for a package `pkg` via `-ignore`, and `pkg` also appears in the list of packages passed to `-ignorepkg`, the latter takes precedence; that is, all functions within `pkg` will be ignored. Note that by default the `fmt` package is ignored entirely, unless a regex is specified for it. To disable this, specify a regex that matches nothing: errcheck -ignore 'fmt:a^' path/to/package The `-ignoretests` flag disables checking of `_test.go` files. It takes no arguments. ## Cgo Currently errcheck is unable to check packages that `import "C"` due to limitations in the importer. However, you can use errcheck on packages that depend on those which use cgo. In order for this to work you need to `go install` the cgo dependencies before running errcheck on the dependant packages. See https://github.com/kisielk/errcheck/issues/16 for more details. ## Exit Codes errcheck returns 1 if any problems were found in the checked files. It returns 2 if there were any other failures. # Editor Integration ## Emacs [go-errcheck.el](https://github.com/dominikh/go-errcheck.el) integrates errcheck with Emacs by providing a `go-errcheck` command and customizable variables to automatically pass flags to errcheck. ## Vim [vim-go](https://github.com/fatih/vim-go) can run errcheck via both its `:GoErrCheck` and `:GoMetaLinter` commands. ================================================ FILE: _tools/src/github.com/kisielk/errcheck/internal/errcheck/errcheck.go ================================================ // Package errcheck is the library used to implement the errcheck command-line tool. // // Note: The API of this package has not been finalized and may change at any point. package errcheck import ( "bufio" "errors" "fmt" "go/ast" "go/build" "go/token" "go/types" "os" "regexp" "sort" "strings" "sync" "golang.org/x/tools/go/loader" ) var errorType *types.Interface func init() { errorType = types.Universe.Lookup("error").Type().Underlying().(*types.Interface) } var ( // ErrNoGoFiles is returned when CheckPackage is run on a package with no Go source files ErrNoGoFiles = errors.New("package contains no go source files") ) // UncheckedError indicates the position of an unchecked error return. type UncheckedError struct { Pos token.Position Line string } // UncheckedErrors is returned from the CheckPackage function if the package contains // any unchecked errors. // Errors should be appended using the Append method, which is safe to use concurrently. type UncheckedErrors struct { mu sync.Mutex // Errors is a list of all the unchecked errors in the package. // Printing an error reports its position within the file and the contents of the line. Errors []UncheckedError } func (e *UncheckedErrors) Append(errors ...UncheckedError) { e.mu.Lock() defer e.mu.Unlock() e.Errors = append(e.Errors, errors...) } func (e *UncheckedErrors) Error() string { return fmt.Sprintf("%d unchecked errors", len(e.Errors)) } // Len is the number of elements in the collection. func (e *UncheckedErrors) Len() int { return len(e.Errors) } // Swap swaps the elements with indexes i and j. func (e *UncheckedErrors) Swap(i, j int) { e.Errors[i], e.Errors[j] = e.Errors[j], e.Errors[i] } type byName struct{ *UncheckedErrors } // Less reports whether the element with index i should sort before the element with index j. func (e byName) Less(i, j int) bool { ei, ej := e.Errors[i], e.Errors[j] pi, pj := ei.Pos, ej.Pos if pi.Filename != pj.Filename { return pi.Filename < pj.Filename } if pi.Line != pj.Line { return pi.Line < pj.Line } if pi.Column != pj.Column { return pi.Column < pj.Column } return ei.Line < ej.Line } type Checker struct { // ignore is a map of package names to regular expressions. Identifiers from a package are // checked against its regular expressions and if any of the expressions match the call // is not checked. Ignore map[string]*regexp.Regexp // If blank is true then assignments to the blank identifier are also considered to be // ignored errors. Blank bool // If asserts is true then ignored type assertion results are also checked Asserts bool // build tags Tags []string Verbose bool // If true, checking of of _test.go files is disabled WithoutTests bool exclude map[string]bool } func NewChecker() *Checker { c := Checker{} c.SetExclude(map[string]bool{}) return &c } func (c *Checker) SetExclude(l map[string]bool) { // Default exclude for stdlib functions c.exclude = map[string]bool{ "math/rand.Read": true, "(*math/rand.Rand).Read": true, "(*bytes.Buffer).Write": true, "(*bytes.Buffer).WriteByte": true, "(*bytes.Buffer).WriteRune": true, "(*bytes.Buffer).WriteString": true, } for k := range l { c.exclude[k] = true } } func (c *Checker) logf(msg string, args ...interface{}) { if c.Verbose { fmt.Fprintf(os.Stderr, msg+"\n", args...) } } func (c *Checker) load(paths ...string) (*loader.Program, error) { ctx := build.Default for _, tag := range c.Tags { ctx.BuildTags = append(ctx.BuildTags, tag) } loadcfg := loader.Config{ Build: &ctx, } rest, err := loadcfg.FromArgs(paths, !c.WithoutTests) if err != nil { return nil, fmt.Errorf("could not parse arguments: %s", err) } if len(rest) > 0 { return nil, fmt.Errorf("unhandled extra arguments: %v", rest) } return loadcfg.Load() } // CheckPackages checks packages for errors. func (c *Checker) CheckPackages(paths ...string) error { program, err := c.load(paths...) if err != nil { return fmt.Errorf("could not type check: %s", err) } var wg sync.WaitGroup u := &UncheckedErrors{} for _, pkgInfo := range program.InitialPackages() { if pkgInfo.Pkg.Path() == "unsafe" { // not a real package continue } wg.Add(1) go func(pkgInfo *loader.PackageInfo) { defer wg.Done() c.logf("Checking %s", pkgInfo.Pkg.Path()) v := &visitor{ prog: program, pkg: pkgInfo, ignore: c.Ignore, blank: c.Blank, asserts: c.Asserts, lines: make(map[string][]string), exclude: c.exclude, errors: []UncheckedError{}, } for _, astFile := range v.pkg.Files { ast.Walk(v, astFile) } u.Append(v.errors...) }(pkgInfo) } wg.Wait() if u.Len() > 0 { sort.Sort(byName{u}) return u } return nil } // visitor implements the errcheck algorithm type visitor struct { prog *loader.Program pkg *loader.PackageInfo ignore map[string]*regexp.Regexp blank bool asserts bool lines map[string][]string exclude map[string]bool errors []UncheckedError } func (v *visitor) excludeCall(call *ast.CallExpr) bool { sel, ok := call.Fun.(*ast.SelectorExpr) if !ok { return false } fn, ok := v.pkg.ObjectOf(sel.Sel).(*types.Func) if !ok { // Shouldn't happen, but be paranoid return false } // The name is fully qualified by the import path, possible type, // function/method name and pointer receiver. // // TODO(dh): vendored packages will have /vendor/ in their name, // thus not matching vendored standard library packages. If we // want to support vendored stdlib packages, we need to implement // FullName with our own logic. name := fn.FullName() return v.exclude[name] } func (v *visitor) ignoreCall(call *ast.CallExpr) bool { if v.excludeCall(call) { return true } // Try to get an identifier. // Currently only supports simple expressions: // 1. f() // 2. x.y.f() var id *ast.Ident switch exp := call.Fun.(type) { case (*ast.Ident): id = exp case (*ast.SelectorExpr): id = exp.Sel default: // eg: *ast.SliceExpr, *ast.IndexExpr } if id == nil { return false } // If we got an identifier for the function, see if it is ignored if re, ok := v.ignore[""]; ok && re.MatchString(id.Name) { return true } if obj := v.pkg.Uses[id]; obj != nil { if pkg := obj.Pkg(); pkg != nil { if re, ok := v.ignore[pkg.Path()]; ok { return re.MatchString(id.Name) } // if current package being considered is vendored, check to see if it should be ignored based // on the unvendored path. if nonVendoredPkg, ok := nonVendoredPkgPath(pkg.Path()); ok { if re, ok := v.ignore[nonVendoredPkg]; ok { return re.MatchString(id.Name) } } } } return false } // nonVendoredPkgPath returns the unvendored version of the provided package path (or returns the provided path if it // does not represent a vendored path). The second return value is true if the provided package was vendored, false // otherwise. func nonVendoredPkgPath(pkgPath string) (string, bool) { lastVendorIndex := strings.LastIndex(pkgPath, "/vendor/") if lastVendorIndex == -1 { return pkgPath, false } return pkgPath[lastVendorIndex+len("/vendor/"):], true } // errorsByArg returns a slice s such that // len(s) == number of return types of call // s[i] == true iff return type at position i from left is an error type func (v *visitor) errorsByArg(call *ast.CallExpr) []bool { switch t := v.pkg.Types[call].Type.(type) { case *types.Named: // Single return return []bool{isErrorType(t)} case *types.Pointer: // Single return via pointer return []bool{isErrorType(t)} case *types.Tuple: // Multiple returns s := make([]bool, t.Len()) for i := 0; i < t.Len(); i++ { switch et := t.At(i).Type().(type) { case *types.Named: // Single return s[i] = isErrorType(et) case *types.Pointer: // Single return via pointer s[i] = isErrorType(et) default: s[i] = false } } return s } return []bool{false} } func (v *visitor) callReturnsError(call *ast.CallExpr) bool { if v.isRecover(call) { return true } for _, isError := range v.errorsByArg(call) { if isError { return true } } return false } // isRecover returns true if the given CallExpr is a call to the built-in recover() function. func (v *visitor) isRecover(call *ast.CallExpr) bool { if fun, ok := call.Fun.(*ast.Ident); ok { if _, ok := v.pkg.Uses[fun].(*types.Builtin); ok { return fun.Name == "recover" } } return false } func (v *visitor) addErrorAtPosition(position token.Pos) { pos := v.prog.Fset.Position(position) lines, ok := v.lines[pos.Filename] if !ok { lines = readfile(pos.Filename) v.lines[pos.Filename] = lines } line := "??" if pos.Line-1 < len(lines) { line = strings.TrimSpace(lines[pos.Line-1]) } v.errors = append(v.errors, UncheckedError{pos, line}) } func readfile(filename string) []string { var f, err = os.Open(filename) if err != nil { return nil } var lines []string var scanner = bufio.NewScanner(f) for scanner.Scan() { lines = append(lines, scanner.Text()) } return lines } func (v *visitor) Visit(node ast.Node) ast.Visitor { switch stmt := node.(type) { case *ast.ExprStmt: if call, ok := stmt.X.(*ast.CallExpr); ok { if !v.ignoreCall(call) && v.callReturnsError(call) { v.addErrorAtPosition(call.Lparen) } } case *ast.GoStmt: if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { v.addErrorAtPosition(stmt.Call.Lparen) } case *ast.DeferStmt: if !v.ignoreCall(stmt.Call) && v.callReturnsError(stmt.Call) { v.addErrorAtPosition(stmt.Call.Lparen) } case *ast.AssignStmt: if len(stmt.Rhs) == 1 { // single value on rhs; check against lhs identifiers if call, ok := stmt.Rhs[0].(*ast.CallExpr); ok { if !v.blank { break } if v.ignoreCall(call) { break } isError := v.errorsByArg(call) for i := 0; i < len(stmt.Lhs); i++ { if id, ok := stmt.Lhs[i].(*ast.Ident); ok { // We shortcut calls to recover() because errorsByArg can't // check its return types for errors since it returns interface{}. if id.Name == "_" && (v.isRecover(call) || isError[i]) { v.addErrorAtPosition(id.NamePos) } } } } else if assert, ok := stmt.Rhs[0].(*ast.TypeAssertExpr); ok { if !v.asserts { break } if assert.Type == nil { // type switch break } if len(stmt.Lhs) < 2 { // assertion result not read v.addErrorAtPosition(stmt.Rhs[0].Pos()) } else if id, ok := stmt.Lhs[1].(*ast.Ident); ok && v.blank && id.Name == "_" { // assertion result ignored v.addErrorAtPosition(id.NamePos) } } } else { // multiple value on rhs; in this case a call can't return // multiple values. Assume len(stmt.Lhs) == len(stmt.Rhs) for i := 0; i < len(stmt.Lhs); i++ { if id, ok := stmt.Lhs[i].(*ast.Ident); ok { if call, ok := stmt.Rhs[i].(*ast.CallExpr); ok { if !v.blank { continue } if v.ignoreCall(call) { continue } if id.Name == "_" && v.callReturnsError(call) { v.addErrorAtPosition(id.NamePos) } } else if assert, ok := stmt.Rhs[i].(*ast.TypeAssertExpr); ok { if !v.asserts { continue } if assert.Type == nil { // Shouldn't happen anyway, no multi assignment in type switches continue } v.addErrorAtPosition(id.NamePos) } } } } default: } return v } func isErrorType(t types.Type) bool { return types.Implements(t, errorType) } ================================================ FILE: _tools/src/github.com/kisielk/errcheck/main.go ================================================ package main import ( "bufio" "flag" "fmt" "os" "path/filepath" "regexp" "runtime" "strings" "github.com/kisielk/errcheck/internal/errcheck" "github.com/kisielk/gotool" ) const ( exitCodeOk int = iota exitUncheckedError exitFatalError ) var abspath bool type ignoreFlag map[string]*regexp.Regexp func (f ignoreFlag) String() string { pairs := make([]string, 0, len(f)) for pkg, re := range f { prefix := "" if pkg != "" { prefix = pkg + ":" } pairs = append(pairs, prefix+re.String()) } return fmt.Sprintf("%q", strings.Join(pairs, ",")) } func (f ignoreFlag) Set(s string) error { if s == "" { return nil } for _, pair := range strings.Split(s, ",") { colonIndex := strings.Index(pair, ":") var pkg, re string if colonIndex == -1 { pkg = "" re = pair } else { pkg = pair[:colonIndex] re = pair[colonIndex+1:] } regex, err := regexp.Compile(re) if err != nil { return err } f[pkg] = regex } return nil } type tagsFlag []string func (f *tagsFlag) String() string { return fmt.Sprintf("%q", strings.Join(*f, " ")) } func (f *tagsFlag) Set(s string) error { if s == "" { return nil } tags := strings.Split(s, " ") if tags == nil { return nil } for _, tag := range tags { if tag != "" { *f = append(*f, tag) } } return nil } var dotStar = regexp.MustCompile(".*") func reportUncheckedErrors(e *errcheck.UncheckedErrors) { wd, err := os.Getwd() if err != nil { wd = "" } for _, uncheckedError := range e.Errors { pos := uncheckedError.Pos.String() if !abspath { newPos, err := filepath.Rel(wd, pos) if err == nil { pos = newPos } } fmt.Printf("%s:\t%s\n", pos, uncheckedError.Line) } } func mainCmd(args []string) int { runtime.GOMAXPROCS(runtime.NumCPU()) checker := errcheck.NewChecker() paths, err := parseFlags(checker, args) if err != exitCodeOk { return err } if err := checker.CheckPackages(paths...); err != nil { if e, ok := err.(*errcheck.UncheckedErrors); ok { reportUncheckedErrors(e) return exitUncheckedError } else if err == errcheck.ErrNoGoFiles { fmt.Fprintln(os.Stderr, err) return exitCodeOk } fmt.Fprintf(os.Stderr, "error: failed to check packages: %s\n", err) return exitFatalError } return exitCodeOk } func parseFlags(checker *errcheck.Checker, args []string) ([]string, int) { flags := flag.NewFlagSet(args[0], flag.ContinueOnError) flags.BoolVar(&checker.Blank, "blank", false, "if true, check for errors assigned to blank identifier") flags.BoolVar(&checker.Asserts, "asserts", false, "if true, check for ignored type assertion results") flags.BoolVar(&checker.WithoutTests, "ignoretests", false, "if true, checking of _test.go files is disabled") flags.BoolVar(&checker.Verbose, "verbose", false, "produce more verbose logging") flags.BoolVar(&abspath, "abspath", false, "print absolute paths to files") tags := tagsFlag{} flags.Var(&tags, "tags", "space-separated list of build tags to include") ignorePkg := flags.String("ignorepkg", "", "comma-separated list of package paths to ignore") ignore := ignoreFlag(map[string]*regexp.Regexp{ "fmt": dotStar, }) flags.Var(ignore, "ignore", "[deprecated] comma-separated list of pairs of the form pkg:regex\n"+ " the regex is used to ignore names within pkg.") var excludeFile string flags.StringVar(&excludeFile, "exclude", "", "Path to a file containing a list of functions to exclude from checking") if err := flags.Parse(args[1:]); err != nil { return nil, exitFatalError } if excludeFile != "" { exclude := make(map[string]bool) fh, err := os.Open(excludeFile) if err != nil { fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err) return nil, exitFatalError } scanner := bufio.NewScanner(fh) for scanner.Scan() { exclude[scanner.Text()] = true } if err := scanner.Err(); err != nil { fmt.Fprintf(os.Stderr, "Could not read exclude file: %s\n", err) return nil, exitFatalError } checker.SetExclude(exclude) } checker.Tags = tags for _, pkg := range strings.Split(*ignorePkg, ",") { if pkg != "" { ignore[pkg] = dotStar } } checker.Ignore = ignore // ImportPaths normalizes paths and expands '...' return gotool.ImportPaths(flags.Args()), exitCodeOk } func main() { os.Exit(mainCmd(os.Args)) } ================================================ FILE: _tools/src/github.com/kisielk/gotool/LEGAL ================================================ All the files in this distribution are covered under either the MIT license (see the file LICENSE) except some files mentioned below. match.go, match_test.go: Copyright (c) 2009 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: _tools/src/github.com/kisielk/gotool/LICENSE ================================================ Copyright (c) 2013 Kamil Kisiel Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: _tools/src/github.com/kisielk/gotool/README.md ================================================ gotool ====== [![GoDoc](https://godoc.org/github.com/kisielk/gotool?status.svg)](https://godoc.org/github.com/kisielk/gotool) [![Build Status](https://travis-ci.org/kisielk/gotool.svg?branch=master)](https://travis-ci.org/kisielk/gotool) Package gotool contains utility functions used to implement the standard "cmd/go" tool, provided as a convenience to developers who want to write tools with similar semantics. ================================================ FILE: _tools/src/github.com/kisielk/gotool/go13.go ================================================ // +build !go1.4 package gotool import ( "go/build" "path/filepath" "runtime" ) var gorootSrc = filepath.Join(runtime.GOROOT(), "src", "pkg") func shouldIgnoreImport(p *build.Package) bool { return true } ================================================ FILE: _tools/src/github.com/kisielk/gotool/go14-15.go ================================================ // +build go1.4,!go1.6 package gotool import ( "go/build" "path/filepath" "runtime" ) var gorootSrc = filepath.Join(runtime.GOROOT(), "src") func shouldIgnoreImport(p *build.Package) bool { return true } ================================================ FILE: _tools/src/github.com/kisielk/gotool/go16-18.go ================================================ // +build go1.6,!go1.9 package gotool import ( "go/build" "path/filepath" "runtime" ) var gorootSrc = filepath.Join(runtime.GOROOT(), "src") func shouldIgnoreImport(p *build.Package) bool { return p == nil || len(p.InvalidGoFiles) == 0 } ================================================ FILE: _tools/src/github.com/kisielk/gotool/internal/load/path.go ================================================ // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.9 package load import ( "strings" ) // hasPathPrefix reports whether the path s begins with the // elements in prefix. func hasPathPrefix(s, prefix string) bool { switch { default: return false case len(s) == len(prefix): return s == prefix case len(s) > len(prefix): if prefix != "" && prefix[len(prefix)-1] == '/' { return strings.HasPrefix(s, prefix) } return s[len(prefix)] == '/' && s[:len(prefix)] == prefix } } ================================================ FILE: _tools/src/github.com/kisielk/gotool/internal/load/pkg.go ================================================ // Copyright 2011 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.9 // Package load loads packages. package load import ( "strings" ) // isStandardImportPath reports whether $GOROOT/src/path should be considered // part of the standard distribution. For historical reasons we allow people to add // their own code to $GOROOT instead of using $GOPATH, but we assume that // code will start with a domain name (dot in the first element). func isStandardImportPath(path string) bool { i := strings.Index(path, "/") if i < 0 { i = len(path) } elem := path[:i] return !strings.Contains(elem, ".") } ================================================ FILE: _tools/src/github.com/kisielk/gotool/internal/load/search.go ================================================ // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.9 package load import ( "fmt" "go/build" "log" "os" "path" "path/filepath" "regexp" "strings" ) // Context specifies values for operation of ImportPaths that would // otherwise come from cmd/go/internal/cfg package. // // This is a construct added for gotool purposes and doesn't have // an equivalent upstream in cmd/go. type Context struct { // BuildContext is the build context to use. BuildContext build.Context // GOROOTsrc is the location of the src directory in GOROOT. // At this time, it's used only in MatchPackages to skip // GOOROOT/src entry from BuildContext.SrcDirs output. GOROOTsrc string } // allPackages returns all the packages that can be found // under the $GOPATH directories and $GOROOT matching pattern. // The pattern is either "all" (all packages), "std" (standard packages), // "cmd" (standard commands), or a path including "...". func (c *Context) allPackages(pattern string) []string { pkgs := c.MatchPackages(pattern) if len(pkgs) == 0 { fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) } return pkgs } // allPackagesInFS is like allPackages but is passed a pattern // beginning ./ or ../, meaning it should scan the tree rooted // at the given directory. There are ... in the pattern too. func (c *Context) allPackagesInFS(pattern string) []string { pkgs := c.MatchPackagesInFS(pattern) if len(pkgs) == 0 { fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) } return pkgs } // MatchPackages returns a list of package paths matching pattern // (see go help packages for pattern syntax). func (c *Context) MatchPackages(pattern string) []string { match := func(string) bool { return true } treeCanMatch := func(string) bool { return true } if !IsMetaPackage(pattern) { match = matchPattern(pattern) treeCanMatch = treeCanMatchPattern(pattern) } have := map[string]bool{ "builtin": true, // ignore pseudo-package that exists only for documentation } if !c.BuildContext.CgoEnabled { have["runtime/cgo"] = true // ignore during walk } var pkgs []string for _, src := range c.BuildContext.SrcDirs() { if (pattern == "std" || pattern == "cmd") && src != c.GOROOTsrc { continue } src = filepath.Clean(src) + string(filepath.Separator) root := src if pattern == "cmd" { root += "cmd" + string(filepath.Separator) } filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { if err != nil || path == src { return nil } want := true // Avoid .foo, _foo, and testdata directory trees. _, elem := filepath.Split(path) if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { want = false } name := filepath.ToSlash(path[len(src):]) if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { // The name "std" is only the standard library. // If the name is cmd, it's the root of the command tree. want = false } if !treeCanMatch(name) { want = false } if !fi.IsDir() { if fi.Mode()&os.ModeSymlink != 0 && want { if target, err := os.Stat(path); err == nil && target.IsDir() { fmt.Fprintf(os.Stderr, "warning: ignoring symlink %s\n", path) } } return nil } if !want { return filepath.SkipDir } if have[name] { return nil } have[name] = true if !match(name) { return nil } pkg, err := c.BuildContext.ImportDir(path, 0) if err != nil { if _, noGo := err.(*build.NoGoError); noGo { return nil } } // If we are expanding "cmd", skip main // packages under cmd/vendor. At least as of // March, 2017, there is one there for the // vendored pprof tool. if pattern == "cmd" && strings.HasPrefix(pkg.ImportPath, "cmd/vendor") && pkg.Name == "main" { return nil } pkgs = append(pkgs, name) return nil }) } return pkgs } // MatchPackagesInFS returns a list of package paths matching pattern, // which must begin with ./ or ../ // (see go help packages for pattern syntax). func (c *Context) MatchPackagesInFS(pattern string) []string { // Find directory to begin the scan. // Could be smarter but this one optimization // is enough for now, since ... is usually at the // end of a path. i := strings.Index(pattern, "...") dir, _ := path.Split(pattern[:i]) // pattern begins with ./ or ../. // path.Clean will discard the ./ but not the ../. // We need to preserve the ./ for pattern matching // and in the returned import paths. prefix := "" if strings.HasPrefix(pattern, "./") { prefix = "./" } match := matchPattern(pattern) var pkgs []string filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { if err != nil || !fi.IsDir() { return nil } if path == dir { // filepath.Walk starts at dir and recurses. For the recursive case, // the path is the result of filepath.Join, which calls filepath.Clean. // The initial case is not Cleaned, though, so we do this explicitly. // // This converts a path like "./io/" to "io". Without this step, running // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io // package, because prepending the prefix "./" to the unclean path would // result in "././io", and match("././io") returns false. path = filepath.Clean(path) } // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". _, elem := filepath.Split(path) dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { return filepath.SkipDir } name := prefix + filepath.ToSlash(path) if !match(name) { return nil } // We keep the directory if we can import it, or if we can't import it // due to invalid Go source files. This means that directories containing // parse errors will be built (and fail) instead of being silently skipped // as not matching the pattern. Go 1.5 and earlier skipped, but that // behavior means people miss serious mistakes. // See golang.org/issue/11407. if p, err := c.BuildContext.ImportDir(path, 0); err != nil && (p == nil || len(p.InvalidGoFiles) == 0) { if _, noGo := err.(*build.NoGoError); !noGo { log.Print(err) } return nil } pkgs = append(pkgs, name) return nil }) return pkgs } // treeCanMatchPattern(pattern)(name) reports whether // name or children of name can possibly match pattern. // Pattern is the same limited glob accepted by matchPattern. func treeCanMatchPattern(pattern string) func(name string) bool { wildCard := false if i := strings.Index(pattern, "..."); i >= 0 { wildCard = true pattern = pattern[:i] } return func(name string) bool { return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || wildCard && strings.HasPrefix(name, pattern) } } // matchPattern(pattern)(name) reports whether // name matches pattern. Pattern is a limited glob // pattern in which '...' means 'any string' and there // is no other special syntax. // Unfortunately, there are two special cases. Quoting "go help packages": // // First, /... at the end of the pattern can match an empty string, // so that net/... matches both net and packages in its subdirectories, like net/http. // Second, any slash-separted pattern element containing a wildcard never // participates in a match of the "vendor" element in the path of a vendored // package, so that ./... does not match packages in subdirectories of // ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do. // Note, however, that a directory named vendor that itself contains code // is not a vendored package: cmd/vendor would be a command named vendor, // and the pattern cmd/... matches it. func matchPattern(pattern string) func(name string) bool { // Convert pattern to regular expression. // The strategy for the trailing /... is to nest it in an explicit ? expression. // The strategy for the vendor exclusion is to change the unmatchable // vendor strings to a disallowed code point (vendorChar) and to use // "(anything but that codepoint)*" as the implementation of the ... wildcard. // This is a bit complicated but the obvious alternative, // namely a hand-written search like in most shell glob matchers, // is too easy to make accidentally exponential. // Using package regexp guarantees linear-time matching. const vendorChar = "\x00" if strings.Contains(pattern, vendorChar) { return func(name string) bool { return false } } re := regexp.QuoteMeta(pattern) re = replaceVendor(re, vendorChar) switch { case strings.HasSuffix(re, `/`+vendorChar+`/\.\.\.`): re = strings.TrimSuffix(re, `/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)` case re == vendorChar+`/\.\.\.`: re = `(/vendor|/` + vendorChar + `/\.\.\.)` case strings.HasSuffix(re, `/\.\.\.`): re = strings.TrimSuffix(re, `/\.\.\.`) + `(/\.\.\.)?` } re = strings.Replace(re, `\.\.\.`, `[^`+vendorChar+`]*`, -1) reg := regexp.MustCompile(`^` + re + `$`) return func(name string) bool { if strings.Contains(name, vendorChar) { return false } return reg.MatchString(replaceVendor(name, vendorChar)) } } // replaceVendor returns the result of replacing // non-trailing vendor path elements in x with repl. func replaceVendor(x, repl string) string { if !strings.Contains(x, "vendor") { return x } elem := strings.Split(x, "/") for i := 0; i < len(elem)-1; i++ { if elem[i] == "vendor" { elem[i] = repl } } return strings.Join(elem, "/") } // ImportPaths returns the import paths to use for the given command line. func (c *Context) ImportPaths(args []string) []string { args = c.ImportPathsNoDotExpansion(args) var out []string for _, a := range args { if strings.Contains(a, "...") { if build.IsLocalImport(a) { out = append(out, c.allPackagesInFS(a)...) } else { out = append(out, c.allPackages(a)...) } continue } out = append(out, a) } return out } // ImportPathsNoDotExpansion returns the import paths to use for the given // command line, but it does no ... expansion. func (c *Context) ImportPathsNoDotExpansion(args []string) []string { if len(args) == 0 { return []string{"."} } var out []string for _, a := range args { // Arguments are supposed to be import paths, but // as a courtesy to Windows developers, rewrite \ to / // in command-line arguments. Handles .\... and so on. if filepath.Separator == '\\' { a = strings.Replace(a, `\`, `/`, -1) } // Put argument in canonical form, but preserve leading ./. if strings.HasPrefix(a, "./") { a = "./" + path.Clean(a) if a == "./." { a = "." } } else { a = path.Clean(a) } if IsMetaPackage(a) { out = append(out, c.allPackages(a)...) continue } out = append(out, a) } return out } // IsMetaPackage checks if name is a reserved package name that expands to multiple packages. func IsMetaPackage(name string) bool { return name == "std" || name == "cmd" || name == "all" } ================================================ FILE: _tools/src/github.com/kisielk/gotool/match.go ================================================ // Copyright (c) 2009 The Go Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +build go1.9 package gotool import ( "path/filepath" "github.com/kisielk/gotool/internal/load" ) // importPaths returns the import paths to use for the given command line. func (c *Context) importPaths(args []string) []string { lctx := load.Context{ BuildContext: c.BuildContext, GOROOTsrc: c.joinPath(c.BuildContext.GOROOT, "src"), } return lctx.ImportPaths(args) } // joinPath calls c.BuildContext.JoinPath (if not nil) or else filepath.Join. // // It's a copy of the unexported build.Context.joinPath helper. func (c *Context) joinPath(elem ...string) string { if f := c.BuildContext.JoinPath; f != nil { return f(elem...) } return filepath.Join(elem...) } ================================================ FILE: _tools/src/github.com/kisielk/gotool/match18.go ================================================ // Copyright (c) 2009 The Go Authors. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // +build !go1.9 package gotool import ( "fmt" "go/build" "log" "os" "path" "path/filepath" "regexp" "strings" ) // This file contains code from the Go distribution. // matchPattern(pattern)(name) reports whether // name matches pattern. Pattern is a limited glob // pattern in which '...' means 'any string' and there // is no other special syntax. func matchPattern(pattern string) func(name string) bool { re := regexp.QuoteMeta(pattern) re = strings.Replace(re, `\.\.\.`, `.*`, -1) // Special case: foo/... matches foo too. if strings.HasSuffix(re, `/.*`) { re = re[:len(re)-len(`/.*`)] + `(/.*)?` } reg := regexp.MustCompile(`^` + re + `$`) return reg.MatchString } // matchPackages returns a list of package paths matching pattern // (see go help packages for pattern syntax). func (c *Context) matchPackages(pattern string) []string { match := func(string) bool { return true } treeCanMatch := func(string) bool { return true } if !isMetaPackage(pattern) { match = matchPattern(pattern) treeCanMatch = treeCanMatchPattern(pattern) } have := map[string]bool{ "builtin": true, // ignore pseudo-package that exists only for documentation } if !c.BuildContext.CgoEnabled { have["runtime/cgo"] = true // ignore during walk } var pkgs []string for _, src := range c.BuildContext.SrcDirs() { if (pattern == "std" || pattern == "cmd") && src != gorootSrc { continue } src = filepath.Clean(src) + string(filepath.Separator) root := src if pattern == "cmd" { root += "cmd" + string(filepath.Separator) } filepath.Walk(root, func(path string, fi os.FileInfo, err error) error { if err != nil || !fi.IsDir() || path == src { return nil } // Avoid .foo, _foo, and testdata directory trees. _, elem := filepath.Split(path) if strings.HasPrefix(elem, ".") || strings.HasPrefix(elem, "_") || elem == "testdata" { return filepath.SkipDir } name := filepath.ToSlash(path[len(src):]) if pattern == "std" && (!isStandardImportPath(name) || name == "cmd") { // The name "std" is only the standard library. // If the name is cmd, it's the root of the command tree. return filepath.SkipDir } if !treeCanMatch(name) { return filepath.SkipDir } if have[name] { return nil } have[name] = true if !match(name) { return nil } _, err = c.BuildContext.ImportDir(path, 0) if err != nil { if _, noGo := err.(*build.NoGoError); noGo { return nil } } pkgs = append(pkgs, name) return nil }) } return pkgs } // importPathsNoDotExpansion returns the import paths to use for the given // command line, but it does no ... expansion. func (c *Context) importPathsNoDotExpansion(args []string) []string { if len(args) == 0 { return []string{"."} } var out []string for _, a := range args { // Arguments are supposed to be import paths, but // as a courtesy to Windows developers, rewrite \ to / // in command-line arguments. Handles .\... and so on. if filepath.Separator == '\\' { a = strings.Replace(a, `\`, `/`, -1) } // Put argument in canonical form, but preserve leading ./. if strings.HasPrefix(a, "./") { a = "./" + path.Clean(a) if a == "./." { a = "." } } else { a = path.Clean(a) } if isMetaPackage(a) { out = append(out, c.allPackages(a)...) continue } out = append(out, a) } return out } // importPaths returns the import paths to use for the given command line. func (c *Context) importPaths(args []string) []string { args = c.importPathsNoDotExpansion(args) var out []string for _, a := range args { if strings.Contains(a, "...") { if build.IsLocalImport(a) { out = append(out, c.allPackagesInFS(a)...) } else { out = append(out, c.allPackages(a)...) } continue } out = append(out, a) } return out } // allPackages returns all the packages that can be found // under the $GOPATH directories and $GOROOT matching pattern. // The pattern is either "all" (all packages), "std" (standard packages), // "cmd" (standard commands), or a path including "...". func (c *Context) allPackages(pattern string) []string { pkgs := c.matchPackages(pattern) if len(pkgs) == 0 { fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) } return pkgs } // allPackagesInFS is like allPackages but is passed a pattern // beginning ./ or ../, meaning it should scan the tree rooted // at the given directory. There are ... in the pattern too. func (c *Context) allPackagesInFS(pattern string) []string { pkgs := c.matchPackagesInFS(pattern) if len(pkgs) == 0 { fmt.Fprintf(os.Stderr, "warning: %q matched no packages\n", pattern) } return pkgs } // matchPackagesInFS returns a list of package paths matching pattern, // which must begin with ./ or ../ // (see go help packages for pattern syntax). func (c *Context) matchPackagesInFS(pattern string) []string { // Find directory to begin the scan. // Could be smarter but this one optimization // is enough for now, since ... is usually at the // end of a path. i := strings.Index(pattern, "...") dir, _ := path.Split(pattern[:i]) // pattern begins with ./ or ../. // path.Clean will discard the ./ but not the ../. // We need to preserve the ./ for pattern matching // and in the returned import paths. prefix := "" if strings.HasPrefix(pattern, "./") { prefix = "./" } match := matchPattern(pattern) var pkgs []string filepath.Walk(dir, func(path string, fi os.FileInfo, err error) error { if err != nil || !fi.IsDir() { return nil } if path == dir { // filepath.Walk starts at dir and recurses. For the recursive case, // the path is the result of filepath.Join, which calls filepath.Clean. // The initial case is not Cleaned, though, so we do this explicitly. // // This converts a path like "./io/" to "io". Without this step, running // "cd $GOROOT/src; go list ./io/..." would incorrectly skip the io // package, because prepending the prefix "./" to the unclean path would // result in "././io", and match("././io") returns false. path = filepath.Clean(path) } // Avoid .foo, _foo, and testdata directory trees, but do not avoid "." or "..". _, elem := filepath.Split(path) dot := strings.HasPrefix(elem, ".") && elem != "." && elem != ".." if dot || strings.HasPrefix(elem, "_") || elem == "testdata" { return filepath.SkipDir } name := prefix + filepath.ToSlash(path) if !match(name) { return nil } // We keep the directory if we can import it, or if we can't import it // due to invalid Go source files. This means that directories containing // parse errors will be built (and fail) instead of being silently skipped // as not matching the pattern. Go 1.5 and earlier skipped, but that // behavior means people miss serious mistakes. // See golang.org/issue/11407. if p, err := c.BuildContext.ImportDir(path, 0); err != nil && shouldIgnoreImport(p) { if _, noGo := err.(*build.NoGoError); !noGo { log.Print(err) } return nil } pkgs = append(pkgs, name) return nil }) return pkgs } // isMetaPackage checks if name is a reserved package name that expands to multiple packages. func isMetaPackage(name string) bool { return name == "std" || name == "cmd" || name == "all" } // isStandardImportPath reports whether $GOROOT/src/path should be considered // part of the standard distribution. For historical reasons we allow people to add // their own code to $GOROOT instead of using $GOPATH, but we assume that // code will start with a domain name (dot in the first element). func isStandardImportPath(path string) bool { i := strings.Index(path, "/") if i < 0 { i = len(path) } elem := path[:i] return !strings.Contains(elem, ".") } // hasPathPrefix reports whether the path s begins with the // elements in prefix. func hasPathPrefix(s, prefix string) bool { switch { default: return false case len(s) == len(prefix): return s == prefix case len(s) > len(prefix): if prefix != "" && prefix[len(prefix)-1] == '/' { return strings.HasPrefix(s, prefix) } return s[len(prefix)] == '/' && s[:len(prefix)] == prefix } } // treeCanMatchPattern(pattern)(name) reports whether // name or children of name can possibly match pattern. // Pattern is the same limited glob accepted by matchPattern. func treeCanMatchPattern(pattern string) func(name string) bool { wildCard := false if i := strings.Index(pattern, "..."); i >= 0 { wildCard = true pattern = pattern[:i] } return func(name string) bool { return len(name) <= len(pattern) && hasPathPrefix(pattern, name) || wildCard && strings.HasPrefix(name, pattern) } } ================================================ FILE: _tools/src/github.com/kisielk/gotool/tool.go ================================================ // Package gotool contains utility functions used to implement the standard // "cmd/go" tool, provided as a convenience to developers who want to write // tools with similar semantics. package gotool import "go/build" // Export functions here to make it easier to keep the implementations up to date with upstream. // DefaultContext is the default context that uses build.Default. var DefaultContext = Context{ BuildContext: build.Default, } // A Context specifies the supporting context. type Context struct { // BuildContext is the build.Context that is used when computing import paths. BuildContext build.Context } // ImportPaths returns the import paths to use for the given command line. // // The path "all" is expanded to all packages in $GOPATH and $GOROOT. // The path "std" is expanded to all packages in the Go standard library. // The path "cmd" is expanded to all Go standard commands. // The string "..." is treated as a wildcard within a path. // When matching recursively, directories are ignored if they are prefixed with // a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata". // Relative import paths are not converted to full import paths. // If args is empty, a single element "." is returned. func (c *Context) ImportPaths(args []string) []string { return c.importPaths(args) } // ImportPaths returns the import paths to use for the given command line // using default context. // // The path "all" is expanded to all packages in $GOPATH and $GOROOT. // The path "std" is expanded to all packages in the Go standard library. // The path "cmd" is expanded to all Go standard commands. // The string "..." is treated as a wildcard within a path. // When matching recursively, directories are ignored if they are prefixed with // a dot or an underscore (such as ".foo" or "_foo"), or are named "testdata". // Relative import paths are not converted to full import paths. // If args is empty, a single element "." is returned. func ImportPaths(args []string) []string { return DefaultContext.importPaths(args) } ================================================ FILE: _tools/src/github.com/twitchtv/retool/LICENSE ================================================ 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 2017 Twitch Interactive, Inc. 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. ================================================ FILE: _tools/src/github.com/twitchtv/retool/README.md ================================================ # Retool: Vendor thy tools! # [![Build Status](https://travis-ci.org/twitchtv/retool.svg?branch=master)](https://travis-ci.org/twitchtv/retool) [![Windows Build status](https://ci.appveyor.com/api/projects/status/06x2vd5nh683iscu/branch/master?svg=true&passingText=Windows%20build%20passing&pendingText=Windows%20build%20pending&failingText=Windows%20build%20failing)](https://ci.appveyor.com/project/spenczar/retool/branch/master) ## what is this ## retool helps manage the versions of _tools_ that you use with your repository. These are executables that are a crucial part of your development environment, but aren't imported by any of your code, so they don't get scooped up by glide or godep (or any other vendoring tool). Some examples of tools: - [github.com/tools/godep](https://github.com/tools/godep) is a tool to vendor Go packages. - [github.com/golang/protobuf/protoc-gen-go](https://github.com/golang/protobuf/protoc-gen-go) is a tool to compile Go code from protobuf definitions. - [github.com/maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) is a tool to generate mocks of interfaces. You want this if you use code generation: if everybody has a different version of the code generator, then you'll get meaningless churn across runs of the generator unless everyone is pinned to the right version. You might also want this if you use linters or tools like [github.com/kisielk/errcheck](https://github.com/kisielk/errcheck) in an automated fashion and you want to make sure that everyone has the same version so you can pass flags to the linter with confidence. retool pins on a per-project basis. It works by making a complete GOPATH within your project. You can choose to commit the source files for those tools, if you like. ## usage ## The expected workflow is something like this: Install retool: ```sh go get github.com/twitchtv/retool ``` Add a tool dependency: ```sh retool add github.com/jteeuwen/go-bindata/go-bindata origin/master ``` Use it to generate code: ```sh retool do go-bindata -pkg testdata -o ./testdata/testdata.go ./testdata/data.json ``` --- There are a few other commands that you'll use much less often: Upgrade a tool to its latest version: ```sh retool upgrade github.com/spf13/hugo origin/master # or to a particular tag retool upgrade github.com/spf13/hugo v0.17 ``` Stop using that tool you dont like anymore: ```sh retool remove github.com/tools/godep ``` Compile all the tools that other people have vendored in a project: ```sh # compiles everything without using the network - useful for isolated build environments retool build ``` Double-check that you're in sync by comparing everything with upstream versions: ```sh # makes sure your tools match tools.json by comparing against their remotes retool sync ``` ## why would i need to manage these things ## **TL;DR:** if you work with anyone else on your project, and they have different versions of their tools, everything turns to shit. One of the best parts about Go is that it is very, very simple. This makes it straightforward to write code generation utilities. You don't need to generate code for every project, but in large ones, code generation can help you be much more productive. Like, if you're writing tests that use an interface, you can use code generation to quickly whip up structs which mock the interface so you can force them to return errors. This way, you can test edge cases for your interaction points with interfaces. [github.com/maxbrunsfeld/counterfeiter](https://github.com/maxbrunsfeld/counterfeiter) does this pretty well! If you want to use the generated code, you should check in the generated `.go` code to git, not just the sources, so that build boxes and the like don't need all these code generation tools, and so that `go get` just works cleanly. This poses a problem, though, as soon as you start working with other people on your project: if you have different versions of your code generation tools, which generate slightly different output, you'll get lots of meaningless churn in your commits. This sucks! There has to be a better way! ## the retool way ## retool records the versions of tools you want in a file, `tools.json`. The file looks like this: ```json { "Tools": [ { "Repository": "github.com/golang/protobuf/protoc-gen-go", "Commit": "2fea9e168bab814ca0c6e292a6be164f624fc6ca" } ] } ``` Tools are identified by repo and commit. Each tool in `tools.json` will be installed to `_tools`, which is a private GOPATH just dedicated to keeping track of these tools. In practice, you don't need to know much about `tools.json`. You check it in to git so that everybody stays in sync, but you manage it with `retool add|upgrade|remove`. When it's time to generate code, **instead of `go generate ./...`**, you use `retool do go generate ./...` to use your sweet, vendored tools. This really just calls `PATH=$PWD/_tools/bin:PATH go generate ./...`; if you want to do anything fancy, you can feel free to use that path too. ## contributing to retool ## Any pull requests are extremely welcome! If you run into problems or have questions, please raise a github issue! Retool's tests are mostly integration tests. They require a working Go compiler, a working version of git, and network access. ================================================ FILE: _tools/src/github.com/twitchtv/retool/add.go ================================================ package main func (s spec) add(t *tool) { if s.find(t) != -1 { log(t.Repository + " already installed (did you mean retool upgrade?)") return } s.Tools = append(s.Tools, t) s.sync() err := s.write() if err != nil { fatal("unable to add "+t.Repository, err) } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/build.go ================================================ package main // builds all tools in the spec file using whatever is installed in the tool directory (_tools, // typically). Shouldn't do any network if _tools is set up correctly. func (s spec) build() { err := setGoEnv() if err != nil { fatal("unable to set GOPATH and GOBIN env variables", err) } m := getManifest() for _, t := range s.Tools { err := install(t) if err != nil { fatalExec("go install "+t.Repository, err) } } m.replace(s.Tools) m.write() } ================================================ FILE: _tools/src/github.com/twitchtv/retool/clean.go ================================================ package main import ( "fmt" "go/build" "os" "path/filepath" "strings" ) type stringSet map[string]struct{} func (ss stringSet) add(val string) { ss[val] = struct{}{} } func (ss stringSet) has(val string) bool { _, ok := ss[val] return ok } // compute the set of dependencies for a list of packages. The packages must // already be present in toolDirPath. func dependencies(pkgs []string) stringSet { deps := stringSet{} buildCtx := build.Default buildCtx.GOPATH = toolDirPath var resolve func(string, []string) resolve = func(parent string, pkgs []string) { for _, pkg := range pkgs { if !strings.Contains(pkg, ".") { continue } p, err := buildCtx.Import(pkg, filepath.Join(toolDirPath, "src", parent), 0) if err != nil { fatal(fmt.Sprintf("couldn't import package %q", pkg), err) } if deps.has(p.ImportPath) { continue } deps.add(p.ImportPath) resolve(p.ImportPath, p.Imports) } } resolve("", pkgs) return deps } // Remove unused files and unused packages from toolDirPath. func clean(pkgs []string) { deps := dependencies(pkgs) base := filepath.Join(toolDirPath, "src") // Resolve any symlinks in the packages to keep, because we're going // to walk through the file system, so we need to trim stuff by // _filename_. for pkgPath := range deps { fullPath := filepath.Join(base, pkgPath) resolved, err := filepath.EvalSymlinks(fullPath) if err != nil { fatal(fmt.Sprintf("couldn't eval symlinks in %q", pkgPath), err) } // Undo the filepath.Join from above pkgPath, err = filepath.Rel(base, resolved) if err != nil { fatal(fmt.Sprintf("couldn't eval symlinks in %q", pkgPath), err) } deps.add(pkgPath) } var toDelete []string err := filepath.Walk(base, func(path string, info os.FileInfo, err error) error { // Bubble up errors if err != nil { return err } // Skip the root directory if base == path { return nil } // Get the package directory pkg, err := filepath.Rel(base, path) if err != nil { return err } // Delete files in packages that aren't in packages we need to build the // tools, and any non-go, non-legal files in packages we *do* need. if info.Mode().IsRegular() { pkg = filepath.Dir(pkg) if !(deps.has(pkg) && keepFile(path)) { toDelete = append(toDelete, path) } return nil } // If the path is a directory that's specially marked for preservation, keep // it and all its contents. if info.IsDir() && preserveDirectory(path) { return filepath.SkipDir } // If the folder is a kept package or a parent, don't delete it and keep recursing for p := range deps { if strings.HasPrefix(p, pkg) { return nil } } // Otherwise this is a package that isn't imported at all. Delete it and stop recursing toDelete = append(toDelete, path) return filepath.SkipDir }) if err != nil { fatal("unable to clean _tools", err) } for _, path := range toDelete { err = os.RemoveAll(path) if err != nil { fatal("unable to remove file or directory", err) } } } func keepFile(filename string) bool { if strings.HasSuffix(filename, "_test.go") { return false } switch filepath.Ext(filename) { case ".go", ".s", ".c", ".h": return true } if isLegalFile(filename) { return true } return false } var commonLegalFilePrefixes = []string{ "licence", // UK spelling "license", // US spelling "copying", "unlicense", "copyright", "copyleft", "authors", "contributors", "readme", // often has a license inline } var commonLegalFileSubstrings = []string{ "legal", "notice", "disclaimer", "patent", "third-party", "thirdparty", } func isLegalFile(filename string) bool { base := strings.ToLower(filepath.Base(filename)) for _, p := range commonLegalFilePrefixes { if strings.HasPrefix(base, p) { return true } } for _, s := range commonLegalFileSubstrings { if strings.Contains(base, s) { return true } } return false } // List of directories that should be completely preserved if they are present. var preservedDirectories = []string{ // gometalinter vendors its own linters and relies on this directory's // existence. See issue #7. filepath.Join("github.com", "alecthomas", "gometalinter", "_linters"), // sqlboiler requires template files to exist at runtime. See pull request #25. filepath.Join("github.com", "vattle", "sqlboiler", "templates"), filepath.Join("github.com", "vattle", "sqlboiler", "templates_test"), filepath.Join("github.com", "volatiletech", "sqlboiler", "templates"), filepath.Join("github.com", "volatiletech", "sqlboiler", "templates_test"), } // checks whether path is in the list of preserved directories. func preserveDirectory(path string) bool { for _, d := range preservedDirectories { if strings.HasSuffix(path, d) { return true } } return false } ================================================ FILE: _tools/src/github.com/twitchtv/retool/do.go ================================================ package main import ( "os" "os/exec" "path/filepath" "strings" ) func setPath() error { prevpath := os.Getenv("PATH") newPath := filepath.Join(toolDirPath, "bin") + string(os.PathListSeparator) + prevpath return os.Setenv("PATH", newPath) } // setGoEnv sets GOBIN and GOPATH to point to _tools/bin and $GOPATH:_tools, // respectively. This is done for github.com/alecthomas/gometalinter // compatibility: gometalinter vendors its own linters, and checks for their // existence by checking in each GOPATH entry for // src/github.com/alecthomas/gometalinter/_linters. // // GOBIN is set so gometalinter will use it to decide where to put its vendored // linters with the gometalinter --install command, and so that it prefers the // binaries built in _tools/bin when executing linters. func setGoEnv() error { newGoBin := filepath.Join(toolDirPath, "bin") if err := os.Setenv("GOBIN", newGoBin); err != nil { return err } prevGoPath := os.Getenv("GOPATH") newGoPath := prevGoPath + string(os.PathListSeparator) + toolDirPath return os.Setenv("GOPATH", newGoPath) } func do() { args := positionalArgs if len(args) == 0 { fatal("no command passed to retool do", nil) } if err := setPath(); err != nil { fatal("unable to set PATH", err) } if err := setGoEnv(); err != nil { fatal("unable to set up go environment variables", err) } cmd := exec.Command(args[0], args[1:]...) cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr cmd.Stdout = os.Stdout err := cmd.Run() if err != nil { msg := "failed on '" + strings.Join(args, " ") + "'" fatal(msg, err) } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/input.go ================================================ package main import ( "flag" "fmt" "os" ) var ( verboseFlag = flag.Bool("verbose", false, "Enable more detailed output that may be helpful for troubleshooting.") forkFlag = flag.String("f", "", "Use a fork of the repository rather than the default upstream") // TODO: Refactor so that this global state is not necessary. positionalArgs []string ) func verbosef(format string, a ...interface{}) { if *verboseFlag { _, _ = fmt.Fprintf(os.Stderr, format, a...) } } func parseArgs() (command string, t *tool) { if !flag.Parsed() { panic("parseArgs expects that flags have already been parsed") } args := flag.Args() if len(args) < 1 { printUsageAndExit("", 1) } command = args[0] args = args[1:] t = new(tool) positionalArgs = args switch command { case "version": assertArgLength(args, command, 0) return "version", t case "sync": assertArgLength(args, command, 0) return "sync", t case "add": assertArgLength(args, command, 2) t.Repository = args[0] t.ref = args[1] t.Fork = *forkFlag return "add", t case "upgrade": assertArgLength(args, command, 2) t.Repository = args[0] t.ref = args[1] t.Fork = *forkFlag return "upgrade", t case "remove": assertArgLength(args, command, 1) t.Repository = args[0] return "remove", t case "do": // A variable number of arguments are permissible for the 'do' subcommand; they are passed via t.PositionalArgs. return "do", t case "clean": assertArgLength(args, command, 0) return "clean", t case "build": assertArgLength(args, command, 0) return "build", t case "help": assertArgLength(args, command, 1) printUsageAndExit(args[0], 0) default: printUsageAndExit("", 1) } return "", t } func assertArgLength(args []string, command string, arglength int) { if len(args) != arglength { printUsageAndExit(command, 1) } } func printUsageAndExit(command string, exitCode int) { switch command { case "add": fmt.Println(addUsage) case "remove": fmt.Println(removeUsage) case "upgrade": fmt.Println(upgradeUsage) case "sync": fmt.Println(syncUsage) case "do": fmt.Println(doUsage) case "clean": fmt.Println(cleanUsage) case "build": fmt.Println(buildUsage) default: fmt.Println(usage) } os.Exit(exitCode) } const usage = `usage: retool (add | remove | upgrade | sync | do | build | help) use retool with a subcommand: add will add a tool remove will remove a tool upgrade will upgrade a tool sync will synchronize your _tools with tools.json, downloading if necessary build will compile all the tools in _tools do will run stuff using your installed tools help [command] will describe a command in more detail version will print the installed version of retool ` const addUsage = `usage: retool add [repository] [commit] eg: retool add github.com/tools/godep 3020345802e4bff23902cfc1d19e90a79fae714e Add will mark a repository as a tool you want to use. It will rewrite tools.json to record this fact. It will then fetch the repository, reset it to the desired commit, and install it to _tools/bin. You can also use a symbolic reference, like 'master' or 'origin/master' or 'origin/v1.0'. Retool will end up parsing this and storing the underlying SHA. ` const upgradeUsage = `usage: retool upgrade [repository] [commit] eg: retool upgrade github.com/tools/godep 3020345802e4bff23902cfc1d19e90a79fae714e Upgrade set the commit SHA of a tool you want to use. It will rewrite tools.json to record this fact. It will then fetch the repository, reset it to the desired commit, and install it to _tools/bin. You can also use a symbolic reference, like 'master' or 'origin/master' or 'origin/v1.0'. Retool will end up parsing this and storing the underlying SHA. ` const removeUsage = `usage: retool remove [repository] eg: retool remove github.com/tools/godep Remove will remove a tool from your tools.json. It won't delete the underlying repo from _tools, because it might be a dependency of some other tool. If you want to clean things up, retool sync will clear out unused dependencies. ` const syncUsage = `usage: retool sync Sync will synchronize your _tools directory to match tools.json. It will do this by making network calls to download tools and set them to the right versions. If you want to just install whatever is in _tools/src without using network, see 'retool build'. ` const doUsage = `usage: retool do [command and args] retool do will make sure your _tools directory is synced, and then execute a command with the tools installed in _tools. This is just retool sync && PATH=$PWD/_tools/bin:$PATH [command and args] That works too. ` const cleanUsage = `usage: retool clean retool clean has no effect, but still exists for compatibility. ` const buildUsage = `usage: retool build retool build will compile all the tools listed in tools.json, obeying whatever is currently downloaded into _tools. It will not do additional network calls. This is typically useful for compiling vendored tools so you can use them inside isolated environments. retool sync is the more full-featured version of retool build. It will actually do git fetches to make sure the right stuff gets installed, but this requires network access. ` ================================================ FILE: _tools/src/github.com/twitchtv/retool/main.go ================================================ package main import ( "flag" "fmt" "os" "github.com/Masterminds/semver" ) var version = semver.MustParse("v1.3.5") func main() { flag.Parse() if err := ensureTooldir(); err != nil { fatal("failed to locate or create tool directory", err) } cmd, tool := parseArgs() if cmd == "version" { fmt.Fprintf(os.Stdout, "retool %s", version) os.Exit(0) } if !specExists() { if cmd == "add" { err := writeBlankSpec() if err != nil { fatal("failed to write blank spec", err) } } else { fatal("tools.json does not yet exist. You need to add a tool first with 'retool add'", nil) } } s, err := read() if err != nil { fatal("failed to load tools.json", err) } switch cmd { case "add": s.add(tool) case "upgrade": s.upgrade(tool) case "remove": s.remove(tool) case "build": s.build() case "sync": s.sync() case "do": s.sync() do() case "clean": log("the clean subcommand is deprecated and has no effect") default: fatal(fmt.Sprintf("unknown cmd %q", cmd), nil) } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/manifest.go ================================================ package main import ( "encoding/json" "os" "path/filepath" ) const manifestFile = "manifest.json" type manifest map[string]string func getManifest() manifest { m := manifest{} file, err := os.Open(filepath.Join(toolDirPath, manifestFile)) if err != nil { return m } defer func() { _ = file.Close() }() err = json.NewDecoder(file).Decode(&m) if err != nil { fatal("Failed to decode manifest", err) } return m } func (m manifest) write() { f, err := os.Create(filepath.Join(toolDirPath, manifestFile)) if err != nil { return } defer func() { _ = f.Close() }() bytes, err := json.MarshalIndent(m, "", " ") if err != nil { return } _, _ = f.Write(bytes) } func (m manifest) outOfDate(ts []*tool) bool { // Make a copy to check for elements in ts but not m m2 := make(map[string]string) for k, v := range m { m2[k] = v } for _, t := range ts { if v, ok := m[t.Repository]; !ok || v != t.Commit { return true } delete(m2, t.Repository) } return len(m2) != 0 } func (m manifest) replace(ts []*tool) { for k := range m { delete(m, k) } for _, t := range ts { m[t.Repository] = t.Commit } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/print.go ================================================ package main import ( "fmt" "os" "os/exec" "github.com/pkg/errors" ) func log(msg string) { fmt.Fprintf(os.Stderr, "retool: %s\n", msg) } func fatal(msg string, err error) { if err == nil { fmt.Fprintf(os.Stderr, "retool: fatal err: %s\n", msg) } else { fmt.Fprintf(os.Stderr, "retool: fatal err: %s: %s\n", msg, err) } os.Exit(1) } func fatalExec(cmd string, err error) { if exErr, ok := errors.Cause(err).(*exec.ExitError); ok { fatal(fmt.Sprintf("execution error on %q: %s", cmd, exErr.Stderr), err) } else { fatal(fmt.Sprintf("execution error on %q", cmd), err) } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/remove.go ================================================ package main func (s spec) remove(t *tool) { idx := s.find(t) if idx == -1 { fatal(t.Repository+" is not in tools.json", nil) } s.Tools = append(s.Tools[:idx], s.Tools[idx+1:]...) err := s.write() if err != nil { fatal("unable to remove "+t.Repository, err) } s.sync() } ================================================ FILE: _tools/src/github.com/twitchtv/retool/spec.go ================================================ package main import ( "encoding/json" "fmt" "os" "path/filepath" "github.com/Masterminds/semver" ) // Filename to read/write the spec data. const specfile = "tools.json" type spec struct { Tools []*tool RetoolVersion *semver.Version } // jsonSpec is a helper type to describe the JSON encoding of a spec type jsonSpec struct { Tools []*tool RetoolVersion string } func (s *spec) UnmarshalJSON(data []byte) error { js := new(jsonSpec) if err := json.Unmarshal(data, js); err != nil { return err } if js.RetoolVersion != "" { v, err := semver.NewVersion(js.RetoolVersion) if err != nil { return err } s.RetoolVersion = v } s.Tools = js.Tools return nil } func (s spec) MarshalJSON() ([]byte, error) { return json.Marshal(&jsonSpec{ Tools: s.Tools, RetoolVersion: s.RetoolVersion.String(), }) } func (s spec) write() error { specfilePath := filepath.Join(baseDirPath, specfile) f, err := os.Create(specfilePath) if err != nil { return fmt.Errorf("unable to open %s: %s", specfile, err) } defer func() { _ = f.Close() }() // s.write() is called when we have successfully added, removed, or upgraded a // tool. The success of that operation indicates that we should be comfortable // bumping up this version. s.RetoolVersion = version bytes, err := json.MarshalIndent(s, "", " ") if err != nil { return fmt.Errorf("unable to marshal json spec: %s", err) } _, err = f.Write(bytes) if err != nil { return fmt.Errorf("unable to write %s: %s", specfile, err) } return nil } func (s spec) find(t *tool) int { for i, tt := range s.Tools { if t.Repository == tt.Repository { return i } } return -1 } func (s spec) cleanup() { var pkgs []string for _, t := range s.Tools { pkgs = append(pkgs, t.Repository) } clean(pkgs) } func readPath(path string) (spec, error) { file, err := os.Open(path) if err != nil { return spec{}, fmt.Errorf("unable to open spec file at %s: %s", path, err) } defer func() { _ = file.Close() }() s := new(spec) err = json.NewDecoder(file).Decode(s) if err != nil { return spec{}, err } return *s, nil } func read() (spec, error) { specfilePath := filepath.Join(baseDirPath, specfile) return readPath(specfilePath) } func specExists() bool { specfilePath := filepath.Join(baseDirPath, specfile) _, err := os.Stat(specfilePath) if os.IsNotExist(err) { return false } if err != nil { fatal("unable to stat tools.json: %s", err) } return true } func writeBlankSpec() error { return spec{ Tools: []*tool{}, RetoolVersion: version, }.write() } ================================================ FILE: _tools/src/github.com/twitchtv/retool/sync.go ================================================ package main import "os" func (s spec) sync() { m := getManifest() if m.outOfDate(s.Tools) { // Delete existing tools directory err := os.RemoveAll(toolDirPath) if err != nil { fatalExec("failed to remove _tools ", err) } // Recreate the tools directory err = ensureTooldir() if err != nil { fatal("failed to ensure tool dir", err) } // Download everything to tool directory for _, t := range s.Tools { err = download(t) if err != nil { fatalExec("failed to sync "+t.Repository, err) } } // Install the packages s.build() // Delete unneccessary source files s.cleanup() } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/tool.go ================================================ package main import ( "fmt" "os" "os/exec" "path/filepath" "strings" "github.com/pkg/errors" ) type tool struct { Repository string // eg "github.com/tools/godep" Commit string // eg "3020345802e4bff23902cfc1d19e90a79fae714e" ref string // eg "origin/master" Fork string `json:"Fork,omitempty"` // eg "code.jusin.tv/twitch/godep" } func (t *tool) path() string { return filepath.Join(toolDirPath, "src", t.Repository) } func (t *tool) executable() string { return filepath.Base(t.Repository) } func setEnvVar(cmd *exec.Cmd, key, val string) { var env []string if cmd.Env != nil { env = cmd.Env } else { env = os.Environ() } envSet := false for i, envVar := range env { if strings.HasPrefix(envVar, key+"=") { env[i] = key + "=" + val envSet = true } } if !envSet { env = append(cmd.Env, key+"="+val) } cmd.Env = env } func get(t *tool) error { log("downloading " + t.Repository) cmd := exec.Command("go", "get", "-d", t.Repository) setEnvVar(cmd, "GOPATH", toolDirPath) _, err := cmd.Output() if err != nil { return errors.Wrap(err, "failed to 'go get' tool") } return err } func setVersion(t *tool) error { // If we're using a fork, add it if t.Fork != "" { cmd := exec.Command("git", "remote") cmd.Dir = t.path() b, err := cmd.Output() if err != nil { return err } rs := strings.Split(string(b), "\n") containsFork := false for _, r := range rs { if r == "fork" { containsFork = true break } } if containsFork { cmd = exec.Command("git", "remote", "rm", "fork") cmd.Dir = t.path() _, err = cmd.Output() if err != nil { return err } } cmd = exec.Command("git", "remote", "add", "-f", "fork", t.Fork) cmd.Dir = t.path() _, err = cmd.Output() if err != nil { return err } } log("setting version for " + t.Repository) cmd := exec.Command("git", "fetch") cmd.Dir = t.path() _, err := cmd.Output() if err != nil { return err } // If we have a symbolic reference, parse it if t.ref != "" { log(fmt.Sprintf("parsing revision %q", t.ref)) cmd = exec.Command("git", "rev-parse", t.ref) cmd.Dir = t.path() var out []byte out, err = cmd.Output() if err != nil { return err } t.Commit = strings.TrimSpace(string(out)) log(fmt.Sprintf("parsed as %q", t.Commit)) } cmd = exec.Command("git", "checkout", t.Commit) cmd.Dir = t.path() _, err = cmd.Output() if err != nil { return errors.Wrap(err, "failed to 'git checkout' tool") } // Re-run 'go get' in case the new version has a different set of dependencies. cmd = exec.Command("go", "get", "-d", t.Repository) setEnvVar(cmd, "GOPATH", toolDirPath) _, err = cmd.Output() if err != nil { return errors.Wrap(err, "failed to 'go get' tool") } return err } func download(t *tool) error { err := get(t) if err != nil { fatalExec("go get -d "+t.Repository, err) } err = setVersion(t) if err != nil { fatalExec("git checkout "+t.Commit, err) } return nil } func install(t *tool) error { log("installing " + t.Repository) cmd := exec.Command("go", "install", t.Repository) setEnvVar(cmd, "GOPATH", toolDirPath) _, err := cmd.Output() if err != nil { return errors.Wrap(err, "failed to 'go install' tool") } return err } ================================================ FILE: _tools/src/github.com/twitchtv/retool/tooldir.go ================================================ package main import ( "flag" "io/ioutil" "os" "os/exec" "path" "path/filepath" "strings" "syscall" "github.com/pkg/errors" ) const ( toolDirName = "_tools" ) var ( baseDir = flag.String("base-dir", "", "Path of project root. If not specified and the working directory is within a git repository, the root of "+ "the repository is used. If the working directory is not within a git repository, the working directory "+ "is used.") toolDir = flag.String("tool-dir", "", "Path where tools are stored. The default value is the subdirectory of -base-dir named '_tools'.") // These globals are set by ensureTooldir() after factoring in the flags above. baseDirPath string toolDirPath string ) // If the working directory is within a git repository, return the path of the repository's root; otherwise, return the // empty string. An error is returned iff invoking 'git' fails for some other reason. func getRepoRoot() (string, error) { cmd := exec.Command("git", "rev-parse", "--show-toplevel") stdout, err := cmd.Output() if err != nil { if exitErr, ok := err.(*exec.ExitError); ok { exitStatus := exitErr.Sys().(syscall.WaitStatus).ExitStatus() if exitStatus == 128 { // not in a repository return "", nil } } return "", errors.Wrap(err, "failed to invoke git") } repoRoot := strings.TrimSpace(string(stdout)) return repoRoot, nil } func ensureTooldir() error { var err error baseDirPath = *baseDir if baseDirPath == "" { var repoRootPath string repoRootPath, err = getRepoRoot() if err != nil { return errors.Wrap(err, "failed to check for enclosing git repository") } if repoRootPath == "" { baseDirPath, err = os.Getwd() if err != nil { return errors.Wrap(err, "failed to get working directory") } } else { baseDirPath = repoRootPath } } toolDirPath = *toolDir if toolDirPath == "" { toolDirPath = filepath.Join(baseDirPath, toolDirName) } verbosef("base dir: %v\n", baseDirPath) verbosef("tool dir: %v\n", toolDirPath) stat, err := os.Stat(toolDirPath) switch { case os.IsNotExist(err): err = os.Mkdir(toolDirPath, 0777) if err != nil { return errors.Wrap(err, "unable to create tooldir") } case err != nil: return errors.Wrap(err, "unable to stat tool directory") case !stat.IsDir(): return errors.New("tool directory already exists, but it is not a directory; you can use -tool-dir to change where tools are saved") } err = ioutil.WriteFile(path.Join(toolDirPath, ".gitignore"), gitignore, 0664) if err != nil { return errors.Wrap(err, "unable to update .gitignore") } return nil } var gitignore = []byte(strings.TrimLeft(` /bin/ /pkg/ /manifest.json `, "\n")) ================================================ FILE: _tools/src/github.com/twitchtv/retool/upgrade.go ================================================ package main func (s spec) upgrade(t *tool) { idx := s.find(t) if idx == -1 { log(t.Repository + " is not yet installed (did you mean retool add?)") return } s.Tools[idx] = t s.sync() err := s.write() if err != nil { fatal("unable to remove "+t.Repository, err) } } ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/LICENSE.txt ================================================ The Masterminds Copyright (C) 2014-2015, Matt Butcher and Matt Farina Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/README.md ================================================ # SemVer The `semver` package provides the ability to work with [Semantic Versions](http://semver.org) in Go. Specifically it provides the ability to: * Parse semantic versions * Sort semantic versions * Check if a semantic version fits within a set of constraints * Optionally work with a `v` prefix [![Build Status](https://travis-ci.org/Masterminds/semver.svg)](https://travis-ci.org/Masterminds/semver) [![Build status](https://ci.appveyor.com/api/projects/status/jfk66lib7hb985k8/branch/master?svg=true&passingText=windows%20build%20passing&failingText=windows%20build%20failing)](https://ci.appveyor.com/project/mattfarina/semver/branch/master) [![GoDoc](https://godoc.org/github.com/Masterminds/semver?status.png)](https://godoc.org/github.com/Masterminds/semver) [![Go Report Card](https://goreportcard.com/badge/github.com/Masterminds/semver)](https://goreportcard.com/report/github.com/Masterminds/semver) ## Parsing Semantic Versions To parse a semantic version use the `NewVersion` function. For example, ```go v, err := semver.NewVersion("1.2.3-beta.1+build345") ``` If there is an error the version wasn't parseable. The version object has methods to get the parts of the version, compare it to other versions, convert the version back into a string, and get the original string. For more details please see the [documentation](https://godoc.org/github.com/Masterminds/semver). ## Sorting Semantic Versions A set of versions can be sorted using the [`sort`](https://golang.org/pkg/sort/) package from the standard library. For example, ```go raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} vs := make([]*semver.Version, len(raw)) for i, r := range raw { v, err := semver.NewVersion(r) if err != nil { t.Errorf("Error parsing version: %s", err) } vs[i] = v } sort.Sort(semver.Collection(vs)) ``` ## Checking Version Constraints Checking a version against version constraints is one of the most featureful parts of the package. ```go c, err := semver.NewConstraint(">= 1.2.3") if err != nil { // Handle constraint not being parseable. } v, _ := semver.NewVersion("1.3") if err != nil { // Handle version not being parseable. } // Check if the version meets the constraints. The a variable will be true. a := c.Check(v) ``` ## Basic Comparisons There are two elements to the comparisons. First, a comparison string is a list of comma separated and comparisons. These are then separated by || separated or comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a comparison that's greater than or equal to 1.2 and less than 3.0.0 or is greater than or equal to 4.2.3. The basic comparisons are: * `=`: equal (aliased to no operator) * `!=`: not equal * `>`: greater than * `<`: less than * `>=`: greater than or equal to * `<=`: less than or equal to _Note, according to the Semantic Version specification pre-releases may not be API compliant with their release counterpart. It says,_ > _A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version._ _SemVer comparisons without a pre-release value will skip pre-release versions. For example, `>1.2.3` will skip pre-releases when looking at a list of values while `>1.2.3-alpha.1` will evaluate pre-releases._ ## Hyphen Range Comparisons There are multiple methods to handle ranges and the first is hyphens ranges. These look like: * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` ## Wildcards In Comparisons The `x`, `X`, and `*` characters can be used as a wildcard character. This works for all comparison operators. When used on the `=` operator it falls back to the pack level comparison (see tilde below). For example, * `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` * `>= 1.2.x` is equivalent to `>= 1.2.0` * `<= 2.x` is equivalent to `<= 3` * `*` is equivalent to `>= 0.0.0` ## Tilde Range Comparisons (Patch) The tilde (`~`) comparison operator is for patch level ranges when a minor version is specified and major level changes when the minor number is missing. For example, * `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` * `~1` is equivalent to `>= 1, < 2` * `~2.3` is equivalent to `>= 2.3, < 2.4` * `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` * `~1.x` is equivalent to `>= 1, < 2` ## Caret Range Comparisons (Major) The caret (`^`) comparison operator is for major level changes. This is useful when comparisons of API versions as a major change is API breaking. For example, * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` * `^2.3` is equivalent to `>= 2.3, < 3` * `^2.x` is equivalent to `>= 2.0.0, < 3` # Validation In addition to testing a version against a constraint, a version can be validated against a constraint. When validation fails a slice of errors containing why a version didn't meet the constraint is returned. For example, ```go c, err := semver.NewConstraint("<= 1.2.3, >= 1.4") if err != nil { // Handle constraint not being parseable. } v, _ := semver.NewVersion("1.3") if err != nil { // Handle version not being parseable. } // Validate a version against a constraint. a, msgs := c.Validate(v) // a is false for _, m := range msgs { fmt.Println(m) // Loops over the errors which would read // "1.3 is greater than 1.2.3" // "1.3 is less than 1.4" } ``` # Contribute If you find an issue or want to contribute please file an [issue](https://github.com/Masterminds/semver/issues) or [create a pull request](https://github.com/Masterminds/semver/pulls). ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/collection.go ================================================ package semver // Collection is a collection of Version instances and implements the sort // interface. See the sort package for more details. // https://golang.org/pkg/sort/ type Collection []*Version // Len returns the length of a collection. The number of Version instances // on the slice. func (c Collection) Len() int { return len(c) } // Less is needed for the sort interface to compare two Version objects on the // slice. If checks if one is less than the other. func (c Collection) Less(i, j int) bool { return c[i].LessThan(c[j]) } // Swap is needed for the sort interface to replace the Version objects // at two different positions in the slice. func (c Collection) Swap(i, j int) { c[i], c[j] = c[j], c[i] } ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/constraints.go ================================================ package semver import ( "errors" "fmt" "regexp" "strings" ) // Constraints is one or more constraint that a semantic version can be // checked against. type Constraints struct { constraints [][]*constraint } // NewConstraint returns a Constraints instance that a Version instance can // be checked against. If there is a parse error it will be returned. func NewConstraint(c string) (*Constraints, error) { // Rewrite - ranges into a comparison operation. c = rewriteRange(c) ors := strings.Split(c, "||") or := make([][]*constraint, len(ors)) for k, v := range ors { cs := strings.Split(v, ",") result := make([]*constraint, len(cs)) for i, s := range cs { pc, err := parseConstraint(s) if err != nil { return nil, err } result[i] = pc } or[k] = result } o := &Constraints{constraints: or} return o, nil } // Check tests if a version satisfies the constraints. func (cs Constraints) Check(v *Version) bool { // loop over the ORs and check the inner ANDs for _, o := range cs.constraints { joy := true for _, c := range o { if !c.check(v) { joy = false break } } if joy { return true } } return false } // Validate checks if a version satisfies a constraint. If not a slice of // reasons for the failure are returned in addition to a bool. func (cs Constraints) Validate(v *Version) (bool, []error) { // loop over the ORs and check the inner ANDs var e []error for _, o := range cs.constraints { joy := true for _, c := range o { if !c.check(v) { em := fmt.Errorf(c.msg, v, c.orig) e = append(e, em) joy = false } } if joy { return true, []error{} } } return false, e } var constraintOps map[string]cfunc var constraintMsg map[string]string var constraintRegex *regexp.Regexp func init() { constraintOps = map[string]cfunc{ "": constraintTildeOrEqual, "=": constraintTildeOrEqual, "!=": constraintNotEqual, ">": constraintGreaterThan, "<": constraintLessThan, ">=": constraintGreaterThanEqual, "=>": constraintGreaterThanEqual, "<=": constraintLessThanEqual, "=<": constraintLessThanEqual, "~": constraintTilde, "~>": constraintTilde, "^": constraintCaret, } constraintMsg = map[string]string{ "": "%s is not equal to %s", "=": "%s is not equal to %s", "!=": "%s is equal to %s", ">": "%s is less than or equal to %s", "<": "%s is greater than or equal to %s", ">=": "%s is less than %s", "=>": "%s is less than %s", "<=": "%s is greater than %s", "=<": "%s is greater than %s", "~": "%s does not have same major and minor version as %s", "~>": "%s does not have same major and minor version as %s", "^": "%s does not have same major version as %s", } ops := make([]string, 0, len(constraintOps)) for k := range constraintOps { ops = append(ops, regexp.QuoteMeta(k)) } constraintRegex = regexp.MustCompile(fmt.Sprintf( `^\s*(%s)\s*(%s)\s*$`, strings.Join(ops, "|"), cvRegex)) constraintRangeRegex = regexp.MustCompile(fmt.Sprintf( `\s*(%s)\s+-\s+(%s)\s*`, cvRegex, cvRegex)) } // An individual constraint type constraint struct { // The callback function for the restraint. It performs the logic for // the constraint. function cfunc msg string // The version used in the constraint check. For example, if a constraint // is '<= 2.0.0' the con a version instance representing 2.0.0. con *Version // The original parsed version (e.g., 4.x from != 4.x) orig string // When an x is used as part of the version (e.g., 1.x) minorDirty bool dirty bool patchDirty bool } // Check if a version meets the constraint func (c *constraint) check(v *Version) bool { return c.function(v, c) } type cfunc func(v *Version, c *constraint) bool func parseConstraint(c string) (*constraint, error) { m := constraintRegex.FindStringSubmatch(c) if m == nil { return nil, fmt.Errorf("improper constraint: %s", c) } ver := m[2] orig := ver minorDirty := false patchDirty := false dirty := false if isX(m[3]) { ver = "0.0.0" dirty = true } else if isX(strings.TrimPrefix(m[4], ".")) { minorDirty = true dirty = true ver = fmt.Sprintf("%s.0.0%s", m[3], m[6]) } else if isX(strings.TrimPrefix(m[5], ".")) { dirty = true patchDirty = true ver = fmt.Sprintf("%s%s.0%s", m[3], m[4], m[6]) } con, err := NewVersion(ver) if err != nil { // The constraintRegex should catch any regex parsing errors. So, // we should never get here. return nil, errors.New("constraint Parser Error") } cs := &constraint{ function: constraintOps[m[1]], msg: constraintMsg[m[1]], con: con, orig: orig, minorDirty: minorDirty, patchDirty: patchDirty, dirty: dirty, } return cs, nil } // Constraint functions func constraintNotEqual(v *Version, c *constraint) bool { if c.dirty { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if c.con.Major() != v.Major() { return true } if c.con.Minor() != v.Minor() && !c.minorDirty { return true } else if c.minorDirty { return false } return false } return !v.Equal(c.con) } func constraintGreaterThan(v *Version, c *constraint) bool { // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease // exists. This that case. if !isNonZero(c.con) && isNonZero(v) { return true } // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } return v.Compare(c.con) == 1 } func constraintLessThan(v *Version, c *constraint) bool { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if !c.dirty { return v.Compare(c.con) < 0 } if v.Major() > c.con.Major() { return false } else if v.Minor() > c.con.Minor() && !c.minorDirty { return false } return true } func constraintGreaterThanEqual(v *Version, c *constraint) bool { // An edge case the constraint is 0.0.0 and the version is 0.0.0-someprerelease // exists. This that case. if !isNonZero(c.con) && isNonZero(v) { return true } // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } return v.Compare(c.con) >= 0 } func constraintLessThanEqual(v *Version, c *constraint) bool { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if !c.dirty { return v.Compare(c.con) <= 0 } if v.Major() > c.con.Major() { return false } else if v.Minor() > c.con.Minor() && !c.minorDirty { return false } return true } // ~*, ~>* --> >= 0.0.0 (any) // ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0, <3.0.0 // ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0, <2.1.0 // ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0, <1.3.0 // ~1.2.3, ~>1.2.3 --> >=1.2.3, <1.3.0 // ~1.2.0, ~>1.2.0 --> >=1.2.0, <1.3.0 func constraintTilde(v *Version, c *constraint) bool { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if v.LessThan(c.con) { return false } // ~0.0.0 is a special case where all constraints are accepted. It's // equivalent to >= 0.0.0. if c.con.Major() == 0 && c.con.Minor() == 0 && c.con.Patch() == 0 && !c.minorDirty && !c.patchDirty { return true } if v.Major() != c.con.Major() { return false } if v.Minor() != c.con.Minor() && !c.minorDirty { return false } return true } // When there is a .x (dirty) status it automatically opts in to ~. Otherwise // it's a straight = func constraintTildeOrEqual(v *Version, c *constraint) bool { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if c.dirty { c.msg = constraintMsg["~"] return constraintTilde(v, c) } return v.Equal(c.con) } // ^* --> (any) // ^2, ^2.x, ^2.x.x --> >=2.0.0, <3.0.0 // ^2.0, ^2.0.x --> >=2.0.0, <3.0.0 // ^1.2, ^1.2.x --> >=1.2.0, <2.0.0 // ^1.2.3 --> >=1.2.3, <2.0.0 // ^1.2.0 --> >=1.2.0, <2.0.0 func constraintCaret(v *Version, c *constraint) bool { // If there is a pre-release on the version but the constraint isn't looking // for them assume that pre-releases are not compatible. See issue 21 for // more details. if v.Prerelease() != "" && c.con.Prerelease() == "" { return false } if v.LessThan(c.con) { return false } if v.Major() != c.con.Major() { return false } return true } var constraintRangeRegex *regexp.Regexp const cvRegex string = `v?([0-9|x|X|\*]+)(\.[0-9|x|X|\*]+)?(\.[0-9|x|X|\*]+)?` + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` func isX(x string) bool { switch x { case "x", "*", "X": return true default: return false } } func rewriteRange(i string) string { m := constraintRangeRegex.FindAllStringSubmatch(i, -1) if m == nil { return i } o := i for _, v := range m { t := fmt.Sprintf(">= %s, <= %s", v[1], v[11]) o = strings.Replace(o, v[0], t, 1) } return o } // Detect if a version is not zero (0.0.0) func isNonZero(v *Version) bool { if v.Major() != 0 || v.Minor() != 0 || v.Patch() != 0 || v.Prerelease() != "" { return true } return false } ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/doc.go ================================================ /* Package semver provides the ability to work with Semantic Versions (http://semver.org) in Go. Specifically it provides the ability to: * Parse semantic versions * Sort semantic versions * Check if a semantic version fits within a set of constraints * Optionally work with a `v` prefix Parsing Semantic Versions To parse a semantic version use the `NewVersion` function. For example, v, err := semver.NewVersion("1.2.3-beta.1+build345") If there is an error the version wasn't parseable. The version object has methods to get the parts of the version, compare it to other versions, convert the version back into a string, and get the original string. For more details please see the documentation at https://godoc.org/github.com/Masterminds/semver. Sorting Semantic Versions A set of versions can be sorted using the `sort` package from the standard library. For example, raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",} vs := make([]*semver.Version, len(raw)) for i, r := range raw { v, err := semver.NewVersion(r) if err != nil { t.Errorf("Error parsing version: %s", err) } vs[i] = v } sort.Sort(semver.Collection(vs)) Checking Version Constraints Checking a version against version constraints is one of the most featureful parts of the package. c, err := semver.NewConstraint(">= 1.2.3") if err != nil { // Handle constraint not being parseable. } v, _ := semver.NewVersion("1.3") if err != nil { // Handle version not being parseable. } // Check if the version meets the constraints. The a variable will be true. a := c.Check(v) Basic Comparisons There are two elements to the comparisons. First, a comparison string is a list of comma separated and comparisons. These are then separated by || separated or comparisons. For example, `">= 1.2, < 3.0.0 || >= 4.2.3"` is looking for a comparison that's greater than or equal to 1.2 and less than 3.0.0 or is greater than or equal to 4.2.3. The basic comparisons are: * `=`: equal (aliased to no operator) * `!=`: not equal * `>`: greater than * `<`: less than * `>=`: greater than or equal to * `<=`: less than or equal to Hyphen Range Comparisons There are multiple methods to handle ranges and the first is hyphens ranges. These look like: * `1.2 - 1.4.5` which is equivalent to `>= 1.2, <= 1.4.5` * `2.3.4 - 4.5` which is equivalent to `>= 2.3.4, <= 4.5` Wildcards In Comparisons The `x`, `X`, and `*` characters can be used as a wildcard character. This works for all comparison operators. When used on the `=` operator it falls back to the pack level comparison (see tilde below). For example, * `1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` * `>= 1.2.x` is equivalent to `>= 1.2.0` * `<= 2.x` is equivalent to `<= 3` * `*` is equivalent to `>= 0.0.0` Tilde Range Comparisons (Patch) The tilde (`~`) comparison operator is for patch level ranges when a minor version is specified and major level changes when the minor number is missing. For example, * `~1.2.3` is equivalent to `>= 1.2.3, < 1.3.0` * `~1` is equivalent to `>= 1, < 2` * `~2.3` is equivalent to `>= 2.3, < 2.4` * `~1.2.x` is equivalent to `>= 1.2.0, < 1.3.0` * `~1.x` is equivalent to `>= 1, < 2` Caret Range Comparisons (Major) The caret (`^`) comparison operator is for major level changes. This is useful when comparisons of API versions as a major change is API breaking. For example, * `^1.2.3` is equivalent to `>= 1.2.3, < 2.0.0` * `^1.2.x` is equivalent to `>= 1.2.0, < 2.0.0` * `^2.3` is equivalent to `>= 2.3, < 3` * `^2.x` is equivalent to `>= 2.0.0, < 3` */ package semver ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/Masterminds/semver/version.go ================================================ package semver import ( "bytes" "errors" "fmt" "regexp" "strconv" "strings" ) // The compiled version of the regex created at init() is cached here so it // only needs to be created once. var versionRegex *regexp.Regexp var validPrereleaseRegex *regexp.Regexp var ( // ErrInvalidSemVer is returned a version is found to be invalid when // being parsed. ErrInvalidSemVer = errors.New("Invalid Semantic Version") // ErrInvalidMetadata is returned when the metadata is an invalid format ErrInvalidMetadata = errors.New("Invalid Metadata string") // ErrInvalidPrerelease is returned when the pre-release is an invalid format ErrInvalidPrerelease = errors.New("Invalid Prerelease string") ) // SemVerRegex is the regular expression used to parse a semantic version. const SemVerRegex string = `v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?` + `(-([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` + `(\+([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*))?` // ValidPrerelease is the regular expression which validates // both prerelease and metadata values. const ValidPrerelease string = `^([0-9A-Za-z\-]+(\.[0-9A-Za-z\-]+)*)` // Version represents a single semantic version. type Version struct { major, minor, patch int64 pre string metadata string original string } func init() { versionRegex = regexp.MustCompile("^" + SemVerRegex + "$") validPrereleaseRegex = regexp.MustCompile(ValidPrerelease) } // NewVersion parses a given version and returns an instance of Version or // an error if unable to parse the version. func NewVersion(v string) (*Version, error) { m := versionRegex.FindStringSubmatch(v) if m == nil { return nil, ErrInvalidSemVer } sv := &Version{ metadata: m[8], pre: m[5], original: v, } var temp int64 temp, err := strconv.ParseInt(m[1], 10, 32) if err != nil { return nil, fmt.Errorf("Error parsing version segment: %s", err) } sv.major = temp if m[2] != "" { temp, err = strconv.ParseInt(strings.TrimPrefix(m[2], "."), 10, 32) if err != nil { return nil, fmt.Errorf("Error parsing version segment: %s", err) } sv.minor = temp } else { sv.minor = 0 } if m[3] != "" { temp, err = strconv.ParseInt(strings.TrimPrefix(m[3], "."), 10, 32) if err != nil { return nil, fmt.Errorf("Error parsing version segment: %s", err) } sv.patch = temp } else { sv.patch = 0 } return sv, nil } // MustParse parses a given version and panics on error. func MustParse(v string) *Version { sv, err := NewVersion(v) if err != nil { panic(err) } return sv } // String converts a Version object to a string. // Note, if the original version contained a leading v this version will not. // See the Original() method to retrieve the original value. Semantic Versions // don't contain a leading v per the spec. Instead it's optional on // impelementation. func (v *Version) String() string { var buf bytes.Buffer fmt.Fprintf(&buf, "%d.%d.%d", v.major, v.minor, v.patch) if v.pre != "" { fmt.Fprintf(&buf, "-%s", v.pre) } if v.metadata != "" { fmt.Fprintf(&buf, "+%s", v.metadata) } return buf.String() } // Original returns the original value passed in to be parsed. func (v *Version) Original() string { return v.original } // Major returns the major version. func (v *Version) Major() int64 { return v.major } // Minor returns the minor version. func (v *Version) Minor() int64 { return v.minor } // Patch returns the patch version. func (v *Version) Patch() int64 { return v.patch } // Prerelease returns the pre-release version. func (v *Version) Prerelease() string { return v.pre } // Metadata returns the metadata on the version. func (v *Version) Metadata() string { return v.metadata } // originalVPrefix returns the original 'v' prefix if any. func (v *Version) originalVPrefix() string { // Note, only lowercase v is supported as a prefix by the parser. if v.original != "" && v.original[:1] == "v" { return v.original[:1] } return "" } // IncPatch produces the next patch version. // If the current version does not have prerelease/metadata information, // it unsets metadata and prerelease values, increments patch number. // If the current version has any of prerelease or metadata information, // it unsets both values and keeps curent patch value func (v Version) IncPatch() Version { vNext := v // according to http://semver.org/#spec-item-9 // Pre-release versions have a lower precedence than the associated normal version. // according to http://semver.org/#spec-item-10 // Build metadata SHOULD be ignored when determining version precedence. if v.pre != "" { vNext.metadata = "" vNext.pre = "" } else { vNext.metadata = "" vNext.pre = "" vNext.patch = v.patch + 1 } vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext } // IncMinor produces the next minor version. // Sets patch to 0. // Increments minor number. // Unsets metadata. // Unsets prerelease status. func (v Version) IncMinor() Version { vNext := v vNext.metadata = "" vNext.pre = "" vNext.patch = 0 vNext.minor = v.minor + 1 vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext } // IncMajor produces the next major version. // Sets patch to 0. // Sets minor to 0. // Increments major number. // Unsets metadata. // Unsets prerelease status. func (v Version) IncMajor() Version { vNext := v vNext.metadata = "" vNext.pre = "" vNext.patch = 0 vNext.minor = 0 vNext.major = v.major + 1 vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext } // SetPrerelease defines the prerelease value. // Value must not include the required 'hypen' prefix. func (v Version) SetPrerelease(prerelease string) (Version, error) { vNext := v if len(prerelease) > 0 && !validPrereleaseRegex.MatchString(prerelease) { return vNext, ErrInvalidPrerelease } vNext.pre = prerelease vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext, nil } // SetMetadata defines metadata value. // Value must not include the required 'plus' prefix. func (v Version) SetMetadata(metadata string) (Version, error) { vNext := v if len(metadata) > 0 && !validPrereleaseRegex.MatchString(metadata) { return vNext, ErrInvalidMetadata } vNext.metadata = metadata vNext.original = v.originalVPrefix() + "" + vNext.String() return vNext, nil } // LessThan tests if one version is less than another one. func (v *Version) LessThan(o *Version) bool { return v.Compare(o) < 0 } // GreaterThan tests if one version is greater than another one. func (v *Version) GreaterThan(o *Version) bool { return v.Compare(o) > 0 } // Equal tests if two versions are equal to each other. // Note, versions can be equal with different metadata since metadata // is not considered part of the comparable version. func (v *Version) Equal(o *Version) bool { return v.Compare(o) == 0 } // Compare compares this version to another one. It returns -1, 0, or 1 if // the version smaller, equal, or larger than the other version. // // Versions are compared by X.Y.Z. Build metadata is ignored. Prerelease is // lower than the version without a prerelease. func (v *Version) Compare(o *Version) int { // Compare the major, minor, and patch version for differences. If a // difference is found return the comparison. if d := compareSegment(v.Major(), o.Major()); d != 0 { return d } if d := compareSegment(v.Minor(), o.Minor()); d != 0 { return d } if d := compareSegment(v.Patch(), o.Patch()); d != 0 { return d } // At this point the major, minor, and patch versions are the same. ps := v.pre po := o.Prerelease() if ps == "" && po == "" { return 0 } if ps == "" { return 1 } if po == "" { return -1 } return comparePrerelease(ps, po) } func compareSegment(v, o int64) int { if v < o { return -1 } if v > o { return 1 } return 0 } func comparePrerelease(v, o string) int { // split the prelease versions by their part. The separator, per the spec, // is a . sparts := strings.Split(v, ".") oparts := strings.Split(o, ".") // Find the longer length of the parts to know how many loop iterations to // go through. slen := len(sparts) olen := len(oparts) l := slen if olen > slen { l = olen } // Iterate over each part of the prereleases to compare the differences. for i := 0; i < l; i++ { // Since the lentgh of the parts can be different we need to create // a placeholder. This is to avoid out of bounds issues. stemp := "" if i < slen { stemp = sparts[i] } otemp := "" if i < olen { otemp = oparts[i] } d := comparePrePart(stemp, otemp) if d != 0 { return d } } // Reaching here means two versions are of equal value but have different // metadata (the part following a +). They are not identical in string form // but the version comparison finds them to be equal. return 0 } func comparePrePart(s, o string) int { // Fastpath if they are equal if s == o { return 0 } // When s or o are empty we can use the other in an attempt to determine // the response. if o == "" { _, n := strconv.ParseInt(s, 10, 64) if n != nil { return -1 } return 1 } if s == "" { _, n := strconv.ParseInt(o, 10, 64) if n != nil { return 1 } return -1 } if s > o { return 1 } return -1 } ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/pkg/errors/LICENSE ================================================ Copyright (c) 2015, Dave Cheney All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 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 HOLDER 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. ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/pkg/errors/README.md ================================================ # errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) Package errors provides simple error handling primitives. `go get github.com/pkg/errors` The traditional error handling idiom in Go is roughly akin to ```go if err != nil { return err } ``` which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. ## Adding context to an error The errors.Wrap function returns a new error that adds context to the original error. For example ```go _, err := ioutil.ReadAll(r) if err != nil { return errors.Wrap(err, "read failed") } ``` ## Retrieving the cause of an error Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. ```go type causer interface { Cause() error } ``` `errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: ```go switch err := errors.Cause(err).(type) { case *MyError: // handle specifically default: // unknown error } ``` [Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). ## Contributing We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high. Before proposing a change, please discuss your change by raising an issue. ## Licence BSD-2-Clause ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/pkg/errors/errors.go ================================================ // Package errors provides simple error handling primitives. // // The traditional error handling idiom in Go is roughly akin to // // if err != nil { // return err // } // // which applied recursively up the call stack results in error reports // without context or debugging information. The errors package allows // programmers to add context to the failure path in their code in a way // that does not destroy the original value of the error. // // Adding context to an error // // The errors.Wrap function returns a new error that adds context to the // original error by recording a stack trace at the point Wrap is called, // and the supplied message. For example // // _, err := ioutil.ReadAll(r) // if err != nil { // return errors.Wrap(err, "read failed") // } // // If additional control is required the errors.WithStack and errors.WithMessage // functions destructure errors.Wrap into its component operations of annotating // an error with a stack trace and an a message, respectively. // // Retrieving the cause of an error // // Using errors.Wrap constructs a stack of errors, adding context to the // preceding error. Depending on the nature of the error it may be necessary // to reverse the operation of errors.Wrap to retrieve the original error // for inspection. Any error value which implements this interface // // type causer interface { // Cause() error // } // // can be inspected by errors.Cause. errors.Cause will recursively retrieve // the topmost error which does not implement causer, which is assumed to be // the original cause. For example: // // switch err := errors.Cause(err).(type) { // case *MyError: // // handle specifically // default: // // unknown error // } // // causer interface is not exported by this package, but is considered a part // of stable public API. // // Formatted printing of errors // // All error values returned from this package implement fmt.Formatter and can // be formatted by the fmt package. The following verbs are supported // // %s print the error. If the error has a Cause it will be // printed recursively // %v see %s // %+v extended format. Each Frame of the error's StackTrace will // be printed in detail. // // Retrieving the stack trace of an error or wrapper // // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are // invoked. This information can be retrieved with the following interface. // // type stackTracer interface { // StackTrace() errors.StackTrace // } // // Where errors.StackTrace is defined as // // type StackTrace []Frame // // The Frame type represents a call site in the stack trace. Frame supports // the fmt.Formatter interface that can be used for printing information about // the stack trace of this error. For example: // // if err, ok := err.(stackTracer); ok { // for _, f := range err.StackTrace() { // fmt.Printf("%+s:%d", f) // } // } // // stackTracer interface is not exported by this package, but is considered a part // of stable public API. // // See the documentation for Frame.Format for more details. package errors import ( "fmt" "io" ) // New returns an error with the supplied message. // New also records the stack trace at the point it was called. func New(message string) error { return &fundamental{ msg: message, stack: callers(), } } // Errorf formats according to a format specifier and returns the string // as a value that satisfies error. // Errorf also records the stack trace at the point it was called. func Errorf(format string, args ...interface{}) error { return &fundamental{ msg: fmt.Sprintf(format, args...), stack: callers(), } } // fundamental is an error that has a message and a stack, but no caller. type fundamental struct { msg string *stack } func (f *fundamental) Error() string { return f.msg } func (f *fundamental) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { io.WriteString(s, f.msg) f.stack.Format(s, verb) return } fallthrough case 's': io.WriteString(s, f.msg) case 'q': fmt.Fprintf(s, "%q", f.msg) } } // WithStack annotates err with a stack trace at the point WithStack was called. // If err is nil, WithStack returns nil. func WithStack(err error) error { if err == nil { return nil } return &withStack{ err, callers(), } } type withStack struct { error *stack } func (w *withStack) Cause() error { return w.error } func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { fmt.Fprintf(s, "%+v", w.Cause()) w.stack.Format(s, verb) return } fallthrough case 's': io.WriteString(s, w.Error()) case 'q': fmt.Fprintf(s, "%q", w.Error()) } } // Wrap returns an error annotating err with a stack trace // at the point Wrap is called, and the supplied message. // If err is nil, Wrap returns nil. func Wrap(err error, message string) error { if err == nil { return nil } err = &withMessage{ cause: err, msg: message, } return &withStack{ err, callers(), } } // Wrapf returns an error annotating err with a stack trace // at the point Wrapf is call, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...interface{}) error { if err == nil { return nil } err = &withMessage{ cause: err, msg: fmt.Sprintf(format, args...), } return &withStack{ err, callers(), } } // WithMessage annotates err with a new message. // If err is nil, WithMessage returns nil. func WithMessage(err error, message string) error { if err == nil { return nil } return &withMessage{ cause: err, msg: message, } } type withMessage struct { cause error msg string } func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } func (w *withMessage) Cause() error { return w.cause } func (w *withMessage) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { fmt.Fprintf(s, "%+v\n", w.Cause()) io.WriteString(s, w.msg) return } fallthrough case 's', 'q': io.WriteString(s, w.Error()) } } // Cause returns the underlying cause of the error, if possible. // An error value has a cause if it implements the following // interface: // // type causer interface { // Cause() error // } // // If the error does not implement Cause, the original error will // be returned. If the error is nil, nil will be returned without further // investigation. func Cause(err error) error { type causer interface { Cause() error } for err != nil { cause, ok := err.(causer) if !ok { break } err = cause.Cause() } return err } ================================================ FILE: _tools/src/github.com/twitchtv/retool/vendor/github.com/pkg/errors/stack.go ================================================ package errors import ( "fmt" "io" "path" "runtime" "strings" ) // Frame represents a program counter inside a stack frame. type Frame uintptr // pc returns the program counter for this frame; // multiple frames may have the same PC value. func (f Frame) pc() uintptr { return uintptr(f) - 1 } // file returns the full path to the file that contains the // function for this Frame's pc. func (f Frame) file() string { fn := runtime.FuncForPC(f.pc()) if fn == nil { return "unknown" } file, _ := fn.FileLine(f.pc()) return file } // line returns the line number of source code of the // function for this Frame's pc. func (f Frame) line() int { fn := runtime.FuncForPC(f.pc()) if fn == nil { return 0 } _, line := fn.FileLine(f.pc()) return line } // Format formats the frame according to the fmt.Formatter interface. // // %s source file // %d source line // %n function name // %v equivalent to %s:%d // // Format accepts flags that alter the printing of some verbs, as follows: // // %+s path of source file relative to the compile time GOPATH // %+v equivalent to %+s:%d func (f Frame) Format(s fmt.State, verb rune) { switch verb { case 's': switch { case s.Flag('+'): pc := f.pc() fn := runtime.FuncForPC(pc) if fn == nil { io.WriteString(s, "unknown") } else { file, _ := fn.FileLine(pc) fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) } default: io.WriteString(s, path.Base(f.file())) } case 'd': fmt.Fprintf(s, "%d", f.line()) case 'n': name := runtime.FuncForPC(f.pc()).Name() io.WriteString(s, funcname(name)) case 'v': f.Format(s, 's') io.WriteString(s, ":") f.Format(s, 'd') } } // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). type StackTrace []Frame func (st StackTrace) Format(s fmt.State, verb rune) { switch verb { case 'v': switch { case s.Flag('+'): for _, f := range st { fmt.Fprintf(s, "\n%+v", f) } case s.Flag('#'): fmt.Fprintf(s, "%#v", []Frame(st)) default: fmt.Fprintf(s, "%v", []Frame(st)) } case 's': fmt.Fprintf(s, "%s", []Frame(st)) } } // stack represents a stack of program counters. type stack []uintptr func (s *stack) Format(st fmt.State, verb rune) { switch verb { case 'v': switch { case st.Flag('+'): for _, pc := range *s { f := Frame(pc) fmt.Fprintf(st, "\n%+v", f) } } } } func (s *stack) StackTrace() StackTrace { f := make([]Frame, len(*s)) for i := 0; i < len(f); i++ { f[i] = Frame((*s)[i]) } return f } func callers() *stack { const depth = 32 var pcs [depth]uintptr n := runtime.Callers(3, pcs[:]) var st stack = pcs[0:n] return &st } // funcname removes the path prefix component of a function's name reported by func.Name(). func funcname(name string) string { i := strings.LastIndex(name, "/") name = name[i+1:] i = strings.Index(name, ".") return name[i+1:] } func trimGOPATH(name, file string) string { // Here we want to get the source file path relative to the compile time // GOPATH. As of Go 1.6.x there is no direct way to know the compiled // GOPATH at runtime, but we can infer the number of path segments in the // GOPATH. We note that fn.Name() returns the function name qualified by // the import path, which does not include the GOPATH. Thus we can trim // segments from the beginning of the file path until the number of path // separators remaining is one more than the number of path separators in // the function name. For example, given: // // GOPATH /home/user // file /home/user/src/pkg/sub/file.go // fn.Name() pkg/sub.Type.Method // // We want to produce: // // pkg/sub/file.go // // From this we can easily see that fn.Name() has one less path separator // than our desired output. We count separators from the end of the file // path until it finds two more than in the function name and then move // one character forward to preserve the initial path segment without a // leading separator. const sep = "/" goal := strings.Count(name, sep) + 2 i := len(file) for n := 0; n < goal; n++ { i = strings.LastIndex(file[:i], sep) if i == -1 { // not enough separators found, set i so that the slice expression // below leaves file unmodified i = -len(sep) break } } // get back to 0 or trim the leading separator file = file[i+len(sep):] return file } ================================================ FILE: _tools/src/golang.org/x/sys/execabs/execabs.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package execabs is a drop-in replacement for os/exec // that requires PATH lookups to find absolute paths. // That is, execabs.Command("cmd") runs the same PATH lookup // as exec.Command("cmd"), but if the result is a path // which is relative, the Run and Start methods will report // an error instead of running the executable. // // See https://blog.golang.org/path-security for more information // about when it may be necessary or appropriate to use this package. package execabs import ( "context" "fmt" "os/exec" "path/filepath" "reflect" "unsafe" ) // ErrNotFound is the error resulting if a path search failed to find an executable file. // It is an alias for exec.ErrNotFound. var ErrNotFound = exec.ErrNotFound // Cmd represents an external command being prepared or run. // It is an alias for exec.Cmd. type Cmd = exec.Cmd // Error is returned by LookPath when it fails to classify a file as an executable. // It is an alias for exec.Error. type Error = exec.Error // An ExitError reports an unsuccessful exit by a command. // It is an alias for exec.ExitError. type ExitError = exec.ExitError func relError(file, path string) error { return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path) } // LookPath searches for an executable named file in the directories // named by the PATH environment variable. If file contains a slash, // it is tried directly and the PATH is not consulted. The result will be // an absolute path. // // LookPath differs from exec.LookPath in its handling of PATH lookups, // which are used for file names without slashes. If exec.LookPath's // PATH lookup would have returned an executable from the current directory, // LookPath instead returns an error. func LookPath(file string) (string, error) { path, err := exec.LookPath(file) if err != nil { return "", err } if filepath.Base(file) == file && !filepath.IsAbs(path) { return "", relError(file, path) } return path, nil } func fixCmd(name string, cmd *exec.Cmd) { if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) { // exec.Command was called with a bare binary name and // exec.LookPath returned a path which is not absolute. // Set cmd.lookPathErr and clear cmd.Path so that it // cannot be run. lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer())) if *lookPathErr == nil { *lookPathErr = relError(name, cmd.Path) } cmd.Path = "" } } // CommandContext is like Command but includes a context. // // The provided context is used to kill the process (by calling os.Process.Kill) // if the context becomes done before the command completes on its own. func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd { cmd := exec.CommandContext(ctx, name, arg...) fixCmd(name, cmd) return cmd } // Command returns the Cmd struct to execute the named program with the given arguments. // See exec.Command for most details. // // Command differs from exec.Command in its handling of PATH lookups, // which are used when the program name contains no slashes. // If exec.Command would have returned an exec.Cmd configured to run an // executable from the current directory, Command instead // returns an exec.Cmd that will return an error from Start or Run. func Command(name string, arg ...string) *exec.Cmd { cmd := exec.Command(name, arg...) fixCmd(name, cmd) return cmd } ================================================ FILE: _tools/src/golang.org/x/tools/go/ast/astutil/enclosing.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package astutil // This file defines utilities for working with source positions. import ( "fmt" "go/ast" "go/token" "sort" ) // PathEnclosingInterval returns the node that encloses the source // interval [start, end), and all its ancestors up to the AST root. // // The definition of "enclosing" used by this function considers // additional whitespace abutting a node to be enclosed by it. // In this example: // // z := x + y // add them // <-A-> // <----B-----> // // the ast.BinaryExpr(+) node is considered to enclose interval B // even though its [Pos()..End()) is actually only interval A. // This behaviour makes user interfaces more tolerant of imperfect // input. // // This function treats tokens as nodes, though they are not included // in the result. e.g. PathEnclosingInterval("+") returns the // enclosing ast.BinaryExpr("x + y"). // // If start==end, the 1-char interval following start is used instead. // // The 'exact' result is true if the interval contains only path[0] // and perhaps some adjacent whitespace. It is false if the interval // overlaps multiple children of path[0], or if it contains only // interior whitespace of path[0]. // In this example: // // z := x + y // add them // <--C--> <---E--> // ^ // D // // intervals C, D and E are inexact. C is contained by the // z-assignment statement, because it spans three of its children (:=, // x, +). So too is the 1-char interval D, because it contains only // interior whitespace of the assignment. E is considered interior // whitespace of the BlockStmt containing the assignment. // // Precondition: [start, end) both lie within the same file as root. // TODO(adonovan): return (nil, false) in this case and remove precond. // Requires FileSet; see loader.tokenFileContainsPos. // // Postcondition: path is never nil; it always contains at least 'root'. // func PathEnclosingInterval(root *ast.File, start, end token.Pos) (path []ast.Node, exact bool) { // fmt.Printf("EnclosingInterval %d %d\n", start, end) // debugging // Precondition: node.[Pos..End) and adjoining whitespace contain [start, end). var visit func(node ast.Node) bool visit = func(node ast.Node) bool { path = append(path, node) nodePos := node.Pos() nodeEnd := node.End() // fmt.Printf("visit(%T, %d, %d)\n", node, nodePos, nodeEnd) // debugging // Intersect [start, end) with interval of node. if start < nodePos { start = nodePos } if end > nodeEnd { end = nodeEnd } // Find sole child that contains [start, end). children := childrenOf(node) l := len(children) for i, child := range children { // [childPos, childEnd) is unaugmented interval of child. childPos := child.Pos() childEnd := child.End() // [augPos, augEnd) is whitespace-augmented interval of child. augPos := childPos augEnd := childEnd if i > 0 { augPos = children[i-1].End() // start of preceding whitespace } if i < l-1 { nextChildPos := children[i+1].Pos() // Does [start, end) lie between child and next child? if start >= augEnd && end <= nextChildPos { return false // inexact match } augEnd = nextChildPos // end of following whitespace } // fmt.Printf("\tchild %d: [%d..%d)\tcontains interval [%d..%d)?\n", // i, augPos, augEnd, start, end) // debugging // Does augmented child strictly contain [start, end)? if augPos <= start && end <= augEnd { _, isToken := child.(tokenNode) return isToken || visit(child) } // Does [start, end) overlap multiple children? // i.e. left-augmented child contains start // but LR-augmented child does not contain end. if start < childEnd && end > augEnd { break } } // No single child contained [start, end), // so node is the result. Is it exact? // (It's tempting to put this condition before the // child loop, but it gives the wrong result in the // case where a node (e.g. ExprStmt) and its sole // child have equal intervals.) if start == nodePos && end == nodeEnd { return true // exact match } return false // inexact: overlaps multiple children } if start > end { start, end = end, start } if start < root.End() && end > root.Pos() { if start == end { end = start + 1 // empty interval => interval of size 1 } exact = visit(root) // Reverse the path: for i, l := 0, len(path); i < l/2; i++ { path[i], path[l-1-i] = path[l-1-i], path[i] } } else { // Selection lies within whitespace preceding the // first (or following the last) declaration in the file. // The result nonetheless always includes the ast.File. path = append(path, root) } return } // tokenNode is a dummy implementation of ast.Node for a single token. // They are used transiently by PathEnclosingInterval but never escape // this package. // type tokenNode struct { pos token.Pos end token.Pos } func (n tokenNode) Pos() token.Pos { return n.pos } func (n tokenNode) End() token.Pos { return n.end } func tok(pos token.Pos, len int) ast.Node { return tokenNode{pos, pos + token.Pos(len)} } // childrenOf returns the direct non-nil children of ast.Node n. // It may include fake ast.Node implementations for bare tokens. // it is not safe to call (e.g.) ast.Walk on such nodes. // func childrenOf(n ast.Node) []ast.Node { var children []ast.Node // First add nodes for all true subtrees. ast.Inspect(n, func(node ast.Node) bool { if node == n { // push n return true // recur } if node != nil { // push child children = append(children, node) } return false // no recursion }) // Then add fake Nodes for bare tokens. switch n := n.(type) { case *ast.ArrayType: children = append(children, tok(n.Lbrack, len("[")), tok(n.Elt.End(), len("]"))) case *ast.AssignStmt: children = append(children, tok(n.TokPos, len(n.Tok.String()))) case *ast.BasicLit: children = append(children, tok(n.ValuePos, len(n.Value))) case *ast.BinaryExpr: children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.BlockStmt: children = append(children, tok(n.Lbrace, len("{")), tok(n.Rbrace, len("}"))) case *ast.BranchStmt: children = append(children, tok(n.TokPos, len(n.Tok.String()))) case *ast.CallExpr: children = append(children, tok(n.Lparen, len("(")), tok(n.Rparen, len(")"))) if n.Ellipsis != 0 { children = append(children, tok(n.Ellipsis, len("..."))) } case *ast.CaseClause: if n.List == nil { children = append(children, tok(n.Case, len("default"))) } else { children = append(children, tok(n.Case, len("case"))) } children = append(children, tok(n.Colon, len(":"))) case *ast.ChanType: switch n.Dir { case ast.RECV: children = append(children, tok(n.Begin, len("<-chan"))) case ast.SEND: children = append(children, tok(n.Begin, len("chan<-"))) case ast.RECV | ast.SEND: children = append(children, tok(n.Begin, len("chan"))) } case *ast.CommClause: if n.Comm == nil { children = append(children, tok(n.Case, len("default"))) } else { children = append(children, tok(n.Case, len("case"))) } children = append(children, tok(n.Colon, len(":"))) case *ast.Comment: // nop case *ast.CommentGroup: // nop case *ast.CompositeLit: children = append(children, tok(n.Lbrace, len("{")), tok(n.Rbrace, len("{"))) case *ast.DeclStmt: // nop case *ast.DeferStmt: children = append(children, tok(n.Defer, len("defer"))) case *ast.Ellipsis: children = append(children, tok(n.Ellipsis, len("..."))) case *ast.EmptyStmt: // nop case *ast.ExprStmt: // nop case *ast.Field: // TODO(adonovan): Field.{Doc,Comment,Tag}? case *ast.FieldList: children = append(children, tok(n.Opening, len("(")), tok(n.Closing, len(")"))) case *ast.File: // TODO test: Doc children = append(children, tok(n.Package, len("package"))) case *ast.ForStmt: children = append(children, tok(n.For, len("for"))) case *ast.FuncDecl: // TODO(adonovan): FuncDecl.Comment? // Uniquely, FuncDecl breaks the invariant that // preorder traversal yields tokens in lexical order: // in fact, FuncDecl.Recv precedes FuncDecl.Type.Func. // // As a workaround, we inline the case for FuncType // here and order things correctly. // children = nil // discard ast.Walk(FuncDecl) info subtrees children = append(children, tok(n.Type.Func, len("func"))) if n.Recv != nil { children = append(children, n.Recv) } children = append(children, n.Name) if n.Type.Params != nil { children = append(children, n.Type.Params) } if n.Type.Results != nil { children = append(children, n.Type.Results) } if n.Body != nil { children = append(children, n.Body) } case *ast.FuncLit: // nop case *ast.FuncType: if n.Func != 0 { children = append(children, tok(n.Func, len("func"))) } case *ast.GenDecl: children = append(children, tok(n.TokPos, len(n.Tok.String()))) if n.Lparen != 0 { children = append(children, tok(n.Lparen, len("(")), tok(n.Rparen, len(")"))) } case *ast.GoStmt: children = append(children, tok(n.Go, len("go"))) case *ast.Ident: children = append(children, tok(n.NamePos, len(n.Name))) case *ast.IfStmt: children = append(children, tok(n.If, len("if"))) case *ast.ImportSpec: // TODO(adonovan): ImportSpec.{Doc,EndPos}? case *ast.IncDecStmt: children = append(children, tok(n.TokPos, len(n.Tok.String()))) case *ast.IndexExpr: children = append(children, tok(n.Lbrack, len("{")), tok(n.Rbrack, len("}"))) case *ast.InterfaceType: children = append(children, tok(n.Interface, len("interface"))) case *ast.KeyValueExpr: children = append(children, tok(n.Colon, len(":"))) case *ast.LabeledStmt: children = append(children, tok(n.Colon, len(":"))) case *ast.MapType: children = append(children, tok(n.Map, len("map"))) case *ast.ParenExpr: children = append(children, tok(n.Lparen, len("(")), tok(n.Rparen, len(")"))) case *ast.RangeStmt: children = append(children, tok(n.For, len("for")), tok(n.TokPos, len(n.Tok.String()))) case *ast.ReturnStmt: children = append(children, tok(n.Return, len("return"))) case *ast.SelectStmt: children = append(children, tok(n.Select, len("select"))) case *ast.SelectorExpr: // nop case *ast.SendStmt: children = append(children, tok(n.Arrow, len("<-"))) case *ast.SliceExpr: children = append(children, tok(n.Lbrack, len("[")), tok(n.Rbrack, len("]"))) case *ast.StarExpr: children = append(children, tok(n.Star, len("*"))) case *ast.StructType: children = append(children, tok(n.Struct, len("struct"))) case *ast.SwitchStmt: children = append(children, tok(n.Switch, len("switch"))) case *ast.TypeAssertExpr: children = append(children, tok(n.Lparen-1, len(".")), tok(n.Lparen, len("(")), tok(n.Rparen, len(")"))) case *ast.TypeSpec: // TODO(adonovan): TypeSpec.{Doc,Comment}? case *ast.TypeSwitchStmt: children = append(children, tok(n.Switch, len("switch"))) case *ast.UnaryExpr: children = append(children, tok(n.OpPos, len(n.Op.String()))) case *ast.ValueSpec: // TODO(adonovan): ValueSpec.{Doc,Comment}? case *ast.BadDecl, *ast.BadExpr, *ast.BadStmt: // nop } // TODO(adonovan): opt: merge the logic of ast.Inspect() into // the switch above so we can make interleaved callbacks for // both Nodes and Tokens in the right order and avoid the need // to sort. sort.Sort(byPos(children)) return children } type byPos []ast.Node func (sl byPos) Len() int { return len(sl) } func (sl byPos) Less(i, j int) bool { return sl[i].Pos() < sl[j].Pos() } func (sl byPos) Swap(i, j int) { sl[i], sl[j] = sl[j], sl[i] } // NodeDescription returns a description of the concrete type of n suitable // for a user interface. // // TODO(adonovan): in some cases (e.g. Field, FieldList, Ident, // StarExpr) we could be much more specific given the path to the AST // root. Perhaps we should do that. // func NodeDescription(n ast.Node) string { switch n := n.(type) { case *ast.ArrayType: return "array type" case *ast.AssignStmt: return "assignment" case *ast.BadDecl: return "bad declaration" case *ast.BadExpr: return "bad expression" case *ast.BadStmt: return "bad statement" case *ast.BasicLit: return "basic literal" case *ast.BinaryExpr: return fmt.Sprintf("binary %s operation", n.Op) case *ast.BlockStmt: return "block" case *ast.BranchStmt: switch n.Tok { case token.BREAK: return "break statement" case token.CONTINUE: return "continue statement" case token.GOTO: return "goto statement" case token.FALLTHROUGH: return "fall-through statement" } case *ast.CallExpr: if len(n.Args) == 1 && !n.Ellipsis.IsValid() { return "function call (or conversion)" } return "function call" case *ast.CaseClause: return "case clause" case *ast.ChanType: return "channel type" case *ast.CommClause: return "communication clause" case *ast.Comment: return "comment" case *ast.CommentGroup: return "comment group" case *ast.CompositeLit: return "composite literal" case *ast.DeclStmt: return NodeDescription(n.Decl) + " statement" case *ast.DeferStmt: return "defer statement" case *ast.Ellipsis: return "ellipsis" case *ast.EmptyStmt: return "empty statement" case *ast.ExprStmt: return "expression statement" case *ast.Field: // Can be any of these: // struct {x, y int} -- struct field(s) // struct {T} -- anon struct field // interface {I} -- interface embedding // interface {f()} -- interface method // func (A) func(B) C -- receiver, param(s), result(s) return "field/method/parameter" case *ast.FieldList: return "field/method/parameter list" case *ast.File: return "source file" case *ast.ForStmt: return "for loop" case *ast.FuncDecl: return "function declaration" case *ast.FuncLit: return "function literal" case *ast.FuncType: return "function type" case *ast.GenDecl: switch n.Tok { case token.IMPORT: return "import declaration" case token.CONST: return "constant declaration" case token.TYPE: return "type declaration" case token.VAR: return "variable declaration" } case *ast.GoStmt: return "go statement" case *ast.Ident: return "identifier" case *ast.IfStmt: return "if statement" case *ast.ImportSpec: return "import specification" case *ast.IncDecStmt: if n.Tok == token.INC { return "increment statement" } return "decrement statement" case *ast.IndexExpr: return "index expression" case *ast.InterfaceType: return "interface type" case *ast.KeyValueExpr: return "key/value association" case *ast.LabeledStmt: return "statement label" case *ast.MapType: return "map type" case *ast.Package: return "package" case *ast.ParenExpr: return "parenthesized " + NodeDescription(n.X) case *ast.RangeStmt: return "range loop" case *ast.ReturnStmt: return "return statement" case *ast.SelectStmt: return "select statement" case *ast.SelectorExpr: return "selector" case *ast.SendStmt: return "channel send" case *ast.SliceExpr: return "slice expression" case *ast.StarExpr: return "*-operation" // load/store expr or pointer type case *ast.StructType: return "struct type" case *ast.SwitchStmt: return "switch statement" case *ast.TypeAssertExpr: return "type assertion" case *ast.TypeSpec: return "type specification" case *ast.TypeSwitchStmt: return "type switch" case *ast.UnaryExpr: return fmt.Sprintf("unary %s operation", n.Op) case *ast.ValueSpec: return "value specification" } panic(fmt.Sprintf("unexpected node type: %T", n)) } ================================================ FILE: _tools/src/golang.org/x/tools/go/ast/astutil/imports.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package astutil contains common utilities for working with the Go AST. package astutil // import "golang.org/x/tools/go/ast/astutil" import ( "fmt" "go/ast" "go/token" "strconv" "strings" ) // AddImport adds the import path to the file f, if absent. func AddImport(fset *token.FileSet, f *ast.File, path string) (added bool) { return AddNamedImport(fset, f, "", path) } // AddNamedImport adds the import with the given name and path to the file f, if absent. // If name is not empty, it is used to rename the import. // // For example, calling // AddNamedImport(fset, f, "pathpkg", "path") // adds // import pathpkg "path" func AddNamedImport(fset *token.FileSet, f *ast.File, name, path string) (added bool) { if imports(f, name, path) { return false } newImport := &ast.ImportSpec{ Path: &ast.BasicLit{ Kind: token.STRING, Value: strconv.Quote(path), }, } if name != "" { newImport.Name = &ast.Ident{Name: name} } // Find an import decl to add to. // The goal is to find an existing import // whose import path has the longest shared // prefix with path. var ( bestMatch = -1 // length of longest shared prefix lastImport = -1 // index in f.Decls of the file's final import decl impDecl *ast.GenDecl // import decl containing the best match impIndex = -1 // spec index in impDecl containing the best match isThirdPartyPath = isThirdParty(path) ) for i, decl := range f.Decls { gen, ok := decl.(*ast.GenDecl) if ok && gen.Tok == token.IMPORT { lastImport = i // Do not add to import "C", to avoid disrupting the // association with its doc comment, breaking cgo. if declImports(gen, "C") { continue } // Match an empty import decl if that's all that is available. if len(gen.Specs) == 0 && bestMatch == -1 { impDecl = gen } // Compute longest shared prefix with imports in this group and find best // matched import spec. // 1. Always prefer import spec with longest shared prefix. // 2. While match length is 0, // - for stdlib package: prefer first import spec. // - for third party package: prefer first third party import spec. // We cannot use last import spec as best match for third party package // because grouped imports are usually placed last by goimports -local // flag. // See issue #19190. seenAnyThirdParty := false for j, spec := range gen.Specs { impspec := spec.(*ast.ImportSpec) p := importPath(impspec) n := matchLen(p, path) if n > bestMatch || (bestMatch == 0 && !seenAnyThirdParty && isThirdPartyPath) { bestMatch = n impDecl = gen impIndex = j } seenAnyThirdParty = seenAnyThirdParty || isThirdParty(p) } } } // If no import decl found, add one after the last import. if impDecl == nil { impDecl = &ast.GenDecl{ Tok: token.IMPORT, } if lastImport >= 0 { impDecl.TokPos = f.Decls[lastImport].End() } else { // There are no existing imports. // Our new import, preceded by a blank line, goes after the package declaration // and after the comment, if any, that starts on the same line as the // package declaration. impDecl.TokPos = f.Package file := fset.File(f.Package) pkgLine := file.Line(f.Package) for _, c := range f.Comments { if file.Line(c.Pos()) > pkgLine { break } // +2 for a blank line impDecl.TokPos = c.End() + 2 } } f.Decls = append(f.Decls, nil) copy(f.Decls[lastImport+2:], f.Decls[lastImport+1:]) f.Decls[lastImport+1] = impDecl } // Insert new import at insertAt. insertAt := 0 if impIndex >= 0 { // insert after the found import insertAt = impIndex + 1 } impDecl.Specs = append(impDecl.Specs, nil) copy(impDecl.Specs[insertAt+1:], impDecl.Specs[insertAt:]) impDecl.Specs[insertAt] = newImport pos := impDecl.Pos() if insertAt > 0 { // If there is a comment after an existing import, preserve the comment // position by adding the new import after the comment. if spec, ok := impDecl.Specs[insertAt-1].(*ast.ImportSpec); ok && spec.Comment != nil { pos = spec.Comment.End() } else { // Assign same position as the previous import, // so that the sorter sees it as being in the same block. pos = impDecl.Specs[insertAt-1].Pos() } } if newImport.Name != nil { newImport.Name.NamePos = pos } newImport.Path.ValuePos = pos newImport.EndPos = pos // Clean up parens. impDecl contains at least one spec. if len(impDecl.Specs) == 1 { // Remove unneeded parens. impDecl.Lparen = token.NoPos } else if !impDecl.Lparen.IsValid() { // impDecl needs parens added. impDecl.Lparen = impDecl.Specs[0].Pos() } f.Imports = append(f.Imports, newImport) if len(f.Decls) <= 1 { return true } // Merge all the import declarations into the first one. var first *ast.GenDecl for i := 0; i < len(f.Decls); i++ { decl := f.Decls[i] gen, ok := decl.(*ast.GenDecl) if !ok || gen.Tok != token.IMPORT || declImports(gen, "C") { continue } if first == nil { first = gen continue // Don't touch the first one. } // We now know there is more than one package in this import // declaration. Ensure that it ends up parenthesized. first.Lparen = first.Pos() // Move the imports of the other import declaration to the first one. for _, spec := range gen.Specs { spec.(*ast.ImportSpec).Path.ValuePos = first.Pos() first.Specs = append(first.Specs, spec) } f.Decls = append(f.Decls[:i], f.Decls[i+1:]...) i-- } return true } func isThirdParty(importPath string) bool { // Third party package import path usually contains "." (".com", ".org", ...) // This logic is taken from golang.org/x/tools/imports package. return strings.Contains(importPath, ".") } // DeleteImport deletes the import path from the file f, if present. // If there are duplicate import declarations, all matching ones are deleted. func DeleteImport(fset *token.FileSet, f *ast.File, path string) (deleted bool) { return DeleteNamedImport(fset, f, "", path) } // DeleteNamedImport deletes the import with the given name and path from the file f, if present. // If there are duplicate import declarations, all matching ones are deleted. func DeleteNamedImport(fset *token.FileSet, f *ast.File, name, path string) (deleted bool) { var delspecs []*ast.ImportSpec var delcomments []*ast.CommentGroup // Find the import nodes that import path, if any. for i := 0; i < len(f.Decls); i++ { decl := f.Decls[i] gen, ok := decl.(*ast.GenDecl) if !ok || gen.Tok != token.IMPORT { continue } for j := 0; j < len(gen.Specs); j++ { spec := gen.Specs[j] impspec := spec.(*ast.ImportSpec) if importName(impspec) != name || importPath(impspec) != path { continue } // We found an import spec that imports path. // Delete it. delspecs = append(delspecs, impspec) deleted = true copy(gen.Specs[j:], gen.Specs[j+1:]) gen.Specs = gen.Specs[:len(gen.Specs)-1] // If this was the last import spec in this decl, // delete the decl, too. if len(gen.Specs) == 0 { copy(f.Decls[i:], f.Decls[i+1:]) f.Decls = f.Decls[:len(f.Decls)-1] i-- break } else if len(gen.Specs) == 1 { if impspec.Doc != nil { delcomments = append(delcomments, impspec.Doc) } if impspec.Comment != nil { delcomments = append(delcomments, impspec.Comment) } for _, cg := range f.Comments { // Found comment on the same line as the import spec. if cg.End() < impspec.Pos() && fset.Position(cg.End()).Line == fset.Position(impspec.Pos()).Line { delcomments = append(delcomments, cg) break } } spec := gen.Specs[0].(*ast.ImportSpec) // Move the documentation right after the import decl. if spec.Doc != nil { for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Doc.Pos()).Line { fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) } } for _, cg := range f.Comments { if cg.End() < spec.Pos() && fset.Position(cg.End()).Line == fset.Position(spec.Pos()).Line { for fset.Position(gen.TokPos).Line+1 < fset.Position(spec.Pos()).Line { fset.File(gen.TokPos).MergeLine(fset.Position(gen.TokPos).Line) } break } } } if j > 0 { lastImpspec := gen.Specs[j-1].(*ast.ImportSpec) lastLine := fset.Position(lastImpspec.Path.ValuePos).Line line := fset.Position(impspec.Path.ValuePos).Line // We deleted an entry but now there may be // a blank line-sized hole where the import was. if line-lastLine > 1 || !gen.Rparen.IsValid() { // There was a blank line immediately preceding the deleted import, // so there's no need to close the hole. The right parenthesis is // invalid after AddImport to an import statement without parenthesis. // Do nothing. } else if line != fset.File(gen.Rparen).LineCount() { // There was no blank line. Close the hole. fset.File(gen.Rparen).MergeLine(line) } } j-- } } // Delete imports from f.Imports. for i := 0; i < len(f.Imports); i++ { imp := f.Imports[i] for j, del := range delspecs { if imp == del { copy(f.Imports[i:], f.Imports[i+1:]) f.Imports = f.Imports[:len(f.Imports)-1] copy(delspecs[j:], delspecs[j+1:]) delspecs = delspecs[:len(delspecs)-1] i-- break } } } // Delete comments from f.Comments. for i := 0; i < len(f.Comments); i++ { cg := f.Comments[i] for j, del := range delcomments { if cg == del { copy(f.Comments[i:], f.Comments[i+1:]) f.Comments = f.Comments[:len(f.Comments)-1] copy(delcomments[j:], delcomments[j+1:]) delcomments = delcomments[:len(delcomments)-1] i-- break } } } if len(delspecs) > 0 { panic(fmt.Sprintf("deleted specs from Decls but not Imports: %v", delspecs)) } return } // RewriteImport rewrites any import of path oldPath to path newPath. func RewriteImport(fset *token.FileSet, f *ast.File, oldPath, newPath string) (rewrote bool) { for _, imp := range f.Imports { if importPath(imp) == oldPath { rewrote = true // record old End, because the default is to compute // it using the length of imp.Path.Value. imp.EndPos = imp.End() imp.Path.Value = strconv.Quote(newPath) } } return } // UsesImport reports whether a given import is used. func UsesImport(f *ast.File, path string) (used bool) { spec := importSpec(f, path) if spec == nil { return } name := spec.Name.String() switch name { case "": // If the package name is not explicitly specified, // make an educated guess. This is not guaranteed to be correct. lastSlash := strings.LastIndex(path, "/") if lastSlash == -1 { name = path } else { name = path[lastSlash+1:] } case "_", ".": // Not sure if this import is used - err on the side of caution. return true } ast.Walk(visitFn(func(n ast.Node) { sel, ok := n.(*ast.SelectorExpr) if ok && isTopName(sel.X, name) { used = true } }), f) return } type visitFn func(node ast.Node) func (fn visitFn) Visit(node ast.Node) ast.Visitor { fn(node) return fn } // imports reports whether f has an import with the specified name and path. func imports(f *ast.File, name, path string) bool { for _, s := range f.Imports { if importName(s) == name && importPath(s) == path { return true } } return false } // importSpec returns the import spec if f imports path, // or nil otherwise. func importSpec(f *ast.File, path string) *ast.ImportSpec { for _, s := range f.Imports { if importPath(s) == path { return s } } return nil } // importName returns the name of s, // or "" if the import is not named. func importName(s *ast.ImportSpec) string { if s.Name == nil { return "" } return s.Name.Name } // importPath returns the unquoted import path of s, // or "" if the path is not properly quoted. func importPath(s *ast.ImportSpec) string { t, err := strconv.Unquote(s.Path.Value) if err != nil { return "" } return t } // declImports reports whether gen contains an import of path. func declImports(gen *ast.GenDecl, path string) bool { if gen.Tok != token.IMPORT { return false } for _, spec := range gen.Specs { impspec := spec.(*ast.ImportSpec) if importPath(impspec) == path { return true } } return false } // matchLen returns the length of the longest path segment prefix shared by x and y. func matchLen(x, y string) int { n := 0 for i := 0; i < len(x) && i < len(y) && x[i] == y[i]; i++ { if x[i] == '/' { n++ } } return n } // isTopName returns true if n is a top-level unresolved identifier with the given name. func isTopName(n ast.Expr, name string) bool { id, ok := n.(*ast.Ident) return ok && id.Name == name && id.Obj == nil } // Imports returns the file imports grouped by paragraph. func Imports(fset *token.FileSet, f *ast.File) [][]*ast.ImportSpec { var groups [][]*ast.ImportSpec for _, decl := range f.Decls { genDecl, ok := decl.(*ast.GenDecl) if !ok || genDecl.Tok != token.IMPORT { break } group := []*ast.ImportSpec{} var lastLine int for _, spec := range genDecl.Specs { importSpec := spec.(*ast.ImportSpec) pos := importSpec.Path.ValuePos line := fset.Position(pos).Line if lastLine > 0 && pos > 0 && line-lastLine > 1 { groups = append(groups, group) group = []*ast.ImportSpec{} } group = append(group, importSpec) lastLine = line } groups = append(groups, group) } return groups } ================================================ FILE: _tools/src/golang.org/x/tools/go/ast/astutil/rewrite.go ================================================ // Copyright 2017 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package astutil import ( "fmt" "go/ast" "reflect" "sort" ) // An ApplyFunc is invoked by Apply for each node n, even if n is nil, // before and/or after the node's children, using a Cursor describing // the current node and providing operations on it. // // The return value of ApplyFunc controls the syntax tree traversal. // See Apply for details. type ApplyFunc func(*Cursor) bool // Apply traverses a syntax tree recursively, starting with root, // and calling pre and post for each node as described below. // Apply returns the syntax tree, possibly modified. // // If pre is not nil, it is called for each node before the node's // children are traversed (pre-order). If pre returns false, no // children are traversed, and post is not called for that node. // // If post is not nil, and a prior call of pre didn't return false, // post is called for each node after its children are traversed // (post-order). If post returns false, traversal is terminated and // Apply returns immediately. // // Only fields that refer to AST nodes are considered children; // i.e., token.Pos, Scopes, Objects, and fields of basic types // (strings, etc.) are ignored. // // Children are traversed in the order in which they appear in the // respective node's struct definition. A package's files are // traversed in the filenames' alphabetical order. // func Apply(root ast.Node, pre, post ApplyFunc) (result ast.Node) { parent := &struct{ ast.Node }{root} defer func() { if r := recover(); r != nil && r != abort { panic(r) } result = parent.Node }() a := &application{pre: pre, post: post} a.apply(parent, "Node", nil, root) return } var abort = new(int) // singleton, to signal termination of Apply // A Cursor describes a node encountered during Apply. // Information about the node and its parent is available // from the Node, Parent, Name, and Index methods. // // If p is a variable of type and value of the current parent node // c.Parent(), and f is the field identifier with name c.Name(), // the following invariants hold: // // p.f == c.Node() if c.Index() < 0 // p.f[c.Index()] == c.Node() if c.Index() >= 0 // // The methods Replace, Delete, InsertBefore, and InsertAfter // can be used to change the AST without disrupting Apply. type Cursor struct { parent ast.Node name string iter *iterator // valid if non-nil node ast.Node } // Node returns the current Node. func (c *Cursor) Node() ast.Node { return c.node } // Parent returns the parent of the current Node. func (c *Cursor) Parent() ast.Node { return c.parent } // Name returns the name of the parent Node field that contains the current Node. // If the parent is a *ast.Package and the current Node is a *ast.File, Name returns // the filename for the current Node. func (c *Cursor) Name() string { return c.name } // Index reports the index >= 0 of the current Node in the slice of Nodes that // contains it, or a value < 0 if the current Node is not part of a slice. // The index of the current node changes if InsertBefore is called while // processing the current node. func (c *Cursor) Index() int { if c.iter != nil { return c.iter.index } return -1 } // field returns the current node's parent field value. func (c *Cursor) field() reflect.Value { return reflect.Indirect(reflect.ValueOf(c.parent)).FieldByName(c.name) } // Replace replaces the current Node with n. // The replacement node is not walked by Apply. func (c *Cursor) Replace(n ast.Node) { if _, ok := c.node.(*ast.File); ok { file, ok := n.(*ast.File) if !ok { panic("attempt to replace *ast.File with non-*ast.File") } c.parent.(*ast.Package).Files[c.name] = file return } v := c.field() if i := c.Index(); i >= 0 { v = v.Index(i) } v.Set(reflect.ValueOf(n)) } // Delete deletes the current Node from its containing slice. // If the current Node is not part of a slice, Delete panics. // As a special case, if the current node is a package file, // Delete removes it from the package's Files map. func (c *Cursor) Delete() { if _, ok := c.node.(*ast.File); ok { delete(c.parent.(*ast.Package).Files, c.name) return } i := c.Index() if i < 0 { panic("Delete node not contained in slice") } v := c.field() l := v.Len() reflect.Copy(v.Slice(i, l), v.Slice(i+1, l)) v.Index(l - 1).Set(reflect.Zero(v.Type().Elem())) v.SetLen(l - 1) c.iter.step-- } // InsertAfter inserts n after the current Node in its containing slice. // If the current Node is not part of a slice, InsertAfter panics. // Apply does not walk n. func (c *Cursor) InsertAfter(n ast.Node) { i := c.Index() if i < 0 { panic("InsertAfter node not contained in slice") } v := c.field() v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) l := v.Len() reflect.Copy(v.Slice(i+2, l), v.Slice(i+1, l)) v.Index(i + 1).Set(reflect.ValueOf(n)) c.iter.step++ } // InsertBefore inserts n before the current Node in its containing slice. // If the current Node is not part of a slice, InsertBefore panics. // Apply will not walk n. func (c *Cursor) InsertBefore(n ast.Node) { i := c.Index() if i < 0 { panic("InsertBefore node not contained in slice") } v := c.field() v.Set(reflect.Append(v, reflect.Zero(v.Type().Elem()))) l := v.Len() reflect.Copy(v.Slice(i+1, l), v.Slice(i, l)) v.Index(i).Set(reflect.ValueOf(n)) c.iter.index++ } // application carries all the shared data so we can pass it around cheaply. type application struct { pre, post ApplyFunc cursor Cursor iter iterator } func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.Node) { // convert typed nil into untyped nil if v := reflect.ValueOf(n); v.Kind() == reflect.Ptr && v.IsNil() { n = nil } // avoid heap-allocating a new cursor for each apply call; reuse a.cursor instead saved := a.cursor a.cursor.parent = parent a.cursor.name = name a.cursor.iter = iter a.cursor.node = n if a.pre != nil && !a.pre(&a.cursor) { a.cursor = saved return } // walk children // (the order of the cases matches the order of the corresponding node types in go/ast) switch n := n.(type) { case nil: // nothing to do // Comments and fields case *ast.Comment: // nothing to do case *ast.CommentGroup: if n != nil { a.applyList(n, "List") } case *ast.Field: a.apply(n, "Doc", nil, n.Doc) a.applyList(n, "Names") a.apply(n, "Type", nil, n.Type) a.apply(n, "Tag", nil, n.Tag) a.apply(n, "Comment", nil, n.Comment) case *ast.FieldList: a.applyList(n, "List") // Expressions case *ast.BadExpr, *ast.Ident, *ast.BasicLit: // nothing to do case *ast.Ellipsis: a.apply(n, "Elt", nil, n.Elt) case *ast.FuncLit: a.apply(n, "Type", nil, n.Type) a.apply(n, "Body", nil, n.Body) case *ast.CompositeLit: a.apply(n, "Type", nil, n.Type) a.applyList(n, "Elts") case *ast.ParenExpr: a.apply(n, "X", nil, n.X) case *ast.SelectorExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Sel", nil, n.Sel) case *ast.IndexExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Index", nil, n.Index) case *ast.SliceExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Low", nil, n.Low) a.apply(n, "High", nil, n.High) a.apply(n, "Max", nil, n.Max) case *ast.TypeAssertExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Type", nil, n.Type) case *ast.CallExpr: a.apply(n, "Fun", nil, n.Fun) a.applyList(n, "Args") case *ast.StarExpr: a.apply(n, "X", nil, n.X) case *ast.UnaryExpr: a.apply(n, "X", nil, n.X) case *ast.BinaryExpr: a.apply(n, "X", nil, n.X) a.apply(n, "Y", nil, n.Y) case *ast.KeyValueExpr: a.apply(n, "Key", nil, n.Key) a.apply(n, "Value", nil, n.Value) // Types case *ast.ArrayType: a.apply(n, "Len", nil, n.Len) a.apply(n, "Elt", nil, n.Elt) case *ast.StructType: a.apply(n, "Fields", nil, n.Fields) case *ast.FuncType: a.apply(n, "Params", nil, n.Params) a.apply(n, "Results", nil, n.Results) case *ast.InterfaceType: a.apply(n, "Methods", nil, n.Methods) case *ast.MapType: a.apply(n, "Key", nil, n.Key) a.apply(n, "Value", nil, n.Value) case *ast.ChanType: a.apply(n, "Value", nil, n.Value) // Statements case *ast.BadStmt: // nothing to do case *ast.DeclStmt: a.apply(n, "Decl", nil, n.Decl) case *ast.EmptyStmt: // nothing to do case *ast.LabeledStmt: a.apply(n, "Label", nil, n.Label) a.apply(n, "Stmt", nil, n.Stmt) case *ast.ExprStmt: a.apply(n, "X", nil, n.X) case *ast.SendStmt: a.apply(n, "Chan", nil, n.Chan) a.apply(n, "Value", nil, n.Value) case *ast.IncDecStmt: a.apply(n, "X", nil, n.X) case *ast.AssignStmt: a.applyList(n, "Lhs") a.applyList(n, "Rhs") case *ast.GoStmt: a.apply(n, "Call", nil, n.Call) case *ast.DeferStmt: a.apply(n, "Call", nil, n.Call) case *ast.ReturnStmt: a.applyList(n, "Results") case *ast.BranchStmt: a.apply(n, "Label", nil, n.Label) case *ast.BlockStmt: a.applyList(n, "List") case *ast.IfStmt: a.apply(n, "Init", nil, n.Init) a.apply(n, "Cond", nil, n.Cond) a.apply(n, "Body", nil, n.Body) a.apply(n, "Else", nil, n.Else) case *ast.CaseClause: a.applyList(n, "List") a.applyList(n, "Body") case *ast.SwitchStmt: a.apply(n, "Init", nil, n.Init) a.apply(n, "Tag", nil, n.Tag) a.apply(n, "Body", nil, n.Body) case *ast.TypeSwitchStmt: a.apply(n, "Init", nil, n.Init) a.apply(n, "Assign", nil, n.Assign) a.apply(n, "Body", nil, n.Body) case *ast.CommClause: a.apply(n, "Comm", nil, n.Comm) a.applyList(n, "Body") case *ast.SelectStmt: a.apply(n, "Body", nil, n.Body) case *ast.ForStmt: a.apply(n, "Init", nil, n.Init) a.apply(n, "Cond", nil, n.Cond) a.apply(n, "Post", nil, n.Post) a.apply(n, "Body", nil, n.Body) case *ast.RangeStmt: a.apply(n, "Key", nil, n.Key) a.apply(n, "Value", nil, n.Value) a.apply(n, "X", nil, n.X) a.apply(n, "Body", nil, n.Body) // Declarations case *ast.ImportSpec: a.apply(n, "Doc", nil, n.Doc) a.apply(n, "Name", nil, n.Name) a.apply(n, "Path", nil, n.Path) a.apply(n, "Comment", nil, n.Comment) case *ast.ValueSpec: a.apply(n, "Doc", nil, n.Doc) a.applyList(n, "Names") a.apply(n, "Type", nil, n.Type) a.applyList(n, "Values") a.apply(n, "Comment", nil, n.Comment) case *ast.TypeSpec: a.apply(n, "Doc", nil, n.Doc) a.apply(n, "Name", nil, n.Name) a.apply(n, "Type", nil, n.Type) a.apply(n, "Comment", nil, n.Comment) case *ast.BadDecl: // nothing to do case *ast.GenDecl: a.apply(n, "Doc", nil, n.Doc) a.applyList(n, "Specs") case *ast.FuncDecl: a.apply(n, "Doc", nil, n.Doc) a.apply(n, "Recv", nil, n.Recv) a.apply(n, "Name", nil, n.Name) a.apply(n, "Type", nil, n.Type) a.apply(n, "Body", nil, n.Body) // Files and packages case *ast.File: a.apply(n, "Doc", nil, n.Doc) a.apply(n, "Name", nil, n.Name) a.applyList(n, "Decls") // Don't walk n.Comments; they have either been walked already if // they are Doc comments, or they can be easily walked explicitly. case *ast.Package: // collect and sort names for reproducible behavior var names []string for name := range n.Files { names = append(names, name) } sort.Strings(names) for _, name := range names { a.apply(n, name, nil, n.Files[name]) } default: panic(fmt.Sprintf("Apply: unexpected node type %T", n)) } if a.post != nil && !a.post(&a.cursor) { panic(abort) } a.cursor = saved } // An iterator controls iteration over a slice of nodes. type iterator struct { index, step int } func (a *application) applyList(parent ast.Node, name string) { // avoid heap-allocating a new iterator for each applyList call; reuse a.iter instead saved := a.iter a.iter.index = 0 for { // must reload parent.name each time, since cursor modifications might change it v := reflect.Indirect(reflect.ValueOf(parent)).FieldByName(name) if a.iter.index >= v.Len() { break } // element x may be nil in a bad AST - be cautious var x ast.Node if e := v.Index(a.iter.index); e.IsValid() { x = e.Interface().(ast.Node) } a.iter.step = 1 a.apply(parent, name, &a.iter, x) a.iter.index += a.iter.step } a.iter = saved } ================================================ FILE: _tools/src/golang.org/x/tools/go/ast/astutil/util.go ================================================ // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package astutil import "go/ast" // Unparen returns e with any enclosing parentheses stripped. func Unparen(e ast.Expr) ast.Expr { for { p, ok := e.(*ast.ParenExpr) if !ok { return e } e = p.X } } ================================================ FILE: _tools/src/golang.org/x/tools/go/buildutil/allpackages.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package buildutil provides utilities related to the go/build // package in the standard library. // // All I/O is done via the build.Context file system interface, which must // be concurrency-safe. package buildutil // import "golang.org/x/tools/go/buildutil" import ( "go/build" "os" "path/filepath" "sort" "strings" "sync" ) // AllPackages returns the package path of each Go package in any source // directory of the specified build context (e.g. $GOROOT or an element // of $GOPATH). Errors are ignored. The results are sorted. // All package paths are canonical, and thus may contain "/vendor/". // // The result may include import paths for directories that contain no // *.go files, such as "archive" (in $GOROOT/src). // // All I/O is done via the build.Context file system interface, // which must be concurrency-safe. // func AllPackages(ctxt *build.Context) []string { var list []string ForEachPackage(ctxt, func(pkg string, _ error) { list = append(list, pkg) }) sort.Strings(list) return list } // ForEachPackage calls the found function with the package path of // each Go package it finds in any source directory of the specified // build context (e.g. $GOROOT or an element of $GOPATH). // All package paths are canonical, and thus may contain "/vendor/". // // If the package directory exists but could not be read, the second // argument to the found function provides the error. // // All I/O is done via the build.Context file system interface, // which must be concurrency-safe. // func ForEachPackage(ctxt *build.Context, found func(importPath string, err error)) { ch := make(chan item) var wg sync.WaitGroup for _, root := range ctxt.SrcDirs() { root := root wg.Add(1) go func() { allPackages(ctxt, root, ch) wg.Done() }() } go func() { wg.Wait() close(ch) }() // All calls to found occur in the caller's goroutine. for i := range ch { found(i.importPath, i.err) } } type item struct { importPath string err error // (optional) } // We use a process-wide counting semaphore to limit // the number of parallel calls to ReadDir. var ioLimit = make(chan bool, 20) func allPackages(ctxt *build.Context, root string, ch chan<- item) { root = filepath.Clean(root) + string(os.PathSeparator) var wg sync.WaitGroup var walkDir func(dir string) walkDir = func(dir string) { // Avoid .foo, _foo, and testdata directory trees. base := filepath.Base(dir) if base == "" || base[0] == '.' || base[0] == '_' || base == "testdata" { return } pkg := filepath.ToSlash(strings.TrimPrefix(dir, root)) // Prune search if we encounter any of these import paths. switch pkg { case "builtin": return } ioLimit <- true files, err := ReadDir(ctxt, dir) <-ioLimit if pkg != "" || err != nil { ch <- item{pkg, err} } for _, fi := range files { fi := fi if fi.IsDir() { wg.Add(1) go func() { walkDir(filepath.Join(dir, fi.Name())) wg.Done() }() } } } walkDir(root) wg.Wait() } // ExpandPatterns returns the set of packages matched by patterns, // which may have the following forms: // // golang.org/x/tools/cmd/guru # a single package // golang.org/x/tools/... # all packages beneath dir // ... # the entire workspace. // // Order is significant: a pattern preceded by '-' removes matching // packages from the set. For example, these patterns match all encoding // packages except encoding/xml: // // encoding/... -encoding/xml // // A trailing slash in a pattern is ignored. (Path components of Go // package names are separated by slash, not the platform's path separator.) // func ExpandPatterns(ctxt *build.Context, patterns []string) map[string]bool { // TODO(adonovan): support other features of 'go list': // - "std"/"cmd"/"all" meta-packages // - "..." not at the end of a pattern // - relative patterns using "./" or "../" prefix pkgs := make(map[string]bool) doPkg := func(pkg string, neg bool) { if neg { delete(pkgs, pkg) } else { pkgs[pkg] = true } } // Scan entire workspace if wildcards are present. // TODO(adonovan): opt: scan only the necessary subtrees of the workspace. var all []string for _, arg := range patterns { if strings.HasSuffix(arg, "...") { all = AllPackages(ctxt) break } } for _, arg := range patterns { if arg == "" { continue } neg := arg[0] == '-' if neg { arg = arg[1:] } if arg == "..." { // ... matches all packages for _, pkg := range all { doPkg(pkg, neg) } } else if dir := strings.TrimSuffix(arg, "/..."); dir != arg { // dir/... matches all packages beneath dir for _, pkg := range all { if strings.HasPrefix(pkg, dir) && (len(pkg) == len(dir) || pkg[len(dir)] == '/') { doPkg(pkg, neg) } } } else { // single package doPkg(strings.TrimSuffix(arg, "/"), neg) } } return pkgs } ================================================ FILE: _tools/src/golang.org/x/tools/go/buildutil/fakecontext.go ================================================ // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package buildutil import ( "fmt" "go/build" "io" "io/ioutil" "os" "path" "path/filepath" "sort" "strings" "time" ) // FakeContext returns a build.Context for the fake file tree specified // by pkgs, which maps package import paths to a mapping from file base // names to contents. // // The fake Context has a GOROOT of "/go" and no GOPATH, and overrides // the necessary file access methods to read from memory instead of the // real file system. // // Unlike a real file tree, the fake one has only two levels---packages // and files---so ReadDir("/go/src/") returns all packages under // /go/src/ including, for instance, "math" and "math/big". // ReadDir("/go/src/math/big") would return all the files in the // "math/big" package. // func FakeContext(pkgs map[string]map[string]string) *build.Context { clean := func(filename string) string { f := path.Clean(filepath.ToSlash(filename)) // Removing "/go/src" while respecting segment // boundaries has this unfortunate corner case: if f == "/go/src" { return "" } return strings.TrimPrefix(f, "/go/src/") } ctxt := build.Default // copy ctxt.GOROOT = "/go" ctxt.GOPATH = "" ctxt.Compiler = "gc" ctxt.IsDir = func(dir string) bool { dir = clean(dir) if dir == "" { return true // needed by (*build.Context).SrcDirs } return pkgs[dir] != nil } ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) { dir = clean(dir) var fis []os.FileInfo if dir == "" { // enumerate packages for importPath := range pkgs { fis = append(fis, fakeDirInfo(importPath)) } } else { // enumerate files of package for basename := range pkgs[dir] { fis = append(fis, fakeFileInfo(basename)) } } sort.Sort(byName(fis)) return fis, nil } ctxt.OpenFile = func(filename string) (io.ReadCloser, error) { filename = clean(filename) dir, base := path.Split(filename) content, ok := pkgs[path.Clean(dir)][base] if !ok { return nil, fmt.Errorf("file not found: %s", filename) } return ioutil.NopCloser(strings.NewReader(content)), nil } ctxt.IsAbsPath = func(path string) bool { path = filepath.ToSlash(path) // Don't rely on the default (filepath.Path) since on // Windows, it reports virtual paths as non-absolute. return strings.HasPrefix(path, "/") } return &ctxt } type byName []os.FileInfo func (s byName) Len() int { return len(s) } func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } type fakeFileInfo string func (fi fakeFileInfo) Name() string { return string(fi) } func (fakeFileInfo) Sys() interface{} { return nil } func (fakeFileInfo) ModTime() time.Time { return time.Time{} } func (fakeFileInfo) IsDir() bool { return false } func (fakeFileInfo) Size() int64 { return 0 } func (fakeFileInfo) Mode() os.FileMode { return 0644 } type fakeDirInfo string func (fd fakeDirInfo) Name() string { return string(fd) } func (fakeDirInfo) Sys() interface{} { return nil } func (fakeDirInfo) ModTime() time.Time { return time.Time{} } func (fakeDirInfo) IsDir() bool { return true } func (fakeDirInfo) Size() int64 { return 0 } func (fakeDirInfo) Mode() os.FileMode { return 0755 } ================================================ FILE: _tools/src/golang.org/x/tools/go/buildutil/overlay.go ================================================ // Copyright 2016 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package buildutil import ( "bufio" "bytes" "fmt" "go/build" "io" "io/ioutil" "path/filepath" "strconv" "strings" ) // OverlayContext overlays a build.Context with additional files from // a map. Files in the map take precedence over other files. // // In addition to plain string comparison, two file names are // considered equal if their base names match and their directory // components point at the same directory on the file system. That is, // symbolic links are followed for directories, but not files. // // A common use case for OverlayContext is to allow editors to pass in // a set of unsaved, modified files. // // Currently, only the Context.OpenFile function will respect the // overlay. This may change in the future. func OverlayContext(orig *build.Context, overlay map[string][]byte) *build.Context { // TODO(dominikh): Implement IsDir, HasSubdir and ReadDir rc := func(data []byte) (io.ReadCloser, error) { return ioutil.NopCloser(bytes.NewBuffer(data)), nil } copy := *orig // make a copy ctxt := © ctxt.OpenFile = func(path string) (io.ReadCloser, error) { // Fast path: names match exactly. if content, ok := overlay[path]; ok { return rc(content) } // Slow path: check for same file under a different // alias, perhaps due to a symbolic link. for filename, content := range overlay { if sameFile(path, filename) { return rc(content) } } return OpenFile(orig, path) } return ctxt } // ParseOverlayArchive parses an archive containing Go files and their // contents. The result is intended to be used with OverlayContext. // // // Archive format // // The archive consists of a series of files. Each file consists of a // name, a decimal file size and the file contents, separated by // newlines. No newline follows after the file contents. func ParseOverlayArchive(archive io.Reader) (map[string][]byte, error) { overlay := make(map[string][]byte) r := bufio.NewReader(archive) for { // Read file name. filename, err := r.ReadString('\n') if err != nil { if err == io.EOF { break // OK } return nil, fmt.Errorf("reading archive file name: %v", err) } filename = filepath.Clean(strings.TrimSpace(filename)) // Read file size. sz, err := r.ReadString('\n') if err != nil { return nil, fmt.Errorf("reading size of archive file %s: %v", filename, err) } sz = strings.TrimSpace(sz) size, err := strconv.ParseUint(sz, 10, 32) if err != nil { return nil, fmt.Errorf("parsing size of archive file %s: %v", filename, err) } // Read file content. content := make([]byte, size) if _, err := io.ReadFull(r, content); err != nil { return nil, fmt.Errorf("reading archive file %s: %v", filename, err) } overlay[filename] = content } return overlay, nil } ================================================ FILE: _tools/src/golang.org/x/tools/go/buildutil/tags.go ================================================ // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package buildutil // This logic was copied from stringsFlag from $GOROOT/src/cmd/go/build.go. import "fmt" const TagsFlagDoc = "a list of `build tags` to consider satisfied during the build. " + "For more information about build tags, see the description of " + "build constraints in the documentation for the go/build package" // TagsFlag is an implementation of the flag.Value and flag.Getter interfaces that parses // a flag value in the same manner as go build's -tags flag and // populates a []string slice. // // See $GOROOT/src/go/build/doc.go for description of build tags. // See $GOROOT/src/cmd/go/doc.go for description of 'go build -tags' flag. // // Example: // flag.Var((*buildutil.TagsFlag)(&build.Default.BuildTags), "tags", buildutil.TagsFlagDoc) type TagsFlag []string func (v *TagsFlag) Set(s string) error { var err error *v, err = splitQuotedFields(s) if *v == nil { *v = []string{} } return err } func (v *TagsFlag) Get() interface{} { return *v } func splitQuotedFields(s string) ([]string, error) { // Split fields allowing '' or "" around elements. // Quotes further inside the string do not count. var f []string for len(s) > 0 { for len(s) > 0 && isSpaceByte(s[0]) { s = s[1:] } if len(s) == 0 { break } // Accepted quoted string. No unescaping inside. if s[0] == '"' || s[0] == '\'' { quote := s[0] s = s[1:] i := 0 for i < len(s) && s[i] != quote { i++ } if i >= len(s) { return nil, fmt.Errorf("unterminated %c string", quote) } f = append(f, s[:i]) s = s[i+1:] continue } i := 0 for i < len(s) && !isSpaceByte(s[i]) { i++ } f = append(f, s[:i]) s = s[i:] } return f, nil } func (v *TagsFlag) String() string { return "" } func isSpaceByte(c byte) bool { return c == ' ' || c == '\t' || c == '\n' || c == '\r' } ================================================ FILE: _tools/src/golang.org/x/tools/go/buildutil/util.go ================================================ // Copyright 2014 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package buildutil import ( "fmt" "go/ast" "go/build" "go/parser" "go/token" "io" "io/ioutil" "os" "path" "path/filepath" "strings" ) // ParseFile behaves like parser.ParseFile, // but uses the build context's file system interface, if any. // // If file is not absolute (as defined by IsAbsPath), the (dir, file) // components are joined using JoinPath; dir must be absolute. // // The displayPath function, if provided, is used to transform the // filename that will be attached to the ASTs. // // TODO(adonovan): call this from go/loader.parseFiles when the tree thaws. // func ParseFile(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, file string, mode parser.Mode) (*ast.File, error) { if !IsAbsPath(ctxt, file) { file = JoinPath(ctxt, dir, file) } rd, err := OpenFile(ctxt, file) if err != nil { return nil, err } defer rd.Close() // ignore error if displayPath != nil { file = displayPath(file) } return parser.ParseFile(fset, file, rd, mode) } // ContainingPackage returns the package containing filename. // // If filename is not absolute, it is interpreted relative to working directory dir. // All I/O is via the build context's file system interface, if any. // // The '...Files []string' fields of the resulting build.Package are not // populated (build.FindOnly mode). // func ContainingPackage(ctxt *build.Context, dir, filename string) (*build.Package, error) { if !IsAbsPath(ctxt, filename) { filename = JoinPath(ctxt, dir, filename) } // We must not assume the file tree uses // "/" always, // `\` always, // or os.PathSeparator (which varies by platform), // but to make any progress, we are forced to assume that // paths will not use `\` unless the PathSeparator // is also `\`, thus we can rely on filepath.ToSlash for some sanity. dirSlash := path.Dir(filepath.ToSlash(filename)) + "/" // We assume that no source root (GOPATH[i] or GOROOT) contains any other. for _, srcdir := range ctxt.SrcDirs() { srcdirSlash := filepath.ToSlash(srcdir) + "/" if importPath, ok := HasSubdir(ctxt, srcdirSlash, dirSlash); ok { return ctxt.Import(importPath, dir, build.FindOnly) } } return nil, fmt.Errorf("can't find package containing %s", filename) } // -- Effective methods of file system interface ------------------------- // (go/build.Context defines these as methods, but does not export them.) // hasSubdir calls ctxt.HasSubdir (if not nil) or else uses // the local file system to answer the question. func HasSubdir(ctxt *build.Context, root, dir string) (rel string, ok bool) { if f := ctxt.HasSubdir; f != nil { return f(root, dir) } // Try using paths we received. if rel, ok = hasSubdir(root, dir); ok { return } // Try expanding symlinks and comparing // expanded against unexpanded and // expanded against expanded. rootSym, _ := filepath.EvalSymlinks(root) dirSym, _ := filepath.EvalSymlinks(dir) if rel, ok = hasSubdir(rootSym, dir); ok { return } if rel, ok = hasSubdir(root, dirSym); ok { return } return hasSubdir(rootSym, dirSym) } func hasSubdir(root, dir string) (rel string, ok bool) { const sep = string(filepath.Separator) root = filepath.Clean(root) if !strings.HasSuffix(root, sep) { root += sep } dir = filepath.Clean(dir) if !strings.HasPrefix(dir, root) { return "", false } return filepath.ToSlash(dir[len(root):]), true } // FileExists returns true if the specified file exists, // using the build context's file system interface. func FileExists(ctxt *build.Context, path string) bool { if ctxt.OpenFile != nil { r, err := ctxt.OpenFile(path) if err != nil { return false } r.Close() // ignore error return true } _, err := os.Stat(path) return err == nil } // OpenFile behaves like os.Open, // but uses the build context's file system interface, if any. func OpenFile(ctxt *build.Context, path string) (io.ReadCloser, error) { if ctxt.OpenFile != nil { return ctxt.OpenFile(path) } return os.Open(path) } // IsAbsPath behaves like filepath.IsAbs, // but uses the build context's file system interface, if any. func IsAbsPath(ctxt *build.Context, path string) bool { if ctxt.IsAbsPath != nil { return ctxt.IsAbsPath(path) } return filepath.IsAbs(path) } // JoinPath behaves like filepath.Join, // but uses the build context's file system interface, if any. func JoinPath(ctxt *build.Context, path ...string) string { if ctxt.JoinPath != nil { return ctxt.JoinPath(path...) } return filepath.Join(path...) } // IsDir behaves like os.Stat plus IsDir, // but uses the build context's file system interface, if any. func IsDir(ctxt *build.Context, path string) bool { if ctxt.IsDir != nil { return ctxt.IsDir(path) } fi, err := os.Stat(path) return err == nil && fi.IsDir() } // ReadDir behaves like ioutil.ReadDir, // but uses the build context's file system interface, if any. func ReadDir(ctxt *build.Context, path string) ([]os.FileInfo, error) { if ctxt.ReadDir != nil { return ctxt.ReadDir(path) } return ioutil.ReadDir(path) } // SplitPathList behaves like filepath.SplitList, // but uses the build context's file system interface, if any. func SplitPathList(ctxt *build.Context, s string) []string { if ctxt.SplitPathList != nil { return ctxt.SplitPathList(s) } return filepath.SplitList(s) } // sameFile returns true if x and y have the same basename and denote // the same file. // func sameFile(x, y string) bool { if path.Clean(x) == path.Clean(y) { return true } if filepath.Base(x) == filepath.Base(y) { // (optimisation) if xi, err := os.Stat(x); err == nil { if yi, err := os.Stat(y); err == nil { return os.SameFile(xi, yi) } } } return false } ================================================ FILE: _tools/src/golang.org/x/tools/go/internal/cgo/cgo.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package cgo handles cgo preprocessing of files containing `import "C"`. // // DESIGN // // The approach taken is to run the cgo processor on the package's // CgoFiles and parse the output, faking the filenames of the // resulting ASTs so that the synthetic file containing the C types is // called "C" (e.g. "~/go/src/net/C") and the preprocessed files // have their original names (e.g. "~/go/src/net/cgo_unix.go"), // not the names of the actual temporary files. // // The advantage of this approach is its fidelity to 'go build'. The // downside is that the token.Position.Offset for each AST node is // incorrect, being an offset within the temporary file. Line numbers // should still be correct because of the //line comments. // // The logic of this file is mostly plundered from the 'go build' // tool, which also invokes the cgo preprocessor. // // // REJECTED ALTERNATIVE // // An alternative approach that we explored is to extend go/types' // Importer mechanism to provide the identity of the importing package // so that each time `import "C"` appears it resolves to a different // synthetic package containing just the objects needed in that case. // The loader would invoke cgo but parse only the cgo_types.go file // defining the package-level objects, discarding the other files // resulting from preprocessing. // // The benefit of this approach would have been that source-level // syntax information would correspond exactly to the original cgo // file, with no preprocessing involved, making source tools like // godoc, guru, and eg happy. However, the approach was rejected // due to the additional complexity it would impose on go/types. (It // made for a beautiful demo, though.) // // cgo files, despite their *.go extension, are not legal Go source // files per the specification since they may refer to unexported // members of package "C" such as C.int. Also, a function such as // C.getpwent has in effect two types, one matching its C type and one // which additionally returns (errno C.int). The cgo preprocessor // uses name mangling to distinguish these two functions in the // processed code, but go/types would need to duplicate this logic in // its handling of function calls, analogous to the treatment of map // lookups in which y=m[k] and y,ok=m[k] are both legal. package cgo import ( "fmt" "go/ast" "go/build" "go/parser" "go/token" "io/ioutil" "log" "os" "path/filepath" "regexp" "strings" exec "golang.org/x/sys/execabs" ) // ProcessFiles invokes the cgo preprocessor on bp.CgoFiles, parses // the output and returns the resulting ASTs. // func ProcessFiles(bp *build.Package, fset *token.FileSet, DisplayPath func(path string) string, mode parser.Mode) ([]*ast.File, error) { tmpdir, err := ioutil.TempDir("", strings.Replace(bp.ImportPath, "/", "_", -1)+"_C") if err != nil { return nil, err } defer os.RemoveAll(tmpdir) pkgdir := bp.Dir if DisplayPath != nil { pkgdir = DisplayPath(pkgdir) } cgoFiles, cgoDisplayFiles, err := Run(bp, pkgdir, tmpdir, false) if err != nil { return nil, err } var files []*ast.File for i := range cgoFiles { rd, err := os.Open(cgoFiles[i]) if err != nil { return nil, err } display := filepath.Join(bp.Dir, cgoDisplayFiles[i]) f, err := parser.ParseFile(fset, display, rd, mode) rd.Close() if err != nil { return nil, err } files = append(files, f) } return files, nil } var cgoRe = regexp.MustCompile(`[/\\:]`) // Run invokes the cgo preprocessor on bp.CgoFiles and returns two // lists of files: the resulting processed files (in temporary // directory tmpdir) and the corresponding names of the unprocessed files. // // Run is adapted from (*builder).cgo in // $GOROOT/src/cmd/go/build.go, but these features are unsupported: // Objective C, CGOPKGPATH, CGO_FLAGS. // // If useabs is set to true, absolute paths of the bp.CgoFiles will be passed in // to the cgo preprocessor. This in turn will set the // line comments // referring to those files to use absolute paths. This is needed for // go/packages using the legacy go list support so it is able to find // the original files. func Run(bp *build.Package, pkgdir, tmpdir string, useabs bool) (files, displayFiles []string, err error) { cgoCPPFLAGS, _, _, _ := cflags(bp, true) _, cgoexeCFLAGS, _, _ := cflags(bp, false) if len(bp.CgoPkgConfig) > 0 { pcCFLAGS, err := pkgConfigFlags(bp) if err != nil { return nil, nil, err } cgoCPPFLAGS = append(cgoCPPFLAGS, pcCFLAGS...) } // Allows including _cgo_export.h from .[ch] files in the package. cgoCPPFLAGS = append(cgoCPPFLAGS, "-I", tmpdir) // _cgo_gotypes.go (displayed "C") contains the type definitions. files = append(files, filepath.Join(tmpdir, "_cgo_gotypes.go")) displayFiles = append(displayFiles, "C") for _, fn := range bp.CgoFiles { // "foo.cgo1.go" (displayed "foo.go") is the processed Go source. f := cgoRe.ReplaceAllString(fn[:len(fn)-len("go")], "_") files = append(files, filepath.Join(tmpdir, f+"cgo1.go")) displayFiles = append(displayFiles, fn) } var cgoflags []string if bp.Goroot && bp.ImportPath == "runtime/cgo" { cgoflags = append(cgoflags, "-import_runtime_cgo=false") } if bp.Goroot && bp.ImportPath == "runtime/race" || bp.ImportPath == "runtime/cgo" { cgoflags = append(cgoflags, "-import_syscall=false") } var cgoFiles []string = bp.CgoFiles if useabs { cgoFiles = make([]string, len(bp.CgoFiles)) for i := range cgoFiles { cgoFiles[i] = filepath.Join(pkgdir, bp.CgoFiles[i]) } } args := stringList( "go", "tool", "cgo", "-srcdir", pkgdir, "-objdir", tmpdir, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, cgoFiles, ) if false { log.Printf("Running cgo for package %q: %s", bp.ImportPath, args) } cmd := exec.Command(args[0], args[1:]...) cmd.Stdout = os.Stderr cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { return nil, nil, fmt.Errorf("cgo failed: %s: %s", args, err) } return files, displayFiles, nil } // -- unmodified from 'go build' --------------------------------------- // Return the flags to use when invoking the C or C++ compilers, or cgo. func cflags(p *build.Package, def bool) (cppflags, cflags, cxxflags, ldflags []string) { var defaults string if def { defaults = "-g -O2" } cppflags = stringList(envList("CGO_CPPFLAGS", ""), p.CgoCPPFLAGS) cflags = stringList(envList("CGO_CFLAGS", defaults), p.CgoCFLAGS) cxxflags = stringList(envList("CGO_CXXFLAGS", defaults), p.CgoCXXFLAGS) ldflags = stringList(envList("CGO_LDFLAGS", defaults), p.CgoLDFLAGS) return } // envList returns the value of the given environment variable broken // into fields, using the default value when the variable is empty. func envList(key, def string) []string { v := os.Getenv(key) if v == "" { v = def } return strings.Fields(v) } // stringList's arguments should be a sequence of string or []string values. // stringList flattens them into a single []string. func stringList(args ...interface{}) []string { var x []string for _, arg := range args { switch arg := arg.(type) { case []string: x = append(x, arg...) case string: x = append(x, arg) default: panic("stringList: invalid argument") } } return x } ================================================ FILE: _tools/src/golang.org/x/tools/go/internal/cgo/cgo_pkgconfig.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package cgo import ( "errors" "fmt" "go/build" exec "golang.org/x/sys/execabs" "strings" ) // pkgConfig runs pkg-config with the specified arguments and returns the flags it prints. func pkgConfig(mode string, pkgs []string) (flags []string, err error) { cmd := exec.Command("pkg-config", append([]string{mode}, pkgs...)...) out, err := cmd.CombinedOutput() if err != nil { s := fmt.Sprintf("%s failed: %v", strings.Join(cmd.Args, " "), err) if len(out) > 0 { s = fmt.Sprintf("%s: %s", s, out) } return nil, errors.New(s) } if len(out) > 0 { flags = strings.Fields(string(out)) } return } // pkgConfigFlags calls pkg-config if needed and returns the cflags // needed to build the package. func pkgConfigFlags(p *build.Package) (cflags []string, err error) { if len(p.CgoPkgConfig) == 0 { return nil, nil } return pkgConfig("--cflags", p.CgoPkgConfig) } ================================================ FILE: _tools/src/golang.org/x/tools/go/loader/doc.go ================================================ // Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package loader loads a complete Go program from source code, parsing // and type-checking the initial packages plus their transitive closure // of dependencies. The ASTs and the derived facts are retained for // later use. // // Deprecated: This is an older API and does not have support // for modules. Use golang.org/x/tools/go/packages instead. // // The package defines two primary types: Config, which specifies a // set of initial packages to load and various other options; and // Program, which is the result of successfully loading the packages // specified by a configuration. // // The configuration can be set directly, but *Config provides various // convenience methods to simplify the common cases, each of which can // be called any number of times. Finally, these are followed by a // call to Load() to actually load and type-check the program. // // var conf loader.Config // // // Use the command-line arguments to specify // // a set of initial packages to load from source. // // See FromArgsUsage for help. // rest, err := conf.FromArgs(os.Args[1:], wantTests) // // // Parse the specified files and create an ad hoc package with path "foo". // // All files must have the same 'package' declaration. // conf.CreateFromFilenames("foo", "foo.go", "bar.go") // // // Create an ad hoc package with path "foo" from // // the specified already-parsed files. // // All ASTs must have the same 'package' declaration. // conf.CreateFromFiles("foo", parsedFiles) // // // Add "runtime" to the set of packages to be loaded. // conf.Import("runtime") // // // Adds "fmt" and "fmt_test" to the set of packages // // to be loaded. "fmt" will include *_test.go files. // conf.ImportWithTests("fmt") // // // Finally, load all the packages specified by the configuration. // prog, err := conf.Load() // // See examples_test.go for examples of API usage. // // // CONCEPTS AND TERMINOLOGY // // The WORKSPACE is the set of packages accessible to the loader. The // workspace is defined by Config.Build, a *build.Context. The // default context treats subdirectories of $GOROOT and $GOPATH as // packages, but this behavior may be overridden. // // An AD HOC package is one specified as a set of source files on the // command line. In the simplest case, it may consist of a single file // such as $GOROOT/src/net/http/triv.go. // // EXTERNAL TEST packages are those comprised of a set of *_test.go // files all with the same 'package foo_test' declaration, all in the // same directory. (go/build.Package calls these files XTestFiles.) // // An IMPORTABLE package is one that can be referred to by some import // spec. Every importable package is uniquely identified by its // PACKAGE PATH or just PATH, a string such as "fmt", "encoding/json", // or "cmd/vendor/golang.org/x/arch/x86/x86asm". A package path // typically denotes a subdirectory of the workspace. // // An import declaration uses an IMPORT PATH to refer to a package. // Most import declarations use the package path as the import path. // // Due to VENDORING (https://golang.org/s/go15vendor), the // interpretation of an import path may depend on the directory in which // it appears. To resolve an import path to a package path, go/build // must search the enclosing directories for a subdirectory named // "vendor". // // ad hoc packages and external test packages are NON-IMPORTABLE. The // path of an ad hoc package is inferred from the package // declarations of its files and is therefore not a unique package key. // For example, Config.CreatePkgs may specify two initial ad hoc // packages, both with path "main". // // An AUGMENTED package is an importable package P plus all the // *_test.go files with same 'package foo' declaration as P. // (go/build.Package calls these files TestFiles.) // // The INITIAL packages are those specified in the configuration. A // DEPENDENCY is a package loaded to satisfy an import in an initial // package or another dependency. // package loader // IMPLEMENTATION NOTES // // 'go test', in-package test files, and import cycles // --------------------------------------------------- // // An external test package may depend upon members of the augmented // package that are not in the unaugmented package, such as functions // that expose internals. (See bufio/export_test.go for an example.) // So, the loader must ensure that for each external test package // it loads, it also augments the corresponding non-test package. // // The import graph over n unaugmented packages must be acyclic; the // import graph over n-1 unaugmented packages plus one augmented // package must also be acyclic. ('go test' relies on this.) But the // import graph over n augmented packages may contain cycles. // // First, all the (unaugmented) non-test packages and their // dependencies are imported in the usual way; the loader reports an // error if it detects an import cycle. // // Then, each package P for which testing is desired is augmented by // the list P' of its in-package test files, by calling // (*types.Checker).Files. This arrangement ensures that P' may // reference definitions within P, but P may not reference definitions // within P'. Furthermore, P' may import any other package, including // ones that depend upon P, without an import cycle error. // // Consider two packages A and B, both of which have lists of // in-package test files we'll call A' and B', and which have the // following import graph edges: // B imports A // B' imports A // A' imports B // This last edge would be expected to create an error were it not // for the special type-checking discipline above. // Cycles of size greater than two are possible. For example: // compress/bzip2/bzip2_test.go (package bzip2) imports "io/ioutil" // io/ioutil/tempfile_test.go (package ioutil) imports "regexp" // regexp/exec_test.go (package regexp) imports "compress/bzip2" // // // Concurrency // ----------- // // Let us define the import dependency graph as follows. Each node is a // list of files passed to (Checker).Files at once. Many of these lists // are the production code of an importable Go package, so those nodes // are labelled by the package's path. The remaining nodes are // ad hoc packages and lists of in-package *_test.go files that augment // an importable package; those nodes have no label. // // The edges of the graph represent import statements appearing within a // file. An edge connects a node (a list of files) to the node it // imports, which is importable and thus always labelled. // // Loading is controlled by this dependency graph. // // To reduce I/O latency, we start loading a package's dependencies // asynchronously as soon as we've parsed its files and enumerated its // imports (scanImports). This performs a preorder traversal of the // import dependency graph. // // To exploit hardware parallelism, we type-check unrelated packages in // parallel, where "unrelated" means not ordered by the partial order of // the import dependency graph. // // We use a concurrency-safe non-blocking cache (importer.imported) to // record the results of type-checking, whether success or failure. An // entry is created in this cache by startLoad the first time the // package is imported. The first goroutine to request an entry becomes // responsible for completing the task and broadcasting completion to // subsequent requestors, which block until then. // // Type checking occurs in (parallel) postorder: we cannot type-check a // set of files until we have loaded and type-checked all of their // immediate dependencies (and thus all of their transitive // dependencies). If the input were guaranteed free of import cycles, // this would be trivial: we could simply wait for completion of the // dependencies and then invoke the typechecker. // // But as we saw in the 'go test' section above, some cycles in the // import graph over packages are actually legal, so long as the // cycle-forming edge originates in the in-package test files that // augment the package. This explains why the nodes of the import // dependency graph are not packages, but lists of files: the unlabelled // nodes avoid the cycles. Consider packages A and B where B imports A // and A's in-package tests AT import B. The naively constructed import // graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but // the graph over lists of files is AT --> B --> A, where AT is an // unlabelled node. // // Awaiting completion of the dependencies in a cyclic graph would // deadlock, so we must materialize the import dependency graph (as // importer.graph) and check whether each import edge forms a cycle. If // x imports y, and the graph already contains a path from y to x, then // there is an import cycle, in which case the processing of x must not // wait for the completion of processing of y. // // When the type-checker makes a callback (doImport) to the loader for a // given import edge, there are two possible cases. In the normal case, // the dependency has already been completely type-checked; doImport // does a cache lookup and returns it. In the cyclic case, the entry in // the cache is still necessarily incomplete, indicating a cycle. We // perform the cycle check again to obtain the error message, and return // the error. // // The result of using concurrency is about a 2.5x speedup for stdlib_test. ================================================ FILE: _tools/src/golang.org/x/tools/go/loader/loader.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package loader // See doc.go for package documentation and implementation notes. import ( "errors" "fmt" "go/ast" "go/build" "go/parser" "go/token" "go/types" "os" "path/filepath" "sort" "strings" "sync" "time" "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/go/internal/cgo" ) var ignoreVendor build.ImportMode const trace = false // show timing info for type-checking // Config specifies the configuration for loading a whole program from // Go source code. // The zero value for Config is a ready-to-use default configuration. type Config struct { // Fset is the file set for the parser to use when loading the // program. If nil, it may be lazily initialized by any // method of Config. Fset *token.FileSet // ParserMode specifies the mode to be used by the parser when // loading source packages. ParserMode parser.Mode // TypeChecker contains options relating to the type checker. // // The supplied IgnoreFuncBodies is not used; the effective // value comes from the TypeCheckFuncBodies func below. // The supplied Import function is not used either. TypeChecker types.Config // TypeCheckFuncBodies is a predicate over package paths. // A package for which the predicate is false will // have its package-level declarations type checked, but not // its function bodies; this can be used to quickly load // dependencies from source. If nil, all func bodies are type // checked. TypeCheckFuncBodies func(path string) bool // If Build is non-nil, it is used to locate source packages. // Otherwise &build.Default is used. // // By default, cgo is invoked to preprocess Go files that // import the fake package "C". This behaviour can be // disabled by setting CGO_ENABLED=0 in the environment prior // to startup, or by setting Build.CgoEnabled=false. Build *build.Context // The current directory, used for resolving relative package // references such as "./go/loader". If empty, os.Getwd will be // used instead. Cwd string // If DisplayPath is non-nil, it is used to transform each // file name obtained from Build.Import(). This can be used // to prevent a virtualized build.Config's file names from // leaking into the user interface. DisplayPath func(path string) string // If AllowErrors is true, Load will return a Program even // if some of the its packages contained I/O, parser or type // errors; such errors are accessible via PackageInfo.Errors. If // false, Load will fail if any package had an error. AllowErrors bool // CreatePkgs specifies a list of non-importable initial // packages to create. The resulting packages will appear in // the corresponding elements of the Program.Created slice. CreatePkgs []PkgSpec // ImportPkgs specifies a set of initial packages to load. // The map keys are package paths. // // The map value indicates whether to load tests. If true, Load // will add and type-check two lists of files to the package: // non-test files followed by in-package *_test.go files. In // addition, it will append the external test package (if any) // to Program.Created. ImportPkgs map[string]bool // FindPackage is called during Load to create the build.Package // for a given import path from a given directory. // If FindPackage is nil, (*build.Context).Import is used. // A client may use this hook to adapt to a proprietary build // system that does not follow the "go build" layout // conventions, for example. // // It must be safe to call concurrently from multiple goroutines. FindPackage func(ctxt *build.Context, importPath, fromDir string, mode build.ImportMode) (*build.Package, error) // AfterTypeCheck is called immediately after a list of files // has been type-checked and appended to info.Files. // // This optional hook function is the earliest opportunity for // the client to observe the output of the type checker, // which may be useful to reduce analysis latency when loading // a large program. // // The function is permitted to modify info.Info, for instance // to clear data structures that are no longer needed, which can // dramatically reduce peak memory consumption. // // The function may be called twice for the same PackageInfo: // once for the files of the package and again for the // in-package test files. // // It must be safe to call concurrently from multiple goroutines. AfterTypeCheck func(info *PackageInfo, files []*ast.File) } // A PkgSpec specifies a non-importable package to be created by Load. // Files are processed first, but typically only one of Files and // Filenames is provided. The path needn't be globally unique. // // For vendoring purposes, the package's directory is the one that // contains the first file. type PkgSpec struct { Path string // package path ("" => use package declaration) Files []*ast.File // ASTs of already-parsed files Filenames []string // names of files to be parsed } // A Program is a Go program loaded from source as specified by a Config. type Program struct { Fset *token.FileSet // the file set for this program // Created[i] contains the initial package whose ASTs or // filenames were supplied by Config.CreatePkgs[i], followed by // the external test package, if any, of each package in // Config.ImportPkgs ordered by ImportPath. // // NOTE: these files must not import "C". Cgo preprocessing is // only performed on imported packages, not ad hoc packages. // // TODO(adonovan): we need to copy and adapt the logic of // goFilesPackage (from $GOROOT/src/cmd/go/build.go) and make // Config.Import and Config.Create methods return the same kind // of entity, essentially a build.Package. // Perhaps we can even reuse that type directly. Created []*PackageInfo // Imported contains the initially imported packages, // as specified by Config.ImportPkgs. Imported map[string]*PackageInfo // AllPackages contains the PackageInfo of every package // encountered by Load: all initial packages and all // dependencies, including incomplete ones. AllPackages map[*types.Package]*PackageInfo // importMap is the canonical mapping of package paths to // packages. It contains all Imported initial packages, but not // Created ones, and all imported dependencies. importMap map[string]*types.Package } // PackageInfo holds the ASTs and facts derived by the type-checker // for a single package. // // Not mutated once exposed via the API. // type PackageInfo struct { Pkg *types.Package Importable bool // true if 'import "Pkg.Path()"' would resolve to this TransitivelyErrorFree bool // true if Pkg and all its dependencies are free of errors Files []*ast.File // syntax trees for the package's files Errors []error // non-nil if the package had errors types.Info // type-checker deductions. dir string // package directory checker *types.Checker // transient type-checker state errorFunc func(error) } func (info *PackageInfo) String() string { return info.Pkg.Path() } func (info *PackageInfo) appendError(err error) { if info.errorFunc != nil { info.errorFunc(err) } else { fmt.Fprintln(os.Stderr, err) } info.Errors = append(info.Errors, err) } func (conf *Config) fset() *token.FileSet { if conf.Fset == nil { conf.Fset = token.NewFileSet() } return conf.Fset } // ParseFile is a convenience function (intended for testing) that invokes // the parser using the Config's FileSet, which is initialized if nil. // // src specifies the parser input as a string, []byte, or io.Reader, and // filename is its apparent name. If src is nil, the contents of // filename are read from the file system. // func (conf *Config) ParseFile(filename string, src interface{}) (*ast.File, error) { // TODO(adonovan): use conf.build() etc like parseFiles does. return parser.ParseFile(conf.fset(), filename, src, conf.ParserMode) } // FromArgsUsage is a partial usage message that applications calling // FromArgs may wish to include in their -help output. const FromArgsUsage = ` is a list of arguments denoting a set of initial packages. It may take one of two forms: 1. A list of *.go source files. All of the specified files are loaded, parsed and type-checked as a single package. All the files must belong to the same directory. 2. A list of import paths, each denoting a package. The package's directory is found relative to the $GOROOT and $GOPATH using similar logic to 'go build', and the *.go files in that directory are loaded, parsed and type-checked as a single package. In addition, all *_test.go files in the directory are then loaded and parsed. Those files whose package declaration equals that of the non-*_test.go files are included in the primary package. Test files whose package declaration ends with "_test" are type-checked as another package, the 'external' test package, so that a single import path may denote two packages. (Whether this behaviour is enabled is tool-specific, and may depend on additional flags.) A '--' argument terminates the list of packages. ` // FromArgs interprets args as a set of initial packages to load from // source and updates the configuration. It returns the list of // unconsumed arguments. // // It is intended for use in command-line interfaces that require a // set of initial packages to be specified; see FromArgsUsage message // for details. // // Only superficial errors are reported at this stage; errors dependent // on I/O are detected during Load. // func (conf *Config) FromArgs(args []string, xtest bool) ([]string, error) { var rest []string for i, arg := range args { if arg == "--" { rest = args[i+1:] args = args[:i] break // consume "--" and return the remaining args } } if len(args) > 0 && strings.HasSuffix(args[0], ".go") { // Assume args is a list of a *.go files // denoting a single ad hoc package. for _, arg := range args { if !strings.HasSuffix(arg, ".go") { return nil, fmt.Errorf("named files must be .go files: %s", arg) } } conf.CreateFromFilenames("", args...) } else { // Assume args are directories each denoting a // package and (perhaps) an external test, iff xtest. for _, arg := range args { if xtest { conf.ImportWithTests(arg) } else { conf.Import(arg) } } } return rest, nil } // CreateFromFilenames is a convenience function that adds // a conf.CreatePkgs entry to create a package of the specified *.go // files. // func (conf *Config) CreateFromFilenames(path string, filenames ...string) { conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Filenames: filenames}) } // CreateFromFiles is a convenience function that adds a conf.CreatePkgs // entry to create package of the specified path and parsed files. // func (conf *Config) CreateFromFiles(path string, files ...*ast.File) { conf.CreatePkgs = append(conf.CreatePkgs, PkgSpec{Path: path, Files: files}) } // ImportWithTests is a convenience function that adds path to // ImportPkgs, the set of initial source packages located relative to // $GOPATH. The package will be augmented by any *_test.go files in // its directory that contain a "package x" (not "package x_test") // declaration. // // In addition, if any *_test.go files contain a "package x_test" // declaration, an additional package comprising just those files will // be added to CreatePkgs. // func (conf *Config) ImportWithTests(path string) { conf.addImport(path, true) } // Import is a convenience function that adds path to ImportPkgs, the // set of initial packages that will be imported from source. // func (conf *Config) Import(path string) { conf.addImport(path, false) } func (conf *Config) addImport(path string, tests bool) { if path == "C" { return // ignore; not a real package } if conf.ImportPkgs == nil { conf.ImportPkgs = make(map[string]bool) } conf.ImportPkgs[path] = conf.ImportPkgs[path] || tests } // PathEnclosingInterval returns the PackageInfo and ast.Node that // contain source interval [start, end), and all the node's ancestors // up to the AST root. It searches all ast.Files of all packages in prog. // exact is defined as for astutil.PathEnclosingInterval. // // The zero value is returned if not found. // func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) { for _, info := range prog.AllPackages { for _, f := range info.Files { if f.Pos() == token.NoPos { // This can happen if the parser saw // too many errors and bailed out. // (Use parser.AllErrors to prevent that.) continue } if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) { continue } if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil { return info, path, exact } } } return nil, nil, false } // InitialPackages returns a new slice containing the set of initial // packages (Created + Imported) in unspecified order. // func (prog *Program) InitialPackages() []*PackageInfo { infos := make([]*PackageInfo, 0, len(prog.Created)+len(prog.Imported)) infos = append(infos, prog.Created...) for _, info := range prog.Imported { infos = append(infos, info) } return infos } // Package returns the ASTs and results of type checking for the // specified package. func (prog *Program) Package(path string) *PackageInfo { if info, ok := prog.AllPackages[prog.importMap[path]]; ok { return info } for _, info := range prog.Created { if path == info.Pkg.Path() { return info } } return nil } // ---------- Implementation ---------- // importer holds the working state of the algorithm. type importer struct { conf *Config // the client configuration start time.Time // for logging progMu sync.Mutex // guards prog prog *Program // the resulting program // findpkg is a memoization of FindPackage. findpkgMu sync.Mutex // guards findpkg findpkg map[findpkgKey]*findpkgValue importedMu sync.Mutex // guards imported imported map[string]*importInfo // all imported packages (incl. failures) by import path // import dependency graph: graph[x][y] => x imports y // // Since non-importable packages cannot be cyclic, we ignore // their imports, thus we only need the subgraph over importable // packages. Nodes are identified by their import paths. graphMu sync.Mutex graph map[string]map[string]bool } type findpkgKey struct { importPath string fromDir string mode build.ImportMode } type findpkgValue struct { ready chan struct{} // closed to broadcast readiness bp *build.Package err error } // importInfo tracks the success or failure of a single import. // // Upon completion, exactly one of info and err is non-nil: // info on successful creation of a package, err otherwise. // A successful package may still contain type errors. // type importInfo struct { path string // import path info *PackageInfo // results of typechecking (including errors) complete chan struct{} // closed to broadcast that info is set. } // awaitCompletion blocks until ii is complete, // i.e. the info field is safe to inspect. func (ii *importInfo) awaitCompletion() { <-ii.complete // wait for close } // Complete marks ii as complete. // Its info and err fields will not be subsequently updated. func (ii *importInfo) Complete(info *PackageInfo) { if info == nil { panic("info == nil") } ii.info = info close(ii.complete) } type importError struct { path string // import path err error // reason for failure to create a package } // Load creates the initial packages specified by conf.{Create,Import}Pkgs, // loading their dependencies packages as needed. // // On success, Load returns a Program containing a PackageInfo for // each package. On failure, it returns an error. // // If AllowErrors is true, Load will return a Program even if some // packages contained I/O, parser or type errors, or if dependencies // were missing. (Such errors are accessible via PackageInfo.Errors. If // false, Load will fail if any package had an error. // // It is an error if no packages were loaded. // func (conf *Config) Load() (*Program, error) { // Create a simple default error handler for parse/type errors. if conf.TypeChecker.Error == nil { conf.TypeChecker.Error = func(e error) { fmt.Fprintln(os.Stderr, e) } } // Set default working directory for relative package references. if conf.Cwd == "" { var err error conf.Cwd, err = os.Getwd() if err != nil { return nil, err } } // Install default FindPackage hook using go/build logic. if conf.FindPackage == nil { conf.FindPackage = (*build.Context).Import } prog := &Program{ Fset: conf.fset(), Imported: make(map[string]*PackageInfo), importMap: make(map[string]*types.Package), AllPackages: make(map[*types.Package]*PackageInfo), } imp := importer{ conf: conf, prog: prog, findpkg: make(map[findpkgKey]*findpkgValue), imported: make(map[string]*importInfo), start: time.Now(), graph: make(map[string]map[string]bool), } // -- loading proper (concurrent phase) -------------------------------- var errpkgs []string // packages that contained errors // Load the initially imported packages and their dependencies, // in parallel. // No vendor check on packages imported from the command line. infos, importErrors := imp.importAll("", conf.Cwd, conf.ImportPkgs, ignoreVendor) for _, ie := range importErrors { conf.TypeChecker.Error(ie.err) // failed to create package errpkgs = append(errpkgs, ie.path) } for _, info := range infos { prog.Imported[info.Pkg.Path()] = info } // Augment the designated initial packages by their tests. // Dependencies are loaded in parallel. var xtestPkgs []*build.Package for importPath, augment := range conf.ImportPkgs { if !augment { continue } // No vendor check on packages imported from command line. bp, err := imp.findPackage(importPath, conf.Cwd, ignoreVendor) if err != nil { // Package not found, or can't even parse package declaration. // Already reported by previous loop; ignore it. continue } // Needs external test package? if len(bp.XTestGoFiles) > 0 { xtestPkgs = append(xtestPkgs, bp) } // Consult the cache using the canonical package path. path := bp.ImportPath imp.importedMu.Lock() // (unnecessary, we're sequential here) ii, ok := imp.imported[path] // Paranoid checks added due to issue #11012. if !ok { // Unreachable. // The previous loop called importAll and thus // startLoad for each path in ImportPkgs, which // populates imp.imported[path] with a non-zero value. panic(fmt.Sprintf("imported[%q] not found", path)) } if ii == nil { // Unreachable. // The ii values in this loop are the same as in // the previous loop, which enforced the invariant // that at least one of ii.err and ii.info is non-nil. panic(fmt.Sprintf("imported[%q] == nil", path)) } if ii.info == nil { // Unreachable. // awaitCompletion has the postcondition // ii.info != nil. panic(fmt.Sprintf("imported[%q].info = nil", path)) } info := ii.info imp.importedMu.Unlock() // Parse the in-package test files. files, errs := imp.conf.parsePackageFiles(bp, 't') for _, err := range errs { info.appendError(err) } // The test files augmenting package P cannot be imported, // but may import packages that import P, // so we must disable the cycle check. imp.addFiles(info, files, false) } createPkg := func(path, dir string, files []*ast.File, errs []error) { info := imp.newPackageInfo(path, dir) for _, err := range errs { info.appendError(err) } // Ad hoc packages are non-importable, // so no cycle check is needed. // addFiles loads dependencies in parallel. imp.addFiles(info, files, false) prog.Created = append(prog.Created, info) } // Create packages specified by conf.CreatePkgs. for _, cp := range conf.CreatePkgs { files, errs := parseFiles(conf.fset(), conf.build(), nil, conf.Cwd, cp.Filenames, conf.ParserMode) files = append(files, cp.Files...) path := cp.Path if path == "" { if len(files) > 0 { path = files[0].Name.Name } else { path = "(unnamed)" } } dir := conf.Cwd if len(files) > 0 && files[0].Pos().IsValid() { dir = filepath.Dir(conf.fset().File(files[0].Pos()).Name()) } createPkg(path, dir, files, errs) } // Create external test packages. sort.Sort(byImportPath(xtestPkgs)) for _, bp := range xtestPkgs { files, errs := imp.conf.parsePackageFiles(bp, 'x') createPkg(bp.ImportPath+"_test", bp.Dir, files, errs) } // -- finishing up (sequential) ---------------------------------------- if len(prog.Imported)+len(prog.Created) == 0 { return nil, errors.New("no initial packages were loaded") } // Create infos for indirectly imported packages. // e.g. incomplete packages without syntax, loaded from export data. for _, obj := range prog.importMap { info := prog.AllPackages[obj] if info == nil { prog.AllPackages[obj] = &PackageInfo{Pkg: obj, Importable: true} } else { // finished info.checker = nil info.errorFunc = nil } } if !conf.AllowErrors { // Report errors in indirectly imported packages. for _, info := range prog.AllPackages { if len(info.Errors) > 0 { errpkgs = append(errpkgs, info.Pkg.Path()) } } if errpkgs != nil { var more string if len(errpkgs) > 3 { more = fmt.Sprintf(" and %d more", len(errpkgs)-3) errpkgs = errpkgs[:3] } return nil, fmt.Errorf("couldn't load packages due to errors: %s%s", strings.Join(errpkgs, ", "), more) } } markErrorFreePackages(prog.AllPackages) return prog, nil } type byImportPath []*build.Package func (b byImportPath) Len() int { return len(b) } func (b byImportPath) Less(i, j int) bool { return b[i].ImportPath < b[j].ImportPath } func (b byImportPath) Swap(i, j int) { b[i], b[j] = b[j], b[i] } // markErrorFreePackages sets the TransitivelyErrorFree flag on all // applicable packages. func markErrorFreePackages(allPackages map[*types.Package]*PackageInfo) { // Build the transpose of the import graph. importedBy := make(map[*types.Package]map[*types.Package]bool) for P := range allPackages { for _, Q := range P.Imports() { clients, ok := importedBy[Q] if !ok { clients = make(map[*types.Package]bool) importedBy[Q] = clients } clients[P] = true } } // Find all packages reachable from some error package. reachable := make(map[*types.Package]bool) var visit func(*types.Package) visit = func(p *types.Package) { if !reachable[p] { reachable[p] = true for q := range importedBy[p] { visit(q) } } } for _, info := range allPackages { if len(info.Errors) > 0 { visit(info.Pkg) } } // Mark the others as "transitively error-free". for _, info := range allPackages { if !reachable[info.Pkg] { info.TransitivelyErrorFree = true } } } // build returns the effective build context. func (conf *Config) build() *build.Context { if conf.Build != nil { return conf.Build } return &build.Default } // parsePackageFiles enumerates the files belonging to package path, // then loads, parses and returns them, plus a list of I/O or parse // errors that were encountered. // // 'which' indicates which files to include: // 'g': include non-test *.go source files (GoFiles + processed CgoFiles) // 't': include in-package *_test.go source files (TestGoFiles) // 'x': include external *_test.go source files. (XTestGoFiles) // func (conf *Config) parsePackageFiles(bp *build.Package, which rune) ([]*ast.File, []error) { if bp.ImportPath == "unsafe" { return nil, nil } var filenames []string switch which { case 'g': filenames = bp.GoFiles case 't': filenames = bp.TestGoFiles case 'x': filenames = bp.XTestGoFiles default: panic(which) } files, errs := parseFiles(conf.fset(), conf.build(), conf.DisplayPath, bp.Dir, filenames, conf.ParserMode) // Preprocess CgoFiles and parse the outputs (sequentially). if which == 'g' && bp.CgoFiles != nil { cgofiles, err := cgo.ProcessFiles(bp, conf.fset(), conf.DisplayPath, conf.ParserMode) if err != nil { errs = append(errs, err) } else { files = append(files, cgofiles...) } } return files, errs } // doImport imports the package denoted by path. // It implements the types.Importer signature. // // It returns an error if a package could not be created // (e.g. go/build or parse error), but type errors are reported via // the types.Config.Error callback (the first of which is also saved // in the package's PackageInfo). // // Idempotent. // func (imp *importer) doImport(from *PackageInfo, to string) (*types.Package, error) { if to == "C" { // This should be unreachable, but ad hoc packages are // not currently subject to cgo preprocessing. // See https://golang.org/issue/11627. return nil, fmt.Errorf(`the loader doesn't cgo-process ad hoc packages like %q; see Go issue 11627`, from.Pkg.Path()) } bp, err := imp.findPackage(to, from.dir, 0) if err != nil { return nil, err } // The standard unsafe package is handled specially, // and has no PackageInfo. if bp.ImportPath == "unsafe" { return types.Unsafe, nil } // Look for the package in the cache using its canonical path. path := bp.ImportPath imp.importedMu.Lock() ii := imp.imported[path] imp.importedMu.Unlock() if ii == nil { panic("internal error: unexpected import: " + path) } if ii.info != nil { return ii.info.Pkg, nil } // Import of incomplete package: this indicates a cycle. fromPath := from.Pkg.Path() if cycle := imp.findPath(path, fromPath); cycle != nil { // Normalize cycle: start from alphabetically largest node. pos, start := -1, "" for i, s := range cycle { if pos < 0 || s > start { pos, start = i, s } } cycle = append(cycle, cycle[:pos]...)[pos:] // rotate cycle to start from largest cycle = append(cycle, cycle[0]) // add start node to end to show cycliness return nil, fmt.Errorf("import cycle: %s", strings.Join(cycle, " -> ")) } panic("internal error: import of incomplete (yet acyclic) package: " + fromPath) } // findPackage locates the package denoted by the importPath in the // specified directory. func (imp *importer) findPackage(importPath, fromDir string, mode build.ImportMode) (*build.Package, error) { // We use a non-blocking duplicate-suppressing cache (gopl.io §9.7) // to avoid holding the lock around FindPackage. key := findpkgKey{importPath, fromDir, mode} imp.findpkgMu.Lock() v, ok := imp.findpkg[key] if ok { // cache hit imp.findpkgMu.Unlock() <-v.ready // wait for entry to become ready } else { // Cache miss: this goroutine becomes responsible for // populating the map entry and broadcasting its readiness. v = &findpkgValue{ready: make(chan struct{})} imp.findpkg[key] = v imp.findpkgMu.Unlock() ioLimit <- true v.bp, v.err = imp.conf.FindPackage(imp.conf.build(), importPath, fromDir, mode) <-ioLimit if _, ok := v.err.(*build.NoGoError); ok { v.err = nil // empty directory is not an error } close(v.ready) // broadcast ready condition } return v.bp, v.err } // importAll loads, parses, and type-checks the specified packages in // parallel and returns their completed importInfos in unspecified order. // // fromPath is the package path of the importing package, if it is // importable, "" otherwise. It is used for cycle detection. // // fromDir is the directory containing the import declaration that // caused these imports. // func (imp *importer) importAll(fromPath, fromDir string, imports map[string]bool, mode build.ImportMode) (infos []*PackageInfo, errors []importError) { if fromPath != "" { // We're loading a set of imports. // // We must record graph edges from the importing package // to its dependencies, and check for cycles. imp.graphMu.Lock() deps, ok := imp.graph[fromPath] if !ok { deps = make(map[string]bool) imp.graph[fromPath] = deps } for importPath := range imports { deps[importPath] = true } imp.graphMu.Unlock() } var pending []*importInfo for importPath := range imports { if fromPath != "" { if cycle := imp.findPath(importPath, fromPath); cycle != nil { // Cycle-forming import: we must not check it // since it would deadlock. if trace { fmt.Fprintf(os.Stderr, "import cycle: %q\n", cycle) } continue } } bp, err := imp.findPackage(importPath, fromDir, mode) if err != nil { errors = append(errors, importError{ path: importPath, err: err, }) continue } pending = append(pending, imp.startLoad(bp)) } for _, ii := range pending { ii.awaitCompletion() infos = append(infos, ii.info) } return infos, errors } // findPath returns an arbitrary path from 'from' to 'to' in the import // graph, or nil if there was none. func (imp *importer) findPath(from, to string) []string { imp.graphMu.Lock() defer imp.graphMu.Unlock() seen := make(map[string]bool) var search func(stack []string, importPath string) []string search = func(stack []string, importPath string) []string { if !seen[importPath] { seen[importPath] = true stack = append(stack, importPath) if importPath == to { return stack } for x := range imp.graph[importPath] { if p := search(stack, x); p != nil { return p } } } return nil } return search(make([]string, 0, 20), from) } // startLoad initiates the loading, parsing and type-checking of the // specified package and its dependencies, if it has not already begun. // // It returns an importInfo, not necessarily in a completed state. The // caller must call awaitCompletion() before accessing its info field. // // startLoad is concurrency-safe and idempotent. // func (imp *importer) startLoad(bp *build.Package) *importInfo { path := bp.ImportPath imp.importedMu.Lock() ii, ok := imp.imported[path] if !ok { ii = &importInfo{path: path, complete: make(chan struct{})} imp.imported[path] = ii go func() { info := imp.load(bp) ii.Complete(info) }() } imp.importedMu.Unlock() return ii } // load implements package loading by parsing Go source files // located by go/build. func (imp *importer) load(bp *build.Package) *PackageInfo { info := imp.newPackageInfo(bp.ImportPath, bp.Dir) info.Importable = true files, errs := imp.conf.parsePackageFiles(bp, 'g') for _, err := range errs { info.appendError(err) } imp.addFiles(info, files, true) imp.progMu.Lock() imp.prog.importMap[bp.ImportPath] = info.Pkg imp.progMu.Unlock() return info } // addFiles adds and type-checks the specified files to info, loading // their dependencies if needed. The order of files determines the // package initialization order. It may be called multiple times on the // same package. Errors are appended to the info.Errors field. // // cycleCheck determines whether the imports within files create // dependency edges that should be checked for potential cycles. // func (imp *importer) addFiles(info *PackageInfo, files []*ast.File, cycleCheck bool) { // Ensure the dependencies are loaded, in parallel. var fromPath string if cycleCheck { fromPath = info.Pkg.Path() } // TODO(adonovan): opt: make the caller do scanImports. // Callers with a build.Package can skip it. imp.importAll(fromPath, info.dir, scanImports(files), 0) if trace { fmt.Fprintf(os.Stderr, "%s: start %q (%d)\n", time.Since(imp.start), info.Pkg.Path(), len(files)) } // Don't call checker.Files on Unsafe, even with zero files, // because it would mutate the package, which is a global. if info.Pkg == types.Unsafe { if len(files) > 0 { panic(`"unsafe" package contains unexpected files`) } } else { // Ignore the returned (first) error since we // already collect them all in the PackageInfo. info.checker.Files(files) info.Files = append(info.Files, files...) } if imp.conf.AfterTypeCheck != nil { imp.conf.AfterTypeCheck(info, files) } if trace { fmt.Fprintf(os.Stderr, "%s: stop %q\n", time.Since(imp.start), info.Pkg.Path()) } } func (imp *importer) newPackageInfo(path, dir string) *PackageInfo { var pkg *types.Package if path == "unsafe" { pkg = types.Unsafe } else { pkg = types.NewPackage(path, "") } info := &PackageInfo{ Pkg: pkg, Info: types.Info{ Types: make(map[ast.Expr]types.TypeAndValue), Defs: make(map[*ast.Ident]types.Object), Uses: make(map[*ast.Ident]types.Object), Implicits: make(map[ast.Node]types.Object), Scopes: make(map[ast.Node]*types.Scope), Selections: make(map[*ast.SelectorExpr]*types.Selection), }, errorFunc: imp.conf.TypeChecker.Error, dir: dir, } // Copy the types.Config so we can vary it across PackageInfos. tc := imp.conf.TypeChecker tc.IgnoreFuncBodies = false if f := imp.conf.TypeCheckFuncBodies; f != nil { tc.IgnoreFuncBodies = !f(path) } tc.Importer = closure{imp, info} tc.Error = info.appendError // appendError wraps the user's Error function info.checker = types.NewChecker(&tc, imp.conf.fset(), pkg, &info.Info) imp.progMu.Lock() imp.prog.AllPackages[pkg] = info imp.progMu.Unlock() return info } type closure struct { imp *importer info *PackageInfo } func (c closure) Import(to string) (*types.Package, error) { return c.imp.doImport(c.info, to) } ================================================ FILE: _tools/src/golang.org/x/tools/go/loader/util.go ================================================ // Copyright 2013 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package loader import ( "go/ast" "go/build" "go/parser" "go/token" "io" "os" "strconv" "sync" "golang.org/x/tools/go/buildutil" ) // We use a counting semaphore to limit // the number of parallel I/O calls per process. var ioLimit = make(chan bool, 10) // parseFiles parses the Go source files within directory dir and // returns the ASTs of the ones that could be at least partially parsed, // along with a list of I/O and parse errors encountered. // // I/O is done via ctxt, which may specify a virtual file system. // displayPath is used to transform the filenames attached to the ASTs. // func parseFiles(fset *token.FileSet, ctxt *build.Context, displayPath func(string) string, dir string, files []string, mode parser.Mode) ([]*ast.File, []error) { if displayPath == nil { displayPath = func(path string) string { return path } } var wg sync.WaitGroup n := len(files) parsed := make([]*ast.File, n) errors := make([]error, n) for i, file := range files { if !buildutil.IsAbsPath(ctxt, file) { file = buildutil.JoinPath(ctxt, dir, file) } wg.Add(1) go func(i int, file string) { ioLimit <- true // wait defer func() { wg.Done() <-ioLimit // signal }() var rd io.ReadCloser var err error if ctxt.OpenFile != nil { rd, err = ctxt.OpenFile(file) } else { rd, err = os.Open(file) } if err != nil { errors[i] = err // open failed return } // ParseFile may return both an AST and an error. parsed[i], errors[i] = parser.ParseFile(fset, displayPath(file), rd, mode) rd.Close() }(i, file) } wg.Wait() // Eliminate nils, preserving order. var o int for _, f := range parsed { if f != nil { parsed[o] = f o++ } } parsed = parsed[:o] o = 0 for _, err := range errors { if err != nil { errors[o] = err o++ } } errors = errors[:o] return parsed, errors } // scanImports returns the set of all import paths from all // import specs in the specified files. func scanImports(files []*ast.File) map[string]bool { imports := make(map[string]bool) for _, f := range files { for _, decl := range f.Decls { if decl, ok := decl.(*ast.GenDecl); ok && decl.Tok == token.IMPORT { for _, spec := range decl.Specs { spec := spec.(*ast.ImportSpec) // NB: do not assume the program is well-formed! path, err := strconv.Unquote(spec.Path.Value) if err != nil { continue // quietly ignore the error } if path == "C" { continue // skip pseudopackage } imports[path] = true } } } } return imports } // ---------- Internal helpers ---------- // TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos) func tokenFileContainsPos(f *token.File, pos token.Pos) bool { p := int(pos) base := f.Base() return base <= p && p < base+f.Size() } ================================================ FILE: _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/init.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package internal_gengo import ( "unicode" "unicode/utf8" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/types/descriptorpb" ) type fileInfo struct { *protogen.File allEnums []*enumInfo allMessages []*messageInfo allExtensions []*extensionInfo allEnumsByPtr map[*enumInfo]int // value is index into allEnums allMessagesByPtr map[*messageInfo]int // value is index into allMessages allMessageFieldsByPtr map[*messageInfo]*structFields // needRawDesc specifies whether the generator should emit logic to provide // the legacy raw descriptor in GZIP'd form. // This is updated by enum and message generation logic as necessary, // and checked at the end of file generation. needRawDesc bool } type structFields struct { count int unexported map[int]string } func (sf *structFields) append(name string) { if r, _ := utf8.DecodeRuneInString(name); !unicode.IsUpper(r) { if sf.unexported == nil { sf.unexported = make(map[int]string) } sf.unexported[sf.count] = name } sf.count++ } func newFileInfo(file *protogen.File) *fileInfo { f := &fileInfo{File: file} // Collect all enums, messages, and extensions in "flattened ordering". // See filetype.TypeBuilder. var walkMessages func([]*protogen.Message, func(*protogen.Message)) walkMessages = func(messages []*protogen.Message, f func(*protogen.Message)) { for _, m := range messages { f(m) walkMessages(m.Messages, f) } } initEnumInfos := func(enums []*protogen.Enum) { for _, enum := range enums { f.allEnums = append(f.allEnums, newEnumInfo(f, enum)) } } initMessageInfos := func(messages []*protogen.Message) { for _, message := range messages { f.allMessages = append(f.allMessages, newMessageInfo(f, message)) } } initExtensionInfos := func(extensions []*protogen.Extension) { for _, extension := range extensions { f.allExtensions = append(f.allExtensions, newExtensionInfo(f, extension)) } } initEnumInfos(f.Enums) initMessageInfos(f.Messages) initExtensionInfos(f.Extensions) walkMessages(f.Messages, func(m *protogen.Message) { initEnumInfos(m.Enums) initMessageInfos(m.Messages) initExtensionInfos(m.Extensions) }) // Derive a reverse mapping of enum and message pointers to their index // in allEnums and allMessages. if len(f.allEnums) > 0 { f.allEnumsByPtr = make(map[*enumInfo]int) for i, e := range f.allEnums { f.allEnumsByPtr[e] = i } } if len(f.allMessages) > 0 { f.allMessagesByPtr = make(map[*messageInfo]int) f.allMessageFieldsByPtr = make(map[*messageInfo]*structFields) for i, m := range f.allMessages { f.allMessagesByPtr[m] = i f.allMessageFieldsByPtr[m] = new(structFields) } } return f } type enumInfo struct { *protogen.Enum genJSONMethod bool genRawDescMethod bool } func newEnumInfo(f *fileInfo, enum *protogen.Enum) *enumInfo { e := &enumInfo{Enum: enum} e.genJSONMethod = true e.genRawDescMethod = true return e } type messageInfo struct { *protogen.Message genRawDescMethod bool genExtRangeMethod bool isTracked bool hasWeak bool } func newMessageInfo(f *fileInfo, message *protogen.Message) *messageInfo { m := &messageInfo{Message: message} m.genRawDescMethod = true m.genExtRangeMethod = true m.isTracked = isTrackedMessage(m) for _, field := range m.Fields { m.hasWeak = m.hasWeak || field.Desc.IsWeak() } return m } // isTrackedMessage reports whether field tracking is enabled on the message. func isTrackedMessage(m *messageInfo) (tracked bool) { const trackFieldUse_fieldNumber = 37383685 // Decode the option from unknown fields to avoid a dependency on the // annotation proto from protoc-gen-go. b := m.Desc.Options().(*descriptorpb.MessageOptions).ProtoReflect().GetUnknown() for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] if num == trackFieldUse_fieldNumber && typ == protowire.VarintType { v, _ := protowire.ConsumeVarint(b) tracked = protowire.DecodeBool(v) } m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } return tracked } type extensionInfo struct { *protogen.Extension } func newExtensionInfo(f *fileInfo, extension *protogen.Extension) *extensionInfo { x := &extensionInfo{Extension: extension} return x } ================================================ FILE: _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/main.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package internal_gengo is internal to the protobuf module. package internal_gengo import ( "fmt" "go/ast" "go/parser" "go/token" "math" "strconv" "strings" "unicode" "unicode/utf8" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/version" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoimpl" "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/pluginpb" ) // SupportedFeatures reports the set of supported protobuf language features. var SupportedFeatures = uint64(pluginpb.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL) // GenerateVersionMarkers specifies whether to generate version markers. var GenerateVersionMarkers = true // Standard library dependencies. const ( base64Package = protogen.GoImportPath("encoding/base64") mathPackage = protogen.GoImportPath("math") reflectPackage = protogen.GoImportPath("reflect") sortPackage = protogen.GoImportPath("sort") stringsPackage = protogen.GoImportPath("strings") syncPackage = protogen.GoImportPath("sync") timePackage = protogen.GoImportPath("time") utf8Package = protogen.GoImportPath("unicode/utf8") ) // Protobuf library dependencies. // // These are declared as an interface type so that they can be more easily // patched to support unique build environments that impose restrictions // on the dependencies of generated source code. var ( protoPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/proto") protoifacePackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoiface") protoimplPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/runtime/protoimpl") protojsonPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/encoding/protojson") protoreflectPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoreflect") protoregistryPackage goImportPath = protogen.GoImportPath("google.golang.org/protobuf/reflect/protoregistry") ) type goImportPath interface { String() string Ident(string) protogen.GoIdent } // GenerateFile generates the contents of a .pb.go file. func GenerateFile(gen *protogen.Plugin, file *protogen.File) *protogen.GeneratedFile { filename := file.GeneratedFilenamePrefix + ".pb.go" g := gen.NewGeneratedFile(filename, file.GoImportPath) f := newFileInfo(file) genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Syntax_field_number)) genGeneratedHeader(gen, g, f) genStandaloneComments(g, f, int32(genid.FileDescriptorProto_Package_field_number)) packageDoc := genPackageKnownComment(f) g.P(packageDoc, "package ", f.GoPackageName) g.P() // Emit a static check that enforces a minimum version of the proto package. if GenerateVersionMarkers { g.P("const (") g.P("// Verify that this generated code is sufficiently up-to-date.") g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimpl.GenVersion, " - ", protoimplPackage.Ident("MinVersion"), ")") g.P("// Verify that runtime/protoimpl is sufficiently up-to-date.") g.P("_ = ", protoimplPackage.Ident("EnforceVersion"), "(", protoimplPackage.Ident("MaxVersion"), " - ", protoimpl.GenVersion, ")") g.P(")") g.P() } for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ { genImport(gen, g, f, imps.Get(i)) } for _, enum := range f.allEnums { genEnum(g, f, enum) } for _, message := range f.allMessages { genMessage(g, f, message) } genExtensions(g, f) genReflectFileDescriptor(gen, g, f) return g } // genStandaloneComments prints all leading comments for a FileDescriptorProto // location identified by the field number n. func genStandaloneComments(g *protogen.GeneratedFile, f *fileInfo, n int32) { loc := f.Desc.SourceLocations().ByPath(protoreflect.SourcePath{n}) for _, s := range loc.LeadingDetachedComments { g.P(protogen.Comments(s)) g.P() } if s := loc.LeadingComments; s != "" { g.P(protogen.Comments(s)) g.P() } } func genGeneratedHeader(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { g.P("// Code generated by protoc-gen-go. DO NOT EDIT.") if GenerateVersionMarkers { g.P("// versions:") protocGenGoVersion := version.String() protocVersion := "(unknown)" if v := gen.Request.GetCompilerVersion(); v != nil { protocVersion = fmt.Sprintf("v%v.%v.%v", v.GetMajor(), v.GetMinor(), v.GetPatch()) if s := v.GetSuffix(); s != "" { protocVersion += "-" + s } } g.P("// \tprotoc-gen-go ", protocGenGoVersion) g.P("// \tprotoc ", protocVersion) } if f.Proto.GetOptions().GetDeprecated() { g.P("// ", f.Desc.Path(), " is a deprecated file.") } else { g.P("// source: ", f.Desc.Path()) } g.P() } func genImport(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo, imp protoreflect.FileImport) { impFile, ok := gen.FilesByPath[imp.Path()] if !ok { return } if impFile.GoImportPath == f.GoImportPath { // Don't generate imports or aliases for types in the same Go package. return } // Generate imports for all non-weak dependencies, even if they are not // referenced, because other code and tools depend on having the // full transitive closure of protocol buffer types in the binary. if !imp.IsWeak { g.Import(impFile.GoImportPath) } if !imp.IsPublic { return } // Generate public imports by generating the imported file, parsing it, // and extracting every symbol that should receive a forwarding declaration. impGen := GenerateFile(gen, impFile) impGen.Skip() b, err := impGen.Content() if err != nil { gen.Error(err) return } fset := token.NewFileSet() astFile, err := parser.ParseFile(fset, "", b, parser.ParseComments) if err != nil { gen.Error(err) return } genForward := func(tok token.Token, name string, expr ast.Expr) { // Don't import unexported symbols. r, _ := utf8.DecodeRuneInString(name) if !unicode.IsUpper(r) { return } // Don't import the FileDescriptor. if name == impFile.GoDescriptorIdent.GoName { return } // Don't import decls referencing a symbol defined in another package. // i.e., don't import decls which are themselves public imports: // // type T = somepackage.T if _, ok := expr.(*ast.SelectorExpr); ok { return } g.P(tok, " ", name, " = ", impFile.GoImportPath.Ident(name)) } g.P("// Symbols defined in public import of ", imp.Path(), ".") g.P() for _, decl := range astFile.Decls { switch decl := decl.(type) { case *ast.GenDecl: for _, spec := range decl.Specs { switch spec := spec.(type) { case *ast.TypeSpec: genForward(decl.Tok, spec.Name.Name, spec.Type) case *ast.ValueSpec: for i, name := range spec.Names { var expr ast.Expr if i < len(spec.Values) { expr = spec.Values[i] } genForward(decl.Tok, name.Name, expr) } case *ast.ImportSpec: default: panic(fmt.Sprintf("can't generate forward for spec type %T", spec)) } } } } g.P() } func genEnum(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) { // Enum type declaration. g.Annotate(e.GoIdent.GoName, e.Location) leadingComments := appendDeprecationSuffix(e.Comments.Leading, e.Desc.Options().(*descriptorpb.EnumOptions).GetDeprecated()) g.P(leadingComments, "type ", e.GoIdent, " int32") // Enum value constants. g.P("const (") for _, value := range e.Values { g.Annotate(value.GoIdent.GoName, value.Location) leadingComments := appendDeprecationSuffix(value.Comments.Leading, value.Desc.Options().(*descriptorpb.EnumValueOptions).GetDeprecated()) g.P(leadingComments, value.GoIdent, " ", e.GoIdent, " = ", value.Desc.Number(), trailingComment(value.Comments.Trailing)) } g.P(")") g.P() // Enum value maps. g.P("// Enum value maps for ", e.GoIdent, ".") g.P("var (") g.P(e.GoIdent.GoName+"_name", " = map[int32]string{") for _, value := range e.Values { duplicate := "" if value.Desc != e.Desc.Values().ByNumber(value.Desc.Number()) { duplicate = "// Duplicate value: " } g.P(duplicate, value.Desc.Number(), ": ", strconv.Quote(string(value.Desc.Name())), ",") } g.P("}") g.P(e.GoIdent.GoName+"_value", " = map[string]int32{") for _, value := range e.Values { g.P(strconv.Quote(string(value.Desc.Name())), ": ", value.Desc.Number(), ",") } g.P("}") g.P(")") g.P() // Enum method. // // NOTE: A pointer value is needed to represent presence in proto2. // Since a proto2 message can reference a proto3 enum, it is useful to // always generate this method (even on proto3 enums) to support that case. g.P("func (x ", e.GoIdent, ") Enum() *", e.GoIdent, " {") g.P("p := new(", e.GoIdent, ")") g.P("*p = x") g.P("return p") g.P("}") g.P() // String method. g.P("func (x ", e.GoIdent, ") String() string {") g.P("return ", protoimplPackage.Ident("X"), ".EnumStringOf(x.Descriptor(), ", protoreflectPackage.Ident("EnumNumber"), "(x))") g.P("}") g.P() genEnumReflectMethods(g, f, e) // UnmarshalJSON method. if e.genJSONMethod && e.Desc.Syntax() == protoreflect.Proto2 { g.P("// Deprecated: Do not use.") g.P("func (x *", e.GoIdent, ") UnmarshalJSON(b []byte) error {") g.P("num, err := ", protoimplPackage.Ident("X"), ".UnmarshalJSONEnum(x.Descriptor(), b)") g.P("if err != nil {") g.P("return err") g.P("}") g.P("*x = ", e.GoIdent, "(num)") g.P("return nil") g.P("}") g.P() } // EnumDescriptor method. if e.genRawDescMethod { var indexes []string for i := 1; i < len(e.Location.Path); i += 2 { indexes = append(indexes, strconv.Itoa(int(e.Location.Path[i]))) } g.P("// Deprecated: Use ", e.GoIdent, ".Descriptor instead.") g.P("func (", e.GoIdent, ") EnumDescriptor() ([]byte, []int) {") g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}") g.P("}") g.P() f.needRawDesc = true } } func genMessage(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { if m.Desc.IsMapEntry() { return } // Message type declaration. g.Annotate(m.GoIdent.GoName, m.Location) leadingComments := appendDeprecationSuffix(m.Comments.Leading, m.Desc.Options().(*descriptorpb.MessageOptions).GetDeprecated()) g.P(leadingComments, "type ", m.GoIdent, " struct {") genMessageFields(g, f, m) g.P("}") g.P() genMessageKnownFunctions(g, f, m) genMessageDefaultDecls(g, f, m) genMessageMethods(g, f, m) genMessageOneofWrapperTypes(g, f, m) } func genMessageFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { sf := f.allMessageFieldsByPtr[m] genMessageInternalFields(g, f, m, sf) for _, field := range m.Fields { genMessageField(g, f, m, field, sf) } } func genMessageInternalFields(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, sf *structFields) { g.P(genid.State_goname, " ", protoimplPackage.Ident("MessageState")) sf.append(genid.State_goname) g.P(genid.SizeCache_goname, " ", protoimplPackage.Ident("SizeCache")) sf.append(genid.SizeCache_goname) if m.hasWeak { g.P(genid.WeakFields_goname, " ", protoimplPackage.Ident("WeakFields")) sf.append(genid.WeakFields_goname) } g.P(genid.UnknownFields_goname, " ", protoimplPackage.Ident("UnknownFields")) sf.append(genid.UnknownFields_goname) if m.Desc.ExtensionRanges().Len() > 0 { g.P(genid.ExtensionFields_goname, " ", protoimplPackage.Ident("ExtensionFields")) sf.append(genid.ExtensionFields_goname) } if sf.count > 0 { g.P() } } func genMessageField(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo, field *protogen.Field, sf *structFields) { if oneof := field.Oneof; oneof != nil && !oneof.Desc.IsSynthetic() { // It would be a bit simpler to iterate over the oneofs below, // but generating the field here keeps the contents of the Go // struct in the same order as the contents of the source // .proto file. if oneof.Fields[0] != field { return // only generate for first appearance } tags := structTags{ {"protobuf_oneof", string(oneof.Desc.Name())}, } if m.isTracked { tags = append(tags, gotrackTags...) } g.Annotate(m.GoIdent.GoName+"."+oneof.GoName, oneof.Location) leadingComments := oneof.Comments.Leading if leadingComments != "" { leadingComments += "\n" } ss := []string{fmt.Sprintf(" Types that are assignable to %s:\n", oneof.GoName)} for _, field := range oneof.Fields { ss = append(ss, "\t*"+field.GoIdent.GoName+"\n") } leadingComments += protogen.Comments(strings.Join(ss, "")) g.P(leadingComments, oneof.GoName, " ", oneofInterfaceName(oneof), tags) sf.append(oneof.GoName) return } goType, pointer := fieldGoType(g, f, field) if pointer { goType = "*" + goType } tags := structTags{ {"protobuf", fieldProtobufTagValue(field)}, {"json", fieldJSONTagValue(field)}, } if field.Desc.IsMap() { key := field.Message.Fields[0] val := field.Message.Fields[1] tags = append(tags, structTags{ {"protobuf_key", fieldProtobufTagValue(key)}, {"protobuf_val", fieldProtobufTagValue(val)}, }...) } if m.isTracked { tags = append(tags, gotrackTags...) } name := field.GoName if field.Desc.IsWeak() { name = genid.WeakFieldPrefix_goname + name } g.Annotate(m.GoIdent.GoName+"."+name, field.Location) leadingComments := appendDeprecationSuffix(field.Comments.Leading, field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()) g.P(leadingComments, name, " ", goType, tags, trailingComment(field.Comments.Trailing)) sf.append(field.GoName) } // genMessageDefaultDecls generates consts and vars holding the default // values of fields. func genMessageDefaultDecls(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { var consts, vars []string for _, field := range m.Fields { if !field.Desc.HasDefault() { continue } name := "Default_" + m.GoIdent.GoName + "_" + field.GoName goType, _ := fieldGoType(g, f, field) defVal := field.Desc.Default() switch field.Desc.Kind() { case protoreflect.StringKind: consts = append(consts, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.String())) case protoreflect.BytesKind: vars = append(vars, fmt.Sprintf("%s = %s(%q)", name, goType, defVal.Bytes())) case protoreflect.EnumKind: idx := field.Desc.DefaultEnumValue().Index() val := field.Enum.Values[idx] consts = append(consts, fmt.Sprintf("%s = %s", name, g.QualifiedGoIdent(val.GoIdent))) case protoreflect.FloatKind, protoreflect.DoubleKind: if f := defVal.Float(); math.IsNaN(f) || math.IsInf(f, 0) { var fn, arg string switch f := defVal.Float(); { case math.IsInf(f, -1): fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "-1" case math.IsInf(f, +1): fn, arg = g.QualifiedGoIdent(mathPackage.Ident("Inf")), "+1" case math.IsNaN(f): fn, arg = g.QualifiedGoIdent(mathPackage.Ident("NaN")), "" } vars = append(vars, fmt.Sprintf("%s = %s(%s(%s))", name, goType, fn, arg)) } else { consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, f)) } default: consts = append(consts, fmt.Sprintf("%s = %s(%v)", name, goType, defVal.Interface())) } } if len(consts) > 0 { g.P("// Default values for ", m.GoIdent, " fields.") g.P("const (") for _, s := range consts { g.P(s) } g.P(")") } if len(vars) > 0 { g.P("// Default values for ", m.GoIdent, " fields.") g.P("var (") for _, s := range vars { g.P(s) } g.P(")") } g.P() } func genMessageMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { genMessageBaseMethods(g, f, m) genMessageGetterMethods(g, f, m) genMessageSetterMethods(g, f, m) } func genMessageBaseMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { // Reset method. g.P("func (x *", m.GoIdent, ") Reset() {") g.P("*x = ", m.GoIdent, "{}") g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " {") g.P("mi := &", messageTypesVarName(f), "[", f.allMessagesByPtr[m], "]") g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))") g.P("ms.StoreMessageInfo(mi)") g.P("}") g.P("}") g.P() // String method. g.P("func (x *", m.GoIdent, ") String() string {") g.P("return ", protoimplPackage.Ident("X"), ".MessageStringOf(x)") g.P("}") g.P() // ProtoMessage method. g.P("func (*", m.GoIdent, ") ProtoMessage() {}") g.P() // ProtoReflect method. genMessageReflectMethods(g, f, m) // Descriptor method. if m.genRawDescMethod { var indexes []string for i := 1; i < len(m.Location.Path); i += 2 { indexes = append(indexes, strconv.Itoa(int(m.Location.Path[i]))) } g.P("// Deprecated: Use ", m.GoIdent, ".ProtoReflect.Descriptor instead.") g.P("func (*", m.GoIdent, ") Descriptor() ([]byte, []int) {") g.P("return ", rawDescVarName(f), "GZIP(), []int{", strings.Join(indexes, ","), "}") g.P("}") g.P() f.needRawDesc = true } } func genMessageGetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { for _, field := range m.Fields { genNoInterfacePragma(g, m.isTracked) // Getter for parent oneof. if oneof := field.Oneof; oneof != nil && oneof.Fields[0] == field && !oneof.Desc.IsSynthetic() { g.Annotate(m.GoIdent.GoName+".Get"+oneof.GoName, oneof.Location) g.P("func (m *", m.GoIdent.GoName, ") Get", oneof.GoName, "() ", oneofInterfaceName(oneof), " {") g.P("if m != nil {") g.P("return m.", oneof.GoName) g.P("}") g.P("return nil") g.P("}") g.P() } // Getter for message field. goType, pointer := fieldGoType(g, f, field) defaultValue := fieldDefaultValue(g, m, field) g.Annotate(m.GoIdent.GoName+".Get"+field.GoName, field.Location) leadingComments := appendDeprecationSuffix("", field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()) switch { case field.Desc.IsWeak(): g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", protoPackage.Ident("Message"), "{") g.P("var w ", protoimplPackage.Ident("WeakFields")) g.P("if x != nil {") g.P("w = x.", genid.WeakFields_goname) if m.isTracked { g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName) } g.P("}") g.P("return ", protoimplPackage.Ident("X"), ".GetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ")") g.P("}") case field.Oneof != nil && !field.Oneof.Desc.IsSynthetic(): g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {") g.P("if x, ok := x.Get", field.Oneof.GoName, "().(*", field.GoIdent, "); ok {") g.P("return x.", field.GoName) g.P("}") g.P("return ", defaultValue) g.P("}") default: g.P(leadingComments, "func (x *", m.GoIdent, ") Get", field.GoName, "() ", goType, " {") if !field.Desc.HasPresence() || defaultValue == "nil" { g.P("if x != nil {") } else { g.P("if x != nil && x.", field.GoName, " != nil {") } star := "" if pointer { star = "*" } g.P("return ", star, " x.", field.GoName) g.P("}") g.P("return ", defaultValue) g.P("}") } g.P() } } func genMessageSetterMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { for _, field := range m.Fields { if !field.Desc.IsWeak() { continue } genNoInterfacePragma(g, m.isTracked) g.Annotate(m.GoIdent.GoName+".Set"+field.GoName, field.Location) leadingComments := appendDeprecationSuffix("", field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()) g.P(leadingComments, "func (x *", m.GoIdent, ") Set", field.GoName, "(v ", protoPackage.Ident("Message"), ") {") g.P("var w *", protoimplPackage.Ident("WeakFields")) g.P("if x != nil {") g.P("w = &x.", genid.WeakFields_goname) if m.isTracked { g.P("_ = x.", genid.WeakFieldPrefix_goname+field.GoName) } g.P("}") g.P(protoimplPackage.Ident("X"), ".SetWeak(w, ", field.Desc.Number(), ", ", strconv.Quote(string(field.Message.Desc.FullName())), ", v)") g.P("}") g.P() } } // fieldGoType returns the Go type used for a field. // // If it returns pointer=true, the struct field is a pointer to the type. func fieldGoType(g *protogen.GeneratedFile, f *fileInfo, field *protogen.Field) (goType string, pointer bool) { if field.Desc.IsWeak() { return "struct{}", false } pointer = field.Desc.HasPresence() switch field.Desc.Kind() { case protoreflect.BoolKind: goType = "bool" case protoreflect.EnumKind: goType = g.QualifiedGoIdent(field.Enum.GoIdent) case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: goType = "int32" case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: goType = "uint32" case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: goType = "int64" case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: goType = "uint64" case protoreflect.FloatKind: goType = "float32" case protoreflect.DoubleKind: goType = "float64" case protoreflect.StringKind: goType = "string" case protoreflect.BytesKind: goType = "[]byte" pointer = false // rely on nullability of slices for presence case protoreflect.MessageKind, protoreflect.GroupKind: goType = "*" + g.QualifiedGoIdent(field.Message.GoIdent) pointer = false // pointer captured as part of the type } switch { case field.Desc.IsList(): return "[]" + goType, false case field.Desc.IsMap(): keyType, _ := fieldGoType(g, f, field.Message.Fields[0]) valType, _ := fieldGoType(g, f, field.Message.Fields[1]) return fmt.Sprintf("map[%v]%v", keyType, valType), false } return goType, pointer } func fieldProtobufTagValue(field *protogen.Field) string { var enumName string if field.Desc.Kind() == protoreflect.EnumKind { enumName = protoimpl.X.LegacyEnumName(field.Enum.Desc) } return tag.Marshal(field.Desc, enumName) } func fieldDefaultValue(g *protogen.GeneratedFile, m *messageInfo, field *protogen.Field) string { if field.Desc.IsList() { return "nil" } if field.Desc.HasDefault() { defVarName := "Default_" + m.GoIdent.GoName + "_" + field.GoName if field.Desc.Kind() == protoreflect.BytesKind { return "append([]byte(nil), " + defVarName + "...)" } return defVarName } switch field.Desc.Kind() { case protoreflect.BoolKind: return "false" case protoreflect.StringKind: return `""` case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.BytesKind: return "nil" case protoreflect.EnumKind: return g.QualifiedGoIdent(field.Enum.Values[0].GoIdent) default: return "0" } } func fieldJSONTagValue(field *protogen.Field) string { return string(field.Desc.Name()) + ",omitempty" } func genExtensions(g *protogen.GeneratedFile, f *fileInfo) { if len(f.allExtensions) == 0 { return } g.P("var ", extensionTypesVarName(f), " = []", protoimplPackage.Ident("ExtensionInfo"), "{") for _, x := range f.allExtensions { g.P("{") g.P("ExtendedType: (*", x.Extendee.GoIdent, ")(nil),") goType, pointer := fieldGoType(g, f, x.Extension) if pointer { goType = "*" + goType } g.P("ExtensionType: (", goType, ")(nil),") g.P("Field: ", x.Desc.Number(), ",") g.P("Name: ", strconv.Quote(string(x.Desc.FullName())), ",") g.P("Tag: ", strconv.Quote(fieldProtobufTagValue(x.Extension)), ",") g.P("Filename: ", strconv.Quote(f.Desc.Path()), ",") g.P("},") } g.P("}") g.P() // Group extensions by the target message. var orderedTargets []protogen.GoIdent allExtensionsByTarget := make(map[protogen.GoIdent][]*extensionInfo) allExtensionsByPtr := make(map[*extensionInfo]int) for i, x := range f.allExtensions { target := x.Extendee.GoIdent if len(allExtensionsByTarget[target]) == 0 { orderedTargets = append(orderedTargets, target) } allExtensionsByTarget[target] = append(allExtensionsByTarget[target], x) allExtensionsByPtr[x] = i } for _, target := range orderedTargets { g.P("// Extension fields to ", target, ".") g.P("var (") for _, x := range allExtensionsByTarget[target] { xd := x.Desc typeName := xd.Kind().String() switch xd.Kind() { case protoreflect.EnumKind: typeName = string(xd.Enum().FullName()) case protoreflect.MessageKind, protoreflect.GroupKind: typeName = string(xd.Message().FullName()) } fieldName := string(xd.Name()) leadingComments := x.Comments.Leading if leadingComments != "" { leadingComments += "\n" } leadingComments += protogen.Comments(fmt.Sprintf(" %v %v %v = %v;\n", xd.Cardinality(), typeName, fieldName, xd.Number())) leadingComments = appendDeprecationSuffix(leadingComments, x.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()) g.P(leadingComments, "E_", x.GoIdent, " = &", extensionTypesVarName(f), "[", allExtensionsByPtr[x], "]", trailingComment(x.Comments.Trailing)) } g.P(")") g.P() } } // genMessageOneofWrapperTypes generates the oneof wrapper types and // associates the types with the parent message type. func genMessageOneofWrapperTypes(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { for _, oneof := range m.Oneofs { if oneof.Desc.IsSynthetic() { continue } ifName := oneofInterfaceName(oneof) g.P("type ", ifName, " interface {") g.P(ifName, "()") g.P("}") g.P() for _, field := range oneof.Fields { g.Annotate(field.GoIdent.GoName, field.Location) g.Annotate(field.GoIdent.GoName+"."+field.GoName, field.Location) g.P("type ", field.GoIdent, " struct {") goType, _ := fieldGoType(g, f, field) tags := structTags{ {"protobuf", fieldProtobufTagValue(field)}, } if m.isTracked { tags = append(tags, gotrackTags...) } leadingComments := appendDeprecationSuffix(field.Comments.Leading, field.Desc.Options().(*descriptorpb.FieldOptions).GetDeprecated()) g.P(leadingComments, field.GoName, " ", goType, tags, trailingComment(field.Comments.Trailing)) g.P("}") g.P() } for _, field := range oneof.Fields { g.P("func (*", field.GoIdent, ") ", ifName, "() {}") g.P() } } } // oneofInterfaceName returns the name of the interface type implemented by // the oneof field value types. func oneofInterfaceName(oneof *protogen.Oneof) string { return "is" + oneof.GoIdent.GoName } // genNoInterfacePragma generates a standalone "nointerface" pragma to // decorate methods with field-tracking support. func genNoInterfacePragma(g *protogen.GeneratedFile, tracked bool) { if tracked { g.P("//go:nointerface") g.P() } } var gotrackTags = structTags{{"go", "track"}} // structTags is a data structure for build idiomatic Go struct tags. // Each [2]string is a key-value pair, where value is the unescaped string. // // Example: structTags{{"key", "value"}}.String() -> `key:"value"` type structTags [][2]string func (tags structTags) String() string { if len(tags) == 0 { return "" } var ss []string for _, tag := range tags { // NOTE: When quoting the value, we need to make sure the backtick // character does not appear. Convert all cases to the escaped hex form. key := tag[0] val := strings.Replace(strconv.Quote(tag[1]), "`", `\x60`, -1) ss = append(ss, fmt.Sprintf("%s:%s", key, val)) } return "`" + strings.Join(ss, " ") + "`" } // appendDeprecationSuffix optionally appends a deprecation notice as a suffix. func appendDeprecationSuffix(prefix protogen.Comments, deprecated bool) protogen.Comments { if !deprecated { return prefix } if prefix != "" { prefix += "\n" } return prefix + " Deprecated: Do not use.\n" } // trailingComment is like protogen.Comments, but lacks a trailing newline. type trailingComment protogen.Comments func (c trailingComment) String() string { s := strings.TrimSuffix(protogen.Comments(c).String(), "\n") if strings.Contains(s, "\n") { // We don't support multi-lined trailing comments as it is unclear // how to best render them in the generated code. return "" } return s } ================================================ FILE: _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/reflect.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package internal_gengo import ( "fmt" "math" "strings" "unicode/utf8" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/descriptorpb" ) func genReflectFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { g.P("var ", f.GoDescriptorIdent, " ", protoreflectPackage.Ident("FileDescriptor")) g.P() genFileDescriptor(gen, g, f) if len(f.allEnums) > 0 { g.P("var ", enumTypesVarName(f), " = make([]", protoimplPackage.Ident("EnumInfo"), ",", len(f.allEnums), ")") } if len(f.allMessages) > 0 { g.P("var ", messageTypesVarName(f), " = make([]", protoimplPackage.Ident("MessageInfo"), ",", len(f.allMessages), ")") } // Generate a unique list of Go types for all declarations and dependencies, // and the associated index into the type list for all dependencies. var goTypes []string var depIdxs []string seen := map[protoreflect.FullName]int{} genDep := func(name protoreflect.FullName, depSource string) { if depSource != "" { line := fmt.Sprintf("%d, // %d: %s -> %s", seen[name], len(depIdxs), depSource, name) depIdxs = append(depIdxs, line) } } genEnum := func(e *protogen.Enum, depSource string) { if e != nil { name := e.Desc.FullName() if _, ok := seen[name]; !ok { line := fmt.Sprintf("(%s)(0), // %d: %s", g.QualifiedGoIdent(e.GoIdent), len(goTypes), name) goTypes = append(goTypes, line) seen[name] = len(seen) } if depSource != "" { genDep(name, depSource) } } } genMessage := func(m *protogen.Message, depSource string) { if m != nil { name := m.Desc.FullName() if _, ok := seen[name]; !ok { line := fmt.Sprintf("(*%s)(nil), // %d: %s", g.QualifiedGoIdent(m.GoIdent), len(goTypes), name) if m.Desc.IsMapEntry() { // Map entry messages have no associated Go type. line = fmt.Sprintf("nil, // %d: %s", len(goTypes), name) } goTypes = append(goTypes, line) seen[name] = len(seen) } if depSource != "" { genDep(name, depSource) } } } // This ordering is significant. // See filetype.TypeBuilder.DependencyIndexes. type offsetEntry struct { start int name string } var depOffsets []offsetEntry for _, enum := range f.allEnums { genEnum(enum.Enum, "") } for _, message := range f.allMessages { genMessage(message.Message, "") } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "field type_name"}) for _, message := range f.allMessages { for _, field := range message.Fields { if field.Desc.IsWeak() { continue } source := string(field.Desc.FullName()) genEnum(field.Enum, source+":type_name") genMessage(field.Message, source+":type_name") } } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension extendee"}) for _, extension := range f.allExtensions { source := string(extension.Desc.FullName()) genMessage(extension.Extendee, source+":extendee") } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "extension type_name"}) for _, extension := range f.allExtensions { source := string(extension.Desc.FullName()) genEnum(extension.Enum, source+":type_name") genMessage(extension.Message, source+":type_name") } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method input_type"}) for _, service := range f.Services { for _, method := range service.Methods { source := string(method.Desc.FullName()) genMessage(method.Input, source+":input_type") } } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), "method output_type"}) for _, service := range f.Services { for _, method := range service.Methods { source := string(method.Desc.FullName()) genMessage(method.Output, source+":output_type") } } depOffsets = append(depOffsets, offsetEntry{len(depIdxs), ""}) for i := len(depOffsets) - 2; i >= 0; i-- { curr, next := depOffsets[i], depOffsets[i+1] depIdxs = append(depIdxs, fmt.Sprintf("%d, // [%d:%d] is the sub-list for %s", curr.start, curr.start, next.start, curr.name)) } if len(depIdxs) > math.MaxInt32 { panic("too many dependencies") // sanity check } g.P("var ", goTypesVarName(f), " = []interface{}{") for _, s := range goTypes { g.P(s) } g.P("}") g.P("var ", depIdxsVarName(f), " = []int32{") for _, s := range depIdxs { g.P(s) } g.P("}") g.P("func init() { ", initFuncName(f.File), "() }") g.P("func ", initFuncName(f.File), "() {") g.P("if ", f.GoDescriptorIdent, " != nil {") g.P("return") g.P("}") // Ensure that initialization functions for different files in the same Go // package run in the correct order: Call the init funcs for every .proto file // imported by this one that is in the same Go package. for i, imps := 0, f.Desc.Imports(); i < imps.Len(); i++ { impFile := gen.FilesByPath[imps.Get(i).Path()] if impFile.GoImportPath != f.GoImportPath { continue } g.P(initFuncName(impFile), "()") } if len(f.allMessages) > 0 { // Populate MessageInfo.Exporters. g.P("if !", protoimplPackage.Ident("UnsafeEnabled"), " {") for _, message := range f.allMessages { if sf := f.allMessageFieldsByPtr[message]; len(sf.unexported) > 0 { idx := f.allMessagesByPtr[message] typesVar := messageTypesVarName(f) g.P(typesVar, "[", idx, "].Exporter = func(v interface{}, i int) interface{} {") g.P("switch v := v.(*", message.GoIdent, "); i {") for i := 0; i < sf.count; i++ { if name := sf.unexported[i]; name != "" { g.P("case ", i, ": return &v.", name) } } g.P("default: return nil") g.P("}") g.P("}") } } g.P("}") // Populate MessageInfo.OneofWrappers. for _, message := range f.allMessages { if len(message.Oneofs) > 0 { idx := f.allMessagesByPtr[message] typesVar := messageTypesVarName(f) // Associate the wrapper types by directly passing them to the MessageInfo. g.P(typesVar, "[", idx, "].OneofWrappers = []interface{} {") for _, oneof := range message.Oneofs { if !oneof.Desc.IsSynthetic() { for _, field := range oneof.Fields { g.P("(*", field.GoIdent, ")(nil),") } } } g.P("}") } } } g.P("type x struct{}") g.P("out := ", protoimplPackage.Ident("TypeBuilder"), "{") g.P("File: ", protoimplPackage.Ident("DescBuilder"), "{") g.P("GoPackagePath: ", reflectPackage.Ident("TypeOf"), "(x{}).PkgPath(),") g.P("RawDescriptor: ", rawDescVarName(f), ",") g.P("NumEnums: ", len(f.allEnums), ",") g.P("NumMessages: ", len(f.allMessages), ",") g.P("NumExtensions: ", len(f.allExtensions), ",") g.P("NumServices: ", len(f.Services), ",") g.P("},") g.P("GoTypes: ", goTypesVarName(f), ",") g.P("DependencyIndexes: ", depIdxsVarName(f), ",") if len(f.allEnums) > 0 { g.P("EnumInfos: ", enumTypesVarName(f), ",") } if len(f.allMessages) > 0 { g.P("MessageInfos: ", messageTypesVarName(f), ",") } if len(f.allExtensions) > 0 { g.P("ExtensionInfos: ", extensionTypesVarName(f), ",") } g.P("}.Build()") g.P(f.GoDescriptorIdent, " = out.File") // Set inputs to nil to allow GC to reclaim resources. g.P(rawDescVarName(f), " = nil") g.P(goTypesVarName(f), " = nil") g.P(depIdxsVarName(f), " = nil") g.P("}") } func genFileDescriptor(gen *protogen.Plugin, g *protogen.GeneratedFile, f *fileInfo) { descProto := proto.Clone(f.Proto).(*descriptorpb.FileDescriptorProto) descProto.SourceCodeInfo = nil // drop source code information b, err := proto.MarshalOptions{AllowPartial: true, Deterministic: true}.Marshal(descProto) if err != nil { gen.Error(err) return } g.P("var ", rawDescVarName(f), " = []byte{") for len(b) > 0 { n := 16 if n > len(b) { n = len(b) } s := "" for _, c := range b[:n] { s += fmt.Sprintf("0x%02x,", c) } g.P(s) b = b[n:] } g.P("}") g.P() if f.needRawDesc { onceVar := rawDescVarName(f) + "Once" dataVar := rawDescVarName(f) + "Data" g.P("var (") g.P(onceVar, " ", syncPackage.Ident("Once")) g.P(dataVar, " = ", rawDescVarName(f)) g.P(")") g.P() g.P("func ", rawDescVarName(f), "GZIP() []byte {") g.P(onceVar, ".Do(func() {") g.P(dataVar, " = ", protoimplPackage.Ident("X"), ".CompressGZIP(", dataVar, ")") g.P("})") g.P("return ", dataVar) g.P("}") g.P() } } func genEnumReflectMethods(g *protogen.GeneratedFile, f *fileInfo, e *enumInfo) { idx := f.allEnumsByPtr[e] typesVar := enumTypesVarName(f) // Descriptor method. g.P("func (", e.GoIdent, ") Descriptor() ", protoreflectPackage.Ident("EnumDescriptor"), " {") g.P("return ", typesVar, "[", idx, "].Descriptor()") g.P("}") g.P() // Type method. g.P("func (", e.GoIdent, ") Type() ", protoreflectPackage.Ident("EnumType"), " {") g.P("return &", typesVar, "[", idx, "]") g.P("}") g.P() // Number method. g.P("func (x ", e.GoIdent, ") Number() ", protoreflectPackage.Ident("EnumNumber"), " {") g.P("return ", protoreflectPackage.Ident("EnumNumber"), "(x)") g.P("}") g.P() } func genMessageReflectMethods(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { idx := f.allMessagesByPtr[m] typesVar := messageTypesVarName(f) // ProtoReflect method. g.P("func (x *", m.GoIdent, ") ProtoReflect() ", protoreflectPackage.Ident("Message"), " {") g.P("mi := &", typesVar, "[", idx, "]") g.P("if ", protoimplPackage.Ident("UnsafeEnabled"), " && x != nil {") g.P("ms := ", protoimplPackage.Ident("X"), ".MessageStateOf(", protoimplPackage.Ident("Pointer"), "(x))") g.P("if ms.LoadMessageInfo() == nil {") g.P("ms.StoreMessageInfo(mi)") g.P("}") g.P("return ms") g.P("}") g.P("return mi.MessageOf(x)") g.P("}") g.P() } func fileVarName(f *protogen.File, suffix string) string { prefix := f.GoDescriptorIdent.GoName _, n := utf8.DecodeRuneInString(prefix) prefix = strings.ToLower(prefix[:n]) + prefix[n:] return prefix + "_" + suffix } func rawDescVarName(f *fileInfo) string { return fileVarName(f.File, "rawDesc") } func goTypesVarName(f *fileInfo) string { return fileVarName(f.File, "goTypes") } func depIdxsVarName(f *fileInfo) string { return fileVarName(f.File, "depIdxs") } func enumTypesVarName(f *fileInfo) string { return fileVarName(f.File, "enumTypes") } func messageTypesVarName(f *fileInfo) string { return fileVarName(f.File, "msgTypes") } func extensionTypesVarName(f *fileInfo) string { return fileVarName(f.File, "extTypes") } func initFuncName(f *protogen.File) string { return fileVarName(f, "init") } ================================================ FILE: _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo/well_known_types.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package internal_gengo import ( "strings" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/internal/genid" ) // Specialized support for well-known types are hard-coded into the generator // as opposed to being injected in adjacent .go sources in the generated package // in order to support specialized build systems like Bazel that always generate // dynamically from the source .proto files. func genPackageKnownComment(f *fileInfo) protogen.Comments { switch f.Desc.Path() { case genid.File_google_protobuf_any_proto: return ` Package anypb contains generated types for ` + genid.File_google_protobuf_any_proto + `. The Any message is a dynamic representation of any other message value. It is functionally a tuple of the full name of the remote message type and the serialized bytes of the remote message value. Constructing an Any An Any message containing another message value is constructed using New: any, err := anypb.New(m) if err != nil { ... // handle error } ... // make use of any Unmarshaling an Any With a populated Any message, the underlying message can be serialized into a remote concrete message value in a few ways. If the exact concrete type is known, then a new (or pre-existing) instance of that message can be passed to the UnmarshalTo method: m := new(foopb.MyMessage) if err := any.UnmarshalTo(m); err != nil { ... // handle error } ... // make use of m If the exact concrete type is not known, then the UnmarshalNew method can be used to unmarshal the contents into a new instance of the remote message type: m, err := any.UnmarshalNew() if err != nil { ... // handle error } ... // make use of m UnmarshalNew uses the global type registry to resolve the message type and construct a new instance of that message to unmarshal into. In order for a message type to appear in the global registry, the Go type representing that protobuf message type must be linked into the Go binary. For messages generated by protoc-gen-go, this is achieved through an import of the generated Go package representing a .proto file. A common pattern with UnmarshalNew is to use a type switch with the resulting proto.Message value: switch m := m.(type) { case *foopb.MyMessage: ... // make use of m as a *foopb.MyMessage case *barpb.OtherMessage: ... // make use of m as a *barpb.OtherMessage case *bazpb.SomeMessage: ... // make use of m as a *bazpb.SomeMessage } This pattern ensures that the generated packages containing the message types listed in the case clauses are linked into the Go binary and therefore also registered in the global registry. Type checking an Any In order to type check whether an Any message represents some other message, then use the MessageIs method: if any.MessageIs((*foopb.MyMessage)(nil)) { ... // make use of any, knowing that it contains a foopb.MyMessage } The MessageIs method can also be used with an allocated instance of the target message type if the intention is to unmarshal into it if the type matches: m := new(foopb.MyMessage) if any.MessageIs(m) { if err := any.UnmarshalTo(m); err != nil { ... // handle error } ... // make use of m } ` case genid.File_google_protobuf_timestamp_proto: return ` Package timestamppb contains generated types for ` + genid.File_google_protobuf_timestamp_proto + `. The Timestamp message represents a timestamp, an instant in time since the Unix epoch (January 1st, 1970). Conversion to a Go Time The AsTime method can be used to convert a Timestamp message to a standard Go time.Time value in UTC: t := ts.AsTime() ... // make use of t as a time.Time Converting to a time.Time is a common operation so that the extensive set of time-based operations provided by the time package can be leveraged. See https://golang.org/pkg/time for more information. The AsTime method performs the conversion on a best-effort basis. Timestamps with denormal values (e.g., nanoseconds beyond 0 and 99999999, inclusive) are normalized during the conversion to a time.Time. To manually check for invalid Timestamps per the documented limitations in timestamp.proto, additionally call the CheckValid method: if err := ts.CheckValid(); err != nil { ... // handle error } Conversion from a Go Time The timestamppb.New function can be used to construct a Timestamp message from a standard Go time.Time value: ts := timestamppb.New(t) ... // make use of ts as a *timestamppb.Timestamp In order to construct a Timestamp representing the current time, use Now: ts := timestamppb.Now() ... // make use of ts as a *timestamppb.Timestamp ` case genid.File_google_protobuf_duration_proto: return ` Package durationpb contains generated types for ` + genid.File_google_protobuf_duration_proto + `. The Duration message represents a signed span of time. Conversion to a Go Duration The AsDuration method can be used to convert a Duration message to a standard Go time.Duration value: d := dur.AsDuration() ... // make use of d as a time.Duration Converting to a time.Duration is a common operation so that the extensive set of time-based operations provided by the time package can be leveraged. See https://golang.org/pkg/time for more information. The AsDuration method performs the conversion on a best-effort basis. Durations with denormal values (e.g., nanoseconds beyond -99999999 and +99999999, inclusive; or seconds and nanoseconds with opposite signs) are normalized during the conversion to a time.Duration. To manually check for invalid Duration per the documented limitations in duration.proto, additionally call the CheckValid method: if err := dur.CheckValid(); err != nil { ... // handle error } Note that the documented limitations in duration.proto does not protect a Duration from overflowing the representable range of a time.Duration in Go. The AsDuration method uses saturation arithmetic such that an overflow clamps the resulting value to the closest representable value (e.g., math.MaxInt64 for positive overflow and math.MinInt64 for negative overflow). Conversion from a Go Duration The durationpb.New function can be used to construct a Duration message from a standard Go time.Duration value: dur := durationpb.New(d) ... // make use of d as a *durationpb.Duration ` case genid.File_google_protobuf_struct_proto: return ` Package structpb contains generated types for ` + genid.File_google_protobuf_struct_proto + `. The messages (i.e., Value, Struct, and ListValue) defined in struct.proto are used to represent arbitrary JSON. The Value message represents a JSON value, the Struct message represents a JSON object, and the ListValue message represents a JSON array. See https://json.org for more information. The Value, Struct, and ListValue types have generated MarshalJSON and UnmarshalJSON methods such that they serialize JSON equivalent to what the messages themselves represent. Use of these types with the "google.golang.org/protobuf/encoding/protojson" package ensures that they will be serialized as their JSON equivalent. Conversion to and from a Go interface The standard Go "encoding/json" package has functionality to serialize arbitrary types to a large degree. The Value.AsInterface, Struct.AsMap, and ListValue.AsSlice methods can convert the protobuf message representation into a form represented by interface{}, map[string]interface{}, and []interface{}. This form can be used with other packages that operate on such data structures and also directly with the standard json package. In order to convert the interface{}, map[string]interface{}, and []interface{} forms back as Value, Struct, and ListValue messages, use the NewStruct, NewList, and NewValue constructor functions. Example usage Consider the following example JSON object: { "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 27, "address": { "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100" }, "phoneNumbers": [ { "type": "home", "number": "212 555-1234" }, { "type": "office", "number": "646 555-4567" } ], "children": [], "spouse": null } To construct a Value message representing the above JSON object: m, err := structpb.NewValue(map[string]interface{}{ "firstName": "John", "lastName": "Smith", "isAlive": true, "age": 27, "address": map[string]interface{}{ "streetAddress": "21 2nd Street", "city": "New York", "state": "NY", "postalCode": "10021-3100", }, "phoneNumbers": []interface{}{ map[string]interface{}{ "type": "home", "number": "212 555-1234", }, map[string]interface{}{ "type": "office", "number": "646 555-4567", }, }, "children": []interface{}{}, "spouse": nil, }) if err != nil { ... // handle error } ... // make use of m as a *structpb.Value ` case genid.File_google_protobuf_field_mask_proto: return ` Package fieldmaskpb contains generated types for ` + genid.File_google_protobuf_field_mask_proto + `. The FieldMask message represents a set of symbolic field paths. The paths are specific to some target message type, which is not stored within the FieldMask message itself. Constructing a FieldMask The New function is used construct a FieldMask: var messageType *descriptorpb.DescriptorProto fm, err := fieldmaskpb.New(messageType, "field.name", "field.number") if err != nil { ... // handle error } ... // make use of fm The "field.name" and "field.number" paths are valid paths according to the google.protobuf.DescriptorProto message. Use of a path that does not correlate to valid fields reachable from DescriptorProto would result in an error. Once a FieldMask message has been constructed, the Append method can be used to insert additional paths to the path set: var messageType *descriptorpb.DescriptorProto if err := fm.Append(messageType, "options"); err != nil { ... // handle error } Type checking a FieldMask In order to verify that a FieldMask represents a set of fields that are reachable from some target message type, use the IsValid method: var messageType *descriptorpb.DescriptorProto if fm.IsValid(messageType) { ... // make use of fm } IsValid needs to be passed the target message type as an input since the FieldMask message itself does not store the message type that the set of paths are for. ` default: return "" } } func genMessageKnownFunctions(g *protogen.GeneratedFile, f *fileInfo, m *messageInfo) { switch m.Desc.FullName() { case genid.Any_message_fullname: g.P("// New marshals src into a new Any instance.") g.P("func New(src ", protoPackage.Ident("Message"), ") (*Any, error) {") g.P(" dst := new(Any)") g.P(" if err := dst.MarshalFrom(src); err != nil {") g.P(" return nil, err") g.P(" }") g.P(" return dst, nil") g.P("}") g.P() g.P("// MarshalFrom marshals src into dst as the underlying message") g.P("// using the provided marshal options.") g.P("//") g.P("// If no options are specified, call dst.MarshalFrom instead.") g.P("func MarshalFrom(dst *Any, src ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("MarshalOptions"), ") error {") g.P(" const urlPrefix = \"type.googleapis.com/\"") g.P(" if src == nil {") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")") g.P(" }") g.P(" b, err := opts.Marshal(src)") g.P(" if err != nil {") g.P(" return err") g.P(" }") g.P(" dst.TypeUrl = urlPrefix + string(src.ProtoReflect().Descriptor().FullName())") g.P(" dst.Value = b") g.P(" return nil") g.P("}") g.P() g.P("// UnmarshalTo unmarshals the underlying message from src into dst") g.P("// using the provided unmarshal options.") g.P("// It reports an error if dst is not of the right message type.") g.P("//") g.P("// If no options are specified, call src.UnmarshalTo instead.") g.P("func UnmarshalTo(src *Any, dst ", protoPackage.Ident("Message"), ", opts ", protoPackage.Ident("UnmarshalOptions"), ") error {") g.P(" if src == nil {") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil source message\")") g.P(" }") g.P(" if !src.MessageIs(dst) {") g.P(" got := dst.ProtoReflect().Descriptor().FullName()") g.P(" want := src.MessageName()") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"mismatched message type: got %q, want %q\", got, want)") g.P(" }") g.P(" return opts.Unmarshal(src.GetValue(), dst)") g.P("}") g.P() g.P("// UnmarshalNew unmarshals the underlying message from src into dst,") g.P("// which is newly created message using a type resolved from the type URL.") g.P("// The message type is resolved according to opt.Resolver,") g.P("// which should implement protoregistry.MessageTypeResolver.") g.P("// It reports an error if the underlying message type could not be resolved.") g.P("//") g.P("// If no options are specified, call src.UnmarshalNew instead.") g.P("func UnmarshalNew(src *Any, opts ", protoPackage.Ident("UnmarshalOptions"), ") (dst ", protoPackage.Ident("Message"), ", err error) {") g.P(" if src.GetTypeUrl() == \"\" {") g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid empty type URL\")") g.P(" }") g.P(" if opts.Resolver == nil {") g.P(" opts.Resolver = ", protoregistryPackage.Ident("GlobalTypes")) g.P(" }") g.P(" r, ok := opts.Resolver.(", protoregistryPackage.Ident("MessageTypeResolver"), ")") g.P(" if !ok {") g.P(" return nil, ", protoregistryPackage.Ident("NotFound")) g.P(" }") g.P(" mt, err := r.FindMessageByURL(src.GetTypeUrl())") g.P(" if err != nil {") g.P(" if err == ", protoregistryPackage.Ident("NotFound"), " {") g.P(" return nil, err") g.P(" }") g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"could not resolve %q: %v\", src.GetTypeUrl(), err)") g.P(" }") g.P(" dst = mt.New().Interface()") g.P(" return dst, opts.Unmarshal(src.GetValue(), dst)") g.P("}") g.P() g.P("// MessageIs reports whether the underlying message is of the same type as m.") g.P("func (x *Any) MessageIs(m ", protoPackage.Ident("Message"), ") bool {") g.P(" if m == nil {") g.P(" return false") g.P(" }") g.P(" url := x.GetTypeUrl()") g.P(" name := string(m.ProtoReflect().Descriptor().FullName())") g.P(" if !", stringsPackage.Ident("HasSuffix"), "(url, name) {") g.P(" return false") g.P(" }") g.P(" return len(url) == len(name) || url[len(url)-len(name)-1] == '/'") g.P("}") g.P() g.P("// MessageName reports the full name of the underlying message,") g.P("// returning an empty string if invalid.") g.P("func (x *Any) MessageName() ", protoreflectPackage.Ident("FullName"), " {") g.P(" url := x.GetTypeUrl()") g.P(" name := ", protoreflectPackage.Ident("FullName"), "(url)") g.P(" if i := ", stringsPackage.Ident("LastIndexByte"), "(url, '/'); i >= 0 {") g.P(" name = name[i+len(\"/\"):]") g.P(" }") g.P(" if !name.IsValid() {") g.P(" return \"\"") g.P(" }") g.P(" return name") g.P("}") g.P() g.P("// MarshalFrom marshals m into x as the underlying message.") g.P("func (x *Any) MarshalFrom(m ", protoPackage.Ident("Message"), ") error {") g.P(" return MarshalFrom(x, m, ", protoPackage.Ident("MarshalOptions"), "{})") g.P("}") g.P() g.P("// UnmarshalTo unmarshals the contents of the underlying message of x into m.") g.P("// It resets m before performing the unmarshal operation.") g.P("// It reports an error if m is not of the right message type.") g.P("func (x *Any) UnmarshalTo(m ", protoPackage.Ident("Message"), ") error {") g.P(" return UnmarshalTo(x, m, ", protoPackage.Ident("UnmarshalOptions"), "{})") g.P("}") g.P() g.P("// UnmarshalNew unmarshals the contents of the underlying message of x into") g.P("// a newly allocated message of the specified type.") g.P("// It reports an error if the underlying message type could not be resolved.") g.P("func (x *Any) UnmarshalNew() (", protoPackage.Ident("Message"), ", error) {") g.P(" return UnmarshalNew(x, ", protoPackage.Ident("UnmarshalOptions"), "{})") g.P("}") g.P() case genid.Timestamp_message_fullname: g.P("// Now constructs a new Timestamp from the current time.") g.P("func Now() *Timestamp {") g.P(" return New(", timePackage.Ident("Now"), "())") g.P("}") g.P() g.P("// New constructs a new Timestamp from the provided time.Time.") g.P("func New(t ", timePackage.Ident("Time"), ") *Timestamp {") g.P(" return &Timestamp{Seconds: int64(t.Unix()), Nanos: int32(t.Nanosecond())}") g.P("}") g.P() g.P("// AsTime converts x to a time.Time.") g.P("func (x *Timestamp) AsTime() ", timePackage.Ident("Time"), " {") g.P(" return ", timePackage.Ident("Unix"), "(int64(x.GetSeconds()), int64(x.GetNanos())).UTC()") g.P("}") g.P() g.P("// IsValid reports whether the timestamp is valid.") g.P("// It is equivalent to CheckValid == nil.") g.P("func (x *Timestamp) IsValid() bool {") g.P(" return x.check() == 0") g.P("}") g.P() g.P("// CheckValid returns an error if the timestamp is invalid.") g.P("// In particular, it checks whether the value represents a date that is") g.P("// in the range of 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z inclusive.") g.P("// An error is reported for a nil Timestamp.") g.P("func (x *Timestamp) CheckValid() error {") g.P(" switch x.check() {") g.P(" case invalidNil:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Timestamp\")") g.P(" case invalidUnderflow:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) before 0001-01-01\", x)") g.P(" case invalidOverflow:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) after 9999-12-31\", x)") g.P(" case invalidNanos:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"timestamp (%v) has out-of-range nanos\", x)") g.P(" default:") g.P(" return nil") g.P(" }") g.P("}") g.P() g.P("const (") g.P(" _ = iota") g.P(" invalidNil") g.P(" invalidUnderflow") g.P(" invalidOverflow") g.P(" invalidNanos") g.P(")") g.P() g.P("func (x *Timestamp) check() uint {") g.P(" const minTimestamp = -62135596800 // Seconds between 1970-01-01T00:00:00Z and 0001-01-01T00:00:00Z, inclusive") g.P(" const maxTimestamp = +253402300799 // Seconds between 1970-01-01T00:00:00Z and 9999-12-31T23:59:59Z, inclusive") g.P(" secs := x.GetSeconds()") g.P(" nanos := x.GetNanos()") g.P(" switch {") g.P(" case x == nil:") g.P(" return invalidNil") g.P(" case secs < minTimestamp:") g.P(" return invalidUnderflow") g.P(" case secs > maxTimestamp:") g.P(" return invalidOverflow") g.P(" case nanos < 0 || nanos >= 1e9:") g.P(" return invalidNanos") g.P(" default:") g.P(" return 0") g.P(" }") g.P("}") g.P() case genid.Duration_message_fullname: g.P("// New constructs a new Duration from the provided time.Duration.") g.P("func New(d ", timePackage.Ident("Duration"), ") *Duration {") g.P(" nanos := d.Nanoseconds()") g.P(" secs := nanos / 1e9") g.P(" nanos -= secs * 1e9") g.P(" return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}") g.P("}") g.P() g.P("// AsDuration converts x to a time.Duration,") g.P("// returning the closest duration value in the event of overflow.") g.P("func (x *Duration) AsDuration() ", timePackage.Ident("Duration"), " {") g.P(" secs := x.GetSeconds()") g.P(" nanos := x.GetNanos()") g.P(" d := ", timePackage.Ident("Duration"), "(secs) * ", timePackage.Ident("Second")) g.P(" overflow := d/", timePackage.Ident("Second"), " != ", timePackage.Ident("Duration"), "(secs)") g.P(" d += ", timePackage.Ident("Duration"), "(nanos) * ", timePackage.Ident("Nanosecond")) g.P(" overflow = overflow || (secs < 0 && nanos < 0 && d > 0)") g.P(" overflow = overflow || (secs > 0 && nanos > 0 && d < 0)") g.P(" if overflow {") g.P(" switch {") g.P(" case secs < 0:") g.P(" return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MinInt64"), ")") g.P(" case secs > 0:") g.P(" return ", timePackage.Ident("Duration"), "(", mathPackage.Ident("MaxInt64"), ")") g.P(" }") g.P(" }") g.P(" return d") g.P("}") g.P() g.P("// IsValid reports whether the duration is valid.") g.P("// It is equivalent to CheckValid == nil.") g.P("func (x *Duration) IsValid() bool {") g.P(" return x.check() == 0") g.P("}") g.P() g.P("// CheckValid returns an error if the duration is invalid.") g.P("// In particular, it checks whether the value is within the range of") g.P("// -10000 years to +10000 years inclusive.") g.P("// An error is reported for a nil Duration.") g.P("func (x *Duration) CheckValid() error {") g.P(" switch x.check() {") g.P(" case invalidNil:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid nil Duration\")") g.P(" case invalidUnderflow:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds -10000 years\", x)") g.P(" case invalidOverflow:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) exceeds +10000 years\", x)") g.P(" case invalidNanosRange:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has out-of-range nanos\", x)") g.P(" case invalidNanosSign:") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"duration (%v) has seconds and nanos with different signs\", x)") g.P(" default:") g.P(" return nil") g.P(" }") g.P("}") g.P() g.P("const (") g.P(" _ = iota") g.P(" invalidNil") g.P(" invalidUnderflow") g.P(" invalidOverflow") g.P(" invalidNanosRange") g.P(" invalidNanosSign") g.P(")") g.P() g.P("func (x *Duration) check() uint {") g.P(" const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min") g.P(" secs := x.GetSeconds()") g.P(" nanos := x.GetNanos()") g.P(" switch {") g.P(" case x == nil:") g.P(" return invalidNil") g.P(" case secs < -absDuration:") g.P(" return invalidUnderflow") g.P(" case secs > +absDuration:") g.P(" return invalidOverflow") g.P(" case nanos <= -1e9 || nanos >= +1e9:") g.P(" return invalidNanosRange") g.P(" case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):") g.P(" return invalidNanosSign") g.P(" default:") g.P(" return 0") g.P(" }") g.P("}") g.P() case genid.Struct_message_fullname: g.P("// NewStruct constructs a Struct from a general-purpose Go map.") g.P("// The map keys must be valid UTF-8.") g.P("// The map values are converted using NewValue.") g.P("func NewStruct(v map[string]interface{}) (*Struct, error) {") g.P(" x := &Struct{Fields: make(map[string]*Value, len(v))}") g.P(" for k, v := range v {") g.P(" if !", utf8Package.Ident("ValidString"), "(k) {") g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", k)") g.P(" }") g.P(" var err error") g.P(" x.Fields[k], err = NewValue(v)") g.P(" if err != nil {") g.P(" return nil, err") g.P(" }") g.P(" }") g.P(" return x, nil") g.P("}") g.P() g.P("// AsMap converts x to a general-purpose Go map.") g.P("// The map values are converted by calling Value.AsInterface.") g.P("func (x *Struct) AsMap() map[string]interface{} {") g.P(" vs := make(map[string]interface{})") g.P(" for k, v := range x.GetFields() {") g.P(" vs[k] = v.AsInterface()") g.P(" }") g.P(" return vs") g.P("}") g.P() g.P("func (x *Struct) MarshalJSON() ([]byte, error) {") g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)") g.P("}") g.P() g.P("func (x *Struct) UnmarshalJSON(b []byte) error {") g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)") g.P("}") g.P() case genid.ListValue_message_fullname: g.P("// NewList constructs a ListValue from a general-purpose Go slice.") g.P("// The slice elements are converted using NewValue.") g.P("func NewList(v []interface{}) (*ListValue, error) {") g.P(" x := &ListValue{Values: make([]*Value, len(v))}") g.P(" for i, v := range v {") g.P(" var err error") g.P(" x.Values[i], err = NewValue(v)") g.P(" if err != nil {") g.P(" return nil, err") g.P(" }") g.P(" }") g.P(" return x, nil") g.P("}") g.P() g.P("// AsSlice converts x to a general-purpose Go slice.") g.P("// The slice elements are converted by calling Value.AsInterface.") g.P("func (x *ListValue) AsSlice() []interface{} {") g.P(" vs := make([]interface{}, len(x.GetValues()))") g.P(" for i, v := range x.GetValues() {") g.P(" vs[i] = v.AsInterface()") g.P(" }") g.P(" return vs") g.P("}") g.P() g.P("func (x *ListValue) MarshalJSON() ([]byte, error) {") g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)") g.P("}") g.P() g.P("func (x *ListValue) UnmarshalJSON(b []byte) error {") g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)") g.P("}") g.P() case genid.Value_message_fullname: g.P("// NewValue constructs a Value from a general-purpose Go interface.") g.P("//") g.P("// ╔════════════════════════╤════════════════════════════════════════════╗") g.P("// ║ Go type │ Conversion ║") g.P("// ╠════════════════════════╪════════════════════════════════════════════╣") g.P("// ║ nil │ stored as NullValue ║") g.P("// ║ bool │ stored as BoolValue ║") g.P("// ║ int, int32, int64 │ stored as NumberValue ║") g.P("// ║ uint, uint32, uint64 │ stored as NumberValue ║") g.P("// ║ float32, float64 │ stored as NumberValue ║") g.P("// ║ string │ stored as StringValue; must be valid UTF-8 ║") g.P("// ║ []byte │ stored as StringValue; base64-encoded ║") g.P("// ║ map[string]interface{} │ stored as StructValue ║") g.P("// ║ []interface{} │ stored as ListValue ║") g.P("// ╚════════════════════════╧════════════════════════════════════════════╝") g.P("//") g.P("// When converting an int64 or uint64 to a NumberValue, numeric precision loss") g.P("// is possible since they are stored as a float64.") g.P("func NewValue(v interface{}) (*Value, error) {") g.P(" switch v := v.(type) {") g.P(" case nil:") g.P(" return NewNullValue(), nil") g.P(" case bool:") g.P(" return NewBoolValue(v), nil") g.P(" case int:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case int32:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case int64:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case uint:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case uint32:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case uint64:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case float32:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case float64:") g.P(" return NewNumberValue(float64(v)), nil") g.P(" case string:") g.P(" if !", utf8Package.Ident("ValidString"), "(v) {") g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid UTF-8 in string: %q\", v)") g.P(" }") g.P(" return NewStringValue(v), nil") g.P(" case []byte:") g.P(" s := ", base64Package.Ident("StdEncoding"), ".EncodeToString(v)") g.P(" return NewStringValue(s), nil") g.P(" case map[string]interface{}:") g.P(" v2, err := NewStruct(v)") g.P(" if err != nil {") g.P(" return nil, err") g.P(" }") g.P(" return NewStructValue(v2), nil") g.P(" case []interface{}:") g.P(" v2, err := NewList(v)") g.P(" if err != nil {") g.P(" return nil, err") g.P(" }") g.P(" return NewListValue(v2), nil") g.P(" default:") g.P(" return nil, ", protoimplPackage.Ident("X"), ".NewError(\"invalid type: %T\", v)") g.P(" }") g.P("}") g.P() g.P("// NewNullValue constructs a new null Value.") g.P("func NewNullValue() *Value {") g.P(" return &Value{Kind: &Value_NullValue{NullValue: NullValue_NULL_VALUE}}") g.P("}") g.P() g.P("// NewBoolValue constructs a new boolean Value.") g.P("func NewBoolValue(v bool) *Value {") g.P(" return &Value{Kind: &Value_BoolValue{BoolValue: v}}") g.P("}") g.P() g.P("// NewNumberValue constructs a new number Value.") g.P("func NewNumberValue(v float64) *Value {") g.P(" return &Value{Kind: &Value_NumberValue{NumberValue: v}}") g.P("}") g.P() g.P("// NewStringValue constructs a new string Value.") g.P("func NewStringValue(v string) *Value {") g.P(" return &Value{Kind: &Value_StringValue{StringValue: v}}") g.P("}") g.P() g.P("// NewStructValue constructs a new struct Value.") g.P("func NewStructValue(v *Struct) *Value {") g.P(" return &Value{Kind: &Value_StructValue{StructValue: v}}") g.P("}") g.P() g.P("// NewListValue constructs a new list Value.") g.P("func NewListValue(v *ListValue) *Value {") g.P(" return &Value{Kind: &Value_ListValue{ListValue: v}}") g.P("}") g.P() g.P("// AsInterface converts x to a general-purpose Go interface.") g.P("//") g.P("// Calling Value.MarshalJSON and \"encoding/json\".Marshal on this output produce") g.P("// semantically equivalent JSON (assuming no errors occur).") g.P("//") g.P("// Floating-point values (i.e., \"NaN\", \"Infinity\", and \"-Infinity\") are") g.P("// converted as strings to remain compatible with MarshalJSON.") g.P("func (x *Value) AsInterface() interface{} {") g.P(" switch v := x.GetKind().(type) {") g.P(" case *Value_NumberValue:") g.P(" if v != nil {") g.P(" switch {") g.P(" case ", mathPackage.Ident("IsNaN"), "(v.NumberValue):") g.P(" return \"NaN\"") g.P(" case ", mathPackage.Ident("IsInf"), "(v.NumberValue, +1):") g.P(" return \"Infinity\"") g.P(" case ", mathPackage.Ident("IsInf"), "(v.NumberValue, -1):") g.P(" return \"-Infinity\"") g.P(" default:") g.P(" return v.NumberValue") g.P(" }") g.P(" }") g.P(" case *Value_StringValue:") g.P(" if v != nil {") g.P(" return v.StringValue") g.P(" }") g.P(" case *Value_BoolValue:") g.P(" if v != nil {") g.P(" return v.BoolValue") g.P(" }") g.P(" case *Value_StructValue:") g.P(" if v != nil {") g.P(" return v.StructValue.AsMap()") g.P(" }") g.P(" case *Value_ListValue:") g.P(" if v != nil {") g.P(" return v.ListValue.AsSlice()") g.P(" }") g.P(" }") g.P(" return nil") g.P("}") g.P() g.P("func (x *Value) MarshalJSON() ([]byte, error) {") g.P(" return ", protojsonPackage.Ident("Marshal"), "(x)") g.P("}") g.P() g.P("func (x *Value) UnmarshalJSON(b []byte) error {") g.P(" return ", protojsonPackage.Ident("Unmarshal"), "(b, x)") g.P("}") g.P() case genid.FieldMask_message_fullname: g.P("// New constructs a field mask from a list of paths and verifies that") g.P("// each one is valid according to the specified message type.") g.P("func New(m ", protoPackage.Ident("Message"), ", paths ...string) (*FieldMask, error) {") g.P(" x := new(FieldMask)") g.P(" return x, x.Append(m, paths...)") g.P("}") g.P() g.P("// Union returns the union of all the paths in the input field masks.") g.P("func Union(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {") g.P(" var out []string") g.P(" out = append(out, mx.GetPaths()...)") g.P(" out = append(out, my.GetPaths()...)") g.P(" for _, m := range ms {") g.P(" out = append(out, m.GetPaths()...)") g.P(" }") g.P(" return &FieldMask{Paths: normalizePaths(out)}") g.P("}") g.P() g.P("// Intersect returns the intersection of all the paths in the input field masks.") g.P("func Intersect(mx *FieldMask, my *FieldMask, ms ...*FieldMask) *FieldMask {") g.P(" var ss1, ss2 []string // reused buffers for performance") g.P(" intersect := func(out, in []string) []string {") g.P(" ss1 = normalizePaths(append(ss1[:0], in...))") g.P(" ss2 = normalizePaths(append(ss2[:0], out...))") g.P(" out = out[:0]") g.P(" for i1, i2 := 0, 0; i1 < len(ss1) && i2 < len(ss2); {") g.P(" switch s1, s2 := ss1[i1], ss2[i2]; {") g.P(" case hasPathPrefix(s1, s2):") g.P(" out = append(out, s1)") g.P(" i1++") g.P(" case hasPathPrefix(s2, s1):") g.P(" out = append(out, s2)") g.P(" i2++") g.P(" case lessPath(s1, s2):") g.P(" i1++") g.P(" case lessPath(s2, s1):") g.P(" i2++") g.P(" }") g.P(" }") g.P(" return out") g.P(" }") g.P() g.P(" out := Union(mx, my, ms...).GetPaths()") g.P(" out = intersect(out, mx.GetPaths())") g.P(" out = intersect(out, my.GetPaths())") g.P(" for _, m := range ms {") g.P(" out = intersect(out, m.GetPaths())") g.P(" }") g.P(" return &FieldMask{Paths: normalizePaths(out)}") g.P("}") g.P() g.P("// IsValid reports whether all the paths are syntactically valid and") g.P("// refer to known fields in the specified message type.") g.P("// It reports false for a nil FieldMask.") g.P("func (x *FieldMask) IsValid(m ", protoPackage.Ident("Message"), ") bool {") g.P(" paths := x.GetPaths()") g.P(" return x != nil && numValidPaths(m, paths) == len(paths)") g.P("}") g.P() g.P("// Append appends a list of paths to the mask and verifies that each one") g.P("// is valid according to the specified message type.") g.P("// An invalid path is not appended and breaks insertion of subsequent paths.") g.P("func (x *FieldMask) Append(m ", protoPackage.Ident("Message"), ", paths ...string) error {") g.P(" numValid := numValidPaths(m, paths)") g.P(" x.Paths = append(x.Paths, paths[:numValid]...)") g.P(" paths = paths[numValid:]") g.P(" if len(paths) > 0 {") g.P(" name := m.ProtoReflect().Descriptor().FullName()") g.P(" return ", protoimplPackage.Ident("X"), ".NewError(\"invalid path %q for message %q\", paths[0], name)") g.P(" }") g.P(" return nil") g.P("}") g.P() g.P("func numValidPaths(m ", protoPackage.Ident("Message"), ", paths []string) int {") g.P(" md0 := m.ProtoReflect().Descriptor()") g.P(" for i, path := range paths {") g.P(" md := md0") g.P(" if !rangeFields(path, func(field string) bool {") g.P(" // Search the field within the message.") g.P(" if md == nil {") g.P(" return false // not within a message") g.P(" }") g.P(" fd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(field))") g.P(" // The real field name of a group is the message name.") g.P(" if fd == nil {") g.P(" gd := md.Fields().ByName(", protoreflectPackage.Ident("Name"), "(", stringsPackage.Ident("ToLower"), "(field)))") g.P(" if gd != nil && gd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(gd.Message().Name()) == field {") g.P(" fd = gd") g.P(" }") g.P(" } else if fd.Kind() == ", protoreflectPackage.Ident("GroupKind"), " && string(fd.Message().Name()) != field {") g.P(" fd = nil") g.P(" }") g.P(" if fd == nil {") g.P(" return false // message has does not have this field") g.P(" }") g.P() g.P(" // Identify the next message to search within.") g.P(" md = fd.Message() // may be nil") g.P() g.P(" // Repeated fields are only allowed at the last postion.") g.P(" if fd.IsList() || fd.IsMap() {") g.P(" md = nil") g.P(" }") g.P() g.P(" return true") g.P(" }) {") g.P(" return i") g.P(" }") g.P(" }") g.P(" return len(paths)") g.P("}") g.P() g.P("// Normalize converts the mask to its canonical form where all paths are sorted") g.P("// and redundant paths are removed.") g.P("func (x *FieldMask) Normalize() {") g.P(" x.Paths = normalizePaths(x.Paths)") g.P("}") g.P() g.P("func normalizePaths(paths []string) []string {") g.P(" ", sortPackage.Ident("Slice"), "(paths, func(i, j int) bool {") g.P(" return lessPath(paths[i], paths[j])") g.P(" })") g.P() g.P(" // Elide any path that is a prefix match on the previous.") g.P(" out := paths[:0]") g.P(" for _, path := range paths {") g.P(" if len(out) > 0 && hasPathPrefix(path, out[len(out)-1]) {") g.P(" continue") g.P(" }") g.P(" out = append(out, path)") g.P(" }") g.P(" return out") g.P("}") g.P() g.P("// hasPathPrefix is like strings.HasPrefix, but further checks for either") g.P("// an exact matche or that the prefix is delimited by a dot.") g.P("func hasPathPrefix(path, prefix string) bool {") g.P(" return ", stringsPackage.Ident("HasPrefix"), "(path, prefix) && (len(path) == len(prefix) || path[len(prefix)] == '.')") g.P("}") g.P() g.P("// lessPath is a lexicographical comparison where dot is specially treated") g.P("// as the smallest symbol.") g.P("func lessPath(x, y string) bool {") g.P(" for i := 0; i < len(x) && i < len(y); i++ {") g.P(" if x[i] != y[i] {") g.P(" return (x[i] - '.') < (y[i] - '.')") g.P(" }") g.P(" }") g.P(" return len(x) < len(y)") g.P("}") g.P() g.P("// rangeFields is like strings.Split(path, \".\"), but avoids allocations by") g.P("// iterating over each field in place and calling a iterator function.") g.P("func rangeFields(path string, f func(field string) bool) bool {") g.P(" for {") g.P(" var field string") g.P(" if i := ", stringsPackage.Ident("IndexByte"), "(path, '.'); i >= 0 {") g.P(" field, path = path[:i], path[i:]") g.P(" } else {") g.P(" field, path = path, \"\"") g.P(" }") g.P() g.P(" if !f(field) {") g.P(" return false") g.P(" }") g.P() g.P(" if len(path) == 0 {") g.P(" return true") g.P(" }") g.P(" path = ", stringsPackage.Ident("TrimPrefix"), "(path, \".\")") g.P(" }") g.P("}") g.P() case genid.BoolValue_message_fullname, genid.Int32Value_message_fullname, genid.Int64Value_message_fullname, genid.UInt32Value_message_fullname, genid.UInt64Value_message_fullname, genid.FloatValue_message_fullname, genid.DoubleValue_message_fullname, genid.StringValue_message_fullname, genid.BytesValue_message_fullname: funcName := strings.TrimSuffix(m.GoIdent.GoName, "Value") typeName := strings.ToLower(funcName) switch typeName { case "float": typeName = "float32" case "double": typeName = "float64" case "bytes": typeName = "[]byte" } g.P("// ", funcName, " stores v in a new ", m.GoIdent, " and returns a pointer to it.") g.P("func ", funcName, "(v ", typeName, ") *", m.GoIdent, " {") g.P(" return &", m.GoIdent, "{Value: v}") g.P("}") g.P() } } ================================================ FILE: _tools/src/google.golang.org/protobuf/cmd/protoc-gen-go/main.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The protoc-gen-go binary is a protoc plugin to generate Go code for // both proto2 and proto3 versions of the protocol buffer language. // // For more information about the usage of this plugin, see: // https://developers.google.com/protocol-buffers/docs/reference/go-generated package main import ( "errors" "flag" "fmt" "os" "path/filepath" gengo "google.golang.org/protobuf/cmd/protoc-gen-go/internal_gengo" "google.golang.org/protobuf/compiler/protogen" "google.golang.org/protobuf/internal/version" ) const genGoDocURL = "https://developers.google.com/protocol-buffers/docs/reference/go-generated" const grpcDocURL = "https://grpc.io/docs/languages/go/quickstart/#regenerate-grpc-code" func main() { if len(os.Args) == 2 && os.Args[1] == "--version" { fmt.Fprintf(os.Stdout, "%v %v\n", filepath.Base(os.Args[0]), version.String()) os.Exit(0) } if len(os.Args) == 2 && os.Args[1] == "--help" { fmt.Fprintf(os.Stdout, "See "+genGoDocURL+" for usage information.\n") os.Exit(0) } var ( flags flag.FlagSet plugins = flags.String("plugins", "", "deprecated option") ) protogen.Options{ ParamFunc: flags.Set, }.Run(func(gen *protogen.Plugin) error { if *plugins != "" { return errors.New("protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC\n\n" + "See " + grpcDocURL + " for more information.") } for _, f := range gen.Files { if f.Generate { gengo.GenerateFile(gen, f) } } gen.SupportedFeatures = gengo.SupportedFeatures return nil }) } ================================================ FILE: _tools/src/google.golang.org/protobuf/compiler/protogen/protogen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protogen provides support for writing protoc plugins. // // Plugins for protoc, the Protocol Buffer compiler, // are programs which read a CodeGeneratorRequest message from standard input // and write a CodeGeneratorResponse message to standard output. // This package provides support for writing plugins which generate Go code. package protogen import ( "bufio" "bytes" "fmt" "go/ast" "go/parser" "go/printer" "go/token" "go/types" "io/ioutil" "os" "path" "path/filepath" "sort" "strconv" "strings" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protodesc" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" "google.golang.org/protobuf/types/pluginpb" ) const goPackageDocURL = "https://developers.google.com/protocol-buffers/docs/reference/go-generated#package" // Run executes a function as a protoc plugin. // // It reads a CodeGeneratorRequest message from os.Stdin, invokes the plugin // function, and writes a CodeGeneratorResponse message to os.Stdout. // // If a failure occurs while reading or writing, Run prints an error to // os.Stderr and calls os.Exit(1). func (opts Options) Run(f func(*Plugin) error) { if err := run(opts, f); err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), err) os.Exit(1) } } func run(opts Options, f func(*Plugin) error) error { if len(os.Args) > 1 { return fmt.Errorf("unknown argument %q (this program should be run by protoc, not directly)", os.Args[1]) } in, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } req := &pluginpb.CodeGeneratorRequest{} if err := proto.Unmarshal(in, req); err != nil { return err } gen, err := opts.New(req) if err != nil { return err } if err := f(gen); err != nil { // Errors from the plugin function are reported by setting the // error field in the CodeGeneratorResponse. // // In contrast, errors that indicate a problem in protoc // itself (unparsable input, I/O errors, etc.) are reported // to stderr. gen.Error(err) } resp := gen.Response() out, err := proto.Marshal(resp) if err != nil { return err } if _, err := os.Stdout.Write(out); err != nil { return err } return nil } // A Plugin is a protoc plugin invocation. type Plugin struct { // Request is the CodeGeneratorRequest provided by protoc. Request *pluginpb.CodeGeneratorRequest // Files is the set of files to generate and everything they import. // Files appear in topological order, so each file appears before any // file that imports it. Files []*File FilesByPath map[string]*File // SupportedFeatures is the set of protobuf language features supported by // this generator plugin. See the documentation for // google.protobuf.CodeGeneratorResponse.supported_features for details. SupportedFeatures uint64 fileReg *protoregistry.Files enumsByName map[protoreflect.FullName]*Enum messagesByName map[protoreflect.FullName]*Message annotateCode bool pathType pathType module string genFiles []*GeneratedFile opts Options err error } type Options struct { // If ParamFunc is non-nil, it will be called with each unknown // generator parameter. // // Plugins for protoc can accept parameters from the command line, // passed in the --_out protoc, separated from the output // directory with a colon; e.g., // // --go_out==,=: // // Parameters passed in this fashion as a comma-separated list of // key=value pairs will be passed to the ParamFunc. // // The (flag.FlagSet).Set method matches this function signature, // so parameters can be converted into flags as in the following: // // var flags flag.FlagSet // value := flags.Bool("param", false, "") // opts := &protogen.Options{ // ParamFunc: flags.Set, // } // protogen.Run(opts, func(p *protogen.Plugin) error { // if *value { ... } // }) ParamFunc func(name, value string) error // ImportRewriteFunc is called with the import path of each package // imported by a generated file. It returns the import path to use // for this package. ImportRewriteFunc func(GoImportPath) GoImportPath } // New returns a new Plugin. func (opts Options) New(req *pluginpb.CodeGeneratorRequest) (*Plugin, error) { gen := &Plugin{ Request: req, FilesByPath: make(map[string]*File), fileReg: new(protoregistry.Files), enumsByName: make(map[protoreflect.FullName]*Enum), messagesByName: make(map[protoreflect.FullName]*Message), opts: opts, } packageNames := make(map[string]GoPackageName) // filename -> package name importPaths := make(map[string]GoImportPath) // filename -> import path for _, param := range strings.Split(req.GetParameter(), ",") { var value string if i := strings.Index(param, "="); i >= 0 { value = param[i+1:] param = param[0:i] } switch param { case "": // Ignore. case "module": gen.module = value case "paths": switch value { case "import": gen.pathType = pathTypeImport case "source_relative": gen.pathType = pathTypeSourceRelative default: return nil, fmt.Errorf(`unknown path type %q: want "import" or "source_relative"`, value) } case "annotate_code": switch value { case "true", "": gen.annotateCode = true case "false": default: return nil, fmt.Errorf(`bad value for parameter %q: want "true" or "false"`, param) } default: if param[0] == 'M' { impPath, pkgName := splitImportPathAndPackageName(value) if pkgName != "" { packageNames[param[1:]] = pkgName } if impPath != "" { importPaths[param[1:]] = impPath } continue } if opts.ParamFunc != nil { if err := opts.ParamFunc(param, value); err != nil { return nil, err } } } } // When the module= option is provided, we strip the module name // prefix from generated files. This only makes sense if generated // filenames are based on the import path. if gen.module != "" && gen.pathType == pathTypeSourceRelative { return nil, fmt.Errorf("cannot use module= with paths=source_relative") } // Figure out the import path and package name for each file. // // The rules here are complicated and have grown organically over time. // Interactions between different ways of specifying package information // may be surprising. // // The recommended approach is to include a go_package option in every // .proto source file specifying the full import path of the Go package // associated with this file. // // option go_package = "google.golang.org/protobuf/types/known/anypb"; // // Alternatively, build systems which want to exert full control over // import paths may specify M= flags. for _, fdesc := range gen.Request.ProtoFile { // The "M" command-line flags take precedence over // the "go_package" option in the .proto source file. filename := fdesc.GetName() impPath, pkgName := splitImportPathAndPackageName(fdesc.GetOptions().GetGoPackage()) if importPaths[filename] == "" && impPath != "" { importPaths[filename] = impPath } if packageNames[filename] == "" && pkgName != "" { packageNames[filename] = pkgName } switch { case importPaths[filename] == "": // The import path must be specified one way or another. return nil, fmt.Errorf( "unable to determine Go import path for %q\n\n"+ "Please specify either:\n"+ "\t• a \"go_package\" option in the .proto source file, or\n"+ "\t• a \"M\" argument on the command line.\n\n"+ "See %v for more information.\n", fdesc.GetName(), goPackageDocURL) case !strings.Contains(string(importPaths[filename]), "/"): // Check that import paths contain at least one slash to avoid a // common mistake where import path is confused with package name. return nil, fmt.Errorf( "invalid Go import path %q for %q\n\n"+ "The import path must contain at least one forward slash ('/') character.\n\n"+ "See %v for more information.\n", string(importPaths[filename]), fdesc.GetName(), goPackageDocURL) case packageNames[filename] == "": // If the package name is not explicitly specified, // then derive a reasonable package name from the import path. // // NOTE: The package name is derived first from the import path in // the "go_package" option (if present) before trying the "M" flag. // The inverted order for this is because the primary use of the "M" // flag is by build systems that have full control over the // import paths all packages, where it is generally expected that // the Go package name still be identical for the Go toolchain and // for custom build systems like Bazel. if impPath == "" { impPath = importPaths[filename] } packageNames[filename] = cleanPackageName(path.Base(string(impPath))) } } // Consistency check: Every file with the same Go import path should have // the same Go package name. packageFiles := make(map[GoImportPath][]string) for filename, importPath := range importPaths { if _, ok := packageNames[filename]; !ok { // Skip files mentioned in a M= parameter // but which do not appear in the CodeGeneratorRequest. continue } packageFiles[importPath] = append(packageFiles[importPath], filename) } for importPath, filenames := range packageFiles { for i := 1; i < len(filenames); i++ { if a, b := packageNames[filenames[0]], packageNames[filenames[i]]; a != b { return nil, fmt.Errorf("Go package %v has inconsistent names %v (%v) and %v (%v)", importPath, a, filenames[0], b, filenames[i]) } } } for _, fdesc := range gen.Request.ProtoFile { filename := fdesc.GetName() if gen.FilesByPath[filename] != nil { return nil, fmt.Errorf("duplicate file name: %q", filename) } f, err := newFile(gen, fdesc, packageNames[filename], importPaths[filename]) if err != nil { return nil, err } gen.Files = append(gen.Files, f) gen.FilesByPath[filename] = f } for _, filename := range gen.Request.FileToGenerate { f, ok := gen.FilesByPath[filename] if !ok { return nil, fmt.Errorf("no descriptor for generated file: %v", filename) } f.Generate = true } return gen, nil } // Error records an error in code generation. The generator will report the // error back to protoc and will not produce output. func (gen *Plugin) Error(err error) { if gen.err == nil { gen.err = err } } // Response returns the generator output. func (gen *Plugin) Response() *pluginpb.CodeGeneratorResponse { resp := &pluginpb.CodeGeneratorResponse{} if gen.err != nil { resp.Error = proto.String(gen.err.Error()) return resp } for _, g := range gen.genFiles { if g.skip { continue } content, err := g.Content() if err != nil { return &pluginpb.CodeGeneratorResponse{ Error: proto.String(err.Error()), } } filename := g.filename if gen.module != "" { trim := gen.module + "/" if !strings.HasPrefix(filename, trim) { return &pluginpb.CodeGeneratorResponse{ Error: proto.String(fmt.Sprintf("%v: generated file does not match prefix %q", filename, gen.module)), } } filename = strings.TrimPrefix(filename, trim) } resp.File = append(resp.File, &pluginpb.CodeGeneratorResponse_File{ Name: proto.String(filename), Content: proto.String(string(content)), }) if gen.annotateCode && strings.HasSuffix(g.filename, ".go") { meta, err := g.metaFile(content) if err != nil { return &pluginpb.CodeGeneratorResponse{ Error: proto.String(err.Error()), } } resp.File = append(resp.File, &pluginpb.CodeGeneratorResponse_File{ Name: proto.String(filename + ".meta"), Content: proto.String(meta), }) } } if gen.SupportedFeatures > 0 { resp.SupportedFeatures = proto.Uint64(gen.SupportedFeatures) } return resp } // A File describes a .proto source file. type File struct { Desc protoreflect.FileDescriptor Proto *descriptorpb.FileDescriptorProto GoDescriptorIdent GoIdent // name of Go variable for the file descriptor GoPackageName GoPackageName // name of this file's Go package GoImportPath GoImportPath // import path of this file's Go package Enums []*Enum // top-level enum declarations Messages []*Message // top-level message declarations Extensions []*Extension // top-level extension declarations Services []*Service // top-level service declarations Generate bool // true if we should generate code for this file // GeneratedFilenamePrefix is used to construct filenames for generated // files associated with this source file. // // For example, the source file "dir/foo.proto" might have a filename prefix // of "dir/foo". Appending ".pb.go" produces an output file of "dir/foo.pb.go". GeneratedFilenamePrefix string location Location } func newFile(gen *Plugin, p *descriptorpb.FileDescriptorProto, packageName GoPackageName, importPath GoImportPath) (*File, error) { desc, err := protodesc.NewFile(p, gen.fileReg) if err != nil { return nil, fmt.Errorf("invalid FileDescriptorProto %q: %v", p.GetName(), err) } if err := gen.fileReg.RegisterFile(desc); err != nil { return nil, fmt.Errorf("cannot register descriptor %q: %v", p.GetName(), err) } f := &File{ Desc: desc, Proto: p, GoPackageName: packageName, GoImportPath: importPath, location: Location{SourceFile: desc.Path()}, } // Determine the prefix for generated Go files. prefix := p.GetName() if ext := path.Ext(prefix); ext == ".proto" || ext == ".protodevel" { prefix = prefix[:len(prefix)-len(ext)] } switch gen.pathType { case pathTypeImport: // If paths=import, the output filename is derived from the Go import path. prefix = path.Join(string(f.GoImportPath), path.Base(prefix)) case pathTypeSourceRelative: // If paths=source_relative, the output filename is derived from // the input filename. } f.GoDescriptorIdent = GoIdent{ GoName: "File_" + strs.GoSanitized(p.GetName()), GoImportPath: f.GoImportPath, } f.GeneratedFilenamePrefix = prefix for i, eds := 0, desc.Enums(); i < eds.Len(); i++ { f.Enums = append(f.Enums, newEnum(gen, f, nil, eds.Get(i))) } for i, mds := 0, desc.Messages(); i < mds.Len(); i++ { f.Messages = append(f.Messages, newMessage(gen, f, nil, mds.Get(i))) } for i, xds := 0, desc.Extensions(); i < xds.Len(); i++ { f.Extensions = append(f.Extensions, newField(gen, f, nil, xds.Get(i))) } for i, sds := 0, desc.Services(); i < sds.Len(); i++ { f.Services = append(f.Services, newService(gen, f, sds.Get(i))) } for _, message := range f.Messages { if err := message.resolveDependencies(gen); err != nil { return nil, err } } for _, extension := range f.Extensions { if err := extension.resolveDependencies(gen); err != nil { return nil, err } } for _, service := range f.Services { for _, method := range service.Methods { if err := method.resolveDependencies(gen); err != nil { return nil, err } } } return f, nil } // splitImportPathAndPackageName splits off the optional Go package name // from the Go import path when seperated by a ';' delimiter. func splitImportPathAndPackageName(s string) (GoImportPath, GoPackageName) { if i := strings.Index(s, ";"); i >= 0 { return GoImportPath(s[:i]), GoPackageName(s[i+1:]) } return GoImportPath(s), "" } // An Enum describes an enum. type Enum struct { Desc protoreflect.EnumDescriptor GoIdent GoIdent // name of the generated Go type Values []*EnumValue // enum value declarations Location Location // location of this enum Comments CommentSet // comments associated with this enum } func newEnum(gen *Plugin, f *File, parent *Message, desc protoreflect.EnumDescriptor) *Enum { var loc Location if parent != nil { loc = parent.Location.appendPath(genid.DescriptorProto_EnumType_field_number, desc.Index()) } else { loc = f.location.appendPath(genid.FileDescriptorProto_EnumType_field_number, desc.Index()) } enum := &Enum{ Desc: desc, GoIdent: newGoIdent(f, desc), Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } gen.enumsByName[desc.FullName()] = enum for i, vds := 0, enum.Desc.Values(); i < vds.Len(); i++ { enum.Values = append(enum.Values, newEnumValue(gen, f, parent, enum, vds.Get(i))) } return enum } // An EnumValue describes an enum value. type EnumValue struct { Desc protoreflect.EnumValueDescriptor GoIdent GoIdent // name of the generated Go declaration Parent *Enum // enum in which this value is declared Location Location // location of this enum value Comments CommentSet // comments associated with this enum value } func newEnumValue(gen *Plugin, f *File, message *Message, enum *Enum, desc protoreflect.EnumValueDescriptor) *EnumValue { // A top-level enum value's name is: EnumName_ValueName // An enum value contained in a message is: MessageName_ValueName // // For historical reasons, enum value names are not camel-cased. parentIdent := enum.GoIdent if message != nil { parentIdent = message.GoIdent } name := parentIdent.GoName + "_" + string(desc.Name()) loc := enum.Location.appendPath(genid.EnumDescriptorProto_Value_field_number, desc.Index()) return &EnumValue{ Desc: desc, GoIdent: f.GoImportPath.Ident(name), Parent: enum, Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } } // A Message describes a message. type Message struct { Desc protoreflect.MessageDescriptor GoIdent GoIdent // name of the generated Go type Fields []*Field // message field declarations Oneofs []*Oneof // message oneof declarations Enums []*Enum // nested enum declarations Messages []*Message // nested message declarations Extensions []*Extension // nested extension declarations Location Location // location of this message Comments CommentSet // comments associated with this message } func newMessage(gen *Plugin, f *File, parent *Message, desc protoreflect.MessageDescriptor) *Message { var loc Location if parent != nil { loc = parent.Location.appendPath(genid.DescriptorProto_NestedType_field_number, desc.Index()) } else { loc = f.location.appendPath(genid.FileDescriptorProto_MessageType_field_number, desc.Index()) } message := &Message{ Desc: desc, GoIdent: newGoIdent(f, desc), Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } gen.messagesByName[desc.FullName()] = message for i, eds := 0, desc.Enums(); i < eds.Len(); i++ { message.Enums = append(message.Enums, newEnum(gen, f, message, eds.Get(i))) } for i, mds := 0, desc.Messages(); i < mds.Len(); i++ { message.Messages = append(message.Messages, newMessage(gen, f, message, mds.Get(i))) } for i, fds := 0, desc.Fields(); i < fds.Len(); i++ { message.Fields = append(message.Fields, newField(gen, f, message, fds.Get(i))) } for i, ods := 0, desc.Oneofs(); i < ods.Len(); i++ { message.Oneofs = append(message.Oneofs, newOneof(gen, f, message, ods.Get(i))) } for i, xds := 0, desc.Extensions(); i < xds.Len(); i++ { message.Extensions = append(message.Extensions, newField(gen, f, message, xds.Get(i))) } // Resolve local references between fields and oneofs. for _, field := range message.Fields { if od := field.Desc.ContainingOneof(); od != nil { oneof := message.Oneofs[od.Index()] field.Oneof = oneof oneof.Fields = append(oneof.Fields, field) } } // Field name conflict resolution. // // We assume well-known method names that may be attached to a generated // message type, as well as a 'Get*' method for each field. For each // field in turn, we add _s to its name until there are no conflicts. // // Any change to the following set of method names is a potential // incompatible API change because it may change generated field names. // // TODO: If we ever support a 'go_name' option to set the Go name of a // field, we should consider dropping this entirely. The conflict // resolution algorithm is subtle and surprising (changing the order // in which fields appear in the .proto source file can change the // names of fields in generated code), and does not adapt well to // adding new per-field methods such as setters. usedNames := map[string]bool{ "Reset": true, "String": true, "ProtoMessage": true, "Marshal": true, "Unmarshal": true, "ExtensionRangeArray": true, "ExtensionMap": true, "Descriptor": true, } makeNameUnique := func(name string, hasGetter bool) string { for usedNames[name] || (hasGetter && usedNames["Get"+name]) { name += "_" } usedNames[name] = true usedNames["Get"+name] = hasGetter return name } for _, field := range message.Fields { field.GoName = makeNameUnique(field.GoName, true) field.GoIdent.GoName = message.GoIdent.GoName + "_" + field.GoName if field.Oneof != nil && field.Oneof.Fields[0] == field { // Make the name for a oneof unique as well. For historical reasons, // this assumes that a getter method is not generated for oneofs. // This is incorrect, but fixing it breaks existing code. field.Oneof.GoName = makeNameUnique(field.Oneof.GoName, false) field.Oneof.GoIdent.GoName = message.GoIdent.GoName + "_" + field.Oneof.GoName } } // Oneof field name conflict resolution. // // This conflict resolution is incomplete as it does not consider collisions // with other oneof field types, but fixing it breaks existing code. for _, field := range message.Fields { if field.Oneof != nil { Loop: for { for _, nestedMessage := range message.Messages { if nestedMessage.GoIdent == field.GoIdent { field.GoIdent.GoName += "_" continue Loop } } for _, nestedEnum := range message.Enums { if nestedEnum.GoIdent == field.GoIdent { field.GoIdent.GoName += "_" continue Loop } } break Loop } } } return message } func (message *Message) resolveDependencies(gen *Plugin) error { for _, field := range message.Fields { if err := field.resolveDependencies(gen); err != nil { return err } } for _, message := range message.Messages { if err := message.resolveDependencies(gen); err != nil { return err } } for _, extension := range message.Extensions { if err := extension.resolveDependencies(gen); err != nil { return err } } return nil } // A Field describes a message field. type Field struct { Desc protoreflect.FieldDescriptor // GoName is the base name of this field's Go field and methods. // For code generated by protoc-gen-go, this means a field named // '{{GoName}}' and a getter method named 'Get{{GoName}}'. GoName string // e.g., "FieldName" // GoIdent is the base name of a top-level declaration for this field. // For code generated by protoc-gen-go, this means a wrapper type named // '{{GoIdent}}' for members fields of a oneof, and a variable named // 'E_{{GoIdent}}' for extension fields. GoIdent GoIdent // e.g., "MessageName_FieldName" Parent *Message // message in which this field is declared; nil if top-level extension Oneof *Oneof // containing oneof; nil if not part of a oneof Extendee *Message // extended message for extension fields; nil otherwise Enum *Enum // type for enum fields; nil otherwise Message *Message // type for message or group fields; nil otherwise Location Location // location of this field Comments CommentSet // comments associated with this field } func newField(gen *Plugin, f *File, message *Message, desc protoreflect.FieldDescriptor) *Field { var loc Location switch { case desc.IsExtension() && message == nil: loc = f.location.appendPath(genid.FileDescriptorProto_Extension_field_number, desc.Index()) case desc.IsExtension() && message != nil: loc = message.Location.appendPath(genid.DescriptorProto_Extension_field_number, desc.Index()) default: loc = message.Location.appendPath(genid.DescriptorProto_Field_field_number, desc.Index()) } camelCased := strs.GoCamelCase(string(desc.Name())) var parentPrefix string if message != nil { parentPrefix = message.GoIdent.GoName + "_" } field := &Field{ Desc: desc, GoName: camelCased, GoIdent: GoIdent{ GoImportPath: f.GoImportPath, GoName: parentPrefix + camelCased, }, Parent: message, Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } return field } func (field *Field) resolveDependencies(gen *Plugin) error { desc := field.Desc switch desc.Kind() { case protoreflect.EnumKind: name := field.Desc.Enum().FullName() enum, ok := gen.enumsByName[name] if !ok { return fmt.Errorf("field %v: no descriptor for enum %v", desc.FullName(), name) } field.Enum = enum case protoreflect.MessageKind, protoreflect.GroupKind: name := desc.Message().FullName() message, ok := gen.messagesByName[name] if !ok { return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), name) } field.Message = message } if desc.IsExtension() { name := desc.ContainingMessage().FullName() message, ok := gen.messagesByName[name] if !ok { return fmt.Errorf("field %v: no descriptor for type %v", desc.FullName(), name) } field.Extendee = message } return nil } // A Oneof describes a message oneof. type Oneof struct { Desc protoreflect.OneofDescriptor // GoName is the base name of this oneof's Go field and methods. // For code generated by protoc-gen-go, this means a field named // '{{GoName}}' and a getter method named 'Get{{GoName}}'. GoName string // e.g., "OneofName" // GoIdent is the base name of a top-level declaration for this oneof. GoIdent GoIdent // e.g., "MessageName_OneofName" Parent *Message // message in which this oneof is declared Fields []*Field // fields that are part of this oneof Location Location // location of this oneof Comments CommentSet // comments associated with this oneof } func newOneof(gen *Plugin, f *File, message *Message, desc protoreflect.OneofDescriptor) *Oneof { loc := message.Location.appendPath(genid.DescriptorProto_OneofDecl_field_number, desc.Index()) camelCased := strs.GoCamelCase(string(desc.Name())) parentPrefix := message.GoIdent.GoName + "_" return &Oneof{ Desc: desc, Parent: message, GoName: camelCased, GoIdent: GoIdent{ GoImportPath: f.GoImportPath, GoName: parentPrefix + camelCased, }, Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } } // Extension is an alias of Field for documentation. type Extension = Field // A Service describes a service. type Service struct { Desc protoreflect.ServiceDescriptor GoName string Methods []*Method // service method declarations Location Location // location of this service Comments CommentSet // comments associated with this service } func newService(gen *Plugin, f *File, desc protoreflect.ServiceDescriptor) *Service { loc := f.location.appendPath(genid.FileDescriptorProto_Service_field_number, desc.Index()) service := &Service{ Desc: desc, GoName: strs.GoCamelCase(string(desc.Name())), Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } for i, mds := 0, desc.Methods(); i < mds.Len(); i++ { service.Methods = append(service.Methods, newMethod(gen, f, service, mds.Get(i))) } return service } // A Method describes a method in a service. type Method struct { Desc protoreflect.MethodDescriptor GoName string Parent *Service // service in which this method is declared Input *Message Output *Message Location Location // location of this method Comments CommentSet // comments associated with this method } func newMethod(gen *Plugin, f *File, service *Service, desc protoreflect.MethodDescriptor) *Method { loc := service.Location.appendPath(genid.ServiceDescriptorProto_Method_field_number, desc.Index()) method := &Method{ Desc: desc, GoName: strs.GoCamelCase(string(desc.Name())), Parent: service, Location: loc, Comments: makeCommentSet(f.Desc.SourceLocations().ByDescriptor(desc)), } return method } func (method *Method) resolveDependencies(gen *Plugin) error { desc := method.Desc inName := desc.Input().FullName() in, ok := gen.messagesByName[inName] if !ok { return fmt.Errorf("method %v: no descriptor for type %v", desc.FullName(), inName) } method.Input = in outName := desc.Output().FullName() out, ok := gen.messagesByName[outName] if !ok { return fmt.Errorf("method %v: no descriptor for type %v", desc.FullName(), outName) } method.Output = out return nil } // A GeneratedFile is a generated file. type GeneratedFile struct { gen *Plugin skip bool filename string goImportPath GoImportPath buf bytes.Buffer packageNames map[GoImportPath]GoPackageName usedPackageNames map[GoPackageName]bool manualImports map[GoImportPath]bool annotations map[string][]Location } // NewGeneratedFile creates a new generated file with the given filename // and import path. func (gen *Plugin) NewGeneratedFile(filename string, goImportPath GoImportPath) *GeneratedFile { g := &GeneratedFile{ gen: gen, filename: filename, goImportPath: goImportPath, packageNames: make(map[GoImportPath]GoPackageName), usedPackageNames: make(map[GoPackageName]bool), manualImports: make(map[GoImportPath]bool), annotations: make(map[string][]Location), } // All predeclared identifiers in Go are already used. for _, s := range types.Universe.Names() { g.usedPackageNames[GoPackageName(s)] = true } gen.genFiles = append(gen.genFiles, g) return g } // P prints a line to the generated output. It converts each parameter to a // string following the same rules as fmt.Print. It never inserts spaces // between parameters. func (g *GeneratedFile) P(v ...interface{}) { for _, x := range v { switch x := x.(type) { case GoIdent: fmt.Fprint(&g.buf, g.QualifiedGoIdent(x)) default: fmt.Fprint(&g.buf, x) } } fmt.Fprintln(&g.buf) } // QualifiedGoIdent returns the string to use for a Go identifier. // // If the identifier is from a different Go package than the generated file, // the returned name will be qualified (package.name) and an import statement // for the identifier's package will be included in the file. func (g *GeneratedFile) QualifiedGoIdent(ident GoIdent) string { if ident.GoImportPath == g.goImportPath { return ident.GoName } if packageName, ok := g.packageNames[ident.GoImportPath]; ok { return string(packageName) + "." + ident.GoName } packageName := cleanPackageName(path.Base(string(ident.GoImportPath))) for i, orig := 1, packageName; g.usedPackageNames[packageName]; i++ { packageName = orig + GoPackageName(strconv.Itoa(i)) } g.packageNames[ident.GoImportPath] = packageName g.usedPackageNames[packageName] = true return string(packageName) + "." + ident.GoName } // Import ensures a package is imported by the generated file. // // Packages referenced by QualifiedGoIdent are automatically imported. // Explicitly importing a package with Import is generally only necessary // when the import will be blank (import _ "package"). func (g *GeneratedFile) Import(importPath GoImportPath) { g.manualImports[importPath] = true } // Write implements io.Writer. func (g *GeneratedFile) Write(p []byte) (n int, err error) { return g.buf.Write(p) } // Skip removes the generated file from the plugin output. func (g *GeneratedFile) Skip() { g.skip = true } // Unskip reverts a previous call to Skip, re-including the generated file in // the plugin output. func (g *GeneratedFile) Unskip() { g.skip = false } // Annotate associates a symbol in a generated Go file with a location in a // source .proto file. // // The symbol may refer to a type, constant, variable, function, method, or // struct field. The "T.sel" syntax is used to identify the method or field // 'sel' on type 'T'. func (g *GeneratedFile) Annotate(symbol string, loc Location) { g.annotations[symbol] = append(g.annotations[symbol], loc) } // Content returns the contents of the generated file. func (g *GeneratedFile) Content() ([]byte, error) { if !strings.HasSuffix(g.filename, ".go") { return g.buf.Bytes(), nil } // Reformat generated code. original := g.buf.Bytes() fset := token.NewFileSet() file, err := parser.ParseFile(fset, "", original, parser.ParseComments) if err != nil { // Print out the bad code with line numbers. // This should never happen in practice, but it can while changing generated code // so consider this a debugging aid. var src bytes.Buffer s := bufio.NewScanner(bytes.NewReader(original)) for line := 1; s.Scan(); line++ { fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes()) } return nil, fmt.Errorf("%v: unparsable Go source: %v\n%v", g.filename, err, src.String()) } // Collect a sorted list of all imports. var importPaths [][2]string rewriteImport := func(importPath string) string { if f := g.gen.opts.ImportRewriteFunc; f != nil { return string(f(GoImportPath(importPath))) } return importPath } for importPath := range g.packageNames { pkgName := string(g.packageNames[GoImportPath(importPath)]) pkgPath := rewriteImport(string(importPath)) importPaths = append(importPaths, [2]string{pkgName, pkgPath}) } for importPath := range g.manualImports { if _, ok := g.packageNames[importPath]; !ok { pkgPath := rewriteImport(string(importPath)) importPaths = append(importPaths, [2]string{"_", pkgPath}) } } sort.Slice(importPaths, func(i, j int) bool { return importPaths[i][1] < importPaths[j][1] }) // Modify the AST to include a new import block. if len(importPaths) > 0 { // Insert block after package statement or // possible comment attached to the end of the package statement. pos := file.Package tokFile := fset.File(file.Package) pkgLine := tokFile.Line(file.Package) for _, c := range file.Comments { if tokFile.Line(c.Pos()) > pkgLine { break } pos = c.End() } // Construct the import block. impDecl := &ast.GenDecl{ Tok: token.IMPORT, TokPos: pos, Lparen: pos, Rparen: pos, } for _, importPath := range importPaths { impDecl.Specs = append(impDecl.Specs, &ast.ImportSpec{ Name: &ast.Ident{ Name: importPath[0], NamePos: pos, }, Path: &ast.BasicLit{ Kind: token.STRING, Value: strconv.Quote(importPath[1]), ValuePos: pos, }, EndPos: pos, }) } file.Decls = append([]ast.Decl{impDecl}, file.Decls...) } var out bytes.Buffer if err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(&out, fset, file); err != nil { return nil, fmt.Errorf("%v: can not reformat Go source: %v", g.filename, err) } return out.Bytes(), nil } // metaFile returns the contents of the file's metadata file, which is a // text formatted string of the google.protobuf.GeneratedCodeInfo. func (g *GeneratedFile) metaFile(content []byte) (string, error) { fset := token.NewFileSet() astFile, err := parser.ParseFile(fset, "", content, 0) if err != nil { return "", err } info := &descriptorpb.GeneratedCodeInfo{} seenAnnotations := make(map[string]bool) annotate := func(s string, ident *ast.Ident) { seenAnnotations[s] = true for _, loc := range g.annotations[s] { info.Annotation = append(info.Annotation, &descriptorpb.GeneratedCodeInfo_Annotation{ SourceFile: proto.String(loc.SourceFile), Path: loc.Path, Begin: proto.Int32(int32(fset.Position(ident.Pos()).Offset)), End: proto.Int32(int32(fset.Position(ident.End()).Offset)), }) } } for _, decl := range astFile.Decls { switch decl := decl.(type) { case *ast.GenDecl: for _, spec := range decl.Specs { switch spec := spec.(type) { case *ast.TypeSpec: annotate(spec.Name.Name, spec.Name) switch st := spec.Type.(type) { case *ast.StructType: for _, field := range st.Fields.List { for _, name := range field.Names { annotate(spec.Name.Name+"."+name.Name, name) } } case *ast.InterfaceType: for _, field := range st.Methods.List { for _, name := range field.Names { annotate(spec.Name.Name+"."+name.Name, name) } } } case *ast.ValueSpec: for _, name := range spec.Names { annotate(name.Name, name) } } } case *ast.FuncDecl: if decl.Recv == nil { annotate(decl.Name.Name, decl.Name) } else { recv := decl.Recv.List[0].Type if s, ok := recv.(*ast.StarExpr); ok { recv = s.X } if id, ok := recv.(*ast.Ident); ok { annotate(id.Name+"."+decl.Name.Name, decl.Name) } } } } for a := range g.annotations { if !seenAnnotations[a] { return "", fmt.Errorf("%v: no symbol matching annotation %q", g.filename, a) } } b, err := prototext.Marshal(info) if err != nil { return "", err } return string(b), nil } // A GoIdent is a Go identifier, consisting of a name and import path. // The name is a single identifier and may not be a dot-qualified selector. type GoIdent struct { GoName string GoImportPath GoImportPath } func (id GoIdent) String() string { return fmt.Sprintf("%q.%v", id.GoImportPath, id.GoName) } // newGoIdent returns the Go identifier for a descriptor. func newGoIdent(f *File, d protoreflect.Descriptor) GoIdent { name := strings.TrimPrefix(string(d.FullName()), string(f.Desc.Package())+".") return GoIdent{ GoName: strs.GoCamelCase(name), GoImportPath: f.GoImportPath, } } // A GoImportPath is the import path of a Go package. // For example: "google.golang.org/protobuf/compiler/protogen" type GoImportPath string func (p GoImportPath) String() string { return strconv.Quote(string(p)) } // Ident returns a GoIdent with s as the GoName and p as the GoImportPath. func (p GoImportPath) Ident(s string) GoIdent { return GoIdent{GoName: s, GoImportPath: p} } // A GoPackageName is the name of a Go package. e.g., "protobuf". type GoPackageName string // cleanPackageName converts a string to a valid Go package name. func cleanPackageName(name string) GoPackageName { return GoPackageName(strs.GoSanitized(name)) } type pathType int const ( pathTypeImport pathType = iota pathTypeSourceRelative ) // A Location is a location in a .proto source file. // // See the google.protobuf.SourceCodeInfo documentation in descriptor.proto // for details. type Location struct { SourceFile string Path protoreflect.SourcePath } // appendPath add elements to a Location's path, returning a new Location. func (loc Location) appendPath(num protoreflect.FieldNumber, idx int) Location { loc.Path = append(protoreflect.SourcePath(nil), loc.Path...) // make copy loc.Path = append(loc.Path, int32(num), int32(idx)) return loc } // CommentSet is a set of leading and trailing comments associated // with a .proto descriptor declaration. type CommentSet struct { LeadingDetached []Comments Leading Comments Trailing Comments } func makeCommentSet(loc protoreflect.SourceLocation) CommentSet { var leadingDetached []Comments for _, s := range loc.LeadingDetachedComments { leadingDetached = append(leadingDetached, Comments(s)) } return CommentSet{ LeadingDetached: leadingDetached, Leading: Comments(loc.LeadingComments), Trailing: Comments(loc.TrailingComments), } } // Comments is a comments string as provided by protoc. type Comments string // String formats the comments by inserting // to the start of each line, // ensuring that there is a trailing newline. // An empty comment is formatted as an empty string. func (c Comments) String() string { if c == "" { return "" } var b []byte for _, line := range strings.Split(strings.TrimSuffix(string(c), "\n"), "\n") { b = append(b, "//"...) b = append(b, line...) b = append(b, "\n"...) } return string(b) } ================================================ FILE: _tools/src/google.golang.org/protobuf/encoding/prototext/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package prototext import ( "fmt" "unicode/utf8" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/set" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // Unmarshal reads the given []byte into the given proto.Message. // The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m proto.Message) error { return UnmarshalOptions{}.Unmarshal(b, m) } // UnmarshalOptions is a configurable textproto format unmarshaler. type UnmarshalOptions struct { pragma.NoUnkeyedLiterals // AllowPartial accepts input for messages that will result in missing // required fields. If AllowPartial is false (the default), Unmarshal will // return error if there are any missing required fields. AllowPartial bool // DiscardUnknown specifies whether to ignore unknown fields when parsing. // An unknown field is any field whose field name or field number does not // resolve to any known or extension field in the message. // By default, unmarshal rejects unknown fields as an error. DiscardUnknown bool // Resolver is used for looking up types when unmarshaling // google.protobuf.Any messages or extension fields. // If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.MessageTypeResolver protoregistry.ExtensionTypeResolver } } // Unmarshal reads the given []byte and populates the given proto.Message // using options in the UnmarshalOptions object. // The provided message must be mutable (e.g., a non-nil pointer to a message). func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { return o.unmarshal(b, m) } // unmarshal is a centralized function that all unmarshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { proto.Reset(m) if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } dec := decoder{text.NewDecoder(b), o} if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { return err } if o.AllowPartial { return nil } return proto.CheckInitialized(m) } type decoder struct { *text.Decoder opts UnmarshalOptions } // newError returns an error object with position info. func (d decoder) newError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("(line %d:%d): ", line, column) return errors.New(head+f, x...) } // unexpectedTokenError returns a syntax error for the given unexpected token. func (d decoder) unexpectedTokenError(tok text.Token) error { return d.syntaxError(tok.Pos(), "unexpected token: %s", tok.RawString()) } // syntaxError returns a syntax error for given position. func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) return errors.New(head+f, x...) } // unmarshalMessage unmarshals into the given protoreflect.Message. func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error { messageDesc := m.Descriptor() if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { return errors.New("no support for proto1 MessageSets") } if messageDesc.FullName() == genid.Any_message_fullname { return d.unmarshalAny(m, checkDelims) } if checkDelims { tok, err := d.Read() if err != nil { return err } if tok.Kind() != text.MessageOpen { return d.unexpectedTokenError(tok) } } var seenNums set.Ints var seenOneofs set.Ints fieldDescs := messageDesc.Fields() for { // Read field name. tok, err := d.Read() if err != nil { return err } switch typ := tok.Kind(); typ { case text.Name: // Continue below. case text.EOF: if checkDelims { return text.ErrUnexpectedEOF } return nil default: if checkDelims && typ == text.MessageClose { return nil } return d.unexpectedTokenError(tok) } // Resolve the field descriptor. var name pref.Name var fd pref.FieldDescriptor var xt pref.ExtensionType var xtErr error var isFieldNumberName bool switch tok.NameKind() { case text.IdentName: name = pref.Name(tok.IdentName()) fd = fieldDescs.ByTextName(string(name)) case text.TypeName: // Handle extensions only. This code path is not for Any. xt, xtErr = d.opts.Resolver.FindExtensionByName(pref.FullName(tok.TypeName())) case text.FieldNumber: isFieldNumberName = true num := pref.FieldNumber(tok.FieldNumber()) if !num.IsValid() { return d.newError(tok.Pos(), "invalid field number: %d", num) } fd = fieldDescs.ByNumber(num) if fd == nil { xt, xtErr = d.opts.Resolver.FindExtensionByNumber(messageDesc.FullName(), num) } } if xt != nil { fd = xt.TypeDescriptor() if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) } } else if xtErr != nil && xtErr != protoregistry.NotFound { return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) } if flags.ProtoLegacy { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } } // Handle unknown fields. if fd == nil { if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) { d.skipValue() continue } return d.newError(tok.Pos(), "unknown field: %v", tok.RawString()) } // Handle fields identified by field number. if isFieldNumberName { // TODO: Add an option to permit parsing field numbers. // // This requires careful thought as the MarshalOptions.EmitUnknown // option allows formatting unknown fields as the field number and the // best-effort textual representation of the field value. In that case, // it may not be possible to unmarshal the value from a parser that does // have information about the unknown field. return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString()) } switch { case fd.IsList(): kind := fd.Kind() if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } list := m.Mutable(fd).List() if err := d.unmarshalList(fd, list); err != nil { return err } case fd.IsMap(): mmap := m.Mutable(fd).Map() if err := d.unmarshalMap(fd, mmap); err != nil { return err } default: kind := fd.Kind() if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } // If field is a oneof, check if it has already been set. if od := fd.ContainingOneof(); od != nil { idx := uint64(od.Index()) if seenOneofs.Has(idx) { return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName()) } seenOneofs.Set(idx) } num := uint64(fd.Number()) if seenNums.Has(num) { return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString()) } if err := d.unmarshalSingular(fd, m); err != nil { return err } seenNums.Set(num) } } return nil } // unmarshalSingular unmarshals a non-repeated field value specified by the // given FieldDescriptor. func (d decoder) unmarshalSingular(fd pref.FieldDescriptor, m pref.Message) error { var val pref.Value var err error switch fd.Kind() { case pref.MessageKind, pref.GroupKind: val = m.NewField(fd) err = d.unmarshalMessage(val.Message(), true) default: val, err = d.unmarshalScalar(fd) } if err == nil { m.Set(fd, val) } return err } // unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the // given FieldDescriptor. func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) { tok, err := d.Read() if err != nil { return pref.Value{}, err } if tok.Kind() != text.Scalar { return pref.Value{}, d.unexpectedTokenError(tok) } kind := fd.Kind() switch kind { case pref.BoolKind: if b, ok := tok.Bool(); ok { return pref.ValueOfBool(b), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if n, ok := tok.Int32(); ok { return pref.ValueOfInt32(n), nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if n, ok := tok.Int64(); ok { return pref.ValueOfInt64(n), nil } case pref.Uint32Kind, pref.Fixed32Kind: if n, ok := tok.Uint32(); ok { return pref.ValueOfUint32(n), nil } case pref.Uint64Kind, pref.Fixed64Kind: if n, ok := tok.Uint64(); ok { return pref.ValueOfUint64(n), nil } case pref.FloatKind: if n, ok := tok.Float32(); ok { return pref.ValueOfFloat32(n), nil } case pref.DoubleKind: if n, ok := tok.Float64(); ok { return pref.ValueOfFloat64(n), nil } case pref.StringKind: if s, ok := tok.String(); ok { if strs.EnforceUTF8(fd) && !utf8.ValidString(s) { return pref.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8") } return pref.ValueOfString(s), nil } case pref.BytesKind: if b, ok := tok.String(); ok { return pref.ValueOfBytes([]byte(b)), nil } case pref.EnumKind: if lit, ok := tok.Enum(); ok { // Lookup EnumNumber based on name. if enumVal := fd.Enum().Values().ByName(pref.Name(lit)); enumVal != nil { return pref.ValueOfEnum(enumVal.Number()), nil } } if num, ok := tok.Int32(); ok { return pref.ValueOfEnum(pref.EnumNumber(num)), nil } default: panic(fmt.Sprintf("invalid scalar kind %v", kind)) } return pref.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) } // unmarshalList unmarshals into given protoreflect.List. A list value can // either be in [] syntax or simply just a single scalar/message value. func (d decoder) unmarshalList(fd pref.FieldDescriptor, list pref.List) error { tok, err := d.Peek() if err != nil { return err } switch fd.Kind() { case pref.MessageKind, pref.GroupKind: switch tok.Kind() { case text.ListOpen: d.Read() for { tok, err := d.Peek() if err != nil { return err } switch tok.Kind() { case text.ListClose: d.Read() return nil case text.MessageOpen: pval := list.NewElement() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return err } list.Append(pval) default: return d.unexpectedTokenError(tok) } } case text.MessageOpen: pval := list.NewElement() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return err } list.Append(pval) return nil } default: switch tok.Kind() { case text.ListOpen: d.Read() for { tok, err := d.Peek() if err != nil { return err } switch tok.Kind() { case text.ListClose: d.Read() return nil case text.Scalar: pval, err := d.unmarshalScalar(fd) if err != nil { return err } list.Append(pval) default: return d.unexpectedTokenError(tok) } } case text.Scalar: pval, err := d.unmarshalScalar(fd) if err != nil { return err } list.Append(pval) return nil } } return d.unexpectedTokenError(tok) } // unmarshalMap unmarshals into given protoreflect.Map. A map value is a // textproto message containing {key: , value: }. func (d decoder) unmarshalMap(fd pref.FieldDescriptor, mmap pref.Map) error { // Determine ahead whether map entry is a scalar type or a message type in // order to call the appropriate unmarshalMapValue func inside // unmarshalMapEntry. var unmarshalMapValue func() (pref.Value, error) switch fd.MapValue().Kind() { case pref.MessageKind, pref.GroupKind: unmarshalMapValue = func() (pref.Value, error) { pval := mmap.NewValue() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return pref.Value{}, err } return pval, nil } default: unmarshalMapValue = func() (pref.Value, error) { return d.unmarshalScalar(fd.MapValue()) } } tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.MessageOpen: return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue) case text.ListOpen: for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.ListClose: return nil case text.MessageOpen: if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil { return err } default: return d.unexpectedTokenError(tok) } } default: return d.unexpectedTokenError(tok) } } // unmarshalMap unmarshals into given protoreflect.Map. A map value is a // textproto message containing {key: , value: }. func (d decoder) unmarshalMapEntry(fd pref.FieldDescriptor, mmap pref.Map, unmarshalMapValue func() (pref.Value, error)) error { var key pref.MapKey var pval pref.Value Loop: for { // Read field name. tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.Name: if tok.NameKind() != text.IdentName { if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString()) } d.skipValue() continue Loop } // Continue below. case text.MessageClose: break Loop default: return d.unexpectedTokenError(tok) } switch name := pref.Name(tok.IdentName()); name { case genid.MapEntry_Key_field_name: if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } if key.IsValid() { return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) } val, err := d.unmarshalScalar(fd.MapKey()) if err != nil { return err } key = val.MapKey() case genid.MapEntry_Value_field_name: if kind := fd.MapValue().Kind(); (kind != pref.MessageKind) && (kind != pref.GroupKind) { if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } } if pval.IsValid() { return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) } pval, err = unmarshalMapValue() if err != nil { return err } default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "unknown map entry field %q", name) } d.skipValue() } } if !key.IsValid() { key = fd.MapKey().Default().MapKey() } if !pval.IsValid() { switch fd.MapValue().Kind() { case pref.MessageKind, pref.GroupKind: // If value field is not set for message/group types, construct an // empty one as default. pval = mmap.NewValue() default: pval = fd.MapValue().Default() } } mmap.Set(key, pval) return nil } // unmarshalAny unmarshals an Any textproto. It can either be in expanded form // or non-expanded form. func (d decoder) unmarshalAny(m pref.Message, checkDelims bool) error { var typeURL string var bValue []byte var seenTypeUrl bool var seenValue bool var isExpanded bool if checkDelims { tok, err := d.Read() if err != nil { return err } if tok.Kind() != text.MessageOpen { return d.unexpectedTokenError(tok) } } Loop: for { // Read field name. Can only have 3 possible field names, i.e. type_url, // value and type URL name inside []. tok, err := d.Read() if err != nil { return err } if typ := tok.Kind(); typ != text.Name { if checkDelims { if typ == text.MessageClose { break Loop } } else if typ == text.EOF { break Loop } return d.unexpectedTokenError(tok) } switch tok.NameKind() { case text.IdentName: // Both type_url and value fields require field separator :. if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } switch name := pref.Name(tok.IdentName()); name { case genid.Any_TypeUrl_field_name: if seenTypeUrl { return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname) } if isExpanded { return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) } tok, err := d.Read() if err != nil { return err } var ok bool typeURL, ok = tok.String() if !ok { return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString()) } seenTypeUrl = true case genid.Any_Value_field_name: if seenValue { return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname) } if isExpanded { return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) } tok, err := d.Read() if err != nil { return err } s, ok := tok.String() if !ok { return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString()) } bValue = []byte(s) seenValue = true default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) } } case text.TypeName: if isExpanded { return d.newError(tok.Pos(), "cannot have more than one type") } if seenTypeUrl { return d.newError(tok.Pos(), "conflict with type_url field") } typeURL = tok.TypeName() var err error bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos()) if err != nil { return err } isExpanded = true default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) } } } fds := m.Descriptor().Fields() if len(typeURL) > 0 { m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), pref.ValueOfString(typeURL)) } if len(bValue) > 0 { m.Set(fds.ByNumber(genid.Any_Value_field_number), pref.ValueOfBytes(bValue)) } return nil } func (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) { mt, err := d.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err) } // Create new message for the embedded message type and unmarshal the value // field into it. m := mt.New() if err := d.unmarshalMessage(m, true); err != nil { return nil, err } // Serialize the embedded message and return the resulting bytes. b, err := proto.MarshalOptions{ AllowPartial: true, // Never check required fields inside an Any. Deterministic: true, }.Marshal(m.Interface()) if err != nil { return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err) } return b, nil } // skipValue makes the decoder parse a field value in order to advance the read // to the next field. It relies on Read returning an error if the types are not // in valid sequence. func (d decoder) skipValue() error { tok, err := d.Read() if err != nil { return err } // Only need to continue reading for messages and lists. switch tok.Kind() { case text.MessageOpen: return d.skipMessageValue() case text.ListOpen: for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.ListClose: return nil case text.MessageOpen: return d.skipMessageValue() default: // Skip items. This will not validate whether skipped values are // of the same type or not, same behavior as C++ // TextFormat::Parser::AllowUnknownField(true) version 3.8.0. if err := d.skipValue(); err != nil { return err } } } } return nil } // skipMessageValue makes the decoder parse and skip over all fields in a // message. It assumes that the previous read type is MessageOpen. func (d decoder) skipMessageValue() error { for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.MessageClose: return nil case text.Name: if err := d.skipValue(); err != nil { return err } } } } ================================================ FILE: _tools/src/google.golang.org/protobuf/encoding/prototext/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package prototext marshals and unmarshals protocol buffer messages as the // textproto format. package prototext ================================================ FILE: _tools/src/google.golang.org/protobuf/encoding/prototext/encode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package prototext import ( "fmt" "strconv" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) const defaultIndent = " " // Format formats the message as a multiline string. // This function is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func Format(m proto.Message) string { return MarshalOptions{Multiline: true}.Format(m) } // Marshal writes the given proto.Message in textproto format using default // options. Do not depend on the output being stable. It may change over time // across different versions of the program. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{}.Marshal(m) } // MarshalOptions is a configurable text format marshaler. type MarshalOptions struct { pragma.NoUnkeyedLiterals // Multiline specifies whether the marshaler should format the output in // indented-form with every textual element on a new line. // If Indent is an empty string, then an arbitrary indent is chosen. Multiline bool // Indent specifies the set of indentation characters to use in a multiline // formatted output such that every entry is preceded by Indent and // terminated by a newline. If non-empty, then Multiline is treated as true. // Indent can only be composed of space or tab characters. Indent string // EmitASCII specifies whether to format strings and bytes as ASCII only // as opposed to using UTF-8 encoding when possible. EmitASCII bool // allowInvalidUTF8 specifies whether to permit the encoding of strings // with invalid UTF-8. This is unexported as it is intended to only // be specified by the Format method. allowInvalidUTF8 bool // AllowPartial allows messages that have missing required fields to marshal // without returning an error. If AllowPartial is false (the default), // Marshal will return error if there are any missing required fields. AllowPartial bool // EmitUnknown specifies whether to emit unknown fields in the output. // If specified, the unmarshaler may be unable to parse the output. // The default is to exclude unknown fields. EmitUnknown bool // Resolver is used for looking up types when expanding google.protobuf.Any // messages. If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.ExtensionTypeResolver protoregistry.MessageTypeResolver } } // Format formats the message as a string. // This method is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func (o MarshalOptions) Format(m proto.Message) string { if m == nil || !m.ProtoReflect().IsValid() { return "" // invalid syntax, but okay since this is for debugging } o.allowInvalidUTF8 = true o.AllowPartial = true o.EmitUnknown = true b, _ := o.Marshal(m) return string(b) } // Marshal writes the given proto.Message in textproto format using options in // MarshalOptions object. Do not depend on the output being stable. It may // change over time across different versions of the program. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { return o.marshal(m) } // marshal is a centralized function that all marshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for marshal that do not go through this. func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { var delims = [2]byte{'{', '}'} if o.Multiline && o.Indent == "" { o.Indent = defaultIndent } if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } internalEnc, err := text.NewEncoder(o.Indent, delims, o.EmitASCII) if err != nil { return nil, err } // Treat nil message interface as an empty message, // in which case there is nothing to output. if m == nil { return []byte{}, nil } enc := encoder{internalEnc, o} err = enc.marshalMessage(m.ProtoReflect(), false) if err != nil { return nil, err } out := enc.Bytes() if len(o.Indent) > 0 && len(out) > 0 { out = append(out, '\n') } if o.AllowPartial { return out, nil } return out, proto.CheckInitialized(m) } type encoder struct { *text.Encoder opts MarshalOptions } // marshalMessage marshals the given protoreflect.Message. func (e encoder) marshalMessage(m pref.Message, inclDelims bool) error { messageDesc := m.Descriptor() if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { return errors.New("no support for proto1 MessageSets") } if inclDelims { e.StartMessage() defer e.EndMessage() } // Handle Any expansion. if messageDesc.FullName() == genid.Any_message_fullname { if e.marshalAny(m) { return nil } // If unable to expand, continue on to marshal Any as a regular message. } // Marshal fields. var err error order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { if err = e.marshalField(fd.TextName(), v, fd); err != nil { return false } return true }) if err != nil { return err } // Marshal unknown fields. if e.opts.EmitUnknown { e.marshalUnknown(m.GetUnknown()) } return nil } // marshalField marshals the given field with protoreflect.Value. func (e encoder) marshalField(name string, val pref.Value, fd pref.FieldDescriptor) error { switch { case fd.IsList(): return e.marshalList(name, val.List(), fd) case fd.IsMap(): return e.marshalMap(name, val.Map(), fd) default: e.WriteName(name) return e.marshalSingular(val, fd) } } // marshalSingular marshals the given non-repeated field value. This includes // all scalar types, enums, messages, and groups. func (e encoder) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error { kind := fd.Kind() switch kind { case pref.BoolKind: e.WriteBool(val.Bool()) case pref.StringKind: s := val.String() if !e.opts.allowInvalidUTF8 && strs.EnforceUTF8(fd) && !utf8.ValidString(s) { return errors.InvalidUTF8(string(fd.FullName())) } e.WriteString(s) case pref.Int32Kind, pref.Int64Kind, pref.Sint32Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: e.WriteInt(val.Int()) case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: e.WriteUint(val.Uint()) case pref.FloatKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 32) case pref.DoubleKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 64) case pref.BytesKind: e.WriteString(string(val.Bytes())) case pref.EnumKind: num := val.Enum() if desc := fd.Enum().Values().ByNumber(num); desc != nil { e.WriteLiteral(string(desc.Name())) } else { // Use numeric value if there is no enum description. e.WriteInt(int64(num)) } case pref.MessageKind, pref.GroupKind: return e.marshalMessage(val.Message(), true) default: panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind)) } return nil } // marshalList marshals the given protoreflect.List as multiple name-value fields. func (e encoder) marshalList(name string, list pref.List, fd pref.FieldDescriptor) error { size := list.Len() for i := 0; i < size; i++ { e.WriteName(name) if err := e.marshalSingular(list.Get(i), fd); err != nil { return err } } return nil } // marshalMap marshals the given protoreflect.Map as multiple name-value fields. func (e encoder) marshalMap(name string, mmap pref.Map, fd pref.FieldDescriptor) error { var err error order.RangeEntries(mmap, order.GenericKeyOrder, func(key pref.MapKey, val pref.Value) bool { e.WriteName(name) e.StartMessage() defer e.EndMessage() e.WriteName(string(genid.MapEntry_Key_field_name)) err = e.marshalSingular(key.Value(), fd.MapKey()) if err != nil { return false } e.WriteName(string(genid.MapEntry_Value_field_name)) err = e.marshalSingular(val, fd.MapValue()) if err != nil { return false } return true }) return err } // marshalUnknown parses the given []byte and marshals fields out. // This function assumes proper encoding in the given []byte. func (e encoder) marshalUnknown(b []byte) { const dec = 10 const hex = 16 for len(b) > 0 { num, wtype, n := protowire.ConsumeTag(b) b = b[n:] e.WriteName(strconv.FormatInt(int64(num), dec)) switch wtype { case protowire.VarintType: var v uint64 v, n = protowire.ConsumeVarint(b) e.WriteUint(v) case protowire.Fixed32Type: var v uint32 v, n = protowire.ConsumeFixed32(b) e.WriteLiteral("0x" + strconv.FormatUint(uint64(v), hex)) case protowire.Fixed64Type: var v uint64 v, n = protowire.ConsumeFixed64(b) e.WriteLiteral("0x" + strconv.FormatUint(v, hex)) case protowire.BytesType: var v []byte v, n = protowire.ConsumeBytes(b) e.WriteString(string(v)) case protowire.StartGroupType: e.StartMessage() var v []byte v, n = protowire.ConsumeGroup(num, b) e.marshalUnknown(v) e.EndMessage() default: panic(fmt.Sprintf("prototext: error parsing unknown field wire type: %v", wtype)) } b = b[n:] } } // marshalAny marshals the given google.protobuf.Any message in expanded form. // It returns true if it was able to marshal, else false. func (e encoder) marshalAny(any pref.Message) bool { // Construct the embedded message. fds := any.Descriptor().Fields() fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) typeURL := any.Get(fdType).String() mt, err := e.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return false } m := mt.New().Interface() // Unmarshal bytes into embedded message. fdValue := fds.ByNumber(genid.Any_Value_field_number) value := any.Get(fdValue) err = proto.UnmarshalOptions{ AllowPartial: true, Resolver: e.opts.Resolver, }.Unmarshal(value.Bytes(), m) if err != nil { return false } // Get current encoder position. If marshaling fails, reset encoder output // back to this position. pos := e.Snapshot() // Field name is the proto field name enclosed in []. e.WriteName("[" + typeURL + "]") err = e.marshalMessage(m.ProtoReflect(), true) if err != nil { e.Reset(pos) return false } return true } ================================================ FILE: _tools/src/google.golang.org/protobuf/encoding/protowire/wire.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protowire parses and formats the raw wire encoding. // See https://developers.google.com/protocol-buffers/docs/encoding. // // For marshaling and unmarshaling entire protobuf messages, // use the "google.golang.org/protobuf/proto" package instead. package protowire import ( "io" "math" "math/bits" "google.golang.org/protobuf/internal/errors" ) // Number represents the field number. type Number int32 const ( MinValidNumber Number = 1 FirstReservedNumber Number = 19000 LastReservedNumber Number = 19999 MaxValidNumber Number = 1<<29 - 1 ) // IsValid reports whether the field number is semantically valid. // // Note that while numbers within the reserved range are semantically invalid, // they are syntactically valid in the wire format. // Implementations may treat records with reserved field numbers as unknown. func (n Number) IsValid() bool { return MinValidNumber <= n && n < FirstReservedNumber || LastReservedNumber < n && n <= MaxValidNumber } // Type represents the wire type. type Type int8 const ( VarintType Type = 0 Fixed32Type Type = 5 Fixed64Type Type = 1 BytesType Type = 2 StartGroupType Type = 3 EndGroupType Type = 4 ) const ( _ = -iota errCodeTruncated errCodeFieldNumber errCodeOverflow errCodeReserved errCodeEndGroup ) var ( errFieldNumber = errors.New("invalid field number") errOverflow = errors.New("variable length integer overflow") errReserved = errors.New("cannot parse reserved wire type") errEndGroup = errors.New("mismatching end group marker") errParse = errors.New("parse error") ) // ParseError converts an error code into an error value. // This returns nil if n is a non-negative number. func ParseError(n int) error { if n >= 0 { return nil } switch n { case errCodeTruncated: return io.ErrUnexpectedEOF case errCodeFieldNumber: return errFieldNumber case errCodeOverflow: return errOverflow case errCodeReserved: return errReserved case errCodeEndGroup: return errEndGroup default: return errParse } } // ConsumeField parses an entire field record (both tag and value) and returns // the field number, the wire type, and the total length. // This returns a negative length upon an error (see ParseError). // // The total length includes the tag header and the end group marker (if the // field is a group). func ConsumeField(b []byte) (Number, Type, int) { num, typ, n := ConsumeTag(b) if n < 0 { return 0, 0, n // forward error code } m := ConsumeFieldValue(num, typ, b[n:]) if m < 0 { return 0, 0, m // forward error code } return num, typ, n + m } // ConsumeFieldValue parses a field value and returns its length. // This assumes that the field Number and wire Type have already been parsed. // This returns a negative length upon an error (see ParseError). // // When parsing a group, the length includes the end group marker and // the end group is verified to match the starting field number. func ConsumeFieldValue(num Number, typ Type, b []byte) (n int) { switch typ { case VarintType: _, n = ConsumeVarint(b) return n case Fixed32Type: _, n = ConsumeFixed32(b) return n case Fixed64Type: _, n = ConsumeFixed64(b) return n case BytesType: _, n = ConsumeBytes(b) return n case StartGroupType: n0 := len(b) for { num2, typ2, n := ConsumeTag(b) if n < 0 { return n // forward error code } b = b[n:] if typ2 == EndGroupType { if num != num2 { return errCodeEndGroup } return n0 - len(b) } n = ConsumeFieldValue(num2, typ2, b) if n < 0 { return n // forward error code } b = b[n:] } case EndGroupType: return errCodeEndGroup default: return errCodeReserved } } // AppendTag encodes num and typ as a varint-encoded tag and appends it to b. func AppendTag(b []byte, num Number, typ Type) []byte { return AppendVarint(b, EncodeTag(num, typ)) } // ConsumeTag parses b as a varint-encoded tag, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeTag(b []byte) (Number, Type, int) { v, n := ConsumeVarint(b) if n < 0 { return 0, 0, n // forward error code } num, typ := DecodeTag(v) if num < MinValidNumber { return 0, 0, errCodeFieldNumber } return num, typ, n } func SizeTag(num Number) int { return SizeVarint(EncodeTag(num, 0)) // wire type has no effect on size } // AppendVarint appends v to b as a varint-encoded uint64. func AppendVarint(b []byte, v uint64) []byte { switch { case v < 1<<7: b = append(b, byte(v)) case v < 1<<14: b = append(b, byte((v>>0)&0x7f|0x80), byte(v>>7)) case v < 1<<21: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte(v>>14)) case v < 1<<28: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte(v>>21)) case v < 1<<35: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte(v>>28)) case v < 1<<42: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte(v>>35)) case v < 1<<49: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte(v>>42)) case v < 1<<56: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte(v>>49)) case v < 1<<63: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte((v>>49)&0x7f|0x80), byte(v>>56)) default: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte((v>>49)&0x7f|0x80), byte((v>>56)&0x7f|0x80), 1) } return b } // ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeVarint(b []byte) (v uint64, n int) { var y uint64 if len(b) <= 0 { return 0, errCodeTruncated } v = uint64(b[0]) if v < 0x80 { return v, 1 } v -= 0x80 if len(b) <= 1 { return 0, errCodeTruncated } y = uint64(b[1]) v += y << 7 if y < 0x80 { return v, 2 } v -= 0x80 << 7 if len(b) <= 2 { return 0, errCodeTruncated } y = uint64(b[2]) v += y << 14 if y < 0x80 { return v, 3 } v -= 0x80 << 14 if len(b) <= 3 { return 0, errCodeTruncated } y = uint64(b[3]) v += y << 21 if y < 0x80 { return v, 4 } v -= 0x80 << 21 if len(b) <= 4 { return 0, errCodeTruncated } y = uint64(b[4]) v += y << 28 if y < 0x80 { return v, 5 } v -= 0x80 << 28 if len(b) <= 5 { return 0, errCodeTruncated } y = uint64(b[5]) v += y << 35 if y < 0x80 { return v, 6 } v -= 0x80 << 35 if len(b) <= 6 { return 0, errCodeTruncated } y = uint64(b[6]) v += y << 42 if y < 0x80 { return v, 7 } v -= 0x80 << 42 if len(b) <= 7 { return 0, errCodeTruncated } y = uint64(b[7]) v += y << 49 if y < 0x80 { return v, 8 } v -= 0x80 << 49 if len(b) <= 8 { return 0, errCodeTruncated } y = uint64(b[8]) v += y << 56 if y < 0x80 { return v, 9 } v -= 0x80 << 56 if len(b) <= 9 { return 0, errCodeTruncated } y = uint64(b[9]) v += y << 63 if y < 2 { return v, 10 } return 0, errCodeOverflow } // SizeVarint returns the encoded size of a varint. // The size is guaranteed to be within 1 and 10, inclusive. func SizeVarint(v uint64) int { // This computes 1 + (bits.Len64(v)-1)/7. // 9/64 is a good enough approximation of 1/7 return int(9*uint32(bits.Len64(v))+64) / 64 } // AppendFixed32 appends v to b as a little-endian uint32. func AppendFixed32(b []byte, v uint32) []byte { return append(b, byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24)) } // ConsumeFixed32 parses b as a little-endian uint32, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeFixed32(b []byte) (v uint32, n int) { if len(b) < 4 { return 0, errCodeTruncated } v = uint32(b[0])<<0 | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 return v, 4 } // SizeFixed32 returns the encoded size of a fixed32; which is always 4. func SizeFixed32() int { return 4 } // AppendFixed64 appends v to b as a little-endian uint64. func AppendFixed64(b []byte, v uint64) []byte { return append(b, byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24), byte(v>>32), byte(v>>40), byte(v>>48), byte(v>>56)) } // ConsumeFixed64 parses b as a little-endian uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeFixed64(b []byte) (v uint64, n int) { if len(b) < 8 { return 0, errCodeTruncated } v = uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 return v, 8 } // SizeFixed64 returns the encoded size of a fixed64; which is always 8. func SizeFixed64() int { return 8 } // AppendBytes appends v to b as a length-prefixed bytes value. func AppendBytes(b []byte, v []byte) []byte { return append(AppendVarint(b, uint64(len(v))), v...) } // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeBytes(b []byte) (v []byte, n int) { m, n := ConsumeVarint(b) if n < 0 { return nil, n // forward error code } if m > uint64(len(b[n:])) { return nil, errCodeTruncated } return b[n:][:m], n + int(m) } // SizeBytes returns the encoded size of a length-prefixed bytes value, // given only the length. func SizeBytes(n int) int { return SizeVarint(uint64(n)) + n } // AppendString appends v to b as a length-prefixed bytes value. func AppendString(b []byte, v string) []byte { return append(AppendVarint(b, uint64(len(v))), v...) } // ConsumeString parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeString(b []byte) (v string, n int) { bb, n := ConsumeBytes(b) return string(bb), n } // AppendGroup appends v to b as group value, with a trailing end group marker. // The value v must not contain the end marker. func AppendGroup(b []byte, num Number, v []byte) []byte { return AppendVarint(append(b, v...), EncodeTag(num, EndGroupType)) } // ConsumeGroup parses b as a group value until the trailing end group marker, // and verifies that the end marker matches the provided num. The value v // does not contain the end marker, while the length does contain the end marker. // This returns a negative length upon an error (see ParseError). func ConsumeGroup(num Number, b []byte) (v []byte, n int) { n = ConsumeFieldValue(num, StartGroupType, b) if n < 0 { return nil, n // forward error code } b = b[:n] // Truncate off end group marker, but need to handle denormalized varints. // Assuming end marker is never 0 (which is always the case since // EndGroupType is non-zero), we can truncate all trailing bytes where the // lower 7 bits are all zero (implying that the varint is denormalized). for len(b) > 0 && b[len(b)-1]&0x7f == 0 { b = b[:len(b)-1] } b = b[:len(b)-SizeTag(num)] return b, n } // SizeGroup returns the encoded size of a group, given only the length. func SizeGroup(num Number, n int) int { return n + SizeTag(num) } // DecodeTag decodes the field Number and wire Type from its unified form. // The Number is -1 if the decoded field number overflows int32. // Other than overflow, this does not check for field number validity. func DecodeTag(x uint64) (Number, Type) { // NOTE: MessageSet allows for larger field numbers than normal. if x>>3 > uint64(math.MaxInt32) { return -1, 0 } return Number(x >> 3), Type(x & 7) } // EncodeTag encodes the field Number and wire Type into its unified form. func EncodeTag(num Number, typ Type) uint64 { return uint64(num)<<3 | uint64(typ&7) } // DecodeZigZag decodes a zig-zag-encoded uint64 as an int64. // Input: {…, 5, 3, 1, 0, 2, 4, 6, …} // Output: {…, -3, -2, -1, 0, +1, +2, +3, …} func DecodeZigZag(x uint64) int64 { return int64(x>>1) ^ int64(x)<<63>>63 } // EncodeZigZag encodes an int64 as a zig-zag-encoded uint64. // Input: {…, -3, -2, -1, 0, +1, +2, +3, …} // Output: {…, 5, 3, 1, 0, 2, 4, 6, …} func EncodeZigZag(x int64) uint64 { return uint64(x<<1) ^ uint64(x>>63) } // DecodeBool decodes a uint64 as a bool. // Input: { 0, 1, 2, …} // Output: {false, true, true, …} func DecodeBool(x uint64) bool { return x != 0 } // EncodeBool encodes a bool as a uint64. // Input: {false, true} // Output: { 0, 1} func EncodeBool(x bool) uint64 { if x { return 1 } return 0 } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/descfmt/stringer.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package descfmt provides functionality to format descriptors. package descfmt import ( "fmt" "io" "reflect" "strconv" "strings" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) type list interface { Len() int pragma.DoNotImplement } func FormatList(s fmt.State, r rune, vs list) { io.WriteString(s, formatListOpt(vs, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) } func formatListOpt(vs list, isRoot, allowMulti bool) string { start, end := "[", "]" if isRoot { var name string switch vs.(type) { case pref.Names: name = "Names" case pref.FieldNumbers: name = "FieldNumbers" case pref.FieldRanges: name = "FieldRanges" case pref.EnumRanges: name = "EnumRanges" case pref.FileImports: name = "FileImports" case pref.Descriptor: name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s" default: name = reflect.ValueOf(vs).Elem().Type().Name() } start, end = name+"{", "}" } var ss []string switch vs := vs.(type) { case pref.Names: for i := 0; i < vs.Len(); i++ { ss = append(ss, fmt.Sprint(vs.Get(i))) } return start + joinStrings(ss, false) + end case pref.FieldNumbers: for i := 0; i < vs.Len(); i++ { ss = append(ss, fmt.Sprint(vs.Get(i))) } return start + joinStrings(ss, false) + end case pref.FieldRanges: for i := 0; i < vs.Len(); i++ { r := vs.Get(i) if r[0]+1 == r[1] { ss = append(ss, fmt.Sprintf("%d", r[0])) } else { ss = append(ss, fmt.Sprintf("%d:%d", r[0], r[1])) // enum ranges are end exclusive } } return start + joinStrings(ss, false) + end case pref.EnumRanges: for i := 0; i < vs.Len(); i++ { r := vs.Get(i) if r[0] == r[1] { ss = append(ss, fmt.Sprintf("%d", r[0])) } else { ss = append(ss, fmt.Sprintf("%d:%d", r[0], int64(r[1])+1)) // enum ranges are end inclusive } } return start + joinStrings(ss, false) + end case pref.FileImports: for i := 0; i < vs.Len(); i++ { var rs records rs.Append(reflect.ValueOf(vs.Get(i)), "Path", "Package", "IsPublic", "IsWeak") ss = append(ss, "{"+rs.Join()+"}") } return start + joinStrings(ss, allowMulti) + end default: _, isEnumValue := vs.(pref.EnumValueDescriptors) for i := 0; i < vs.Len(); i++ { m := reflect.ValueOf(vs).MethodByName("Get") v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface() ss = append(ss, formatDescOpt(v.(pref.Descriptor), false, allowMulti && !isEnumValue)) } return start + joinStrings(ss, allowMulti && isEnumValue) + end } } // descriptorAccessors is a list of accessors to print for each descriptor. // // Do not print all accessors since some contain redundant information, // while others are pointers that we do not want to follow since the descriptor // is actually a cyclic graph. // // Using a list allows us to print the accessors in a sensible order. var descriptorAccessors = map[reflect.Type][]string{ reflect.TypeOf((*pref.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"}, reflect.TypeOf((*pref.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"}, reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"}, reflect.TypeOf((*pref.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt reflect.TypeOf((*pref.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"}, reflect.TypeOf((*pref.EnumValueDescriptor)(nil)).Elem(): {"Number"}, reflect.TypeOf((*pref.ServiceDescriptor)(nil)).Elem(): {"Methods"}, reflect.TypeOf((*pref.MethodDescriptor)(nil)).Elem(): {"Input", "Output", "IsStreamingClient", "IsStreamingServer"}, } func FormatDesc(s fmt.State, r rune, t pref.Descriptor) { io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) } func formatDescOpt(t pref.Descriptor, isRoot, allowMulti bool) string { rv := reflect.ValueOf(t) rt := rv.MethodByName("ProtoType").Type().In(0) start, end := "{", "}" if isRoot { start = rt.Name() + "{" } _, isFile := t.(pref.FileDescriptor) rs := records{allowMulti: allowMulti} if t.IsPlaceholder() { if isFile { rs.Append(rv, "Path", "Package", "IsPlaceholder") } else { rs.Append(rv, "FullName", "IsPlaceholder") } } else { switch { case isFile: rs.Append(rv, "Syntax") case isRoot: rs.Append(rv, "Syntax", "FullName") default: rs.Append(rv, "Name") } switch t := t.(type) { case pref.FieldDescriptor: for _, s := range descriptorAccessors[rt] { switch s { case "MapKey": if k := t.MapKey(); k != nil { rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()}) } case "MapValue": if v := t.MapValue(); v != nil { switch v.Kind() { case pref.EnumKind: rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())}) case pref.MessageKind, pref.GroupKind: rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())}) default: rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()}) } } case "ContainingOneof": if od := t.ContainingOneof(); od != nil { rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())}) } case "ContainingMessage": if t.IsExtension() { rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())}) } case "Message": if !t.IsMap() { rs.Append(rv, s) } default: rs.Append(rv, s) } } case pref.OneofDescriptor: var ss []string fs := t.Fields() for i := 0; i < fs.Len(); i++ { ss = append(ss, string(fs.Get(i).Name())) } if len(ss) > 0 { rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"}) } default: rs.Append(rv, descriptorAccessors[rt]...) } if rv.MethodByName("GoType").IsValid() { rs.Append(rv, "GoType") } } return start + rs.Join() + end } type records struct { recs [][2]string allowMulti bool } func (rs *records) Append(v reflect.Value, accessors ...string) { for _, a := range accessors { var rv reflect.Value if m := v.MethodByName(a); m.IsValid() { rv = m.Call(nil)[0] } if v.Kind() == reflect.Struct && !rv.IsValid() { rv = v.FieldByName(a) } if !rv.IsValid() { panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a)) } if _, ok := rv.Interface().(pref.Value); ok { rv = rv.MethodByName("Interface").Call(nil)[0] if !rv.IsNil() { rv = rv.Elem() } } // Ignore zero values. var isZero bool switch rv.Kind() { case reflect.Interface, reflect.Slice: isZero = rv.IsNil() case reflect.Bool: isZero = rv.Bool() == false case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: isZero = rv.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: isZero = rv.Uint() == 0 case reflect.String: isZero = rv.String() == "" } if n, ok := rv.Interface().(list); ok { isZero = n.Len() == 0 } if isZero { continue } // Format the value. var s string v := rv.Interface() switch v := v.(type) { case list: s = formatListOpt(v, false, rs.allowMulti) case pref.FieldDescriptor, pref.OneofDescriptor, pref.EnumValueDescriptor, pref.MethodDescriptor: s = string(v.(pref.Descriptor).Name()) case pref.Descriptor: s = string(v.FullName()) case string: s = strconv.Quote(v) case []byte: s = fmt.Sprintf("%q", v) default: s = fmt.Sprint(v) } rs.recs = append(rs.recs, [2]string{a, s}) } } func (rs *records) Join() string { var ss []string // In single line mode, simply join all records with commas. if !rs.allowMulti { for _, r := range rs.recs { ss = append(ss, r[0]+formatColon(0)+r[1]) } return joinStrings(ss, false) } // In allowMulti line mode, align single line records for more readable output. var maxLen int flush := func(i int) { for _, r := range rs.recs[len(ss):i] { ss = append(ss, r[0]+formatColon(maxLen-len(r[0]))+r[1]) } maxLen = 0 } for i, r := range rs.recs { if isMulti := strings.Contains(r[1], "\n"); isMulti { flush(i) ss = append(ss, r[0]+formatColon(0)+strings.Join(strings.Split(r[1], "\n"), "\n\t")) } else if maxLen < len(r[0]) { maxLen = len(r[0]) } } flush(len(rs.recs)) return joinStrings(ss, true) } func formatColon(padding int) string { // Deliberately introduce instability into the debug output to // discourage users from performing string comparisons. // This provides us flexibility to change the output in the future. if detrand.Bool() { return ":" + strings.Repeat(" ", 1+padding) // use non-breaking spaces (U+00a0) } else { return ":" + strings.Repeat(" ", 1+padding) // use regular spaces (U+0020) } } func joinStrings(ss []string, isMulti bool) string { if len(ss) == 0 { return "" } if isMulti { return "\n\t" + strings.Join(ss, "\n\t") + "\n" } return strings.Join(ss, ", ") } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/descopts/options.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package descopts contains the nil pointers to concrete descriptor options. // // This package exists as a form of reverse dependency injection so that certain // packages (e.g., internal/filedesc and internal/filetype can avoid a direct // dependency on the descriptor proto package). package descopts import pref "google.golang.org/protobuf/reflect/protoreflect" // These variables are set by the init function in descriptor.pb.go via logic // in internal/filetype. In other words, so long as the descriptor proto package // is linked in, these variables will be populated. // // Each variable is populated with a nil pointer to the options struct. var ( File pref.ProtoMessage Enum pref.ProtoMessage EnumValue pref.ProtoMessage Message pref.ProtoMessage Field pref.ProtoMessage Oneof pref.ProtoMessage ExtensionRange pref.ProtoMessage Service pref.ProtoMessage Method pref.ProtoMessage ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/detrand/rand.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package detrand provides deterministically random functionality. // // The pseudo-randomness of these functions is seeded by the program binary // itself and guarantees that the output does not change within a program, // while ensuring that the output is unstable across different builds. package detrand import ( "encoding/binary" "hash/fnv" "os" ) // Disable disables detrand such that all functions returns the zero value. // This function is not concurrent-safe and must be called during program init. func Disable() { randSeed = 0 } // Bool returns a deterministically random boolean. func Bool() bool { return randSeed%2 == 1 } // Intn returns a deterministically random integer between 0 and n-1, inclusive. func Intn(n int) int { if n <= 0 { panic("must be positive") } return int(randSeed % uint64(n)) } // randSeed is a best-effort at an approximate hash of the Go binary. var randSeed = binaryHash() func binaryHash() uint64 { // Open the Go binary. s, err := os.Executable() if err != nil { return 0 } f, err := os.Open(s) if err != nil { return 0 } defer f.Close() // Hash the size and several samples of the Go binary. const numSamples = 8 var buf [64]byte h := fnv.New64() fi, err := f.Stat() if err != nil { return 0 } binary.LittleEndian.PutUint64(buf[:8], uint64(fi.Size())) h.Write(buf[:8]) for i := int64(0); i < numSamples; i++ { if _, err := f.ReadAt(buf[:], i*fi.Size()/numSamples); err != nil { return 0 } h.Write(buf[:]) } return h.Sum64() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/defval/default.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package defval marshals and unmarshals textual forms of default values. // // This package handles both the form historically used in Go struct field tags // and also the form used by google.protobuf.FieldDescriptorProto.default_value // since they differ in superficial ways. package defval import ( "fmt" "math" "strconv" ptext "google.golang.org/protobuf/internal/encoding/text" errors "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) // Format is the serialization format used to represent the default value. type Format int const ( _ Format = iota // Descriptor uses the serialization format that protoc uses with the // google.protobuf.FieldDescriptorProto.default_value field. Descriptor // GoTag uses the historical serialization format in Go struct field tags. GoTag ) // Unmarshal deserializes the default string s according to the given kind k. // When k is an enum, a list of enum value descriptors must be provided. func Unmarshal(s string, k pref.Kind, evs pref.EnumValueDescriptors, f Format) (pref.Value, pref.EnumValueDescriptor, error) { switch k { case pref.BoolKind: if f == GoTag { switch s { case "1": return pref.ValueOfBool(true), nil, nil case "0": return pref.ValueOfBool(false), nil, nil } } else { switch s { case "true": return pref.ValueOfBool(true), nil, nil case "false": return pref.ValueOfBool(false), nil, nil } } case pref.EnumKind: if f == GoTag { // Go tags use the numeric form of the enum value. if n, err := strconv.ParseInt(s, 10, 32); err == nil { if ev := evs.ByNumber(pref.EnumNumber(n)); ev != nil { return pref.ValueOfEnum(ev.Number()), ev, nil } } } else { // Descriptor default_value use the enum identifier. ev := evs.ByName(pref.Name(s)) if ev != nil { return pref.ValueOfEnum(ev.Number()), ev, nil } } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if v, err := strconv.ParseInt(s, 10, 32); err == nil { return pref.ValueOfInt32(int32(v)), nil, nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if v, err := strconv.ParseInt(s, 10, 64); err == nil { return pref.ValueOfInt64(int64(v)), nil, nil } case pref.Uint32Kind, pref.Fixed32Kind: if v, err := strconv.ParseUint(s, 10, 32); err == nil { return pref.ValueOfUint32(uint32(v)), nil, nil } case pref.Uint64Kind, pref.Fixed64Kind: if v, err := strconv.ParseUint(s, 10, 64); err == nil { return pref.ValueOfUint64(uint64(v)), nil, nil } case pref.FloatKind, pref.DoubleKind: var v float64 var err error switch s { case "-inf": v = math.Inf(-1) case "inf": v = math.Inf(+1) case "nan": v = math.NaN() default: v, err = strconv.ParseFloat(s, 64) } if err == nil { if k == pref.FloatKind { return pref.ValueOfFloat32(float32(v)), nil, nil } else { return pref.ValueOfFloat64(float64(v)), nil, nil } } case pref.StringKind: // String values are already unescaped and can be used as is. return pref.ValueOfString(s), nil, nil case pref.BytesKind: if b, ok := unmarshalBytes(s); ok { return pref.ValueOfBytes(b), nil, nil } } return pref.Value{}, nil, errors.New("could not parse value for %v: %q", k, s) } // Marshal serializes v as the default string according to the given kind k. // When specifying the Descriptor format for an enum kind, the associated // enum value descriptor must be provided. func Marshal(v pref.Value, ev pref.EnumValueDescriptor, k pref.Kind, f Format) (string, error) { switch k { case pref.BoolKind: if f == GoTag { if v.Bool() { return "1", nil } else { return "0", nil } } else { if v.Bool() { return "true", nil } else { return "false", nil } } case pref.EnumKind: if f == GoTag { return strconv.FormatInt(int64(v.Enum()), 10), nil } else { return string(ev.Name()), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: return strconv.FormatInt(v.Int(), 10), nil case pref.Uint32Kind, pref.Fixed32Kind, pref.Uint64Kind, pref.Fixed64Kind: return strconv.FormatUint(v.Uint(), 10), nil case pref.FloatKind, pref.DoubleKind: f := v.Float() switch { case math.IsInf(f, -1): return "-inf", nil case math.IsInf(f, +1): return "inf", nil case math.IsNaN(f): return "nan", nil default: if k == pref.FloatKind { return strconv.FormatFloat(f, 'g', -1, 32), nil } else { return strconv.FormatFloat(f, 'g', -1, 64), nil } } case pref.StringKind: // String values are serialized as is without any escaping. return v.String(), nil case pref.BytesKind: if s, ok := marshalBytes(v.Bytes()); ok { return s, nil } } return "", errors.New("could not format value for %v: %v", k, v) } // unmarshalBytes deserializes bytes by applying C unescaping. func unmarshalBytes(s string) ([]byte, bool) { // Bytes values use the same escaping as the text format, // however they lack the surrounding double quotes. v, err := ptext.UnmarshalString(`"` + s + `"`) if err != nil { return nil, false } return []byte(v), true } // marshalBytes serializes bytes by using C escaping. // To match the exact output of protoc, this is identical to the // CEscape function in strutil.cc of the protoc source code. func marshalBytes(b []byte) (string, bool) { var s []byte for _, c := range b { switch c { case '\n': s = append(s, `\n`...) case '\r': s = append(s, `\r`...) case '\t': s = append(s, `\t`...) case '"': s = append(s, `\"`...) case '\'': s = append(s, `\'`...) case '\\': s = append(s, `\\`...) default: if printableASCII := c >= 0x20 && c <= 0x7e; printableASCII { s = append(s, c) } else { s = append(s, fmt.Sprintf(`\%03o`, c)...) } } } return string(s), true } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/messageset/messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package messageset encodes and decodes the obsolete MessageSet wire format. package messageset import ( "math" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) // The MessageSet wire format is equivalent to a message defined as follows, // where each Item defines an extension field with a field number of 'type_id' // and content of 'message'. MessageSet extensions must be non-repeated message // fields. // // message MessageSet { // repeated group Item = 1 { // required int32 type_id = 2; // required string message = 3; // } // } const ( FieldItem = protowire.Number(1) FieldTypeID = protowire.Number(2) FieldMessage = protowire.Number(3) ) // ExtensionName is the field name for extensions of MessageSet. // // A valid MessageSet extension must be of the form: // message MyMessage { // extend proto2.bridge.MessageSet { // optional MyMessage message_set_extension = 1234; // } // ... // } const ExtensionName = "message_set_extension" // IsMessageSet returns whether the message uses the MessageSet wire format. func IsMessageSet(md pref.MessageDescriptor) bool { xmd, ok := md.(interface{ IsMessageSet() bool }) return ok && xmd.IsMessageSet() } // IsMessageSetExtension reports this field properly extends a MessageSet. func IsMessageSetExtension(fd pref.FieldDescriptor) bool { switch { case fd.Name() != ExtensionName: return false case !IsMessageSet(fd.ContainingMessage()): return false case fd.FullName().Parent() != fd.Message().FullName(): return false } return true } // SizeField returns the size of a MessageSet item field containing an extension // with the given field number, not counting the contents of the message subfield. func SizeField(num protowire.Number) int { return 2*protowire.SizeTag(FieldItem) + protowire.SizeTag(FieldTypeID) + protowire.SizeVarint(uint64(num)) } // Unmarshal parses a MessageSet. // // It calls fn with the type ID and value of each item in the MessageSet. // Unknown fields are discarded. // // If wantLen is true, the item values include the varint length prefix. // This is ugly, but simplifies the fast-path decoder in internal/impl. func Unmarshal(b []byte, wantLen bool, fn func(typeID protowire.Number, value []byte) error) error { for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return protowire.ParseError(n) } b = b[n:] if num != FieldItem || wtyp != protowire.StartGroupType { n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return protowire.ParseError(n) } b = b[n:] continue } typeID, value, n, err := ConsumeFieldValue(b, wantLen) if err != nil { return err } b = b[n:] if typeID == 0 { continue } if err := fn(typeID, value); err != nil { return err } } return nil } // ConsumeFieldValue parses b as a MessageSet item field value until and including // the trailing end group marker. It assumes the start group tag has already been parsed. // It returns the contents of the type_id and message subfields and the total // item length. // // If wantLen is true, the returned message value includes the length prefix. func ConsumeFieldValue(b []byte, wantLen bool) (typeid protowire.Number, message []byte, n int, err error) { ilen := len(b) for { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] switch { case num == FieldItem && wtyp == protowire.EndGroupType: if wantLen && len(message) == 0 { // The message field was missing, which should never happen. // Be prepared for this case anyway. message = protowire.AppendVarint(message, 0) } return typeid, message, ilen - len(b), nil case num == FieldTypeID && wtyp == protowire.VarintType: v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] if v < 1 || v > math.MaxInt32 { return 0, nil, 0, errors.New("invalid type_id in message set") } typeid = protowire.Number(v) case num == FieldMessage && wtyp == protowire.BytesType: m, n := protowire.ConsumeBytes(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } if message == nil { if wantLen { message = b[:n:n] } else { message = m[:len(m):len(m)] } } else { // This case should never happen in practice, but handle it for // correctness: The MessageSet item contains multiple message // fields, which need to be merged. // // In the case where we're returning the length, this becomes // quite inefficient since we need to strip the length off // the existing data and reconstruct it with the combined length. if wantLen { _, nn := protowire.ConsumeVarint(message) m0 := message[nn:] message = nil message = protowire.AppendVarint(message, uint64(len(m0)+len(m))) message = append(message, m0...) message = append(message, m...) } else { message = append(message, m...) } } b = b[n:] default: // We have no place to put it, so we just ignore unknown fields. n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] } } } // AppendFieldStart appends the start of a MessageSet item field containing // an extension with the given number. The caller must add the message // subfield (including the tag). func AppendFieldStart(b []byte, num protowire.Number) []byte { b = protowire.AppendTag(b, FieldItem, protowire.StartGroupType) b = protowire.AppendTag(b, FieldTypeID, protowire.VarintType) b = protowire.AppendVarint(b, uint64(num)) return b } // AppendFieldEnd appends the trailing end group marker for a MessageSet item field. func AppendFieldEnd(b []byte) []byte { return protowire.AppendTag(b, FieldItem, protowire.EndGroupType) } // SizeUnknown returns the size of an unknown fields section in MessageSet format. // // See AppendUnknown. func SizeUnknown(unknown []byte) (size int) { for len(unknown) > 0 { num, typ, n := protowire.ConsumeTag(unknown) if n < 0 || typ != protowire.BytesType { return 0 } unknown = unknown[n:] _, n = protowire.ConsumeBytes(unknown) if n < 0 { return 0 } unknown = unknown[n:] size += SizeField(num) + protowire.SizeTag(FieldMessage) + n } return size } // AppendUnknown appends unknown fields to b in MessageSet format. // // For historic reasons, unresolved items in a MessageSet are stored in a // message's unknown fields section in non-MessageSet format. That is, an // unknown item with typeID T and value V appears in the unknown fields as // a field with number T and value V. // // This function converts the unknown fields back into MessageSet form. func AppendUnknown(b, unknown []byte) ([]byte, error) { for len(unknown) > 0 { num, typ, n := protowire.ConsumeTag(unknown) if n < 0 || typ != protowire.BytesType { return nil, errors.New("invalid data in message set unknown fields") } unknown = unknown[n:] _, n = protowire.ConsumeBytes(unknown) if n < 0 { return nil, errors.New("invalid data in message set unknown fields") } b = AppendFieldStart(b, num) b = protowire.AppendTag(b, FieldMessage, protowire.BytesType) b = append(b, unknown[:n]...) b = AppendFieldEnd(b) unknown = unknown[n:] } return b, nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/tag/tag.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package tag marshals and unmarshals the legacy struct tags as generated // by historical versions of protoc-gen-go. package tag import ( "reflect" "strconv" "strings" defval "google.golang.org/protobuf/internal/encoding/defval" fdesc "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) var byteType = reflect.TypeOf(byte(0)) // Unmarshal decodes the tag into a prototype.Field. // // The goType is needed to determine the original protoreflect.Kind since the // tag does not record sufficient information to determine that. // The type is the underlying field type (e.g., a repeated field may be // represented by []T, but the Go type passed in is just T). // A list of enum value descriptors must be provided for enum fields. // This does not populate the Enum or Message (except for weak message). // // This function is a best effort attempt; parsing errors are ignored. func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor { f := new(fdesc.Field) f.L0.ParentFile = fdesc.SurrogateProto2 for len(tag) > 0 { i := strings.IndexByte(tag, ',') if i < 0 { i = len(tag) } switch s := tag[:i]; { case strings.HasPrefix(s, "name="): f.L0.FullName = pref.FullName(s[len("name="):]) case strings.Trim(s, "0123456789") == "": n, _ := strconv.ParseUint(s, 10, 32) f.L1.Number = pref.FieldNumber(n) case s == "opt": f.L1.Cardinality = pref.Optional case s == "req": f.L1.Cardinality = pref.Required case s == "rep": f.L1.Cardinality = pref.Repeated case s == "varint": switch goType.Kind() { case reflect.Bool: f.L1.Kind = pref.BoolKind case reflect.Int32: f.L1.Kind = pref.Int32Kind case reflect.Int64: f.L1.Kind = pref.Int64Kind case reflect.Uint32: f.L1.Kind = pref.Uint32Kind case reflect.Uint64: f.L1.Kind = pref.Uint64Kind } case s == "zigzag32": if goType.Kind() == reflect.Int32 { f.L1.Kind = pref.Sint32Kind } case s == "zigzag64": if goType.Kind() == reflect.Int64 { f.L1.Kind = pref.Sint64Kind } case s == "fixed32": switch goType.Kind() { case reflect.Int32: f.L1.Kind = pref.Sfixed32Kind case reflect.Uint32: f.L1.Kind = pref.Fixed32Kind case reflect.Float32: f.L1.Kind = pref.FloatKind } case s == "fixed64": switch goType.Kind() { case reflect.Int64: f.L1.Kind = pref.Sfixed64Kind case reflect.Uint64: f.L1.Kind = pref.Fixed64Kind case reflect.Float64: f.L1.Kind = pref.DoubleKind } case s == "bytes": switch { case goType.Kind() == reflect.String: f.L1.Kind = pref.StringKind case goType.Kind() == reflect.Slice && goType.Elem() == byteType: f.L1.Kind = pref.BytesKind default: f.L1.Kind = pref.MessageKind } case s == "group": f.L1.Kind = pref.GroupKind case strings.HasPrefix(s, "enum="): f.L1.Kind = pref.EnumKind case strings.HasPrefix(s, "json="): jsonName := s[len("json="):] if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) { f.L1.StringName.InitJSON(jsonName) } case s == "packed": f.L1.HasPacked = true f.L1.IsPacked = true case strings.HasPrefix(s, "weak="): f.L1.IsWeak = true f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):])) case strings.HasPrefix(s, "def="): // The default tag is special in that everything afterwards is the // default regardless of the presence of commas. s, i = tag[len("def="):], len(tag) v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag) f.L1.Default = fdesc.DefaultValue(v, ev) case s == "proto3": f.L0.ParentFile = fdesc.SurrogateProto3 } tag = strings.TrimPrefix(tag[i:], ",") } // The generator uses the group message name instead of the field name. // We obtain the real field name by lowercasing the group name. if f.L1.Kind == pref.GroupKind { f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName))) } return f } // Marshal encodes the protoreflect.FieldDescriptor as a tag. // // The enumName must be provided if the kind is an enum. // Historically, the formulation of the enum "name" was the proto package // dot-concatenated with the generated Go identifier for the enum type. // Depending on the context on how Marshal is called, there are different ways // through which that information is determined. As such it is the caller's // responsibility to provide a function to obtain that information. func Marshal(fd pref.FieldDescriptor, enumName string) string { var tag []string switch fd.Kind() { case pref.BoolKind, pref.EnumKind, pref.Int32Kind, pref.Uint32Kind, pref.Int64Kind, pref.Uint64Kind: tag = append(tag, "varint") case pref.Sint32Kind: tag = append(tag, "zigzag32") case pref.Sint64Kind: tag = append(tag, "zigzag64") case pref.Sfixed32Kind, pref.Fixed32Kind, pref.FloatKind: tag = append(tag, "fixed32") case pref.Sfixed64Kind, pref.Fixed64Kind, pref.DoubleKind: tag = append(tag, "fixed64") case pref.StringKind, pref.BytesKind, pref.MessageKind: tag = append(tag, "bytes") case pref.GroupKind: tag = append(tag, "group") } tag = append(tag, strconv.Itoa(int(fd.Number()))) switch fd.Cardinality() { case pref.Optional: tag = append(tag, "opt") case pref.Required: tag = append(tag, "req") case pref.Repeated: tag = append(tag, "rep") } if fd.IsPacked() { tag = append(tag, "packed") } name := string(fd.Name()) if fd.Kind() == pref.GroupKind { // The name of the FieldDescriptor for a group field is // lowercased. To find the original capitalization, we // look in the field's MessageType. name = string(fd.Message().Name()) } tag = append(tag, "name="+name) if jsonName := fd.JSONName(); jsonName != "" && jsonName != name && !fd.IsExtension() { // NOTE: The jsonName != name condition is suspect, but it preserve // the exact same semantics from the previous generator. tag = append(tag, "json="+jsonName) } if fd.IsWeak() { tag = append(tag, "weak="+string(fd.Message().FullName())) } // The previous implementation does not tag extension fields as proto3, // even when the field is defined in a proto3 file. Match that behavior // for consistency. if fd.Syntax() == pref.Proto3 && !fd.IsExtension() { tag = append(tag, "proto3") } if fd.Kind() == pref.EnumKind && enumName != "" { tag = append(tag, "enum="+enumName) } if fd.ContainingOneof() != nil { tag = append(tag, "oneof") } // This must appear last in the tag, since commas in strings aren't escaped. if fd.HasDefault() { def, _ := defval.Marshal(fd.Default(), fd.DefaultEnumValue(), fd.Kind(), defval.GoTag) tag = append(tag, "def="+def) } return strings.Join(tag, ",") } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "fmt" "io" "regexp" "strconv" "unicode/utf8" "google.golang.org/protobuf/internal/errors" ) // Decoder is a token-based textproto decoder. type Decoder struct { // lastCall is last method called, either readCall or peekCall. // Initial value is readCall. lastCall call // lastToken contains the last read token. lastToken Token // lastErr contains the last read error. lastErr error // openStack is a stack containing the byte characters for MessageOpen and // ListOpen kinds. The top of stack represents the message or the list that // the current token is nested in. An empty stack means the current token is // at the top level message. The characters '{' and '<' both represent the // MessageOpen kind. openStack []byte // orig is used in reporting line and column. orig []byte // in contains the unconsumed input. in []byte } // NewDecoder returns a Decoder to read the given []byte. func NewDecoder(b []byte) *Decoder { return &Decoder{orig: b, in: b} } // ErrUnexpectedEOF means that EOF was encountered in the middle of the input. var ErrUnexpectedEOF = errors.New("%v", io.ErrUnexpectedEOF) // call specifies which Decoder method was invoked. type call uint8 const ( readCall call = iota peekCall ) // Peek looks ahead and returns the next token and error without advancing a read. func (d *Decoder) Peek() (Token, error) { defer func() { d.lastCall = peekCall }() if d.lastCall == readCall { d.lastToken, d.lastErr = d.Read() } return d.lastToken, d.lastErr } // Read returns the next token. // It will return an error if there is no valid token. func (d *Decoder) Read() (Token, error) { defer func() { d.lastCall = readCall }() if d.lastCall == peekCall { return d.lastToken, d.lastErr } tok, err := d.parseNext(d.lastToken.kind) if err != nil { return Token{}, err } switch tok.kind { case comma, semicolon: tok, err = d.parseNext(tok.kind) if err != nil { return Token{}, err } } d.lastToken = tok return tok, nil } const ( mismatchedFmt = "mismatched close character %q" unexpectedFmt = "unexpected character %q" ) // parseNext parses the next Token based on given last kind. func (d *Decoder) parseNext(lastKind Kind) (Token, error) { // Trim leading spaces. d.consume(0) isEOF := false if len(d.in) == 0 { isEOF = true } switch lastKind { case EOF: return d.consumeToken(EOF, 0, 0), nil case bof: // Start of top level message. Next token can be EOF or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } return d.parseFieldName() case Name: // Next token can be MessageOpen, ListOpen or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil case '[': d.pushOpenStack(ch) return d.consumeToken(ListOpen, 1, 0), nil default: return d.parseScalar() } case Scalar: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch d.in[0] { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case ListOpen: // Next token can be ListClose or comma. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case ']': d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case ',': return d.consumeToken(comma, 1, 0), nil default: return Token{}, d.newSyntaxError(unexpectedFmt, ch) } } case MessageOpen: // Next token can be MessageClose or Name. if isEOF { return Token{}, ErrUnexpectedEOF } _, closeCh := d.currentOpenKind() switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) default: return d.parseFieldName() } case MessageClose: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch ch := d.in[0]; ch { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case ListOpen: // Next token can be ListClose or comma if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case ',': return d.consumeToken(comma, 1, 0), nil default: return Token{}, d.newSyntaxError(unexpectedFmt, ch) } } case ListOpen: // Next token can be ListClose, MessageStart or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case ']': d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil default: return d.parseScalar() } case ListClose: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch ch := d.in[0]; ch { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } default: // It is not possible to have this case. Let it panic below. } case comma, semicolon: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. Next token can be EOF or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } return d.parseFieldName() case MessageOpen: // Next token can be MessageClose or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) default: return d.parseFieldName() } case ListOpen: if lastKind == semicolon { // It is not be possible to have this case as logic here // should not have produced a semicolon Token when inside a // list. Let it panic below. break } // Next token can be MessageOpen or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil default: return d.parseScalar() } } } line, column := d.Position(len(d.orig) - len(d.in)) panic(fmt.Sprintf("Decoder.parseNext: bug at handling line %d:%d with lastKind=%v", line, column, lastKind)) } var otherCloseChar = map[byte]byte{ '}': '>', '>': '}', } // currentOpenKind indicates whether current position is inside a message, list // or top-level message by returning MessageOpen, ListOpen or bof respectively. // If the returned kind is either a MessageOpen or ListOpen, it also returns the // corresponding closing character. func (d *Decoder) currentOpenKind() (Kind, byte) { if len(d.openStack) == 0 { return bof, 0 } openCh := d.openStack[len(d.openStack)-1] switch openCh { case '{': return MessageOpen, '}' case '<': return MessageOpen, '>' case '[': return ListOpen, ']' } panic(fmt.Sprintf("Decoder: openStack contains invalid byte %s", string(openCh))) } func (d *Decoder) pushOpenStack(ch byte) { d.openStack = append(d.openStack, ch) } func (d *Decoder) popOpenStack() { d.openStack = d.openStack[:len(d.openStack)-1] } // parseFieldName parses field name and separator. func (d *Decoder) parseFieldName() (tok Token, err error) { defer func() { if err == nil && d.tryConsumeChar(':') { tok.attrs |= hasSeparator } }() // Extension or Any type URL. if d.in[0] == '[' { return d.parseTypeName() } // Identifier. if size := parseIdent(d.in, false); size > 0 { return d.consumeToken(Name, size, uint8(IdentName)), nil } // Field number. Identify if input is a valid number that is not negative // and is decimal integer within 32-bit range. if num := parseNumber(d.in); num.size > 0 { if !num.neg && num.kind == numDec { if _, err := strconv.ParseInt(string(d.in[:num.size]), 10, 32); err == nil { return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil } } return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) } return Token{}, d.newSyntaxError("invalid field name: %s", errRegexp.Find(d.in)) } // parseTypeName parses Any type URL or extension field name. The name is // enclosed in [ and ] characters. The C++ parser does not handle many legal URL // strings. This implementation is more liberal and allows for the pattern // ^[-_a-zA-Z0-9]+([./][-_a-zA-Z0-9]+)*`). Whitespaces and comments are allowed // in between [ ], '.', '/' and the sub names. func (d *Decoder) parseTypeName() (Token, error) { startPos := len(d.orig) - len(d.in) // Use alias s to advance first in order to use d.in for error handling. // Caller already checks for [ as first character. s := consume(d.in[1:], 0) if len(s) == 0 { return Token{}, ErrUnexpectedEOF } var name []byte for len(s) > 0 && isTypeNameChar(s[0]) { name = append(name, s[0]) s = s[1:] } s = consume(s, 0) var closed bool for len(s) > 0 && !closed { switch { case s[0] == ']': s = s[1:] closed = true case s[0] == '/', s[0] == '.': if len(name) > 0 && (name[len(name)-1] == '/' || name[len(name)-1] == '.') { return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1]) } name = append(name, s[0]) s = s[1:] s = consume(s, 0) for len(s) > 0 && isTypeNameChar(s[0]) { name = append(name, s[0]) s = s[1:] } s = consume(s, 0) default: return Token{}, d.newSyntaxError( "invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1]) } } if !closed { return Token{}, ErrUnexpectedEOF } // First character cannot be '.'. Last character cannot be '.' or '/'. size := len(name) if size == 0 || name[0] == '.' || name[size-1] == '.' || name[size-1] == '/' { return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)]) } d.in = s endPos := len(d.orig) - len(d.in) d.consume(0) return Token{ kind: Name, attrs: uint8(TypeName), pos: startPos, raw: d.orig[startPos:endPos], str: string(name), }, nil } func isTypeNameChar(b byte) bool { return (b == '-' || b == '_' || ('0' <= b && b <= '9') || ('a' <= b && b <= 'z') || ('A' <= b && b <= 'Z')) } func isWhiteSpace(b byte) bool { switch b { case ' ', '\n', '\r', '\t': return true default: return false } } // parseIdent parses an unquoted proto identifier and returns size. // If allowNeg is true, it allows '-' to be the first character in the // identifier. This is used when parsing literal values like -infinity, etc. // Regular expression matches an identifier: `^[_a-zA-Z][_a-zA-Z0-9]*` func parseIdent(input []byte, allowNeg bool) int { var size int s := input if len(s) == 0 { return 0 } if allowNeg && s[0] == '-' { s = s[1:] size++ if len(s) == 0 { return 0 } } switch { case s[0] == '_', 'a' <= s[0] && s[0] <= 'z', 'A' <= s[0] && s[0] <= 'Z': s = s[1:] size++ default: return 0 } for len(s) > 0 && (s[0] == '_' || 'a' <= s[0] && s[0] <= 'z' || 'A' <= s[0] && s[0] <= 'Z' || '0' <= s[0] && s[0] <= '9') { s = s[1:] size++ } if len(s) > 0 && !isDelim(s[0]) { return 0 } return size } // parseScalar parses for a string, literal or number value. func (d *Decoder) parseScalar() (Token, error) { if d.in[0] == '"' || d.in[0] == '\'' { return d.parseStringValue() } if tok, ok := d.parseLiteralValue(); ok { return tok, nil } if tok, ok := d.parseNumberValue(); ok { return tok, nil } return Token{}, d.newSyntaxError("invalid scalar value: %s", errRegexp.Find(d.in)) } // parseLiteralValue parses a literal value. A literal value is used for // bools, special floats and enums. This function simply identifies that the // field value is a literal. func (d *Decoder) parseLiteralValue() (Token, bool) { size := parseIdent(d.in, true) if size == 0 { return Token{}, false } return d.consumeToken(Scalar, size, literalValue), true } // consumeToken constructs a Token for given Kind from d.in and consumes given // size-length from it. func (d *Decoder) consumeToken(kind Kind, size int, attrs uint8) Token { // Important to compute raw and pos before consuming. tok := Token{ kind: kind, attrs: attrs, pos: len(d.orig) - len(d.in), raw: d.in[:size], } d.consume(size) return tok } // newSyntaxError returns a syntax error with line and column information for // current position. func (d *Decoder) newSyntaxError(f string, x ...interface{}) error { e := errors.New(f, x...) line, column := d.Position(len(d.orig) - len(d.in)) return errors.New("syntax error (line %d:%d): %v", line, column, e) } // Position returns line and column number of given index of the original input. // It will panic if index is out of range. func (d *Decoder) Position(idx int) (line int, column int) { b := d.orig[:idx] line = bytes.Count(b, []byte("\n")) + 1 if i := bytes.LastIndexByte(b, '\n'); i >= 0 { b = b[i+1:] } column = utf8.RuneCount(b) + 1 // ignore multi-rune characters return line, column } func (d *Decoder) tryConsumeChar(c byte) bool { if len(d.in) > 0 && d.in[0] == c { d.consume(1) return true } return false } // consume consumes n bytes of input and any subsequent whitespace or comments. func (d *Decoder) consume(n int) { d.in = consume(d.in, n) return } // consume consumes n bytes of input and any subsequent whitespace or comments. func consume(b []byte, n int) []byte { b = b[n:] for len(b) > 0 { switch b[0] { case ' ', '\n', '\r', '\t': b = b[1:] case '#': if i := bytes.IndexByte(b, '\n'); i >= 0 { b = b[i+len("\n"):] } else { b = nil } default: return b } } return b } // Any sequence that looks like a non-delimiter (for error reporting). var errRegexp = regexp.MustCompile(`^([-+._a-zA-Z0-9\/]+|.)`) // isDelim returns true if given byte is a delimiter character. func isDelim(c byte) bool { return !(c == '-' || c == '+' || c == '.' || c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/decode_number.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text // parseNumberValue parses a number from the input and returns a Token object. func (d *Decoder) parseNumberValue() (Token, bool) { in := d.in num := parseNumber(in) if num.size == 0 { return Token{}, false } numAttrs := num.kind if num.neg { numAttrs |= isNegative } strSize := num.size last := num.size - 1 if num.kind == numFloat && (d.in[last] == 'f' || d.in[last] == 'F') { strSize = last } tok := Token{ kind: Scalar, attrs: numberValue, pos: len(d.orig) - len(d.in), raw: d.in[:num.size], str: string(d.in[:strSize]), numAttrs: numAttrs, } d.consume(num.size) return tok, true } const ( numDec uint8 = (1 << iota) / 2 numHex numOct numFloat ) // number is the result of parsing out a valid number from parseNumber. It // contains data for doing float or integer conversion via the strconv package // in conjunction with the input bytes. type number struct { kind uint8 neg bool size int } // parseNumber constructs a number object from given input. It allows for the // following patterns: // integer: ^-?([1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]*) // float: ^-?((0|[1-9][0-9]*)?([.][0-9]*)?([eE][+-]?[0-9]+)?[fF]?) // It also returns the number of parsed bytes for the given number, 0 if it is // not a number. func parseNumber(input []byte) number { kind := numDec var size int var neg bool s := input if len(s) == 0 { return number{} } // Optional - if s[0] == '-' { neg = true s = s[1:] size++ if len(s) == 0 { return number{} } } // C++ allows for whitespace and comments in between the negative sign and // the rest of the number. This logic currently does not but is consistent // with v1. switch { case s[0] == '0': if len(s) > 1 { switch { case s[1] == 'x' || s[1] == 'X': // Parse as hex number. kind = numHex n := 2 s = s[2:] for len(s) > 0 && (('0' <= s[0] && s[0] <= '9') || ('a' <= s[0] && s[0] <= 'f') || ('A' <= s[0] && s[0] <= 'F')) { s = s[1:] n++ } if n == 2 { return number{} } size += n case '0' <= s[1] && s[1] <= '7': // Parse as octal number. kind = numOct n := 2 s = s[2:] for len(s) > 0 && '0' <= s[0] && s[0] <= '7' { s = s[1:] n++ } size += n } if kind&(numHex|numOct) > 0 { if len(s) > 0 && !isDelim(s[0]) { return number{} } return number{kind: kind, neg: neg, size: size} } } s = s[1:] size++ case '1' <= s[0] && s[0] <= '9': n := 1 s = s[1:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n case s[0] == '.': // Set kind to numFloat to signify the intent to parse as float. And // that it needs to have other digits after '.'. kind = numFloat default: return number{} } // . followed by 0 or more digits. if len(s) > 0 && s[0] == '.' { n := 1 s = s[1:] // If decimal point was before any digits, it should be followed by // other digits. if len(s) == 0 && kind == numFloat { return number{} } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n kind = numFloat } // e or E followed by an optional - or + and 1 or more digits. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { kind = numFloat s = s[1:] n := 1 if s[0] == '+' || s[0] == '-' { s = s[1:] n++ if len(s) == 0 { return number{} } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n } // Optional suffix f or F for floats. if len(s) > 0 && (s[0] == 'f' || s[0] == 'F') { kind = numFloat s = s[1:] size++ } // Check that next byte is a delimiter or it is at the end. if len(s) > 0 && !isDelim(s[0]) { return number{} } return number{kind: kind, neg: neg, size: size} } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/decode_string.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "strconv" "strings" "unicode" "unicode/utf16" "unicode/utf8" "google.golang.org/protobuf/internal/strs" ) // parseStringValue parses string field token. // This differs from parseString since the text format allows // multiple back-to-back string literals where they are semantically treated // as a single large string with all values concatenated. // // E.g., `"foo" "bar" "baz"` => "foobarbaz" func (d *Decoder) parseStringValue() (Token, error) { // Note that the ending quote is sufficient to unambiguously mark the end // of a string. Thus, the text grammar does not require intervening // whitespace or control characters in-between strings. // Thus, the following is valid: // `"foo"'bar'"baz"` => "foobarbaz" in0 := d.in var ss []string for len(d.in) > 0 && (d.in[0] == '"' || d.in[0] == '\'') { s, err := d.parseString() if err != nil { return Token{}, err } ss = append(ss, s) } // d.in already points to the end of the value at this point. return Token{ kind: Scalar, attrs: stringValue, pos: len(d.orig) - len(in0), raw: in0[:len(in0)-len(d.in)], str: strings.Join(ss, ""), }, nil } // parseString parses a string value enclosed in " or '. func (d *Decoder) parseString() (string, error) { in := d.in if len(in) == 0 { return "", ErrUnexpectedEOF } quote := in[0] in = in[1:] i := indexNeedEscapeInBytes(in) in, out := in[i:], in[:i:i] // set cap to prevent mutations for len(in) > 0 { switch r, n := utf8.DecodeRune(in); { case r == utf8.RuneError && n == 1: return "", d.newSyntaxError("invalid UTF-8 detected") case r == 0 || r == '\n': return "", d.newSyntaxError("invalid character %q in string", r) case r == rune(quote): in = in[1:] d.consume(len(d.in) - len(in)) return string(out), nil case r == '\\': if len(in) < 2 { return "", ErrUnexpectedEOF } switch r := in[1]; r { case '"', '\'', '\\', '?': in, out = in[2:], append(out, r) case 'a': in, out = in[2:], append(out, '\a') case 'b': in, out = in[2:], append(out, '\b') case 'n': in, out = in[2:], append(out, '\n') case 'r': in, out = in[2:], append(out, '\r') case 't': in, out = in[2:], append(out, '\t') case 'v': in, out = in[2:], append(out, '\v') case 'f': in, out = in[2:], append(out, '\f') case '0', '1', '2', '3', '4', '5', '6', '7': // One, two, or three octal characters. n := len(in[1:]) - len(bytes.TrimLeft(in[1:], "01234567")) if n > 3 { n = 3 } v, err := strconv.ParseUint(string(in[1:1+n]), 8, 8) if err != nil { return "", d.newSyntaxError("invalid octal escape code %q in string", in[:1+n]) } in, out = in[1+n:], append(out, byte(v)) case 'x': // One or two hexadecimal characters. n := len(in[2:]) - len(bytes.TrimLeft(in[2:], "0123456789abcdefABCDEF")) if n > 2 { n = 2 } v, err := strconv.ParseUint(string(in[2:2+n]), 16, 8) if err != nil { return "", d.newSyntaxError("invalid hex escape code %q in string", in[:2+n]) } in, out = in[2+n:], append(out, byte(v)) case 'u', 'U': // Four or eight hexadecimal characters n := 6 if r == 'U' { n = 10 } if len(in) < n { return "", ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:n]), 16, 32) if utf8.MaxRune < v || err != nil { return "", d.newSyntaxError("invalid Unicode escape code %q in string", in[:n]) } in = in[n:] r := rune(v) if utf16.IsSurrogate(r) { if len(in) < 6 { return "", ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:6]), 16, 16) r = utf16.DecodeRune(r, rune(v)) if in[0] != '\\' || in[1] != 'u' || r == unicode.ReplacementChar || err != nil { return "", d.newSyntaxError("invalid Unicode escape code %q in string", in[:6]) } in = in[6:] } out = append(out, string(r)...) default: return "", d.newSyntaxError("invalid escape code %q in string", in[:2]) } default: i := indexNeedEscapeInBytes(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } return "", ErrUnexpectedEOF } // indexNeedEscapeInString returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInBytes(b []byte) int { return indexNeedEscapeInString(strs.UnsafeString(b)) } // UnmarshalString returns an unescaped string given a textproto string value. // String value needs to contain single or double quotes. This is only used by // internal/encoding/defval package for unmarshaling bytes. func UnmarshalString(s string) (string, error) { d := NewDecoder([]byte(s)) return d.parseString() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/decode_token.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "fmt" "math" "strconv" "strings" "google.golang.org/protobuf/internal/flags" ) // Kind represents a token kind expressible in the textproto format. type Kind uint8 // Kind values. const ( Invalid Kind = iota EOF Name // Name indicates the field name. Scalar // Scalar are scalar values, e.g. "string", 47, ENUM_LITERAL, true. MessageOpen MessageClose ListOpen ListClose // comma and semi-colon are only for parsing in between values and should not be exposed. comma semicolon // bof indicates beginning of file, which is the default token // kind at the beginning of parsing. bof = Invalid ) func (t Kind) String() string { switch t { case Invalid: return "" case EOF: return "eof" case Scalar: return "scalar" case Name: return "name" case MessageOpen: return "{" case MessageClose: return "}" case ListOpen: return "[" case ListClose: return "]" case comma: return "," case semicolon: return ";" default: return fmt.Sprintf("", uint8(t)) } } // NameKind represents different types of field names. type NameKind uint8 // NameKind values. const ( IdentName NameKind = iota + 1 TypeName FieldNumber ) func (t NameKind) String() string { switch t { case IdentName: return "IdentName" case TypeName: return "TypeName" case FieldNumber: return "FieldNumber" default: return fmt.Sprintf("", uint8(t)) } } // Bit mask in Token.attrs to indicate if a Name token is followed by the // separator char ':'. The field name separator char is optional for message // field or repeated message field, but required for all other types. Decoder // simply indicates whether a Name token is followed by separator or not. It is // up to the prototext package to validate. const hasSeparator = 1 << 7 // Scalar value types. const ( numberValue = iota + 1 stringValue literalValue ) // Bit mask in Token.numAttrs to indicate that the number is a negative. const isNegative = 1 << 7 // Token provides a parsed token kind and value. Values are provided by the // different accessor methods. type Token struct { // Kind of the Token object. kind Kind // attrs contains metadata for the following Kinds: // Name: hasSeparator bit and one of NameKind. // Scalar: one of numberValue, stringValue, literalValue. attrs uint8 // numAttrs contains metadata for numberValue: // - highest bit is whether negative or positive. // - lower bits indicate one of numDec, numHex, numOct, numFloat. numAttrs uint8 // pos provides the position of the token in the original input. pos int // raw bytes of the serialized token. // This is a subslice into the original input. raw []byte // str contains parsed string for the following: // - stringValue of Scalar kind // - numberValue of Scalar kind // - TypeName of Name kind str string } // Kind returns the token kind. func (t Token) Kind() Kind { return t.kind } // RawString returns the read value in string. func (t Token) RawString() string { return string(t.raw) } // Pos returns the token position from the input. func (t Token) Pos() int { return t.pos } // NameKind returns IdentName, TypeName or FieldNumber. // It panics if type is not Name. func (t Token) NameKind() NameKind { if t.kind == Name { return NameKind(t.attrs &^ hasSeparator) } panic(fmt.Sprintf("Token is not a Name type: %s", t.kind)) } // HasSeparator returns true if the field name is followed by the separator char // ':', else false. It panics if type is not Name. func (t Token) HasSeparator() bool { if t.kind == Name { return t.attrs&hasSeparator != 0 } panic(fmt.Sprintf("Token is not a Name type: %s", t.kind)) } // IdentName returns the value for IdentName type. func (t Token) IdentName() string { if t.kind == Name && t.attrs&uint8(IdentName) != 0 { return string(t.raw) } panic(fmt.Sprintf("Token is not an IdentName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // TypeName returns the value for TypeName type. func (t Token) TypeName() string { if t.kind == Name && t.attrs&uint8(TypeName) != 0 { return t.str } panic(fmt.Sprintf("Token is not a TypeName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // FieldNumber returns the value for FieldNumber type. It returns a // non-negative int32 value. Caller will still need to validate for the correct // field number range. func (t Token) FieldNumber() int32 { if t.kind != Name || t.attrs&uint8(FieldNumber) == 0 { panic(fmt.Sprintf("Token is not a FieldNumber: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // Following should not return an error as it had already been called right // before this Token was constructed. num, _ := strconv.ParseInt(string(t.raw), 10, 32) return int32(num) } // String returns the string value for a Scalar type. func (t Token) String() (string, bool) { if t.kind != Scalar || t.attrs != stringValue { return "", false } return t.str, true } // Enum returns the literal value for a Scalar type for use as enum literals. func (t Token) Enum() (string, bool) { if t.kind != Scalar || t.attrs != literalValue || (len(t.raw) > 0 && t.raw[0] == '-') { return "", false } return string(t.raw), true } // Bool returns the bool value for a Scalar type. func (t Token) Bool() (bool, bool) { if t.kind != Scalar { return false, false } switch t.attrs { case literalValue: if b, ok := boolLits[string(t.raw)]; ok { return b, true } case numberValue: // Unsigned integer representation of 0 or 1 is permitted: 00, 0x0, 01, // 0x1, etc. n, err := strconv.ParseUint(t.str, 0, 64) if err == nil { switch n { case 0: return false, true case 1: return true, true } } } return false, false } // These exact boolean literals are the ones supported in C++. var boolLits = map[string]bool{ "t": true, "true": true, "True": true, "f": false, "false": false, "False": false, } // Uint64 returns the uint64 value for a Scalar type. func (t Token) Uint64() (uint64, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 { return 0, false } n, err := strconv.ParseUint(t.str, 0, 64) if err != nil { return 0, false } return n, true } // Uint32 returns the uint32 value for a Scalar type. func (t Token) Uint32() (uint32, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 { return 0, false } n, err := strconv.ParseUint(t.str, 0, 32) if err != nil { return 0, false } return uint32(n), true } // Int64 returns the int64 value for a Scalar type. func (t Token) Int64() (int64, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 { return 0, false } if n, err := strconv.ParseInt(t.str, 0, 64); err == nil { return n, true } // C++ accepts large positive hex numbers as negative values. // This feature is here for proto1 backwards compatibility purposes. if flags.ProtoLegacy && (t.numAttrs == numHex) { if n, err := strconv.ParseUint(t.str, 0, 64); err == nil { return int64(n), true } } return 0, false } // Int32 returns the int32 value for a Scalar type. func (t Token) Int32() (int32, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 { return 0, false } if n, err := strconv.ParseInt(t.str, 0, 32); err == nil { return int32(n), true } // C++ accepts large positive hex numbers as negative values. // This feature is here for proto1 backwards compatibility purposes. if flags.ProtoLegacy && (t.numAttrs == numHex) { if n, err := strconv.ParseUint(t.str, 0, 32); err == nil { return int32(n), true } } return 0, false } // Float64 returns the float64 value for a Scalar type. func (t Token) Float64() (float64, bool) { if t.kind != Scalar { return 0, false } switch t.attrs { case literalValue: if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok { return f, true } case numberValue: n, err := strconv.ParseFloat(t.str, 64) if err == nil { return n, true } nerr := err.(*strconv.NumError) if nerr.Err == strconv.ErrRange { return n, true } } return 0, false } // Float32 returns the float32 value for a Scalar type. func (t Token) Float32() (float32, bool) { if t.kind != Scalar { return 0, false } switch t.attrs { case literalValue: if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok { return float32(f), true } case numberValue: n, err := strconv.ParseFloat(t.str, 64) if err == nil { // Overflows are treated as (-)infinity. return float32(n), true } nerr := err.(*strconv.NumError) if nerr.Err == strconv.ErrRange { return float32(n), true } } return 0, false } // These are the supported float literals which C++ permits case-insensitive // variants of these. var floatLits = map[string]float64{ "nan": math.NaN(), "inf": math.Inf(1), "infinity": math.Inf(1), "-inf": math.Inf(-1), "-infinity": math.Inf(-1), } // TokenEquals returns true if given Tokens are equal, else false. func TokenEquals(x, y Token) bool { return x.kind == y.kind && x.attrs == y.attrs && x.numAttrs == y.numAttrs && x.pos == y.pos && bytes.Equal(x.raw, y.raw) && x.str == y.str } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/doc.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package text implements the text format for protocol buffers. // This package has no semantic understanding for protocol buffers and is only // a parser and composer for the format. // // There is no formal specification for the protobuf text format, as such the // C++ implementation (see google::protobuf::TextFormat) is the reference // implementation of the text format. // // This package is neither a superset nor a subset of the C++ implementation. // This implementation permits a more liberal grammar in some cases to be // backwards compatible with the historical Go implementation. // Future parsings unique to Go should not be added. // Some grammars allowed by the C++ implementation are deliberately // not implemented here because they are considered a bug by the protobuf team // and should not be replicated. // // The Go implementation should implement a sufficient amount of the C++ // grammar such that the default text serialization by C++ can be parsed by Go. // However, just because the C++ parser accepts some input does not mean that // the Go implementation should as well. // // The text format is almost a superset of JSON except: // * message keys are not quoted strings, but identifiers // * the top-level value must be a message without the delimiters package text ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/encoding/text/encode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "math" "math/bits" "strconv" "strings" "unicode/utf8" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/errors" ) // encType represents an encoding type. type encType uint8 const ( _ encType = (1 << iota) / 2 name scalar messageOpen messageClose ) // Encoder provides methods to write out textproto constructs and values. The user is // responsible for producing valid sequences of constructs and values. type Encoder struct { encoderState indent string delims [2]byte outputASCII bool } type encoderState struct { lastType encType indents []byte out []byte } // NewEncoder returns an Encoder. // // If indent is a non-empty string, it causes every entry in a List or Message // to be preceded by the indent and trailed by a newline. // // If delims is not the zero value, it controls the delimiter characters used // for messages (e.g., "{}" vs "<>"). // // If outputASCII is true, strings will be serialized in such a way that // multi-byte UTF-8 sequences are escaped. This property ensures that the // overall output is ASCII (as opposed to UTF-8). func NewEncoder(indent string, delims [2]byte, outputASCII bool) (*Encoder, error) { e := &Encoder{} if len(indent) > 0 { if strings.Trim(indent, " \t") != "" { return nil, errors.New("indent may only be composed of space and tab characters") } e.indent = indent } switch delims { case [2]byte{0, 0}: e.delims = [2]byte{'{', '}'} case [2]byte{'{', '}'}, [2]byte{'<', '>'}: e.delims = delims default: return nil, errors.New("delimiters may only be \"{}\" or \"<>\"") } e.outputASCII = outputASCII return e, nil } // Bytes returns the content of the written bytes. func (e *Encoder) Bytes() []byte { return e.out } // StartMessage writes out the '{' or '<' symbol. func (e *Encoder) StartMessage() { e.prepareNext(messageOpen) e.out = append(e.out, e.delims[0]) } // EndMessage writes out the '}' or '>' symbol. func (e *Encoder) EndMessage() { e.prepareNext(messageClose) e.out = append(e.out, e.delims[1]) } // WriteName writes out the field name and the separator ':'. func (e *Encoder) WriteName(s string) { e.prepareNext(name) e.out = append(e.out, s...) e.out = append(e.out, ':') } // WriteBool writes out the given boolean value. func (e *Encoder) WriteBool(b bool) { if b { e.WriteLiteral("true") } else { e.WriteLiteral("false") } } // WriteString writes out the given string value. func (e *Encoder) WriteString(s string) { e.prepareNext(scalar) e.out = appendString(e.out, s, e.outputASCII) } func appendString(out []byte, in string, outputASCII bool) []byte { out = append(out, '"') i := indexNeedEscapeInString(in) in, out = in[i:], append(out, in[:i]...) for len(in) > 0 { switch r, n := utf8.DecodeRuneInString(in); { case r == utf8.RuneError && n == 1: // We do not report invalid UTF-8 because strings in the text format // are used to represent both the proto string and bytes type. r = rune(in[0]) fallthrough case r < ' ' || r == '"' || r == '\\' || r == 0x7f: out = append(out, '\\') switch r { case '"', '\\': out = append(out, byte(r)) case '\n': out = append(out, 'n') case '\r': out = append(out, 'r') case '\t': out = append(out, 't') default: out = append(out, 'x') out = append(out, "00"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } in = in[n:] case r >= utf8.RuneSelf && (outputASCII || r <= 0x009f): out = append(out, '\\') if r <= math.MaxUint16 { out = append(out, 'u') out = append(out, "0000"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } else { out = append(out, 'U') out = append(out, "00000000"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } in = in[n:] default: i := indexNeedEscapeInString(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } out = append(out, '"') return out } // indexNeedEscapeInString returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInString(s string) int { for i := 0; i < len(s); i++ { if c := s[i]; c < ' ' || c == '"' || c == '\'' || c == '\\' || c >= 0x7f { return i } } return len(s) } // WriteFloat writes out the given float value for given bitSize. func (e *Encoder) WriteFloat(n float64, bitSize int) { e.prepareNext(scalar) e.out = appendFloat(e.out, n, bitSize) } func appendFloat(out []byte, n float64, bitSize int) []byte { switch { case math.IsNaN(n): return append(out, "nan"...) case math.IsInf(n, +1): return append(out, "inf"...) case math.IsInf(n, -1): return append(out, "-inf"...) default: return strconv.AppendFloat(out, n, 'g', -1, bitSize) } } // WriteInt writes out the given signed integer value. func (e *Encoder) WriteInt(n int64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatInt(n, 10)...) } // WriteUint writes out the given unsigned integer value. func (e *Encoder) WriteUint(n uint64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatUint(n, 10)...) } // WriteLiteral writes out the given string as a literal value without quotes. // This is used for writing enum literal strings. func (e *Encoder) WriteLiteral(s string) { e.prepareNext(scalar) e.out = append(e.out, s...) } // prepareNext adds possible space and indentation for the next value based // on last encType and indent option. It also updates e.lastType to next. func (e *Encoder) prepareNext(next encType) { defer func() { e.lastType = next }() // Single line. if len(e.indent) == 0 { // Add space after each field before the next one. if e.lastType&(scalar|messageClose) != 0 && next == name { e.out = append(e.out, ' ') // Add a random extra space to make output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } } return } // Multi-line. switch { case e.lastType == name: e.out = append(e.out, ' ') // Add a random extra space after name: to make output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } case e.lastType == messageOpen && next != messageClose: e.indents = append(e.indents, e.indent...) e.out = append(e.out, '\n') e.out = append(e.out, e.indents...) case e.lastType&(scalar|messageClose) != 0: if next == messageClose { e.indents = e.indents[:len(e.indents)-len(e.indent)] } e.out = append(e.out, '\n') e.out = append(e.out, e.indents...) } } // Snapshot returns the current snapshot for use in Reset. func (e *Encoder) Snapshot() encoderState { return e.encoderState } // Reset resets the Encoder to the given encoderState from a Snapshot. func (e *Encoder) Reset(es encoderState) { e.encoderState = es } // AppendString appends the escaped form of the input string to b. func AppendString(b []byte, s string) []byte { return appendString(b, s, false) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/errors/errors.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package errors implements functions to manipulate errors. package errors import ( "errors" "fmt" "google.golang.org/protobuf/internal/detrand" ) // Error is a sentinel matching all errors produced by this package. var Error = errors.New("protobuf error") // New formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. func New(f string, x ...interface{}) error { return &prefixError{s: format(f, x...)} } type prefixError struct{ s string } var prefix = func() string { // Deliberately introduce instability into the error message string to // discourage users from performing error string comparisons. if detrand.Bool() { return "proto: " // use non-breaking spaces (U+00a0) } else { return "proto: " // use regular spaces (U+0020) } }() func (e *prefixError) Error() string { return prefix + e.s } func (e *prefixError) Unwrap() error { return Error } // Wrap returns an error that has a "proto" prefix, the formatted string described // by the format specifier and arguments, and a suffix of err. The error wraps err. func Wrap(err error, f string, x ...interface{}) error { return &wrapError{ s: format(f, x...), err: err, } } type wrapError struct { s string err error } func (e *wrapError) Error() string { return format("%v%v: %v", prefix, e.s, e.err) } func (e *wrapError) Unwrap() error { return e.err } func (e *wrapError) Is(target error) bool { return target == Error } func format(f string, x ...interface{}) string { // avoid "proto: " prefix when chaining for i := 0; i < len(x); i++ { switch e := x[i].(type) { case *prefixError: x[i] = e.s case *wrapError: x[i] = format("%v: %v", e.s, e.err) } } return fmt.Sprintf(f, x...) } func InvalidUTF8(name string) error { return New("field %v contains invalid UTF-8", name) } func RequiredNotSet(name string) error { return New("required field %v not set", name) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/errors/is_go112.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !go1.13 package errors import "reflect" // Is is a copy of Go 1.13's errors.Is for use with older Go versions. func Is(err, target error) bool { if target == nil { return err == target } isComparable := reflect.TypeOf(target).Comparable() for { if isComparable && err == target { return true } if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { return true } if err = unwrap(err); err == nil { return false } } } func unwrap(err error) error { u, ok := err.(interface { Unwrap() error }) if !ok { return nil } return u.Unwrap() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/errors/is_go113.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.13 package errors import "errors" // Is is errors.Is. func Is(err, target error) bool { return errors.Is(err, target) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/build.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package filedesc provides functionality for constructing descriptors. // // The types in this package implement interfaces in the protoreflect package // related to protobuf descripriptors. package filedesc import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // Builder construct a protoreflect.FileDescriptor from the raw descriptor. type Builder struct { // GoPackagePath is the Go package path that is invoking this builder. GoPackagePath string // RawDescriptor is the wire-encoded bytes of FileDescriptorProto // and must be populated. RawDescriptor []byte // NumEnums is the total number of enums declared in the file. NumEnums int32 // NumMessages is the total number of messages declared in the file. // It includes the implicit message declarations for map entries. NumMessages int32 // NumExtensions is the total number of extensions declared in the file. NumExtensions int32 // NumServices is the total number of services declared in the file. NumServices int32 // TypeResolver resolves extension field types for descriptor options. // If nil, it uses protoregistry.GlobalTypes. TypeResolver interface { preg.ExtensionTypeResolver } // FileRegistry is use to lookup file, enum, and message dependencies. // Once constructed, the file descriptor is registered here. // If nil, it uses protoregistry.GlobalFiles. FileRegistry interface { FindFileByPath(string) (protoreflect.FileDescriptor, error) FindDescriptorByName(pref.FullName) (pref.Descriptor, error) RegisterFile(pref.FileDescriptor) error } } // resolverByIndex is an interface Builder.FileRegistry may implement. // If so, it permits looking up an enum or message dependency based on the // sub-list and element index into filetype.Builder.DependencyIndexes. type resolverByIndex interface { FindEnumByIndex(int32, int32, []Enum, []Message) pref.EnumDescriptor FindMessageByIndex(int32, int32, []Enum, []Message) pref.MessageDescriptor } // Indexes of each sub-list in filetype.Builder.DependencyIndexes. const ( listFieldDeps int32 = iota listExtTargets listExtDeps listMethInDeps listMethOutDeps ) // Out is the output of the Builder. type Out struct { File pref.FileDescriptor // Enums is all enum descriptors in "flattened ordering". Enums []Enum // Messages is all message descriptors in "flattened ordering". // It includes the implicit message declarations for map entries. Messages []Message // Extensions is all extension descriptors in "flattened ordering". Extensions []Extension // Service is all service descriptors in "flattened ordering". Services []Service } // Build constructs a FileDescriptor given the parameters set in Builder. // It assumes that the inputs are well-formed and panics if any inconsistencies // are encountered. // // If NumEnums+NumMessages+NumExtensions+NumServices is zero, // then Build automatically derives them from the raw descriptor. func (db Builder) Build() (out Out) { // Populate the counts if uninitialized. if db.NumEnums+db.NumMessages+db.NumExtensions+db.NumServices == 0 { db.unmarshalCounts(db.RawDescriptor, true) } // Initialize resolvers and registries if unpopulated. if db.TypeResolver == nil { db.TypeResolver = preg.GlobalTypes } if db.FileRegistry == nil { db.FileRegistry = preg.GlobalFiles } fd := newRawFile(db) out.File = fd out.Enums = fd.allEnums out.Messages = fd.allMessages out.Extensions = fd.allExtensions out.Services = fd.allServices if err := db.FileRegistry.RegisterFile(fd); err != nil { panic(err) } return out } // unmarshalCounts counts the number of enum, message, extension, and service // declarations in the raw message, which is either a FileDescriptorProto // or a MessageDescriptorProto depending on whether isFile is set. func (db *Builder) unmarshalCounts(b []byte, isFile bool) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] if isFile { switch num { case genid.FileDescriptorProto_EnumType_field_number: db.NumEnums++ case genid.FileDescriptorProto_MessageType_field_number: db.unmarshalCounts(v, false) db.NumMessages++ case genid.FileDescriptorProto_Extension_field_number: db.NumExtensions++ case genid.FileDescriptorProto_Service_field_number: db.NumServices++ } } else { switch num { case genid.DescriptorProto_EnumType_field_number: db.NumEnums++ case genid.DescriptorProto_NestedType_field_number: db.unmarshalCounts(v, false) db.NumMessages++ case genid.DescriptorProto_Extension_field_number: db.NumExtensions++ } } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/desc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "bytes" "fmt" "sync" "sync/atomic" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/encoding/defval" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // The types in this file may have a suffix: // • L0: Contains fields common to all descriptors (except File) and // must be initialized up front. // • L1: Contains fields specific to a descriptor and // must be initialized up front. // • L2: Contains fields that are lazily initialized when constructing // from the raw file descriptor. When constructing as a literal, the L2 // fields must be initialized up front. // // The types are exported so that packages like reflect/protodesc can // directly construct descriptors. type ( File struct { fileRaw L1 FileL1 once uint32 // atomically set if L2 is valid mu sync.Mutex // protects L2 L2 *FileL2 } FileL1 struct { Syntax pref.Syntax Path string Package pref.FullName Enums Enums Messages Messages Extensions Extensions Services Services } FileL2 struct { Options func() pref.ProtoMessage Imports FileImports Locations SourceLocations } ) func (fd *File) ParentFile() pref.FileDescriptor { return fd } func (fd *File) Parent() pref.Descriptor { return nil } func (fd *File) Index() int { return 0 } func (fd *File) Syntax() pref.Syntax { return fd.L1.Syntax } func (fd *File) Name() pref.Name { return fd.L1.Package.Name() } func (fd *File) FullName() pref.FullName { return fd.L1.Package } func (fd *File) IsPlaceholder() bool { return false } func (fd *File) Options() pref.ProtoMessage { if f := fd.lazyInit().Options; f != nil { return f() } return descopts.File } func (fd *File) Path() string { return fd.L1.Path } func (fd *File) Package() pref.FullName { return fd.L1.Package } func (fd *File) Imports() pref.FileImports { return &fd.lazyInit().Imports } func (fd *File) Enums() pref.EnumDescriptors { return &fd.L1.Enums } func (fd *File) Messages() pref.MessageDescriptors { return &fd.L1.Messages } func (fd *File) Extensions() pref.ExtensionDescriptors { return &fd.L1.Extensions } func (fd *File) Services() pref.ServiceDescriptors { return &fd.L1.Services } func (fd *File) SourceLocations() pref.SourceLocations { return &fd.lazyInit().Locations } func (fd *File) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) } func (fd *File) ProtoType(pref.FileDescriptor) {} func (fd *File) ProtoInternal(pragma.DoNotImplement) {} func (fd *File) lazyInit() *FileL2 { if atomic.LoadUint32(&fd.once) == 0 { fd.lazyInitOnce() } return fd.L2 } func (fd *File) lazyInitOnce() { fd.mu.Lock() if fd.L2 == nil { fd.lazyRawInit() // recursively initializes all L2 structures } atomic.StoreUint32(&fd.once, 1) fd.mu.Unlock() } // GoPackagePath is a pseudo-internal API for determining the Go package path // that this file descriptor is declared in. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (fd *File) GoPackagePath() string { return fd.builder.GoPackagePath } type ( Enum struct { Base L1 EnumL1 L2 *EnumL2 // protected by fileDesc.once } EnumL1 struct { eagerValues bool // controls whether EnumL2.Values is already populated } EnumL2 struct { Options func() pref.ProtoMessage Values EnumValues ReservedNames Names ReservedRanges EnumRanges } EnumValue struct { Base L1 EnumValueL1 } EnumValueL1 struct { Options func() pref.ProtoMessage Number pref.EnumNumber } ) func (ed *Enum) Options() pref.ProtoMessage { if f := ed.lazyInit().Options; f != nil { return f() } return descopts.Enum } func (ed *Enum) Values() pref.EnumValueDescriptors { if ed.L1.eagerValues { return &ed.L2.Values } return &ed.lazyInit().Values } func (ed *Enum) ReservedNames() pref.Names { return &ed.lazyInit().ReservedNames } func (ed *Enum) ReservedRanges() pref.EnumRanges { return &ed.lazyInit().ReservedRanges } func (ed *Enum) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) } func (ed *Enum) ProtoType(pref.EnumDescriptor) {} func (ed *Enum) lazyInit() *EnumL2 { ed.L0.ParentFile.lazyInit() // implicitly initializes L2 return ed.L2 } func (ed *EnumValue) Options() pref.ProtoMessage { if f := ed.L1.Options; f != nil { return f() } return descopts.EnumValue } func (ed *EnumValue) Number() pref.EnumNumber { return ed.L1.Number } func (ed *EnumValue) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) } func (ed *EnumValue) ProtoType(pref.EnumValueDescriptor) {} type ( Message struct { Base L1 MessageL1 L2 *MessageL2 // protected by fileDesc.once } MessageL1 struct { Enums Enums Messages Messages Extensions Extensions IsMapEntry bool // promoted from google.protobuf.MessageOptions IsMessageSet bool // promoted from google.protobuf.MessageOptions } MessageL2 struct { Options func() pref.ProtoMessage Fields Fields Oneofs Oneofs ReservedNames Names ReservedRanges FieldRanges RequiredNumbers FieldNumbers // must be consistent with Fields.Cardinality ExtensionRanges FieldRanges ExtensionRangeOptions []func() pref.ProtoMessage // must be same length as ExtensionRanges } Field struct { Base L1 FieldL1 } FieldL1 struct { Options func() pref.ProtoMessage Number pref.FieldNumber Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers Kind pref.Kind StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsWeak bool // promoted from google.protobuf.FieldOptions HasPacked bool // promoted from google.protobuf.FieldOptions IsPacked bool // promoted from google.protobuf.FieldOptions HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions EnforceUTF8 bool // promoted from google.protobuf.FieldOptions Default defaultValue ContainingOneof pref.OneofDescriptor // must be consistent with Message.Oneofs.Fields Enum pref.EnumDescriptor Message pref.MessageDescriptor } Oneof struct { Base L1 OneofL1 } OneofL1 struct { Options func() pref.ProtoMessage Fields OneofFields // must be consistent with Message.Fields.ContainingOneof } ) func (md *Message) Options() pref.ProtoMessage { if f := md.lazyInit().Options; f != nil { return f() } return descopts.Message } func (md *Message) IsMapEntry() bool { return md.L1.IsMapEntry } func (md *Message) Fields() pref.FieldDescriptors { return &md.lazyInit().Fields } func (md *Message) Oneofs() pref.OneofDescriptors { return &md.lazyInit().Oneofs } func (md *Message) ReservedNames() pref.Names { return &md.lazyInit().ReservedNames } func (md *Message) ReservedRanges() pref.FieldRanges { return &md.lazyInit().ReservedRanges } func (md *Message) RequiredNumbers() pref.FieldNumbers { return &md.lazyInit().RequiredNumbers } func (md *Message) ExtensionRanges() pref.FieldRanges { return &md.lazyInit().ExtensionRanges } func (md *Message) ExtensionRangeOptions(i int) pref.ProtoMessage { if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil { return f() } return descopts.ExtensionRange } func (md *Message) Enums() pref.EnumDescriptors { return &md.L1.Enums } func (md *Message) Messages() pref.MessageDescriptors { return &md.L1.Messages } func (md *Message) Extensions() pref.ExtensionDescriptors { return &md.L1.Extensions } func (md *Message) ProtoType(pref.MessageDescriptor) {} func (md *Message) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) } func (md *Message) lazyInit() *MessageL2 { md.L0.ParentFile.lazyInit() // implicitly initializes L2 return md.L2 } // IsMessageSet is a pseudo-internal API for checking whether a message // should serialize in the proto1 message format. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (md *Message) IsMessageSet() bool { return md.L1.IsMessageSet } func (fd *Field) Options() pref.ProtoMessage { if f := fd.L1.Options; f != nil { return f() } return descopts.Field } func (fd *Field) Number() pref.FieldNumber { return fd.L1.Number } func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality } func (fd *Field) Kind() pref.Kind { return fd.L1.Kind } func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON } func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) } func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) } func (fd *Field) HasPresence() bool { return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil) } func (fd *Field) HasOptionalKeyword() bool { return (fd.L0.ParentFile.L1.Syntax == pref.Proto2 && fd.L1.Cardinality == pref.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional } func (fd *Field) IsPacked() bool { if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != pref.Proto2 && fd.L1.Cardinality == pref.Repeated { switch fd.L1.Kind { case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind: default: return true } } return fd.L1.IsPacked } func (fd *Field) IsExtension() bool { return false } func (fd *Field) IsWeak() bool { return fd.L1.IsWeak } func (fd *Field) IsList() bool { return fd.Cardinality() == pref.Repeated && !fd.IsMap() } func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() } func (fd *Field) MapKey() pref.FieldDescriptor { if !fd.IsMap() { return nil } return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number) } func (fd *Field) MapValue() pref.FieldDescriptor { if !fd.IsMap() { return nil } return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number) } func (fd *Field) HasDefault() bool { return fd.L1.Default.has } func (fd *Field) Default() pref.Value { return fd.L1.Default.get(fd) } func (fd *Field) DefaultEnumValue() pref.EnumValueDescriptor { return fd.L1.Default.enum } func (fd *Field) ContainingOneof() pref.OneofDescriptor { return fd.L1.ContainingOneof } func (fd *Field) ContainingMessage() pref.MessageDescriptor { return fd.L0.Parent.(pref.MessageDescriptor) } func (fd *Field) Enum() pref.EnumDescriptor { return fd.L1.Enum } func (fd *Field) Message() pref.MessageDescriptor { if fd.L1.IsWeak { if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil { return d.(pref.MessageDescriptor) } } return fd.L1.Message } func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) } func (fd *Field) ProtoType(pref.FieldDescriptor) {} // EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8 // validation for the string field. This exists for Google-internal use only // since proto3 did not enforce UTF-8 validity prior to the open-source release. // If this method does not exist, the default is to enforce valid UTF-8. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (fd *Field) EnforceUTF8() bool { if fd.L1.HasEnforceUTF8 { return fd.L1.EnforceUTF8 } return fd.L0.ParentFile.L1.Syntax == pref.Proto3 } func (od *Oneof) IsSynthetic() bool { return od.L0.ParentFile.L1.Syntax == pref.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword() } func (od *Oneof) Options() pref.ProtoMessage { if f := od.L1.Options; f != nil { return f() } return descopts.Oneof } func (od *Oneof) Fields() pref.FieldDescriptors { return &od.L1.Fields } func (od *Oneof) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, od) } func (od *Oneof) ProtoType(pref.OneofDescriptor) {} type ( Extension struct { Base L1 ExtensionL1 L2 *ExtensionL2 // protected by fileDesc.once } ExtensionL1 struct { Number pref.FieldNumber Extendee pref.MessageDescriptor Cardinality pref.Cardinality Kind pref.Kind } ExtensionL2 struct { Options func() pref.ProtoMessage StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsPacked bool // promoted from google.protobuf.FieldOptions Default defaultValue Enum pref.EnumDescriptor Message pref.MessageDescriptor } ) func (xd *Extension) Options() pref.ProtoMessage { if f := xd.lazyInit().Options; f != nil { return f() } return descopts.Field } func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number } func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality } func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind } func (xd *Extension) HasJSONName() bool { return xd.lazyInit().StringName.hasJSON } func (xd *Extension) JSONName() string { return xd.lazyInit().StringName.getJSON(xd) } func (xd *Extension) TextName() string { return xd.lazyInit().StringName.getText(xd) } func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != pref.Repeated } func (xd *Extension) HasOptionalKeyword() bool { return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional } func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked } func (xd *Extension) IsExtension() bool { return true } func (xd *Extension) IsWeak() bool { return false } func (xd *Extension) IsList() bool { return xd.Cardinality() == pref.Repeated } func (xd *Extension) IsMap() bool { return false } func (xd *Extension) MapKey() pref.FieldDescriptor { return nil } func (xd *Extension) MapValue() pref.FieldDescriptor { return nil } func (xd *Extension) HasDefault() bool { return xd.lazyInit().Default.has } func (xd *Extension) Default() pref.Value { return xd.lazyInit().Default.get(xd) } func (xd *Extension) DefaultEnumValue() pref.EnumValueDescriptor { return xd.lazyInit().Default.enum } func (xd *Extension) ContainingOneof() pref.OneofDescriptor { return nil } func (xd *Extension) ContainingMessage() pref.MessageDescriptor { return xd.L1.Extendee } func (xd *Extension) Enum() pref.EnumDescriptor { return xd.lazyInit().Enum } func (xd *Extension) Message() pref.MessageDescriptor { return xd.lazyInit().Message } func (xd *Extension) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, xd) } func (xd *Extension) ProtoType(pref.FieldDescriptor) {} func (xd *Extension) ProtoInternal(pragma.DoNotImplement) {} func (xd *Extension) lazyInit() *ExtensionL2 { xd.L0.ParentFile.lazyInit() // implicitly initializes L2 return xd.L2 } type ( Service struct { Base L1 ServiceL1 L2 *ServiceL2 // protected by fileDesc.once } ServiceL1 struct{} ServiceL2 struct { Options func() pref.ProtoMessage Methods Methods } Method struct { Base L1 MethodL1 } MethodL1 struct { Options func() pref.ProtoMessage Input pref.MessageDescriptor Output pref.MessageDescriptor IsStreamingClient bool IsStreamingServer bool } ) func (sd *Service) Options() pref.ProtoMessage { if f := sd.lazyInit().Options; f != nil { return f() } return descopts.Service } func (sd *Service) Methods() pref.MethodDescriptors { return &sd.lazyInit().Methods } func (sd *Service) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, sd) } func (sd *Service) ProtoType(pref.ServiceDescriptor) {} func (sd *Service) ProtoInternal(pragma.DoNotImplement) {} func (sd *Service) lazyInit() *ServiceL2 { sd.L0.ParentFile.lazyInit() // implicitly initializes L2 return sd.L2 } func (md *Method) Options() pref.ProtoMessage { if f := md.L1.Options; f != nil { return f() } return descopts.Method } func (md *Method) Input() pref.MessageDescriptor { return md.L1.Input } func (md *Method) Output() pref.MessageDescriptor { return md.L1.Output } func (md *Method) IsStreamingClient() bool { return md.L1.IsStreamingClient } func (md *Method) IsStreamingServer() bool { return md.L1.IsStreamingServer } func (md *Method) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) } func (md *Method) ProtoType(pref.MethodDescriptor) {} func (md *Method) ProtoInternal(pragma.DoNotImplement) {} // Surrogate files are can be used to create standalone descriptors // where the syntax is only information derived from the parent file. var ( SurrogateProto2 = &File{L1: FileL1{Syntax: pref.Proto2}, L2: &FileL2{}} SurrogateProto3 = &File{L1: FileL1{Syntax: pref.Proto3}, L2: &FileL2{}} ) type ( Base struct { L0 BaseL0 } BaseL0 struct { FullName pref.FullName // must be populated ParentFile *File // must be populated Parent pref.Descriptor Index int } ) func (d *Base) Name() pref.Name { return d.L0.FullName.Name() } func (d *Base) FullName() pref.FullName { return d.L0.FullName } func (d *Base) ParentFile() pref.FileDescriptor { if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 { return nil // surrogate files are not real parents } return d.L0.ParentFile } func (d *Base) Parent() pref.Descriptor { return d.L0.Parent } func (d *Base) Index() int { return d.L0.Index } func (d *Base) Syntax() pref.Syntax { return d.L0.ParentFile.Syntax() } func (d *Base) IsPlaceholder() bool { return false } func (d *Base) ProtoInternal(pragma.DoNotImplement) {} type stringName struct { hasJSON bool once sync.Once nameJSON string nameText string } // InitJSON initializes the name. It is exported for use by other internal packages. func (s *stringName) InitJSON(name string) { s.hasJSON = true s.nameJSON = name } func (s *stringName) lazyInit(fd pref.FieldDescriptor) *stringName { s.once.Do(func() { if fd.IsExtension() { // For extensions, JSON and text are formatted the same way. var name string if messageset.IsMessageSetExtension(fd) { name = string("[" + fd.FullName().Parent() + "]") } else { name = string("[" + fd.FullName() + "]") } s.nameJSON = name s.nameText = name } else { // Format the JSON name. if !s.hasJSON { s.nameJSON = strs.JSONCamelCase(string(fd.Name())) } // Format the text name. s.nameText = string(fd.Name()) if fd.Kind() == pref.GroupKind { s.nameText = string(fd.Message().Name()) } } }) return s } func (s *stringName) getJSON(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameJSON } func (s *stringName) getText(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameText } func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue { dv := defaultValue{has: v.IsValid(), val: v, enum: ev} if b, ok := v.Interface().([]byte); ok { // Store a copy of the default bytes, so that we can detect // accidental mutations of the original value. dv.bytes = append([]byte(nil), b...) } return dv } func unmarshalDefault(b []byte, k pref.Kind, pf *File, ed pref.EnumDescriptor) defaultValue { var evs pref.EnumValueDescriptors if k == pref.EnumKind { // If the enum is declared within the same file, be careful not to // blindly call the Values method, lest we bind ourselves in a deadlock. if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf { evs = &e.L2.Values } else { evs = ed.Values() } // If we are unable to resolve the enum dependency, use a placeholder // enum value since we will not be able to parse the default value. if ed.IsPlaceholder() && pref.Name(b).IsValid() { v := pref.ValueOfEnum(0) ev := PlaceholderEnumValue(ed.FullName().Parent().Append(pref.Name(b))) return DefaultValue(v, ev) } } v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor) if err != nil { panic(err) } return DefaultValue(v, ev) } type defaultValue struct { has bool val pref.Value enum pref.EnumValueDescriptor bytes []byte } func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value { // Return the zero value as the default if unpopulated. if !dv.has { if fd.Cardinality() == pref.Repeated { return pref.Value{} } switch fd.Kind() { case pref.BoolKind: return pref.ValueOfBool(false) case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: return pref.ValueOfInt32(0) case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: return pref.ValueOfInt64(0) case pref.Uint32Kind, pref.Fixed32Kind: return pref.ValueOfUint32(0) case pref.Uint64Kind, pref.Fixed64Kind: return pref.ValueOfUint64(0) case pref.FloatKind: return pref.ValueOfFloat32(0) case pref.DoubleKind: return pref.ValueOfFloat64(0) case pref.StringKind: return pref.ValueOfString("") case pref.BytesKind: return pref.ValueOfBytes(nil) case pref.EnumKind: if evs := fd.Enum().Values(); evs.Len() > 0 { return pref.ValueOfEnum(evs.Get(0).Number()) } return pref.ValueOfEnum(0) } } if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) { // TODO: Avoid panic if we're running with the race detector // and instead spawn a goroutine that periodically resets // this value back to the original to induce a race. panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName())) } return dv.val } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/desc_init.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) // fileRaw is a data struct used when initializing a file descriptor from // a raw FileDescriptorProto. type fileRaw struct { builder Builder allEnums []Enum allMessages []Message allExtensions []Extension allServices []Service } func newRawFile(db Builder) *File { fd := &File{fileRaw: fileRaw{builder: db}} fd.initDecls(db.NumEnums, db.NumMessages, db.NumExtensions, db.NumServices) fd.unmarshalSeed(db.RawDescriptor) // Extended message targets are eagerly resolved since registration // needs this information at program init time. for i := range fd.allExtensions { xd := &fd.allExtensions[i] xd.L1.Extendee = fd.resolveMessageDependency(xd.L1.Extendee, listExtTargets, int32(i)) } fd.checkDecls() return fd } // initDecls pre-allocates slices for the exact number of enums, messages // (including map entries), extensions, and services declared in the proto file. // This is done to avoid regrowing the slice, which would change the address // for any previously seen declaration. // // The alloc methods "allocates" slices by pulling from the capacity. func (fd *File) initDecls(numEnums, numMessages, numExtensions, numServices int32) { fd.allEnums = make([]Enum, 0, numEnums) fd.allMessages = make([]Message, 0, numMessages) fd.allExtensions = make([]Extension, 0, numExtensions) fd.allServices = make([]Service, 0, numServices) } func (fd *File) allocEnums(n int) []Enum { total := len(fd.allEnums) es := fd.allEnums[total : total+n] fd.allEnums = fd.allEnums[:total+n] return es } func (fd *File) allocMessages(n int) []Message { total := len(fd.allMessages) ms := fd.allMessages[total : total+n] fd.allMessages = fd.allMessages[:total+n] return ms } func (fd *File) allocExtensions(n int) []Extension { total := len(fd.allExtensions) xs := fd.allExtensions[total : total+n] fd.allExtensions = fd.allExtensions[:total+n] return xs } func (fd *File) allocServices(n int) []Service { total := len(fd.allServices) xs := fd.allServices[total : total+n] fd.allServices = fd.allServices[:total+n] return xs } // checkDecls performs a sanity check that the expected number of expected // declarations matches the number that were found in the descriptor proto. func (fd *File) checkDecls() { switch { case len(fd.allEnums) != cap(fd.allEnums): case len(fd.allMessages) != cap(fd.allMessages): case len(fd.allExtensions) != cap(fd.allExtensions): case len(fd.allServices) != cap(fd.allServices): default: return } panic("mismatching cardinality") } func (fd *File) unmarshalSeed(b []byte) { sb := getBuilder() defer putBuilder(sb) var prevField pref.FieldNumber var numEnums, numMessages, numExtensions, numServices int var posEnums, posMessages, posExtensions, posServices int b0 := b for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FileDescriptorProto_Syntax_field_number: switch string(v) { case "proto2": fd.L1.Syntax = pref.Proto2 case "proto3": fd.L1.Syntax = pref.Proto3 default: panic("invalid syntax") } case genid.FileDescriptorProto_Name_field_number: fd.L1.Path = sb.MakeString(v) case genid.FileDescriptorProto_Package_field_number: fd.L1.Package = pref.FullName(sb.MakeString(v)) case genid.FileDescriptorProto_EnumType_field_number: if prevField != genid.FileDescriptorProto_EnumType_field_number { if numEnums > 0 { panic("non-contiguous repeated field") } posEnums = len(b0) - len(b) - n - m } numEnums++ case genid.FileDescriptorProto_MessageType_field_number: if prevField != genid.FileDescriptorProto_MessageType_field_number { if numMessages > 0 { panic("non-contiguous repeated field") } posMessages = len(b0) - len(b) - n - m } numMessages++ case genid.FileDescriptorProto_Extension_field_number: if prevField != genid.FileDescriptorProto_Extension_field_number { if numExtensions > 0 { panic("non-contiguous repeated field") } posExtensions = len(b0) - len(b) - n - m } numExtensions++ case genid.FileDescriptorProto_Service_field_number: if prevField != genid.FileDescriptorProto_Service_field_number { if numServices > 0 { panic("non-contiguous repeated field") } posServices = len(b0) - len(b) - n - m } numServices++ } prevField = num default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] prevField = -1 // ignore known field numbers of unknown wire type } } // If syntax is missing, it is assumed to be proto2. if fd.L1.Syntax == 0 { fd.L1.Syntax = pref.Proto2 } // Must allocate all declarations before parsing each descriptor type // to ensure we handled all descriptors in "flattened ordering". if numEnums > 0 { fd.L1.Enums.List = fd.allocEnums(numEnums) } if numMessages > 0 { fd.L1.Messages.List = fd.allocMessages(numMessages) } if numExtensions > 0 { fd.L1.Extensions.List = fd.allocExtensions(numExtensions) } if numServices > 0 { fd.L1.Services.List = fd.allocServices(numServices) } if numEnums > 0 { b := b0[posEnums:] for i := range fd.L1.Enums.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numMessages > 0 { b := b0[posMessages:] for i := range fd.L1.Messages.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numExtensions > 0 { b := b0[posExtensions:] for i := range fd.L1.Extensions.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numServices > 0 { b := b0[posServices:] for i := range fd.L1.Services.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } } func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { ed.L0.ParentFile = pf ed.L0.Parent = pd ed.L0.Index = i var numValues int for b := b; len(b) > 0; { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Name_field_number: ed.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.EnumDescriptorProto_Value_field_number: numValues++ } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } // Only construct enum value descriptors for top-level enums since // they are needed for registration. if pd != pf { return } ed.L1.eagerValues = true ed.L2 = new(EnumL2) ed.L2.Values.List = make([]EnumValue, numValues) for i := 0; len(b) > 0; { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Value_field_number: ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i) i++ } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { md.L0.ParentFile = pf md.L0.Parent = pd md.L0.Index = i var prevField pref.FieldNumber var numEnums, numMessages, numExtensions int var posEnums, posMessages, posExtensions int b0 := b for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_Name_field_number: md.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.DescriptorProto_EnumType_field_number: if prevField != genid.DescriptorProto_EnumType_field_number { if numEnums > 0 { panic("non-contiguous repeated field") } posEnums = len(b0) - len(b) - n - m } numEnums++ case genid.DescriptorProto_NestedType_field_number: if prevField != genid.DescriptorProto_NestedType_field_number { if numMessages > 0 { panic("non-contiguous repeated field") } posMessages = len(b0) - len(b) - n - m } numMessages++ case genid.DescriptorProto_Extension_field_number: if prevField != genid.DescriptorProto_Extension_field_number { if numExtensions > 0 { panic("non-contiguous repeated field") } posExtensions = len(b0) - len(b) - n - m } numExtensions++ case genid.DescriptorProto_Options_field_number: md.unmarshalSeedOptions(v) } prevField = num default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] prevField = -1 // ignore known field numbers of unknown wire type } } // Must allocate all declarations before parsing each descriptor type // to ensure we handled all descriptors in "flattened ordering". if numEnums > 0 { md.L1.Enums.List = pf.allocEnums(numEnums) } if numMessages > 0 { md.L1.Messages.List = pf.allocMessages(numMessages) } if numExtensions > 0 { md.L1.Extensions.List = pf.allocExtensions(numExtensions) } if numEnums > 0 { b := b0[posEnums:] for i := range md.L1.Enums.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } if numMessages > 0 { b := b0[posMessages:] for i := range md.L1.Messages.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } if numExtensions > 0 { b := b0[posExtensions:] for i := range md.L1.Extensions.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } } func (md *Message) unmarshalSeedOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MessageOptions_MapEntry_field_number: md.L1.IsMapEntry = protowire.DecodeBool(v) case genid.MessageOptions_MessageSetWireFormat_field_number: md.L1.IsMessageSet = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { xd.L0.ParentFile = pf xd.L0.Parent = pd xd.L0.Index = i for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Number_field_number: xd.L1.Number = pref.FieldNumber(v) case genid.FieldDescriptorProto_Label_field_number: xd.L1.Cardinality = pref.Cardinality(v) case genid.FieldDescriptorProto_Type_field_number: xd.L1.Kind = pref.Kind(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Name_field_number: xd.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.FieldDescriptorProto_Extendee_field_number: xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v)) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { sd.L0.ParentFile = pf sd.L0.Parent = pd sd.L0.Index = i for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.ServiceDescriptorProto_Name_field_number: sd.L0.FullName = appendFullName(sb, pd.FullName(), v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } var nameBuilderPool = sync.Pool{ New: func() interface{} { return new(strs.Builder) }, } func getBuilder() *strs.Builder { return nameBuilderPool.Get().(*strs.Builder) } func putBuilder(b *strs.Builder) { nameBuilderPool.Put(b) } // makeFullName converts b to a protoreflect.FullName, // where b must start with a leading dot. func makeFullName(sb *strs.Builder, b []byte) pref.FullName { if len(b) == 0 || b[0] != '.' { panic("name reference must be fully qualified") } return pref.FullName(sb.MakeString(b[1:])) } func appendFullName(sb *strs.Builder, prefix pref.FullName, suffix []byte) pref.FullName { return sb.AppendFullName(prefix, pref.Name(strs.UnsafeString(suffix))) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/desc_lazy.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "reflect" "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" ) func (fd *File) lazyRawInit() { fd.unmarshalFull(fd.builder.RawDescriptor) fd.resolveMessages() fd.resolveExtensions() fd.resolveServices() } func (file *File) resolveMessages() { var depIdx int32 for i := range file.allMessages { md := &file.allMessages[i] // Resolve message field dependencies. for j := range md.L2.Fields.List { fd := &md.L2.Fields.List[j] // Weak fields are resolved upon actual use. if fd.L1.IsWeak { continue } // Resolve message field dependency. switch fd.L1.Kind { case pref.EnumKind: fd.L1.Enum = file.resolveEnumDependency(fd.L1.Enum, listFieldDeps, depIdx) depIdx++ case pref.MessageKind, pref.GroupKind: fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx) depIdx++ } // Default is resolved here since it depends on Enum being resolved. if v := fd.L1.Default.val; v.IsValid() { fd.L1.Default = unmarshalDefault(v.Bytes(), fd.L1.Kind, file, fd.L1.Enum) } } } } func (file *File) resolveExtensions() { var depIdx int32 for i := range file.allExtensions { xd := &file.allExtensions[i] // Resolve extension field dependency. switch xd.L1.Kind { case pref.EnumKind: xd.L2.Enum = file.resolveEnumDependency(xd.L2.Enum, listExtDeps, depIdx) depIdx++ case pref.MessageKind, pref.GroupKind: xd.L2.Message = file.resolveMessageDependency(xd.L2.Message, listExtDeps, depIdx) depIdx++ } // Default is resolved here since it depends on Enum being resolved. if v := xd.L2.Default.val; v.IsValid() { xd.L2.Default = unmarshalDefault(v.Bytes(), xd.L1.Kind, file, xd.L2.Enum) } } } func (file *File) resolveServices() { var depIdx int32 for i := range file.allServices { sd := &file.allServices[i] // Resolve method dependencies. for j := range sd.L2.Methods.List { md := &sd.L2.Methods.List[j] md.L1.Input = file.resolveMessageDependency(md.L1.Input, listMethInDeps, depIdx) md.L1.Output = file.resolveMessageDependency(md.L1.Output, listMethOutDeps, depIdx) depIdx++ } } } func (file *File) resolveEnumDependency(ed pref.EnumDescriptor, i, j int32) pref.EnumDescriptor { r := file.builder.FileRegistry if r, ok := r.(resolverByIndex); ok { if ed2 := r.FindEnumByIndex(i, j, file.allEnums, file.allMessages); ed2 != nil { return ed2 } } for i := range file.allEnums { if ed2 := &file.allEnums[i]; ed2.L0.FullName == ed.FullName() { return ed2 } } if d, _ := r.FindDescriptorByName(ed.FullName()); d != nil { return d.(pref.EnumDescriptor) } return ed } func (file *File) resolveMessageDependency(md pref.MessageDescriptor, i, j int32) pref.MessageDescriptor { r := file.builder.FileRegistry if r, ok := r.(resolverByIndex); ok { if md2 := r.FindMessageByIndex(i, j, file.allEnums, file.allMessages); md2 != nil { return md2 } } for i := range file.allMessages { if md2 := &file.allMessages[i]; md2.L0.FullName == md.FullName() { return md2 } } if d, _ := r.FindDescriptorByName(md.FullName()); d != nil { return d.(pref.MessageDescriptor) } return md } func (fd *File) unmarshalFull(b []byte) { sb := getBuilder() defer putBuilder(sb) var enumIdx, messageIdx, extensionIdx, serviceIdx int var rawOptions []byte fd.L2 = new(FileL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FileDescriptorProto_PublicDependency_field_number: fd.L2.Imports[v].IsPublic = true case genid.FileDescriptorProto_WeakDependency_field_number: fd.L2.Imports[v].IsWeak = true } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FileDescriptorProto_Dependency_field_number: path := sb.MakeString(v) imp, _ := fd.builder.FileRegistry.FindFileByPath(path) if imp == nil { imp = PlaceholderFile(path) } fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp}) case genid.FileDescriptorProto_EnumType_field_number: fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb) enumIdx++ case genid.FileDescriptorProto_MessageType_field_number: fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb) messageIdx++ case genid.FileDescriptorProto_Extension_field_number: fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) extensionIdx++ case genid.FileDescriptorProto_Service_field_number: fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb) serviceIdx++ case genid.FileDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions) } func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) { var rawValues [][]byte var rawOptions []byte if !ed.L1.eagerValues { ed.L2 = new(EnumL2) } for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Value_field_number: rawValues = append(rawValues, v) case genid.EnumDescriptorProto_ReservedName_field_number: ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) case genid.EnumDescriptorProto_ReservedRange_field_number: ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v)) case genid.EnumDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if !ed.L1.eagerValues && len(rawValues) > 0 { ed.L2.Values.List = make([]EnumValue, len(rawValues)) for i, b := range rawValues { ed.L2.Values.List[i].unmarshalFull(b, sb, ed.L0.ParentFile, ed, i) } } ed.L2.Options = ed.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Enum, rawOptions) } func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.EnumDescriptorProto_EnumReservedRange_Start_field_number: r[0] = pref.EnumNumber(v) case genid.EnumDescriptorProto_EnumReservedRange_End_field_number: r[1] = pref.EnumNumber(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r } func (vd *EnumValue) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { vd.L0.ParentFile = pf vd.L0.Parent = pd vd.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.EnumValueDescriptorProto_Number_field_number: vd.L1.Number = pref.EnumNumber(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumValueDescriptorProto_Name_field_number: // NOTE: Enum values are in the same scope as the enum parent. vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v) case genid.EnumValueDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } vd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.EnumValue, rawOptions) } func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) { var rawFields, rawOneofs [][]byte var enumIdx, messageIdx, extensionIdx int var rawOptions []byte md.L2 = new(MessageL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_Field_field_number: rawFields = append(rawFields, v) case genid.DescriptorProto_OneofDecl_field_number: rawOneofs = append(rawOneofs, v) case genid.DescriptorProto_ReservedName_field_number: md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) case genid.DescriptorProto_ReservedRange_field_number: md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v)) case genid.DescriptorProto_ExtensionRange_field_number: r, rawOptions := unmarshalMessageExtensionRange(v) opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions) md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r) md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts) case genid.DescriptorProto_EnumType_field_number: md.L1.Enums.List[enumIdx].unmarshalFull(v, sb) enumIdx++ case genid.DescriptorProto_NestedType_field_number: md.L1.Messages.List[messageIdx].unmarshalFull(v, sb) messageIdx++ case genid.DescriptorProto_Extension_field_number: md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) extensionIdx++ case genid.DescriptorProto_Options_field_number: md.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if len(rawFields) > 0 || len(rawOneofs) > 0 { md.L2.Fields.List = make([]Field, len(rawFields)) md.L2.Oneofs.List = make([]Oneof, len(rawOneofs)) for i, b := range rawFields { fd := &md.L2.Fields.List[i] fd.unmarshalFull(b, sb, md.L0.ParentFile, md, i) if fd.L1.Cardinality == pref.Required { md.L2.RequiredNumbers.List = append(md.L2.RequiredNumbers.List, fd.L1.Number) } } for i, b := range rawOneofs { od := &md.L2.Oneofs.List[i] od.unmarshalFull(b, sb, md.L0.ParentFile, md, i) } } md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions) } func (md *Message) unmarshalOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MessageOptions_MapEntry_field_number: md.L1.IsMapEntry = protowire.DecodeBool(v) case genid.MessageOptions_MessageSetWireFormat_field_number: md.L1.IsMessageSet = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.DescriptorProto_ReservedRange_Start_field_number: r[0] = pref.FieldNumber(v) case genid.DescriptorProto_ReservedRange_End_field_number: r[1] = pref.FieldNumber(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r } func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, rawOptions []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.DescriptorProto_ExtensionRange_Start_field_number: r[0] = pref.FieldNumber(v) case genid.DescriptorProto_ExtensionRange_End_field_number: r[1] = pref.FieldNumber(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_ExtensionRange_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r, rawOptions } func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { fd.L0.ParentFile = pf fd.L0.Parent = pd fd.L0.Index = i var rawTypeName []byte var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Number_field_number: fd.L1.Number = pref.FieldNumber(v) case genid.FieldDescriptorProto_Label_field_number: fd.L1.Cardinality = pref.Cardinality(v) case genid.FieldDescriptorProto_Type_field_number: fd.L1.Kind = pref.Kind(v) case genid.FieldDescriptorProto_OneofIndex_field_number: // In Message.unmarshalFull, we allocate slices for both // the field and oneof descriptors before unmarshaling either // of them. This ensures pointers to slice elements are stable. od := &pd.(*Message).L2.Oneofs.List[v] od.L1.Fields.List = append(od.L1.Fields.List, fd) if fd.L1.ContainingOneof != nil { panic("oneof type already set") } fd.L1.ContainingOneof = od case genid.FieldDescriptorProto_Proto3Optional_field_number: fd.L1.IsProto3Optional = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Name_field_number: fd.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.FieldDescriptorProto_JsonName_field_number: fd.L1.StringName.InitJSON(sb.MakeString(v)) case genid.FieldDescriptorProto_DefaultValue_field_number: fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages case genid.FieldDescriptorProto_TypeName_field_number: rawTypeName = v case genid.FieldDescriptorProto_Options_field_number: fd.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if rawTypeName != nil { name := makeFullName(sb, rawTypeName) switch fd.L1.Kind { case pref.EnumKind: fd.L1.Enum = PlaceholderEnum(name) case pref.MessageKind, pref.GroupKind: fd.L1.Message = PlaceholderMessage(name) } } fd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Field, rawOptions) } func (fd *Field) unmarshalOptions(b []byte) { const FieldOptions_EnforceUTF8 = 13 for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldOptions_Packed_field_number: fd.L1.HasPacked = true fd.L1.IsPacked = protowire.DecodeBool(v) case genid.FieldOptions_Weak_field_number: fd.L1.IsWeak = protowire.DecodeBool(v) case FieldOptions_EnforceUTF8: fd.L1.HasEnforceUTF8 = true fd.L1.EnforceUTF8 = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { od.L0.ParentFile = pf od.L0.Parent = pd od.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.OneofDescriptorProto_Name_field_number: od.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.OneofDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } od.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Oneof, rawOptions) } func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { var rawTypeName []byte var rawOptions []byte xd.L2 = new(ExtensionL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Proto3Optional_field_number: xd.L2.IsProto3Optional = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_JsonName_field_number: xd.L2.StringName.InitJSON(sb.MakeString(v)) case genid.FieldDescriptorProto_DefaultValue_field_number: xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions case genid.FieldDescriptorProto_TypeName_field_number: rawTypeName = v case genid.FieldDescriptorProto_Options_field_number: xd.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if rawTypeName != nil { name := makeFullName(sb, rawTypeName) switch xd.L1.Kind { case pref.EnumKind: xd.L2.Enum = PlaceholderEnum(name) case pref.MessageKind, pref.GroupKind: xd.L2.Message = PlaceholderMessage(name) } } xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions) } func (xd *Extension) unmarshalOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldOptions_Packed_field_number: xd.L2.IsPacked = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) { var rawMethods [][]byte var rawOptions []byte sd.L2 = new(ServiceL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.ServiceDescriptorProto_Method_field_number: rawMethods = append(rawMethods, v) case genid.ServiceDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if len(rawMethods) > 0 { sd.L2.Methods.List = make([]Method, len(rawMethods)) for i, b := range rawMethods { sd.L2.Methods.List[i].unmarshalFull(b, sb, sd.L0.ParentFile, sd, i) } } sd.L2.Options = sd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Service, rawOptions) } func (md *Method) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { md.L0.ParentFile = pf md.L0.Parent = pd md.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MethodDescriptorProto_ClientStreaming_field_number: md.L1.IsStreamingClient = protowire.DecodeBool(v) case genid.MethodDescriptorProto_ServerStreaming_field_number: md.L1.IsStreamingServer = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.MethodDescriptorProto_Name_field_number: md.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.MethodDescriptorProto_InputType_field_number: md.L1.Input = PlaceholderMessage(makeFullName(sb, v)) case genid.MethodDescriptorProto_OutputType_field_number: md.L1.Output = PlaceholderMessage(makeFullName(sb, v)) case genid.MethodDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } md.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Method, rawOptions) } // appendOptions appends src to dst, where the returned slice is never nil. // This is necessary to distinguish between empty and unpopulated options. func appendOptions(dst, src []byte) []byte { if dst == nil { dst = []byte{} } return append(dst, src...) } // optionsUnmarshaler constructs a lazy unmarshal function for an options message. // // The type of message to unmarshal to is passed as a pointer since the // vars in descopts may not yet be populated at the time this function is called. func (db *Builder) optionsUnmarshaler(p *pref.ProtoMessage, b []byte) func() pref.ProtoMessage { if b == nil { return nil } var opts pref.ProtoMessage var once sync.Once return func() pref.ProtoMessage { once.Do(func() { if *p == nil { panic("Descriptor.Options called without importing the descriptor package") } opts = reflect.New(reflect.TypeOf(*p).Elem()).Interface().(pref.ProtoMessage) if err := (proto.UnmarshalOptions{ AllowPartial: true, Resolver: db.TypeResolver, }).Unmarshal(b, opts); err != nil { panic(err) } }) return opts } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/desc_list.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "fmt" "math" "sort" "sync" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type FileImports []pref.FileImport func (p *FileImports) Len() int { return len(*p) } func (p *FileImports) Get(i int) pref.FileImport { return (*p)[i] } func (p *FileImports) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FileImports) ProtoInternal(pragma.DoNotImplement) {} type Names struct { List []pref.Name once sync.Once has map[pref.Name]int // protected by once } func (p *Names) Len() int { return len(p.List) } func (p *Names) Get(i int) pref.Name { return p.List[i] } func (p *Names) Has(s pref.Name) bool { return p.lazyInit().has[s] > 0 } func (p *Names) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Names) ProtoInternal(pragma.DoNotImplement) {} func (p *Names) lazyInit() *Names { p.once.Do(func() { if len(p.List) > 0 { p.has = make(map[pref.Name]int, len(p.List)) for _, s := range p.List { p.has[s] = p.has[s] + 1 } } }) return p } // CheckValid reports any errors with the set of names with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *Names) CheckValid() error { for s, n := range p.lazyInit().has { switch { case n > 1: return errors.New("duplicate name: %q", s) case false && !s.IsValid(): // NOTE: The C++ implementation does not validate the identifier. // See https://github.com/protocolbuffers/protobuf/issues/6335. return errors.New("invalid name: %q", s) } } return nil } type EnumRanges struct { List [][2]pref.EnumNumber // start inclusive; end inclusive once sync.Once sorted [][2]pref.EnumNumber // protected by once } func (p *EnumRanges) Len() int { return len(p.List) } func (p *EnumRanges) Get(i int) [2]pref.EnumNumber { return p.List[i] } func (p *EnumRanges) Has(n pref.EnumNumber) bool { for ls := p.lazyInit().sorted; len(ls) > 0; { i := len(ls) / 2 switch r := enumRange(ls[i]); { case n < r.Start(): ls = ls[:i] // search lower case n > r.End(): ls = ls[i+1:] // search upper default: return true } } return false } func (p *EnumRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *EnumRanges) ProtoInternal(pragma.DoNotImplement) {} func (p *EnumRanges) lazyInit() *EnumRanges { p.once.Do(func() { p.sorted = append(p.sorted, p.List...) sort.Slice(p.sorted, func(i, j int) bool { return p.sorted[i][0] < p.sorted[j][0] }) }) return p } // CheckValid reports any errors with the set of names with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *EnumRanges) CheckValid() error { var rp enumRange for i, r := range p.lazyInit().sorted { r := enumRange(r) switch { case !(r.Start() <= r.End()): return errors.New("invalid range: %v", r) case !(rp.End() < r.Start()) && i > 0: return errors.New("overlapping ranges: %v with %v", rp, r) } rp = r } return nil } type enumRange [2]protoreflect.EnumNumber func (r enumRange) Start() protoreflect.EnumNumber { return r[0] } // inclusive func (r enumRange) End() protoreflect.EnumNumber { return r[1] } // inclusive func (r enumRange) String() string { if r.Start() == r.End() { return fmt.Sprintf("%d", r.Start()) } return fmt.Sprintf("%d to %d", r.Start(), r.End()) } type FieldRanges struct { List [][2]pref.FieldNumber // start inclusive; end exclusive once sync.Once sorted [][2]pref.FieldNumber // protected by once } func (p *FieldRanges) Len() int { return len(p.List) } func (p *FieldRanges) Get(i int) [2]pref.FieldNumber { return p.List[i] } func (p *FieldRanges) Has(n pref.FieldNumber) bool { for ls := p.lazyInit().sorted; len(ls) > 0; { i := len(ls) / 2 switch r := fieldRange(ls[i]); { case n < r.Start(): ls = ls[:i] // search lower case n > r.End(): ls = ls[i+1:] // search upper default: return true } } return false } func (p *FieldRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FieldRanges) ProtoInternal(pragma.DoNotImplement) {} func (p *FieldRanges) lazyInit() *FieldRanges { p.once.Do(func() { p.sorted = append(p.sorted, p.List...) sort.Slice(p.sorted, func(i, j int) bool { return p.sorted[i][0] < p.sorted[j][0] }) }) return p } // CheckValid reports any errors with the set of ranges with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *FieldRanges) CheckValid(isMessageSet bool) error { var rp fieldRange for i, r := range p.lazyInit().sorted { r := fieldRange(r) switch { case !isValidFieldNumber(r.Start(), isMessageSet): return errors.New("invalid field number: %d", r.Start()) case !isValidFieldNumber(r.End(), isMessageSet): return errors.New("invalid field number: %d", r.End()) case !(r.Start() <= r.End()): return errors.New("invalid range: %v", r) case !(rp.End() < r.Start()) && i > 0: return errors.New("overlapping ranges: %v with %v", rp, r) } rp = r } return nil } // isValidFieldNumber reports whether the field number is valid. // Unlike the FieldNumber.IsValid method, it allows ranges that cover the // reserved number range. func isValidFieldNumber(n protoreflect.FieldNumber, isMessageSet bool) bool { return protowire.MinValidNumber <= n && (n <= protowire.MaxValidNumber || isMessageSet) } // CheckOverlap reports an error if p and q overlap. func (p *FieldRanges) CheckOverlap(q *FieldRanges) error { rps := p.lazyInit().sorted rqs := q.lazyInit().sorted for pi, qi := 0, 0; pi < len(rps) && qi < len(rqs); { rp := fieldRange(rps[pi]) rq := fieldRange(rqs[qi]) if !(rp.End() < rq.Start() || rq.End() < rp.Start()) { return errors.New("overlapping ranges: %v with %v", rp, rq) } if rp.Start() < rq.Start() { pi++ } else { qi++ } } return nil } type fieldRange [2]protoreflect.FieldNumber func (r fieldRange) Start() protoreflect.FieldNumber { return r[0] } // inclusive func (r fieldRange) End() protoreflect.FieldNumber { return r[1] - 1 } // inclusive func (r fieldRange) String() string { if r.Start() == r.End() { return fmt.Sprintf("%d", r.Start()) } return fmt.Sprintf("%d to %d", r.Start(), r.End()) } type FieldNumbers struct { List []pref.FieldNumber once sync.Once has map[pref.FieldNumber]struct{} // protected by once } func (p *FieldNumbers) Len() int { return len(p.List) } func (p *FieldNumbers) Get(i int) pref.FieldNumber { return p.List[i] } func (p *FieldNumbers) Has(n pref.FieldNumber) bool { p.once.Do(func() { if len(p.List) > 0 { p.has = make(map[pref.FieldNumber]struct{}, len(p.List)) for _, n := range p.List { p.has[n] = struct{}{} } } }) _, ok := p.has[n] return ok } func (p *FieldNumbers) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FieldNumbers) ProtoInternal(pragma.DoNotImplement) {} type OneofFields struct { List []pref.FieldDescriptor once sync.Once byName map[pref.Name]pref.FieldDescriptor // protected by once byJSON map[string]pref.FieldDescriptor // protected by once byText map[string]pref.FieldDescriptor // protected by once byNum map[pref.FieldNumber]pref.FieldDescriptor // protected by once } func (p *OneofFields) Len() int { return len(p.List) } func (p *OneofFields) Get(i int) pref.FieldDescriptor { return p.List[i] } func (p *OneofFields) ByName(s pref.Name) pref.FieldDescriptor { return p.lazyInit().byName[s] } func (p *OneofFields) ByJSONName(s string) pref.FieldDescriptor { return p.lazyInit().byJSON[s] } func (p *OneofFields) ByTextName(s string) pref.FieldDescriptor { return p.lazyInit().byText[s] } func (p *OneofFields) ByNumber(n pref.FieldNumber) pref.FieldDescriptor { return p.lazyInit().byNum[n] } func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {} func (p *OneofFields) lazyInit() *OneofFields { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[pref.Name]pref.FieldDescriptor, len(p.List)) p.byJSON = make(map[string]pref.FieldDescriptor, len(p.List)) p.byText = make(map[string]pref.FieldDescriptor, len(p.List)) p.byNum = make(map[pref.FieldNumber]pref.FieldDescriptor, len(p.List)) for _, f := range p.List { // Field names and numbers are guaranteed to be unique. p.byName[f.Name()] = f p.byJSON[f.JSONName()] = f p.byText[f.TextName()] = f p.byNum[f.Number()] = f } } }) return p } type SourceLocations struct { // List is a list of SourceLocations. // The SourceLocation.Next field does not need to be populated // as it will be lazily populated upon first need. List []pref.SourceLocation // File is the parent file descriptor that these locations are relative to. // If non-nil, ByDescriptor verifies that the provided descriptor // is a child of this file descriptor. File pref.FileDescriptor once sync.Once byPath map[pathKey]int } func (p *SourceLocations) Len() int { return len(p.List) } func (p *SourceLocations) Get(i int) pref.SourceLocation { return p.lazyInit().List[i] } func (p *SourceLocations) byKey(k pathKey) pref.SourceLocation { if i, ok := p.lazyInit().byPath[k]; ok { return p.List[i] } return pref.SourceLocation{} } func (p *SourceLocations) ByPath(path pref.SourcePath) pref.SourceLocation { return p.byKey(newPathKey(path)) } func (p *SourceLocations) ByDescriptor(desc pref.Descriptor) pref.SourceLocation { if p.File != nil && desc != nil && p.File != desc.ParentFile() { return pref.SourceLocation{} // mismatching parent files } var pathArr [16]int32 path := pathArr[:0] for { switch desc.(type) { case pref.FileDescriptor: // Reverse the path since it was constructed in reverse. for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 { path[i], path[j] = path[j], path[i] } return p.byKey(newPathKey(path)) case pref.MessageDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_MessageType_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_NestedType_field_number)) default: return pref.SourceLocation{} } case pref.FieldDescriptor: isExtension := desc.(pref.FieldDescriptor).IsExtension() path = append(path, int32(desc.Index())) desc = desc.Parent() if isExtension { switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_Extension_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_Extension_field_number)) default: return pref.SourceLocation{} } } else { switch desc.(type) { case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_Field_field_number)) default: return pref.SourceLocation{} } } case pref.OneofDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_OneofDecl_field_number)) default: return pref.SourceLocation{} } case pref.EnumDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_EnumType_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_EnumType_field_number)) default: return pref.SourceLocation{} } case pref.EnumValueDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.EnumDescriptor: path = append(path, int32(genid.EnumDescriptorProto_Value_field_number)) default: return pref.SourceLocation{} } case pref.ServiceDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_Service_field_number)) default: return pref.SourceLocation{} } case pref.MethodDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.ServiceDescriptor: path = append(path, int32(genid.ServiceDescriptorProto_Method_field_number)) default: return pref.SourceLocation{} } default: return pref.SourceLocation{} } } } func (p *SourceLocations) lazyInit() *SourceLocations { p.once.Do(func() { if len(p.List) > 0 { // Collect all the indexes for a given path. pathIdxs := make(map[pathKey][]int, len(p.List)) for i, l := range p.List { k := newPathKey(l.Path) pathIdxs[k] = append(pathIdxs[k], i) } // Update the next index for all locations. p.byPath = make(map[pathKey]int, len(p.List)) for k, idxs := range pathIdxs { for i := 0; i < len(idxs)-1; i++ { p.List[idxs[i]].Next = idxs[i+1] } p.List[idxs[len(idxs)-1]].Next = 0 p.byPath[k] = idxs[0] // record the first location for this path } } }) return p } func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {} // pathKey is a comparable representation of protoreflect.SourcePath. type pathKey struct { arr [16]uint8 // first n-1 path segments; last element is the length str string // used if the path does not fit in arr } func newPathKey(p pref.SourcePath) (k pathKey) { if len(p) < len(k.arr) { for i, ps := range p { if ps < 0 || math.MaxUint8 <= ps { return pathKey{str: p.String()} } k.arr[i] = uint8(ps) } k.arr[len(k.arr)-1] = uint8(len(p)) return k } return pathKey{str: p.String()} } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package filedesc import ( "fmt" "sync" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" ) type Enums struct { List []Enum once sync.Once byName map[protoreflect.Name]*Enum // protected by once } func (p *Enums) Len() int { return len(p.List) } func (p *Enums) Get(i int) protoreflect.EnumDescriptor { return &p.List[i] } func (p *Enums) ByName(s protoreflect.Name) protoreflect.EnumDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Enums) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Enums) ProtoInternal(pragma.DoNotImplement) {} func (p *Enums) lazyInit() *Enums { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Enum, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type EnumValues struct { List []EnumValue once sync.Once byName map[protoreflect.Name]*EnumValue // protected by once byNum map[protoreflect.EnumNumber]*EnumValue // protected by once } func (p *EnumValues) Len() int { return len(p.List) } func (p *EnumValues) Get(i int) protoreflect.EnumValueDescriptor { return &p.List[i] } func (p *EnumValues) ByName(s protoreflect.Name) protoreflect.EnumValueDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *EnumValues) ByNumber(n protoreflect.EnumNumber) protoreflect.EnumValueDescriptor { if d := p.lazyInit().byNum[n]; d != nil { return d } return nil } func (p *EnumValues) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *EnumValues) ProtoInternal(pragma.DoNotImplement) {} func (p *EnumValues) lazyInit() *EnumValues { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*EnumValue, len(p.List)) p.byNum = make(map[protoreflect.EnumNumber]*EnumValue, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } if _, ok := p.byNum[d.Number()]; !ok { p.byNum[d.Number()] = d } } } }) return p } type Messages struct { List []Message once sync.Once byName map[protoreflect.Name]*Message // protected by once } func (p *Messages) Len() int { return len(p.List) } func (p *Messages) Get(i int) protoreflect.MessageDescriptor { return &p.List[i] } func (p *Messages) ByName(s protoreflect.Name) protoreflect.MessageDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Messages) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Messages) ProtoInternal(pragma.DoNotImplement) {} func (p *Messages) lazyInit() *Messages { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Message, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Fields struct { List []Field once sync.Once byName map[protoreflect.Name]*Field // protected by once byJSON map[string]*Field // protected by once byText map[string]*Field // protected by once byNum map[protoreflect.FieldNumber]*Field // protected by once } func (p *Fields) Len() int { return len(p.List) } func (p *Fields) Get(i int) protoreflect.FieldDescriptor { return &p.List[i] } func (p *Fields) ByName(s protoreflect.Name) protoreflect.FieldDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Fields) ByJSONName(s string) protoreflect.FieldDescriptor { if d := p.lazyInit().byJSON[s]; d != nil { return d } return nil } func (p *Fields) ByTextName(s string) protoreflect.FieldDescriptor { if d := p.lazyInit().byText[s]; d != nil { return d } return nil } func (p *Fields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor { if d := p.lazyInit().byNum[n]; d != nil { return d } return nil } func (p *Fields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Fields) ProtoInternal(pragma.DoNotImplement) {} func (p *Fields) lazyInit() *Fields { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Field, len(p.List)) p.byJSON = make(map[string]*Field, len(p.List)) p.byText = make(map[string]*Field, len(p.List)) p.byNum = make(map[protoreflect.FieldNumber]*Field, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } if _, ok := p.byJSON[d.JSONName()]; !ok { p.byJSON[d.JSONName()] = d } if _, ok := p.byText[d.TextName()]; !ok { p.byText[d.TextName()] = d } if _, ok := p.byNum[d.Number()]; !ok { p.byNum[d.Number()] = d } } } }) return p } type Oneofs struct { List []Oneof once sync.Once byName map[protoreflect.Name]*Oneof // protected by once } func (p *Oneofs) Len() int { return len(p.List) } func (p *Oneofs) Get(i int) protoreflect.OneofDescriptor { return &p.List[i] } func (p *Oneofs) ByName(s protoreflect.Name) protoreflect.OneofDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Oneofs) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Oneofs) ProtoInternal(pragma.DoNotImplement) {} func (p *Oneofs) lazyInit() *Oneofs { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Oneof, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Extensions struct { List []Extension once sync.Once byName map[protoreflect.Name]*Extension // protected by once } func (p *Extensions) Len() int { return len(p.List) } func (p *Extensions) Get(i int) protoreflect.ExtensionDescriptor { return &p.List[i] } func (p *Extensions) ByName(s protoreflect.Name) protoreflect.ExtensionDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Extensions) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Extensions) ProtoInternal(pragma.DoNotImplement) {} func (p *Extensions) lazyInit() *Extensions { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Extension, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Services struct { List []Service once sync.Once byName map[protoreflect.Name]*Service // protected by once } func (p *Services) Len() int { return len(p.List) } func (p *Services) Get(i int) protoreflect.ServiceDescriptor { return &p.List[i] } func (p *Services) ByName(s protoreflect.Name) protoreflect.ServiceDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Services) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Services) ProtoInternal(pragma.DoNotImplement) {} func (p *Services) lazyInit() *Services { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Service, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Methods struct { List []Method once sync.Once byName map[protoreflect.Name]*Method // protected by once } func (p *Methods) Len() int { return len(p.List) } func (p *Methods) Get(i int) protoreflect.MethodDescriptor { return &p.List[i] } func (p *Methods) ByName(s protoreflect.Name) protoreflect.MethodDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Methods) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Methods) ProtoInternal(pragma.DoNotImplement) {} func (p *Methods) lazyInit() *Methods { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Method, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filedesc/placeholder.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) var ( emptyNames = new(Names) emptyEnumRanges = new(EnumRanges) emptyFieldRanges = new(FieldRanges) emptyFieldNumbers = new(FieldNumbers) emptySourceLocations = new(SourceLocations) emptyFiles = new(FileImports) emptyMessages = new(Messages) emptyFields = new(Fields) emptyOneofs = new(Oneofs) emptyEnums = new(Enums) emptyEnumValues = new(EnumValues) emptyExtensions = new(Extensions) emptyServices = new(Services) ) // PlaceholderFile is a placeholder, representing only the file path. type PlaceholderFile string func (f PlaceholderFile) ParentFile() pref.FileDescriptor { return f } func (f PlaceholderFile) Parent() pref.Descriptor { return nil } func (f PlaceholderFile) Index() int { return 0 } func (f PlaceholderFile) Syntax() pref.Syntax { return 0 } func (f PlaceholderFile) Name() pref.Name { return "" } func (f PlaceholderFile) FullName() pref.FullName { return "" } func (f PlaceholderFile) IsPlaceholder() bool { return true } func (f PlaceholderFile) Options() pref.ProtoMessage { return descopts.File } func (f PlaceholderFile) Path() string { return string(f) } func (f PlaceholderFile) Package() pref.FullName { return "" } func (f PlaceholderFile) Imports() pref.FileImports { return emptyFiles } func (f PlaceholderFile) Messages() pref.MessageDescriptors { return emptyMessages } func (f PlaceholderFile) Enums() pref.EnumDescriptors { return emptyEnums } func (f PlaceholderFile) Extensions() pref.ExtensionDescriptors { return emptyExtensions } func (f PlaceholderFile) Services() pref.ServiceDescriptors { return emptyServices } func (f PlaceholderFile) SourceLocations() pref.SourceLocations { return emptySourceLocations } func (f PlaceholderFile) ProtoType(pref.FileDescriptor) { return } func (f PlaceholderFile) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderEnum is a placeholder, representing only the full name. type PlaceholderEnum pref.FullName func (e PlaceholderEnum) ParentFile() pref.FileDescriptor { return nil } func (e PlaceholderEnum) Parent() pref.Descriptor { return nil } func (e PlaceholderEnum) Index() int { return 0 } func (e PlaceholderEnum) Syntax() pref.Syntax { return 0 } func (e PlaceholderEnum) Name() pref.Name { return pref.FullName(e).Name() } func (e PlaceholderEnum) FullName() pref.FullName { return pref.FullName(e) } func (e PlaceholderEnum) IsPlaceholder() bool { return true } func (e PlaceholderEnum) Options() pref.ProtoMessage { return descopts.Enum } func (e PlaceholderEnum) Values() pref.EnumValueDescriptors { return emptyEnumValues } func (e PlaceholderEnum) ReservedNames() pref.Names { return emptyNames } func (e PlaceholderEnum) ReservedRanges() pref.EnumRanges { return emptyEnumRanges } func (e PlaceholderEnum) ProtoType(pref.EnumDescriptor) { return } func (e PlaceholderEnum) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderEnumValue is a placeholder, representing only the full name. type PlaceholderEnumValue pref.FullName func (e PlaceholderEnumValue) ParentFile() pref.FileDescriptor { return nil } func (e PlaceholderEnumValue) Parent() pref.Descriptor { return nil } func (e PlaceholderEnumValue) Index() int { return 0 } func (e PlaceholderEnumValue) Syntax() pref.Syntax { return 0 } func (e PlaceholderEnumValue) Name() pref.Name { return pref.FullName(e).Name() } func (e PlaceholderEnumValue) FullName() pref.FullName { return pref.FullName(e) } func (e PlaceholderEnumValue) IsPlaceholder() bool { return true } func (e PlaceholderEnumValue) Options() pref.ProtoMessage { return descopts.EnumValue } func (e PlaceholderEnumValue) Number() pref.EnumNumber { return 0 } func (e PlaceholderEnumValue) ProtoType(pref.EnumValueDescriptor) { return } func (e PlaceholderEnumValue) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderMessage is a placeholder, representing only the full name. type PlaceholderMessage pref.FullName func (m PlaceholderMessage) ParentFile() pref.FileDescriptor { return nil } func (m PlaceholderMessage) Parent() pref.Descriptor { return nil } func (m PlaceholderMessage) Index() int { return 0 } func (m PlaceholderMessage) Syntax() pref.Syntax { return 0 } func (m PlaceholderMessage) Name() pref.Name { return pref.FullName(m).Name() } func (m PlaceholderMessage) FullName() pref.FullName { return pref.FullName(m) } func (m PlaceholderMessage) IsPlaceholder() bool { return true } func (m PlaceholderMessage) Options() pref.ProtoMessage { return descopts.Message } func (m PlaceholderMessage) IsMapEntry() bool { return false } func (m PlaceholderMessage) Fields() pref.FieldDescriptors { return emptyFields } func (m PlaceholderMessage) Oneofs() pref.OneofDescriptors { return emptyOneofs } func (m PlaceholderMessage) ReservedNames() pref.Names { return emptyNames } func (m PlaceholderMessage) ReservedRanges() pref.FieldRanges { return emptyFieldRanges } func (m PlaceholderMessage) RequiredNumbers() pref.FieldNumbers { return emptyFieldNumbers } func (m PlaceholderMessage) ExtensionRanges() pref.FieldRanges { return emptyFieldRanges } func (m PlaceholderMessage) ExtensionRangeOptions(int) pref.ProtoMessage { panic("index out of range") } func (m PlaceholderMessage) Messages() pref.MessageDescriptors { return emptyMessages } func (m PlaceholderMessage) Enums() pref.EnumDescriptors { return emptyEnums } func (m PlaceholderMessage) Extensions() pref.ExtensionDescriptors { return emptyExtensions } func (m PlaceholderMessage) ProtoType(pref.MessageDescriptor) { return } func (m PlaceholderMessage) ProtoInternal(pragma.DoNotImplement) { return } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/filetype/build.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package filetype provides functionality for wrapping descriptors // with Go type information. package filetype import ( "reflect" "google.golang.org/protobuf/internal/descopts" fdesc "google.golang.org/protobuf/internal/filedesc" pimpl "google.golang.org/protobuf/internal/impl" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // Builder constructs type descriptors from a raw file descriptor // and associated Go types for each enum and message declaration. // // // Flattened Ordering // // The protobuf type system represents declarations as a tree. Certain nodes in // the tree require us to either associate it with a concrete Go type or to // resolve a dependency, which is information that must be provided separately // since it cannot be derived from the file descriptor alone. // // However, representing a tree as Go literals is difficult to simply do in a // space and time efficient way. Thus, we store them as a flattened list of // objects where the serialization order from the tree-based form is important. // // The "flattened ordering" is defined as a tree traversal of all enum, message, // extension, and service declarations using the following algorithm: // // def VisitFileDecls(fd): // for e in fd.Enums: yield e // for m in fd.Messages: yield m // for x in fd.Extensions: yield x // for s in fd.Services: yield s // for m in fd.Messages: yield from VisitMessageDecls(m) // // def VisitMessageDecls(md): // for e in md.Enums: yield e // for m in md.Messages: yield m // for x in md.Extensions: yield x // for m in md.Messages: yield from VisitMessageDecls(m) // // The traversal starts at the root file descriptor and yields each direct // declaration within each node before traversing into sub-declarations // that children themselves may have. type Builder struct { // File is the underlying file descriptor builder. File fdesc.Builder // GoTypes is a unique set of the Go types for all declarations and // dependencies. Each type is represented as a zero value of the Go type. // // Declarations are Go types generated for enums and messages directly // declared (not publicly imported) in the proto source file. // Messages for map entries are accounted for, but represented by nil. // Enum declarations in "flattened ordering" come first, followed by // message declarations in "flattened ordering". // // Dependencies are Go types for enums or messages referenced by // message fields (excluding weak fields), for parent extended messages of // extension fields, for enums or messages referenced by extension fields, // and for input and output messages referenced by service methods. // Dependencies must come after declarations, but the ordering of // dependencies themselves is unspecified. GoTypes []interface{} // DependencyIndexes is an ordered list of indexes into GoTypes for the // dependencies of messages, extensions, or services. // // There are 5 sub-lists in "flattened ordering" concatenated back-to-back: // 0. Message field dependencies: list of the enum or message type // referred to by every message field. // 1. Extension field targets: list of the extended parent message of // every extension. // 2. Extension field dependencies: list of the enum or message type // referred to by every extension field. // 3. Service method inputs: list of the input message type // referred to by every service method. // 4. Service method outputs: list of the output message type // referred to by every service method. // // The offset into DependencyIndexes for the start of each sub-list // is appended to the end in reverse order. DependencyIndexes []int32 // EnumInfos is a list of enum infos in "flattened ordering". EnumInfos []pimpl.EnumInfo // MessageInfos is a list of message infos in "flattened ordering". // If provided, the GoType and PBType for each element is populated. // // Requirement: len(MessageInfos) == len(Build.Messages) MessageInfos []pimpl.MessageInfo // ExtensionInfos is a list of extension infos in "flattened ordering". // Each element is initialized and registered with the protoregistry package. // // Requirement: len(LegacyExtensions) == len(Build.Extensions) ExtensionInfos []pimpl.ExtensionInfo // TypeRegistry is the registry to register each type descriptor. // If nil, it uses protoregistry.GlobalTypes. TypeRegistry interface { RegisterMessage(pref.MessageType) error RegisterEnum(pref.EnumType) error RegisterExtension(pref.ExtensionType) error } } // Out is the output of the builder. type Out struct { File pref.FileDescriptor } func (tb Builder) Build() (out Out) { // Replace the resolver with one that resolves dependencies by index, // which is faster and more reliable than relying on the global registry. if tb.File.FileRegistry == nil { tb.File.FileRegistry = preg.GlobalFiles } tb.File.FileRegistry = &resolverByIndex{ goTypes: tb.GoTypes, depIdxs: tb.DependencyIndexes, fileRegistry: tb.File.FileRegistry, } // Initialize registry if unpopulated. if tb.TypeRegistry == nil { tb.TypeRegistry = preg.GlobalTypes } fbOut := tb.File.Build() out.File = fbOut.File // Process enums. enumGoTypes := tb.GoTypes[:len(fbOut.Enums)] if len(tb.EnumInfos) != len(fbOut.Enums) { panic("mismatching enum lengths") } if len(fbOut.Enums) > 0 { for i := range fbOut.Enums { tb.EnumInfos[i] = pimpl.EnumInfo{ GoReflectType: reflect.TypeOf(enumGoTypes[i]), Desc: &fbOut.Enums[i], } // Register enum types. if err := tb.TypeRegistry.RegisterEnum(&tb.EnumInfos[i]); err != nil { panic(err) } } } // Process messages. messageGoTypes := tb.GoTypes[len(fbOut.Enums):][:len(fbOut.Messages)] if len(tb.MessageInfos) != len(fbOut.Messages) { panic("mismatching message lengths") } if len(fbOut.Messages) > 0 { for i := range fbOut.Messages { if messageGoTypes[i] == nil { continue // skip map entry } tb.MessageInfos[i].GoReflectType = reflect.TypeOf(messageGoTypes[i]) tb.MessageInfos[i].Desc = &fbOut.Messages[i] // Register message types. if err := tb.TypeRegistry.RegisterMessage(&tb.MessageInfos[i]); err != nil { panic(err) } } // As a special-case for descriptor.proto, // locally register concrete message type for the options. if out.File.Path() == "google/protobuf/descriptor.proto" && out.File.Package() == "google.protobuf" { for i := range fbOut.Messages { switch fbOut.Messages[i].Name() { case "FileOptions": descopts.File = messageGoTypes[i].(pref.ProtoMessage) case "EnumOptions": descopts.Enum = messageGoTypes[i].(pref.ProtoMessage) case "EnumValueOptions": descopts.EnumValue = messageGoTypes[i].(pref.ProtoMessage) case "MessageOptions": descopts.Message = messageGoTypes[i].(pref.ProtoMessage) case "FieldOptions": descopts.Field = messageGoTypes[i].(pref.ProtoMessage) case "OneofOptions": descopts.Oneof = messageGoTypes[i].(pref.ProtoMessage) case "ExtensionRangeOptions": descopts.ExtensionRange = messageGoTypes[i].(pref.ProtoMessage) case "ServiceOptions": descopts.Service = messageGoTypes[i].(pref.ProtoMessage) case "MethodOptions": descopts.Method = messageGoTypes[i].(pref.ProtoMessage) } } } } // Process extensions. if len(tb.ExtensionInfos) != len(fbOut.Extensions) { panic("mismatching extension lengths") } var depIdx int32 for i := range fbOut.Extensions { // For enum and message kinds, determine the referent Go type so // that we can construct their constructors. const listExtDeps = 2 var goType reflect.Type switch fbOut.Extensions[i].L1.Kind { case pref.EnumKind: j := depIdxs.Get(tb.DependencyIndexes, listExtDeps, depIdx) goType = reflect.TypeOf(tb.GoTypes[j]) depIdx++ case pref.MessageKind, pref.GroupKind: j := depIdxs.Get(tb.DependencyIndexes, listExtDeps, depIdx) goType = reflect.TypeOf(tb.GoTypes[j]) depIdx++ default: goType = goTypeForPBKind[fbOut.Extensions[i].L1.Kind] } if fbOut.Extensions[i].IsList() { goType = reflect.SliceOf(goType) } pimpl.InitExtensionInfo(&tb.ExtensionInfos[i], &fbOut.Extensions[i], goType) // Register extension types. if err := tb.TypeRegistry.RegisterExtension(&tb.ExtensionInfos[i]); err != nil { panic(err) } } return out } var goTypeForPBKind = map[pref.Kind]reflect.Type{ pref.BoolKind: reflect.TypeOf(bool(false)), pref.Int32Kind: reflect.TypeOf(int32(0)), pref.Sint32Kind: reflect.TypeOf(int32(0)), pref.Sfixed32Kind: reflect.TypeOf(int32(0)), pref.Int64Kind: reflect.TypeOf(int64(0)), pref.Sint64Kind: reflect.TypeOf(int64(0)), pref.Sfixed64Kind: reflect.TypeOf(int64(0)), pref.Uint32Kind: reflect.TypeOf(uint32(0)), pref.Fixed32Kind: reflect.TypeOf(uint32(0)), pref.Uint64Kind: reflect.TypeOf(uint64(0)), pref.Fixed64Kind: reflect.TypeOf(uint64(0)), pref.FloatKind: reflect.TypeOf(float32(0)), pref.DoubleKind: reflect.TypeOf(float64(0)), pref.StringKind: reflect.TypeOf(string("")), pref.BytesKind: reflect.TypeOf([]byte(nil)), } type depIdxs []int32 // Get retrieves the jth element of the ith sub-list. func (x depIdxs) Get(i, j int32) int32 { return x[x[int32(len(x))-i-1]+j] } type ( resolverByIndex struct { goTypes []interface{} depIdxs depIdxs fileRegistry } fileRegistry interface { FindFileByPath(string) (pref.FileDescriptor, error) FindDescriptorByName(pref.FullName) (pref.Descriptor, error) RegisterFile(pref.FileDescriptor) error } ) func (r *resolverByIndex) FindEnumByIndex(i, j int32, es []fdesc.Enum, ms []fdesc.Message) pref.EnumDescriptor { if depIdx := int(r.depIdxs.Get(i, j)); int(depIdx) < len(es)+len(ms) { return &es[depIdx] } else { return pimpl.Export{}.EnumDescriptorOf(r.goTypes[depIdx]) } } func (r *resolverByIndex) FindMessageByIndex(i, j int32, es []fdesc.Enum, ms []fdesc.Message) pref.MessageDescriptor { if depIdx := int(r.depIdxs.Get(i, j)); depIdx < len(es)+len(ms) { return &ms[depIdx-len(es)] } else { return pimpl.Export{}.MessageDescriptorOf(r.goTypes[depIdx]) } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/flags/flags.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package flags provides a set of flags controlled by build tags. package flags // ProtoLegacy specifies whether to enable support for legacy functionality // such as MessageSets, weak fields, and various other obscure behavior // that is necessary to maintain backwards compatibility with proto1 or // the pre-release variants of proto2 and proto3. // // This is disabled by default unless built with the "protolegacy" tag. // // WARNING: The compatibility agreement covers nothing provided by this flag. // As such, functionality may suddenly be removed or changed at our discretion. const ProtoLegacy = protoLegacy // LazyUnmarshalExtensions specifies whether to lazily unmarshal extensions. // // Lazy extension unmarshaling validates the contents of message-valued // extension fields at unmarshal time, but defers creating the message // structure until the extension is first accessed. const LazyUnmarshalExtensions = ProtoLegacy ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/flags/proto_legacy_disable.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !protolegacy package flags const protoLegacy = false ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/flags/proto_legacy_enable.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build protolegacy package flags const protoLegacy = true ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/any_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_any_proto = "google/protobuf/any.proto" // Names for google.protobuf.Any. const ( Any_message_name protoreflect.Name = "Any" Any_message_fullname protoreflect.FullName = "google.protobuf.Any" ) // Field names for google.protobuf.Any. const ( Any_TypeUrl_field_name protoreflect.Name = "type_url" Any_Value_field_name protoreflect.Name = "value" Any_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Any.type_url" Any_Value_field_fullname protoreflect.FullName = "google.protobuf.Any.value" ) // Field numbers for google.protobuf.Any. const ( Any_TypeUrl_field_number protoreflect.FieldNumber = 1 Any_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/api_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_api_proto = "google/protobuf/api.proto" // Names for google.protobuf.Api. const ( Api_message_name protoreflect.Name = "Api" Api_message_fullname protoreflect.FullName = "google.protobuf.Api" ) // Field names for google.protobuf.Api. const ( Api_Name_field_name protoreflect.Name = "name" Api_Methods_field_name protoreflect.Name = "methods" Api_Options_field_name protoreflect.Name = "options" Api_Version_field_name protoreflect.Name = "version" Api_SourceContext_field_name protoreflect.Name = "source_context" Api_Mixins_field_name protoreflect.Name = "mixins" Api_Syntax_field_name protoreflect.Name = "syntax" Api_Name_field_fullname protoreflect.FullName = "google.protobuf.Api.name" Api_Methods_field_fullname protoreflect.FullName = "google.protobuf.Api.methods" Api_Options_field_fullname protoreflect.FullName = "google.protobuf.Api.options" Api_Version_field_fullname protoreflect.FullName = "google.protobuf.Api.version" Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context" Api_Mixins_field_fullname protoreflect.FullName = "google.protobuf.Api.mixins" Api_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Api.syntax" ) // Field numbers for google.protobuf.Api. const ( Api_Name_field_number protoreflect.FieldNumber = 1 Api_Methods_field_number protoreflect.FieldNumber = 2 Api_Options_field_number protoreflect.FieldNumber = 3 Api_Version_field_number protoreflect.FieldNumber = 4 Api_SourceContext_field_number protoreflect.FieldNumber = 5 Api_Mixins_field_number protoreflect.FieldNumber = 6 Api_Syntax_field_number protoreflect.FieldNumber = 7 ) // Names for google.protobuf.Method. const ( Method_message_name protoreflect.Name = "Method" Method_message_fullname protoreflect.FullName = "google.protobuf.Method" ) // Field names for google.protobuf.Method. const ( Method_Name_field_name protoreflect.Name = "name" Method_RequestTypeUrl_field_name protoreflect.Name = "request_type_url" Method_RequestStreaming_field_name protoreflect.Name = "request_streaming" Method_ResponseTypeUrl_field_name protoreflect.Name = "response_type_url" Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming" Method_Options_field_name protoreflect.Name = "options" Method_Syntax_field_name protoreflect.Name = "syntax" Method_Name_field_fullname protoreflect.FullName = "google.protobuf.Method.name" Method_RequestTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.request_type_url" Method_RequestStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.request_streaming" Method_ResponseTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.response_type_url" Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming" Method_Options_field_fullname protoreflect.FullName = "google.protobuf.Method.options" Method_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Method.syntax" ) // Field numbers for google.protobuf.Method. const ( Method_Name_field_number protoreflect.FieldNumber = 1 Method_RequestTypeUrl_field_number protoreflect.FieldNumber = 2 Method_RequestStreaming_field_number protoreflect.FieldNumber = 3 Method_ResponseTypeUrl_field_number protoreflect.FieldNumber = 4 Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5 Method_Options_field_number protoreflect.FieldNumber = 6 Method_Syntax_field_number protoreflect.FieldNumber = 7 ) // Names for google.protobuf.Mixin. const ( Mixin_message_name protoreflect.Name = "Mixin" Mixin_message_fullname protoreflect.FullName = "google.protobuf.Mixin" ) // Field names for google.protobuf.Mixin. const ( Mixin_Name_field_name protoreflect.Name = "name" Mixin_Root_field_name protoreflect.Name = "root" Mixin_Name_field_fullname protoreflect.FullName = "google.protobuf.Mixin.name" Mixin_Root_field_fullname protoreflect.FullName = "google.protobuf.Mixin.root" ) // Field numbers for google.protobuf.Mixin. const ( Mixin_Name_field_number protoreflect.FieldNumber = 1 Mixin_Root_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/descriptor_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto" // Names for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet" FileDescriptorSet_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet" ) // Field names for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_File_field_name protoreflect.Name = "file" FileDescriptorSet_File_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet.file" ) // Field numbers for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_File_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_message_name protoreflect.Name = "FileDescriptorProto" FileDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto" ) // Field names for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_Name_field_name protoreflect.Name = "name" FileDescriptorProto_Package_field_name protoreflect.Name = "package" FileDescriptorProto_Dependency_field_name protoreflect.Name = "dependency" FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency" FileDescriptorProto_WeakDependency_field_name protoreflect.Name = "weak_dependency" FileDescriptorProto_MessageType_field_name protoreflect.Name = "message_type" FileDescriptorProto_EnumType_field_name protoreflect.Name = "enum_type" FileDescriptorProto_Service_field_name protoreflect.Name = "service" FileDescriptorProto_Extension_field_name protoreflect.Name = "extension" FileDescriptorProto_Options_field_name protoreflect.Name = "options" FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info" FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax" FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name" FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package" FileDescriptorProto_Dependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency" FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency" FileDescriptorProto_WeakDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency" FileDescriptorProto_MessageType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type" FileDescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type" FileDescriptorProto_Service_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.service" FileDescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.extension" FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options" FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info" FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax" ) // Field numbers for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 FileDescriptorProto_Package_field_number protoreflect.FieldNumber = 2 FileDescriptorProto_Dependency_field_number protoreflect.FieldNumber = 3 FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10 FileDescriptorProto_WeakDependency_field_number protoreflect.FieldNumber = 11 FileDescriptorProto_MessageType_field_number protoreflect.FieldNumber = 4 FileDescriptorProto_EnumType_field_number protoreflect.FieldNumber = 5 FileDescriptorProto_Service_field_number protoreflect.FieldNumber = 6 FileDescriptorProto_Extension_field_number protoreflect.FieldNumber = 7 FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9 FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12 ) // Names for google.protobuf.DescriptorProto. const ( DescriptorProto_message_name protoreflect.Name = "DescriptorProto" DescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto" ) // Field names for google.protobuf.DescriptorProto. const ( DescriptorProto_Name_field_name protoreflect.Name = "name" DescriptorProto_Field_field_name protoreflect.Name = "field" DescriptorProto_Extension_field_name protoreflect.Name = "extension" DescriptorProto_NestedType_field_name protoreflect.Name = "nested_type" DescriptorProto_EnumType_field_name protoreflect.Name = "enum_type" DescriptorProto_ExtensionRange_field_name protoreflect.Name = "extension_range" DescriptorProto_OneofDecl_field_name protoreflect.Name = "oneof_decl" DescriptorProto_Options_field_name protoreflect.Name = "options" DescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range" DescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name" DescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.name" DescriptorProto_Field_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.field" DescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension" DescriptorProto_NestedType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.nested_type" DescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.enum_type" DescriptorProto_ExtensionRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension_range" DescriptorProto_OneofDecl_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.oneof_decl" DescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.options" DescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range" DescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name" ) // Field numbers for google.protobuf.DescriptorProto. const ( DescriptorProto_Name_field_number protoreflect.FieldNumber = 1 DescriptorProto_Field_field_number protoreflect.FieldNumber = 2 DescriptorProto_Extension_field_number protoreflect.FieldNumber = 6 DescriptorProto_NestedType_field_number protoreflect.FieldNumber = 3 DescriptorProto_EnumType_field_number protoreflect.FieldNumber = 4 DescriptorProto_ExtensionRange_field_number protoreflect.FieldNumber = 5 DescriptorProto_OneofDecl_field_number protoreflect.FieldNumber = 8 DescriptorProto_Options_field_number protoreflect.FieldNumber = 7 DescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 9 DescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 10 ) // Names for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_message_name protoreflect.Name = "ExtensionRange" DescriptorProto_ExtensionRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange" ) // Field names for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_Start_field_name protoreflect.Name = "start" DescriptorProto_ExtensionRange_End_field_name protoreflect.Name = "end" DescriptorProto_ExtensionRange_Options_field_name protoreflect.Name = "options" DescriptorProto_ExtensionRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.start" DescriptorProto_ExtensionRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.end" DescriptorProto_ExtensionRange_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.options" ) // Field numbers for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_Start_field_number protoreflect.FieldNumber = 1 DescriptorProto_ExtensionRange_End_field_number protoreflect.FieldNumber = 2 DescriptorProto_ExtensionRange_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_message_name protoreflect.Name = "ReservedRange" DescriptorProto_ReservedRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange" ) // Field names for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_Start_field_name protoreflect.Name = "start" DescriptorProto_ReservedRange_End_field_name protoreflect.Name = "end" DescriptorProto_ReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.start" DescriptorProto_ReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.end" ) // Field numbers for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_Start_field_number protoreflect.FieldNumber = 1 DescriptorProto_ReservedRange_End_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_message_name protoreflect.Name = "ExtensionRangeOptions" ExtensionRangeOptions_message_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions" ) // Field names for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option" ) // Field numbers for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_message_name protoreflect.Name = "FieldDescriptorProto" FieldDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto" ) // Field names for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_Name_field_name protoreflect.Name = "name" FieldDescriptorProto_Number_field_name protoreflect.Name = "number" FieldDescriptorProto_Label_field_name protoreflect.Name = "label" FieldDescriptorProto_Type_field_name protoreflect.Name = "type" FieldDescriptorProto_TypeName_field_name protoreflect.Name = "type_name" FieldDescriptorProto_Extendee_field_name protoreflect.Name = "extendee" FieldDescriptorProto_DefaultValue_field_name protoreflect.Name = "default_value" FieldDescriptorProto_OneofIndex_field_name protoreflect.Name = "oneof_index" FieldDescriptorProto_JsonName_field_name protoreflect.Name = "json_name" FieldDescriptorProto_Options_field_name protoreflect.Name = "options" FieldDescriptorProto_Proto3Optional_field_name protoreflect.Name = "proto3_optional" FieldDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.name" FieldDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.number" FieldDescriptorProto_Label_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.label" FieldDescriptorProto_Type_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type" FieldDescriptorProto_TypeName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type_name" FieldDescriptorProto_Extendee_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.extendee" FieldDescriptorProto_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.default_value" FieldDescriptorProto_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.oneof_index" FieldDescriptorProto_JsonName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.json_name" FieldDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.options" FieldDescriptorProto_Proto3Optional_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.proto3_optional" ) // Field numbers for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 FieldDescriptorProto_Number_field_number protoreflect.FieldNumber = 3 FieldDescriptorProto_Label_field_number protoreflect.FieldNumber = 4 FieldDescriptorProto_Type_field_number protoreflect.FieldNumber = 5 FieldDescriptorProto_TypeName_field_number protoreflect.FieldNumber = 6 FieldDescriptorProto_Extendee_field_number protoreflect.FieldNumber = 2 FieldDescriptorProto_DefaultValue_field_number protoreflect.FieldNumber = 7 FieldDescriptorProto_OneofIndex_field_number protoreflect.FieldNumber = 9 FieldDescriptorProto_JsonName_field_number protoreflect.FieldNumber = 10 FieldDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FieldDescriptorProto_Proto3Optional_field_number protoreflect.FieldNumber = 17 ) // Full and short names for google.protobuf.FieldDescriptorProto.Type. const ( FieldDescriptorProto_Type_enum_fullname = "google.protobuf.FieldDescriptorProto.Type" FieldDescriptorProto_Type_enum_name = "Type" ) // Full and short names for google.protobuf.FieldDescriptorProto.Label. const ( FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label" FieldDescriptorProto_Label_enum_name = "Label" ) // Names for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto" OneofDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto" ) // Field names for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_Name_field_name protoreflect.Name = "name" OneofDescriptorProto_Options_field_name protoreflect.Name = "options" OneofDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.name" OneofDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.options" ) // Field numbers for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 OneofDescriptorProto_Options_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_message_name protoreflect.Name = "EnumDescriptorProto" EnumDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto" ) // Field names for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_Name_field_name protoreflect.Name = "name" EnumDescriptorProto_Value_field_name protoreflect.Name = "value" EnumDescriptorProto_Options_field_name protoreflect.Name = "options" EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range" EnumDescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name" EnumDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name" EnumDescriptorProto_Value_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value" EnumDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options" EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range" EnumDescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name" ) // Field numbers for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 EnumDescriptorProto_Value_field_number protoreflect.FieldNumber = 2 EnumDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4 EnumDescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 5 ) // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_message_name protoreflect.Name = "EnumReservedRange" EnumDescriptorProto_EnumReservedRange_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange" ) // Field names for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_Start_field_name protoreflect.Name = "start" EnumDescriptorProto_EnumReservedRange_End_field_name protoreflect.Name = "end" EnumDescriptorProto_EnumReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.start" EnumDescriptorProto_EnumReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.end" ) // Field numbers for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_Start_field_number protoreflect.FieldNumber = 1 EnumDescriptorProto_EnumReservedRange_End_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_message_name protoreflect.Name = "EnumValueDescriptorProto" EnumValueDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto" ) // Field names for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_Name_field_name protoreflect.Name = "name" EnumValueDescriptorProto_Number_field_name protoreflect.Name = "number" EnumValueDescriptorProto_Options_field_name protoreflect.Name = "options" EnumValueDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.name" EnumValueDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.number" EnumValueDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.options" ) // Field numbers for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 EnumValueDescriptorProto_Number_field_number protoreflect.FieldNumber = 2 EnumValueDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_message_name protoreflect.Name = "ServiceDescriptorProto" ServiceDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto" ) // Field names for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_Name_field_name protoreflect.Name = "name" ServiceDescriptorProto_Method_field_name protoreflect.Name = "method" ServiceDescriptorProto_Options_field_name protoreflect.Name = "options" ServiceDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.name" ServiceDescriptorProto_Method_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.method" ServiceDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.options" ) // Field numbers for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 ServiceDescriptorProto_Method_field_number protoreflect.FieldNumber = 2 ServiceDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_message_name protoreflect.Name = "MethodDescriptorProto" MethodDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto" ) // Field names for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_Name_field_name protoreflect.Name = "name" MethodDescriptorProto_InputType_field_name protoreflect.Name = "input_type" MethodDescriptorProto_OutputType_field_name protoreflect.Name = "output_type" MethodDescriptorProto_Options_field_name protoreflect.Name = "options" MethodDescriptorProto_ClientStreaming_field_name protoreflect.Name = "client_streaming" MethodDescriptorProto_ServerStreaming_field_name protoreflect.Name = "server_streaming" MethodDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.name" MethodDescriptorProto_InputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.input_type" MethodDescriptorProto_OutputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.output_type" MethodDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.options" MethodDescriptorProto_ClientStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.client_streaming" MethodDescriptorProto_ServerStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.server_streaming" ) // Field numbers for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 MethodDescriptorProto_InputType_field_number protoreflect.FieldNumber = 2 MethodDescriptorProto_OutputType_field_number protoreflect.FieldNumber = 3 MethodDescriptorProto_Options_field_number protoreflect.FieldNumber = 4 MethodDescriptorProto_ClientStreaming_field_number protoreflect.FieldNumber = 5 MethodDescriptorProto_ServerStreaming_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.FileOptions. const ( FileOptions_message_name protoreflect.Name = "FileOptions" FileOptions_message_fullname protoreflect.FullName = "google.protobuf.FileOptions" ) // Field names for google.protobuf.FileOptions. const ( FileOptions_JavaPackage_field_name protoreflect.Name = "java_package" FileOptions_JavaOuterClassname_field_name protoreflect.Name = "java_outer_classname" FileOptions_JavaMultipleFiles_field_name protoreflect.Name = "java_multiple_files" FileOptions_JavaGenerateEqualsAndHash_field_name protoreflect.Name = "java_generate_equals_and_hash" FileOptions_JavaStringCheckUtf8_field_name protoreflect.Name = "java_string_check_utf8" FileOptions_OptimizeFor_field_name protoreflect.Name = "optimize_for" FileOptions_GoPackage_field_name protoreflect.Name = "go_package" FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services" FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services" FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services" FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services" FileOptions_Deprecated_field_name protoreflect.Name = "deprecated" FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas" FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix" FileOptions_CsharpNamespace_field_name protoreflect.Name = "csharp_namespace" FileOptions_SwiftPrefix_field_name protoreflect.Name = "swift_prefix" FileOptions_PhpClassPrefix_field_name protoreflect.Name = "php_class_prefix" FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace" FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace" FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package" FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package" FileOptions_JavaOuterClassname_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_outer_classname" FileOptions_JavaMultipleFiles_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_multiple_files" FileOptions_JavaGenerateEqualsAndHash_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generate_equals_and_hash" FileOptions_JavaStringCheckUtf8_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_string_check_utf8" FileOptions_OptimizeFor_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.optimize_for" FileOptions_GoPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.go_package" FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services" FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services" FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services" FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services" FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated" FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas" FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix" FileOptions_CsharpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.csharp_namespace" FileOptions_SwiftPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.swift_prefix" FileOptions_PhpClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_class_prefix" FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace" FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace" FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package" FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option" ) // Field numbers for google.protobuf.FileOptions. const ( FileOptions_JavaPackage_field_number protoreflect.FieldNumber = 1 FileOptions_JavaOuterClassname_field_number protoreflect.FieldNumber = 8 FileOptions_JavaMultipleFiles_field_number protoreflect.FieldNumber = 10 FileOptions_JavaGenerateEqualsAndHash_field_number protoreflect.FieldNumber = 20 FileOptions_JavaStringCheckUtf8_field_number protoreflect.FieldNumber = 27 FileOptions_OptimizeFor_field_number protoreflect.FieldNumber = 9 FileOptions_GoPackage_field_number protoreflect.FieldNumber = 11 FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16 FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17 FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18 FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42 FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23 FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31 FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36 FileOptions_CsharpNamespace_field_number protoreflect.FieldNumber = 37 FileOptions_SwiftPrefix_field_number protoreflect.FieldNumber = 39 FileOptions_PhpClassPrefix_field_number protoreflect.FieldNumber = 40 FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41 FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44 FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45 FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.FileOptions.OptimizeMode. const ( FileOptions_OptimizeMode_enum_fullname = "google.protobuf.FileOptions.OptimizeMode" FileOptions_OptimizeMode_enum_name = "OptimizeMode" ) // Names for google.protobuf.MessageOptions. const ( MessageOptions_message_name protoreflect.Name = "MessageOptions" MessageOptions_message_fullname protoreflect.FullName = "google.protobuf.MessageOptions" ) // Field names for google.protobuf.MessageOptions. const ( MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format" MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor" MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor" MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" ) // Field numbers for google.protobuf.MessageOptions. const ( MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1 MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2 MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.FieldOptions. const ( FieldOptions_message_name protoreflect.Name = "FieldOptions" FieldOptions_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions" ) // Field names for google.protobuf.FieldOptions. const ( FieldOptions_Ctype_field_name protoreflect.Name = "ctype" FieldOptions_Packed_field_name protoreflect.Name = "packed" FieldOptions_Jstype_field_name protoreflect.Name = "jstype" FieldOptions_Lazy_field_name protoreflect.Name = "lazy" FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated" FieldOptions_Weak_field_name protoreflect.Name = "weak" FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed" FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype" FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy" FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated" FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak" FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" ) // Field numbers for google.protobuf.FieldOptions. const ( FieldOptions_Ctype_field_number protoreflect.FieldNumber = 1 FieldOptions_Packed_field_number protoreflect.FieldNumber = 2 FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6 FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5 FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3 FieldOptions_Weak_field_number protoreflect.FieldNumber = 10 FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.FieldOptions.CType. const ( FieldOptions_CType_enum_fullname = "google.protobuf.FieldOptions.CType" FieldOptions_CType_enum_name = "CType" ) // Full and short names for google.protobuf.FieldOptions.JSType. const ( FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType" FieldOptions_JSType_enum_name = "JSType" ) // Names for google.protobuf.OneofOptions. const ( OneofOptions_message_name protoreflect.Name = "OneofOptions" OneofOptions_message_fullname protoreflect.FullName = "google.protobuf.OneofOptions" ) // Field names for google.protobuf.OneofOptions. const ( OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option" ) // Field numbers for google.protobuf.OneofOptions. const ( OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.EnumOptions. const ( EnumOptions_message_name protoreflect.Name = "EnumOptions" EnumOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumOptions" ) // Field names for google.protobuf.EnumOptions. const ( EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" ) // Field numbers for google.protobuf.EnumOptions. const ( EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.EnumValueOptions. const ( EnumValueOptions_message_name protoreflect.Name = "EnumValueOptions" EnumValueOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions" ) // Field names for google.protobuf.EnumValueOptions. const ( EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated" EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option" ) // Field numbers for google.protobuf.EnumValueOptions. const ( EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1 EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.ServiceOptions. const ( ServiceOptions_message_name protoreflect.Name = "ServiceOptions" ServiceOptions_message_fullname protoreflect.FullName = "google.protobuf.ServiceOptions" ) // Field names for google.protobuf.ServiceOptions. const ( ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated" ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated" ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option" ) // Field numbers for google.protobuf.ServiceOptions. const ( ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33 ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.MethodOptions. const ( MethodOptions_message_name protoreflect.Name = "MethodOptions" MethodOptions_message_fullname protoreflect.FullName = "google.protobuf.MethodOptions" ) // Field names for google.protobuf.MethodOptions. const ( MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated" MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level" MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated" MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level" MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option" ) // Field numbers for google.protobuf.MethodOptions. const ( MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33 MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34 MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.MethodOptions.IdempotencyLevel. const ( MethodOptions_IdempotencyLevel_enum_fullname = "google.protobuf.MethodOptions.IdempotencyLevel" MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel" ) // Names for google.protobuf.UninterpretedOption. const ( UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption" UninterpretedOption_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption" ) // Field names for google.protobuf.UninterpretedOption. const ( UninterpretedOption_Name_field_name protoreflect.Name = "name" UninterpretedOption_IdentifierValue_field_name protoreflect.Name = "identifier_value" UninterpretedOption_PositiveIntValue_field_name protoreflect.Name = "positive_int_value" UninterpretedOption_NegativeIntValue_field_name protoreflect.Name = "negative_int_value" UninterpretedOption_DoubleValue_field_name protoreflect.Name = "double_value" UninterpretedOption_StringValue_field_name protoreflect.Name = "string_value" UninterpretedOption_AggregateValue_field_name protoreflect.Name = "aggregate_value" UninterpretedOption_Name_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.name" UninterpretedOption_IdentifierValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.identifier_value" UninterpretedOption_PositiveIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.positive_int_value" UninterpretedOption_NegativeIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.negative_int_value" UninterpretedOption_DoubleValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.double_value" UninterpretedOption_StringValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.string_value" UninterpretedOption_AggregateValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.aggregate_value" ) // Field numbers for google.protobuf.UninterpretedOption. const ( UninterpretedOption_Name_field_number protoreflect.FieldNumber = 2 UninterpretedOption_IdentifierValue_field_number protoreflect.FieldNumber = 3 UninterpretedOption_PositiveIntValue_field_number protoreflect.FieldNumber = 4 UninterpretedOption_NegativeIntValue_field_number protoreflect.FieldNumber = 5 UninterpretedOption_DoubleValue_field_number protoreflect.FieldNumber = 6 UninterpretedOption_StringValue_field_number protoreflect.FieldNumber = 7 UninterpretedOption_AggregateValue_field_number protoreflect.FieldNumber = 8 ) // Names for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_message_name protoreflect.Name = "NamePart" UninterpretedOption_NamePart_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart" ) // Field names for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_NamePart_field_name protoreflect.Name = "name_part" UninterpretedOption_NamePart_IsExtension_field_name protoreflect.Name = "is_extension" UninterpretedOption_NamePart_NamePart_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.name_part" UninterpretedOption_NamePart_IsExtension_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.is_extension" ) // Field numbers for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_NamePart_field_number protoreflect.FieldNumber = 1 UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo" SourceCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo" ) // Field names for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_Location_field_name protoreflect.Name = "location" SourceCodeInfo_Location_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.location" ) // Field numbers for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_Location_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_message_name protoreflect.Name = "Location" SourceCodeInfo_Location_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location" ) // Field names for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_Path_field_name protoreflect.Name = "path" SourceCodeInfo_Location_Span_field_name protoreflect.Name = "span" SourceCodeInfo_Location_LeadingComments_field_name protoreflect.Name = "leading_comments" SourceCodeInfo_Location_TrailingComments_field_name protoreflect.Name = "trailing_comments" SourceCodeInfo_Location_LeadingDetachedComments_field_name protoreflect.Name = "leading_detached_comments" SourceCodeInfo_Location_Path_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.path" SourceCodeInfo_Location_Span_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.span" SourceCodeInfo_Location_LeadingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_comments" SourceCodeInfo_Location_TrailingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.trailing_comments" SourceCodeInfo_Location_LeadingDetachedComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_detached_comments" ) // Field numbers for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_Path_field_number protoreflect.FieldNumber = 1 SourceCodeInfo_Location_Span_field_number protoreflect.FieldNumber = 2 SourceCodeInfo_Location_LeadingComments_field_number protoreflect.FieldNumber = 3 SourceCodeInfo_Location_TrailingComments_field_number protoreflect.FieldNumber = 4 SourceCodeInfo_Location_LeadingDetachedComments_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_message_name protoreflect.Name = "GeneratedCodeInfo" GeneratedCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo" ) // Field names for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_Annotation_field_name protoreflect.Name = "annotation" GeneratedCodeInfo_Annotation_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.annotation" ) // Field numbers for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_Annotation_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_message_name protoreflect.Name = "Annotation" GeneratedCodeInfo_Annotation_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation" ) // Field names for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_Path_field_name protoreflect.Name = "path" GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file" GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin" GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end" GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path" GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file" GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin" GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end" ) // Field numbers for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_Path_field_number protoreflect.FieldNumber = 1 GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2 GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3 GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package genid contains constants for declarations in descriptor.proto // and the well-known types. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" const GoogleProtobuf_package protoreflect.FullName = "google.protobuf" ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/duration_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_duration_proto = "google/protobuf/duration.proto" // Names for google.protobuf.Duration. const ( Duration_message_name protoreflect.Name = "Duration" Duration_message_fullname protoreflect.FullName = "google.protobuf.Duration" ) // Field names for google.protobuf.Duration. const ( Duration_Seconds_field_name protoreflect.Name = "seconds" Duration_Nanos_field_name protoreflect.Name = "nanos" Duration_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Duration.seconds" Duration_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Duration.nanos" ) // Field numbers for google.protobuf.Duration. const ( Duration_Seconds_field_number protoreflect.FieldNumber = 1 Duration_Nanos_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/empty_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_empty_proto = "google/protobuf/empty.proto" // Names for google.protobuf.Empty. const ( Empty_message_name protoreflect.Name = "Empty" Empty_message_fullname protoreflect.FullName = "google.protobuf.Empty" ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/field_mask_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_field_mask_proto = "google/protobuf/field_mask.proto" // Names for google.protobuf.FieldMask. const ( FieldMask_message_name protoreflect.Name = "FieldMask" FieldMask_message_fullname protoreflect.FullName = "google.protobuf.FieldMask" ) // Field names for google.protobuf.FieldMask. const ( FieldMask_Paths_field_name protoreflect.Name = "paths" FieldMask_Paths_field_fullname protoreflect.FullName = "google.protobuf.FieldMask.paths" ) // Field numbers for google.protobuf.FieldMask. const ( FieldMask_Paths_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/goname.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid // Go names of implementation-specific struct fields in generated messages. const ( State_goname = "state" SizeCache_goname = "sizeCache" SizeCacheA_goname = "XXX_sizecache" WeakFields_goname = "weakFields" WeakFieldsA_goname = "XXX_weak" UnknownFields_goname = "unknownFields" UnknownFieldsA_goname = "XXX_unrecognized" ExtensionFields_goname = "extensionFields" ExtensionFieldsA_goname = "XXX_InternalExtensions" ExtensionFieldsB_goname = "XXX_extensions" WeakFieldPrefix_goname = "XXX_weak_" ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/map_entry.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" // Generic field names and numbers for synthetic map entry messages. const ( MapEntry_Key_field_name protoreflect.Name = "key" MapEntry_Value_field_name protoreflect.Name = "value" MapEntry_Key_field_number protoreflect.FieldNumber = 1 MapEntry_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/source_context_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_source_context_proto = "google/protobuf/source_context.proto" // Names for google.protobuf.SourceContext. const ( SourceContext_message_name protoreflect.Name = "SourceContext" SourceContext_message_fullname protoreflect.FullName = "google.protobuf.SourceContext" ) // Field names for google.protobuf.SourceContext. const ( SourceContext_FileName_field_name protoreflect.Name = "file_name" SourceContext_FileName_field_fullname protoreflect.FullName = "google.protobuf.SourceContext.file_name" ) // Field numbers for google.protobuf.SourceContext. const ( SourceContext_FileName_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/struct_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_struct_proto = "google/protobuf/struct.proto" // Full and short names for google.protobuf.NullValue. const ( NullValue_enum_fullname = "google.protobuf.NullValue" NullValue_enum_name = "NullValue" ) // Names for google.protobuf.Struct. const ( Struct_message_name protoreflect.Name = "Struct" Struct_message_fullname protoreflect.FullName = "google.protobuf.Struct" ) // Field names for google.protobuf.Struct. const ( Struct_Fields_field_name protoreflect.Name = "fields" Struct_Fields_field_fullname protoreflect.FullName = "google.protobuf.Struct.fields" ) // Field numbers for google.protobuf.Struct. const ( Struct_Fields_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_message_name protoreflect.Name = "FieldsEntry" Struct_FieldsEntry_message_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry" ) // Field names for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_Key_field_name protoreflect.Name = "key" Struct_FieldsEntry_Value_field_name protoreflect.Name = "value" Struct_FieldsEntry_Key_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.key" Struct_FieldsEntry_Value_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.value" ) // Field numbers for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_Key_field_number protoreflect.FieldNumber = 1 Struct_FieldsEntry_Value_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.Value. const ( Value_message_name protoreflect.Name = "Value" Value_message_fullname protoreflect.FullName = "google.protobuf.Value" ) // Field names for google.protobuf.Value. const ( Value_NullValue_field_name protoreflect.Name = "null_value" Value_NumberValue_field_name protoreflect.Name = "number_value" Value_StringValue_field_name protoreflect.Name = "string_value" Value_BoolValue_field_name protoreflect.Name = "bool_value" Value_StructValue_field_name protoreflect.Name = "struct_value" Value_ListValue_field_name protoreflect.Name = "list_value" Value_NullValue_field_fullname protoreflect.FullName = "google.protobuf.Value.null_value" Value_NumberValue_field_fullname protoreflect.FullName = "google.protobuf.Value.number_value" Value_StringValue_field_fullname protoreflect.FullName = "google.protobuf.Value.string_value" Value_BoolValue_field_fullname protoreflect.FullName = "google.protobuf.Value.bool_value" Value_StructValue_field_fullname protoreflect.FullName = "google.protobuf.Value.struct_value" Value_ListValue_field_fullname protoreflect.FullName = "google.protobuf.Value.list_value" ) // Field numbers for google.protobuf.Value. const ( Value_NullValue_field_number protoreflect.FieldNumber = 1 Value_NumberValue_field_number protoreflect.FieldNumber = 2 Value_StringValue_field_number protoreflect.FieldNumber = 3 Value_BoolValue_field_number protoreflect.FieldNumber = 4 Value_StructValue_field_number protoreflect.FieldNumber = 5 Value_ListValue_field_number protoreflect.FieldNumber = 6 ) // Oneof names for google.protobuf.Value. const ( Value_Kind_oneof_name protoreflect.Name = "kind" Value_Kind_oneof_fullname protoreflect.FullName = "google.protobuf.Value.kind" ) // Names for google.protobuf.ListValue. const ( ListValue_message_name protoreflect.Name = "ListValue" ListValue_message_fullname protoreflect.FullName = "google.protobuf.ListValue" ) // Field names for google.protobuf.ListValue. const ( ListValue_Values_field_name protoreflect.Name = "values" ListValue_Values_field_fullname protoreflect.FullName = "google.protobuf.ListValue.values" ) // Field numbers for google.protobuf.ListValue. const ( ListValue_Values_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/timestamp_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_timestamp_proto = "google/protobuf/timestamp.proto" // Names for google.protobuf.Timestamp. const ( Timestamp_message_name protoreflect.Name = "Timestamp" Timestamp_message_fullname protoreflect.FullName = "google.protobuf.Timestamp" ) // Field names for google.protobuf.Timestamp. const ( Timestamp_Seconds_field_name protoreflect.Name = "seconds" Timestamp_Nanos_field_name protoreflect.Name = "nanos" Timestamp_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.seconds" Timestamp_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.nanos" ) // Field numbers for google.protobuf.Timestamp. const ( Timestamp_Seconds_field_number protoreflect.FieldNumber = 1 Timestamp_Nanos_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/type_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_type_proto = "google/protobuf/type.proto" // Full and short names for google.protobuf.Syntax. const ( Syntax_enum_fullname = "google.protobuf.Syntax" Syntax_enum_name = "Syntax" ) // Names for google.protobuf.Type. const ( Type_message_name protoreflect.Name = "Type" Type_message_fullname protoreflect.FullName = "google.protobuf.Type" ) // Field names for google.protobuf.Type. const ( Type_Name_field_name protoreflect.Name = "name" Type_Fields_field_name protoreflect.Name = "fields" Type_Oneofs_field_name protoreflect.Name = "oneofs" Type_Options_field_name protoreflect.Name = "options" Type_SourceContext_field_name protoreflect.Name = "source_context" Type_Syntax_field_name protoreflect.Name = "syntax" Type_Name_field_fullname protoreflect.FullName = "google.protobuf.Type.name" Type_Fields_field_fullname protoreflect.FullName = "google.protobuf.Type.fields" Type_Oneofs_field_fullname protoreflect.FullName = "google.protobuf.Type.oneofs" Type_Options_field_fullname protoreflect.FullName = "google.protobuf.Type.options" Type_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Type.source_context" Type_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Type.syntax" ) // Field numbers for google.protobuf.Type. const ( Type_Name_field_number protoreflect.FieldNumber = 1 Type_Fields_field_number protoreflect.FieldNumber = 2 Type_Oneofs_field_number protoreflect.FieldNumber = 3 Type_Options_field_number protoreflect.FieldNumber = 4 Type_SourceContext_field_number protoreflect.FieldNumber = 5 Type_Syntax_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.Field. const ( Field_message_name protoreflect.Name = "Field" Field_message_fullname protoreflect.FullName = "google.protobuf.Field" ) // Field names for google.protobuf.Field. const ( Field_Kind_field_name protoreflect.Name = "kind" Field_Cardinality_field_name protoreflect.Name = "cardinality" Field_Number_field_name protoreflect.Name = "number" Field_Name_field_name protoreflect.Name = "name" Field_TypeUrl_field_name protoreflect.Name = "type_url" Field_OneofIndex_field_name protoreflect.Name = "oneof_index" Field_Packed_field_name protoreflect.Name = "packed" Field_Options_field_name protoreflect.Name = "options" Field_JsonName_field_name protoreflect.Name = "json_name" Field_DefaultValue_field_name protoreflect.Name = "default_value" Field_Kind_field_fullname protoreflect.FullName = "google.protobuf.Field.kind" Field_Cardinality_field_fullname protoreflect.FullName = "google.protobuf.Field.cardinality" Field_Number_field_fullname protoreflect.FullName = "google.protobuf.Field.number" Field_Name_field_fullname protoreflect.FullName = "google.protobuf.Field.name" Field_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Field.type_url" Field_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.Field.oneof_index" Field_Packed_field_fullname protoreflect.FullName = "google.protobuf.Field.packed" Field_Options_field_fullname protoreflect.FullName = "google.protobuf.Field.options" Field_JsonName_field_fullname protoreflect.FullName = "google.protobuf.Field.json_name" Field_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.Field.default_value" ) // Field numbers for google.protobuf.Field. const ( Field_Kind_field_number protoreflect.FieldNumber = 1 Field_Cardinality_field_number protoreflect.FieldNumber = 2 Field_Number_field_number protoreflect.FieldNumber = 3 Field_Name_field_number protoreflect.FieldNumber = 4 Field_TypeUrl_field_number protoreflect.FieldNumber = 6 Field_OneofIndex_field_number protoreflect.FieldNumber = 7 Field_Packed_field_number protoreflect.FieldNumber = 8 Field_Options_field_number protoreflect.FieldNumber = 9 Field_JsonName_field_number protoreflect.FieldNumber = 10 Field_DefaultValue_field_number protoreflect.FieldNumber = 11 ) // Full and short names for google.protobuf.Field.Kind. const ( Field_Kind_enum_fullname = "google.protobuf.Field.Kind" Field_Kind_enum_name = "Kind" ) // Full and short names for google.protobuf.Field.Cardinality. const ( Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality" Field_Cardinality_enum_name = "Cardinality" ) // Names for google.protobuf.Enum. const ( Enum_message_name protoreflect.Name = "Enum" Enum_message_fullname protoreflect.FullName = "google.protobuf.Enum" ) // Field names for google.protobuf.Enum. const ( Enum_Name_field_name protoreflect.Name = "name" Enum_Enumvalue_field_name protoreflect.Name = "enumvalue" Enum_Options_field_name protoreflect.Name = "options" Enum_SourceContext_field_name protoreflect.Name = "source_context" Enum_Syntax_field_name protoreflect.Name = "syntax" Enum_Name_field_fullname protoreflect.FullName = "google.protobuf.Enum.name" Enum_Enumvalue_field_fullname protoreflect.FullName = "google.protobuf.Enum.enumvalue" Enum_Options_field_fullname protoreflect.FullName = "google.protobuf.Enum.options" Enum_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Enum.source_context" Enum_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Enum.syntax" ) // Field numbers for google.protobuf.Enum. const ( Enum_Name_field_number protoreflect.FieldNumber = 1 Enum_Enumvalue_field_number protoreflect.FieldNumber = 2 Enum_Options_field_number protoreflect.FieldNumber = 3 Enum_SourceContext_field_number protoreflect.FieldNumber = 4 Enum_Syntax_field_number protoreflect.FieldNumber = 5 ) // Names for google.protobuf.EnumValue. const ( EnumValue_message_name protoreflect.Name = "EnumValue" EnumValue_message_fullname protoreflect.FullName = "google.protobuf.EnumValue" ) // Field names for google.protobuf.EnumValue. const ( EnumValue_Name_field_name protoreflect.Name = "name" EnumValue_Number_field_name protoreflect.Name = "number" EnumValue_Options_field_name protoreflect.Name = "options" EnumValue_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.name" EnumValue_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.number" EnumValue_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.options" ) // Field numbers for google.protobuf.EnumValue. const ( EnumValue_Name_field_number protoreflect.FieldNumber = 1 EnumValue_Number_field_number protoreflect.FieldNumber = 2 EnumValue_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.Option. const ( Option_message_name protoreflect.Name = "Option" Option_message_fullname protoreflect.FullName = "google.protobuf.Option" ) // Field names for google.protobuf.Option. const ( Option_Name_field_name protoreflect.Name = "name" Option_Value_field_name protoreflect.Name = "value" Option_Name_field_fullname protoreflect.FullName = "google.protobuf.Option.name" Option_Value_field_fullname protoreflect.FullName = "google.protobuf.Option.value" ) // Field numbers for google.protobuf.Option. const ( Option_Name_field_number protoreflect.FieldNumber = 1 Option_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/wrappers.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" // Generic field name and number for messages in wrappers.proto. const ( WrapperValue_Value_field_name protoreflect.Name = "value" WrapperValue_Value_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/genid/wrappers_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_wrappers_proto = "google/protobuf/wrappers.proto" // Names for google.protobuf.DoubleValue. const ( DoubleValue_message_name protoreflect.Name = "DoubleValue" DoubleValue_message_fullname protoreflect.FullName = "google.protobuf.DoubleValue" ) // Field names for google.protobuf.DoubleValue. const ( DoubleValue_Value_field_name protoreflect.Name = "value" DoubleValue_Value_field_fullname protoreflect.FullName = "google.protobuf.DoubleValue.value" ) // Field numbers for google.protobuf.DoubleValue. const ( DoubleValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.FloatValue. const ( FloatValue_message_name protoreflect.Name = "FloatValue" FloatValue_message_fullname protoreflect.FullName = "google.protobuf.FloatValue" ) // Field names for google.protobuf.FloatValue. const ( FloatValue_Value_field_name protoreflect.Name = "value" FloatValue_Value_field_fullname protoreflect.FullName = "google.protobuf.FloatValue.value" ) // Field numbers for google.protobuf.FloatValue. const ( FloatValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Int64Value. const ( Int64Value_message_name protoreflect.Name = "Int64Value" Int64Value_message_fullname protoreflect.FullName = "google.protobuf.Int64Value" ) // Field names for google.protobuf.Int64Value. const ( Int64Value_Value_field_name protoreflect.Name = "value" Int64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int64Value.value" ) // Field numbers for google.protobuf.Int64Value. const ( Int64Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.UInt64Value. const ( UInt64Value_message_name protoreflect.Name = "UInt64Value" UInt64Value_message_fullname protoreflect.FullName = "google.protobuf.UInt64Value" ) // Field names for google.protobuf.UInt64Value. const ( UInt64Value_Value_field_name protoreflect.Name = "value" UInt64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt64Value.value" ) // Field numbers for google.protobuf.UInt64Value. const ( UInt64Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Int32Value. const ( Int32Value_message_name protoreflect.Name = "Int32Value" Int32Value_message_fullname protoreflect.FullName = "google.protobuf.Int32Value" ) // Field names for google.protobuf.Int32Value. const ( Int32Value_Value_field_name protoreflect.Name = "value" Int32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int32Value.value" ) // Field numbers for google.protobuf.Int32Value. const ( Int32Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.UInt32Value. const ( UInt32Value_message_name protoreflect.Name = "UInt32Value" UInt32Value_message_fullname protoreflect.FullName = "google.protobuf.UInt32Value" ) // Field names for google.protobuf.UInt32Value. const ( UInt32Value_Value_field_name protoreflect.Name = "value" UInt32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt32Value.value" ) // Field numbers for google.protobuf.UInt32Value. const ( UInt32Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.BoolValue. const ( BoolValue_message_name protoreflect.Name = "BoolValue" BoolValue_message_fullname protoreflect.FullName = "google.protobuf.BoolValue" ) // Field names for google.protobuf.BoolValue. const ( BoolValue_Value_field_name protoreflect.Name = "value" BoolValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BoolValue.value" ) // Field numbers for google.protobuf.BoolValue. const ( BoolValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.StringValue. const ( StringValue_message_name protoreflect.Name = "StringValue" StringValue_message_fullname protoreflect.FullName = "google.protobuf.StringValue" ) // Field names for google.protobuf.StringValue. const ( StringValue_Value_field_name protoreflect.Name = "value" StringValue_Value_field_fullname protoreflect.FullName = "google.protobuf.StringValue.value" ) // Field numbers for google.protobuf.StringValue. const ( StringValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.BytesValue. const ( BytesValue_message_name protoreflect.Name = "BytesValue" BytesValue_message_fullname protoreflect.FullName = "google.protobuf.BytesValue" ) // Field names for google.protobuf.BytesValue. const ( BytesValue_Value_field_name protoreflect.Name = "value" BytesValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BytesValue.value" ) // Field numbers for google.protobuf.BytesValue. const ( BytesValue_Value_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/api_export.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strconv" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // Export is a zero-length named type that exists only to export a set of // functions that we do not want to appear in godoc. type Export struct{} // NewError formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. func (Export) NewError(f string, x ...interface{}) error { return errors.New(f, x...) } // enum is any enum type generated by protoc-gen-go // and must be a named int32 type. type enum = interface{} // EnumOf returns the protoreflect.Enum interface over e. // It returns nil if e is nil. func (Export) EnumOf(e enum) pref.Enum { switch e := e.(type) { case nil: return nil case pref.Enum: return e default: return legacyWrapEnum(reflect.ValueOf(e)) } } // EnumDescriptorOf returns the protoreflect.EnumDescriptor for e. // It returns nil if e is nil. func (Export) EnumDescriptorOf(e enum) pref.EnumDescriptor { switch e := e.(type) { case nil: return nil case pref.Enum: return e.Descriptor() default: return LegacyLoadEnumDesc(reflect.TypeOf(e)) } } // EnumTypeOf returns the protoreflect.EnumType for e. // It returns nil if e is nil. func (Export) EnumTypeOf(e enum) pref.EnumType { switch e := e.(type) { case nil: return nil case pref.Enum: return e.Type() default: return legacyLoadEnumType(reflect.TypeOf(e)) } } // EnumStringOf returns the enum value as a string, either as the name if // the number is resolvable, or the number formatted as a string. func (Export) EnumStringOf(ed pref.EnumDescriptor, n pref.EnumNumber) string { ev := ed.Values().ByNumber(n) if ev != nil { return string(ev.Name()) } return strconv.Itoa(int(n)) } // message is any message type generated by protoc-gen-go // and must be a pointer to a named struct type. type message = interface{} // legacyMessageWrapper wraps a v2 message as a v1 message. type legacyMessageWrapper struct{ m pref.ProtoMessage } func (m legacyMessageWrapper) Reset() { proto.Reset(m.m) } func (m legacyMessageWrapper) String() string { return Export{}.MessageStringOf(m.m) } func (m legacyMessageWrapper) ProtoMessage() {} // ProtoMessageV1Of converts either a v1 or v2 message to a v1 message. // It returns nil if m is nil. func (Export) ProtoMessageV1Of(m message) piface.MessageV1 { switch mv := m.(type) { case nil: return nil case piface.MessageV1: return mv case unwrapper: return Export{}.ProtoMessageV1Of(mv.protoUnwrap()) case pref.ProtoMessage: return legacyMessageWrapper{mv} default: panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) } } func (Export) protoMessageV2Of(m message) pref.ProtoMessage { switch mv := m.(type) { case nil: return nil case pref.ProtoMessage: return mv case legacyMessageWrapper: return mv.m case piface.MessageV1: return nil default: panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) } } // ProtoMessageV2Of converts either a v1 or v2 message to a v2 message. // It returns nil if m is nil. func (Export) ProtoMessageV2Of(m message) pref.ProtoMessage { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv } return legacyWrapMessage(reflect.ValueOf(m)).Interface() } // MessageOf returns the protoreflect.Message interface over m. // It returns nil if m is nil. func (Export) MessageOf(m message) pref.Message { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect() } return legacyWrapMessage(reflect.ValueOf(m)) } // MessageDescriptorOf returns the protoreflect.MessageDescriptor for m. // It returns nil if m is nil. func (Export) MessageDescriptorOf(m message) pref.MessageDescriptor { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Descriptor() } return LegacyLoadMessageDesc(reflect.TypeOf(m)) } // MessageTypeOf returns the protoreflect.MessageType for m. // It returns nil if m is nil. func (Export) MessageTypeOf(m message) pref.MessageType { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Type() } return legacyLoadMessageType(reflect.TypeOf(m), "") } // MessageStringOf returns the message value as a string, // which is the message serialized in the protobuf text format. func (Export) MessageStringOf(m pref.ProtoMessage) string { return prototext.MarshalOptions{Multiline: false}.Format(m) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/checkinit.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sync" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) func (mi *MessageInfo) checkInitialized(in piface.CheckInitializedInput) (piface.CheckInitializedOutput, error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } return piface.CheckInitializedOutput{}, mi.checkInitializedPointer(p) } func (mi *MessageInfo) checkInitializedPointer(p pointer) error { mi.init() if !mi.needsInitCheck { return nil } if p.IsNil() { for _, f := range mi.orderedCoderFields { if f.isRequired { return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName())) } } return nil } if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() if err := mi.isInitExtensions(e); err != nil { return err } } for _, f := range mi.orderedCoderFields { if !f.isRequired && f.funcs.isInit == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { if f.isRequired { return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName())) } continue } if f.funcs.isInit == nil { continue } if err := f.funcs.isInit(fptr, f); err != nil { return err } } return nil } func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error { if ext == nil { return nil } for _, x := range *ext { ei := getExtensionFieldInfo(x.Type()) if ei.funcs.isInit == nil { continue } v := x.Value() if !v.IsValid() { continue } if err := ei.funcs.isInit(v); err != nil { return err } } return nil } var ( needsInitCheckMu sync.Mutex needsInitCheckMap sync.Map ) // needsInitCheck reports whether a message needs to be checked for partial initialization. // // It returns true if the message transitively includes any required or extension fields. func needsInitCheck(md pref.MessageDescriptor) bool { if v, ok := needsInitCheckMap.Load(md); ok { if has, ok := v.(bool); ok { return has } } needsInitCheckMu.Lock() defer needsInitCheckMu.Unlock() return needsInitCheckLocked(md) } func needsInitCheckLocked(md pref.MessageDescriptor) (has bool) { if v, ok := needsInitCheckMap.Load(md); ok { // If has is true, we've previously determined that this message // needs init checks. // // If has is false, we've previously determined that it can never // be uninitialized. // // If has is not a bool, we've just encountered a cycle in the // message graph. In this case, it is safe to return false: If // the message does have required fields, we'll detect them later // in the graph traversal. has, ok := v.(bool) return ok && has } needsInitCheckMap.Store(md, struct{}{}) // avoid cycles while descending into this message defer func() { needsInitCheckMap.Store(md, has) }() if md.RequiredNumbers().Len() > 0 { return true } if md.ExtensionRanges().Len() > 0 { return true } for i := 0; i < md.Fields().Len(); i++ { fd := md.Fields().Get(i) // Map keys are never messages, so just consider the map value. if fd.IsMap() { fd = fd.MapValue() } fmd := fd.Message() if fmd != nil && needsInitCheckLocked(fmd) { return true } } return false } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sync" "sync/atomic" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) type extensionFieldInfo struct { wiretag uint64 tagsize int unmarshalNeedsValue bool funcs valueCoderFuncs validation validationInfo } var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo func getExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { if xi, ok := xt.(*ExtensionInfo); ok { xi.lazyInit() return xi.info } return legacyLoadExtensionFieldInfo(xt) } // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. func legacyLoadExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { return xi.(*extensionFieldInfo) } e := makeExtensionFieldInfo(xt.TypeDescriptor()) if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok { return e.(*extensionFieldInfo) } return e } func makeExtensionFieldInfo(xd pref.ExtensionDescriptor) *extensionFieldInfo { var wiretag uint64 if !xd.IsPacked() { wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()]) } else { wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType) } e := &extensionFieldInfo{ wiretag: wiretag, tagsize: protowire.SizeVarint(wiretag), funcs: encoderFuncsForValue(xd), } // Does the unmarshal function need a value passed to it? // This is true for composite types, where we pass in a message, list, or map to fill in, // and for enums, where we pass in a prototype value to specify the concrete enum type. switch xd.Kind() { case pref.MessageKind, pref.GroupKind, pref.EnumKind: e.unmarshalNeedsValue = true default: if xd.Cardinality() == pref.Repeated { e.unmarshalNeedsValue = true } } return e } type lazyExtensionValue struct { atomicOnce uint32 // atomically set if value is valid mu sync.Mutex xi *extensionFieldInfo value pref.Value b []byte fn func() pref.Value } type ExtensionField struct { typ pref.ExtensionType // value is either the value of GetValue, // or a *lazyExtensionValue that then returns the value of GetValue. value pref.Value lazy *lazyExtensionValue } func (f *ExtensionField) appendLazyBytes(xt pref.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) { if f.lazy == nil { f.lazy = &lazyExtensionValue{xi: xi} } f.typ = xt f.lazy.xi = xi f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp) f.lazy.b = append(f.lazy.b, b...) } func (f *ExtensionField) canLazy(xt pref.ExtensionType) bool { if f.typ == nil { return true } if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { return true } return false } func (f *ExtensionField) lazyInit() { f.lazy.mu.Lock() defer f.lazy.mu.Unlock() if atomic.LoadUint32(&f.lazy.atomicOnce) == 1 { return } if f.lazy.xi != nil { b := f.lazy.b val := f.typ.New() for len(b) > 0 { var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { panic(errors.New("bad tag in lazy extension decoding")) } b = b[n:] } num := protowire.Number(tag >> 3) wtyp := protowire.Type(tag & 7) var out unmarshalOutput var err error val, out, err = f.lazy.xi.funcs.unmarshal(b, val, num, wtyp, lazyUnmarshalOptions) if err != nil { panic(errors.New("decode failure in lazy extension decoding: %v", err)) } b = b[out.n:] } f.lazy.value = val } else { f.lazy.value = f.lazy.fn() } f.lazy.xi = nil f.lazy.fn = nil f.lazy.b = nil atomic.StoreUint32(&f.lazy.atomicOnce, 1) } // Set sets the type and value of the extension field. // This must not be called concurrently. func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) { f.typ = t f.value = v f.lazy = nil } // SetLazy sets the type and a value that is to be lazily evaluated upon first use. // This must not be called concurrently. func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) { f.typ = t f.lazy = &lazyExtensionValue{fn: fn} } // Value returns the value of the extension field. // This may be called concurrently. func (f *ExtensionField) Value() pref.Value { if f.lazy != nil { if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { f.lazyInit() } return f.lazy.value } return f.value } // Type returns the type of the extension field. // This may be called concurrently. func (f ExtensionField) Type() pref.ExtensionType { return f.typ } // IsSet returns whether the extension field is set. // This may be called concurrently. func (f ExtensionField) IsSet() bool { return f.typ != nil } // IsLazy reports whether a field is lazily encoded. // It is exported for testing. func IsLazy(m pref.Message, fd pref.FieldDescriptor) bool { var mi *MessageInfo var p pointer switch m := m.(type) { case *messageState: mi = m.messageInfo() p = m.pointer() case *messageReflectWrapper: mi = m.messageInfo() p = m.pointer() default: return false } xd, ok := fd.(pref.ExtensionTypeDescriptor) if !ok { return false } xt := xd.Type() ext := mi.extensionMap(p) if ext == nil { return false } f, ok := (*ext)[int32(fd.Number())] if !ok { return false } return f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_field.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) type errInvalidUTF8 struct{} func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" } func (errInvalidUTF8) InvalidUTF8() bool { return true } func (errInvalidUTF8) Unwrap() error { return errors.Error } // initOneofFieldCoders initializes the fast-path functions for the fields in a oneof. // // For size, marshal, and isInit operations, functions are set only on the first field // in the oneof. The functions are called when the oneof is non-nil, and will dispatch // to the appropriate field-specific function as necessary. // // The unmarshal function is set on each field individually as usual. func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) { fs := si.oneofsByName[od.Name()] ft := fs.Type oneofFields := make(map[reflect.Type]*coderFieldInfo) needIsInit := false fields := od.Fields() for i, lim := 0, fields.Len(); i < lim; i++ { fd := od.Fields().Get(i) num := fd.Number() // Make a copy of the original coderFieldInfo for use in unmarshaling. // // oneofFields[oneofType].funcs.marshal is the field-specific marshal function. // // mi.coderFields[num].marshal is set on only the first field in the oneof, // and dispatches to the field-specific marshaler in oneofFields. cf := *mi.coderFields[num] ot := si.oneofWrappersByNumber[num] cf.ft = ot.Field(0).Type cf.mi, cf.funcs = fieldCoder(fd, cf.ft) oneofFields[ot] = &cf if cf.funcs.isInit != nil { needIsInit = true } mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { var vw reflect.Value // pointer to wrapper type vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot { vw = vi.Elem() } else { vw = reflect.New(ot) } out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts) if err != nil { return out, err } vi.Set(vw) return out, nil } } getInfo := func(p pointer) (pointer, *coderFieldInfo) { v := p.AsValueOf(ft).Elem() if v.IsNil() { return pointer{}, nil } v = v.Elem() // interface -> *struct if v.IsNil() { return pointer{}, nil } return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()] } first := mi.coderFields[od.Fields().Get(0).Number()] first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int { p, info := getInfo(p) if info == nil || info.funcs.size == nil { return 0 } return info.funcs.size(p, info, opts) } first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) { p, info := getInfo(p) if info == nil || info.funcs.marshal == nil { return b, nil } return info.funcs.marshal(b, p, info, opts) } first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) { srcp, srcinfo := getInfo(src) if srcinfo == nil || srcinfo.funcs.merge == nil { return } dstp, dstinfo := getInfo(dst) if dstinfo != srcinfo { dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type())) dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset) } srcinfo.funcs.merge(dstp, srcp, srcinfo, opts) } if needIsInit { first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error { p, info := getInfo(p) if info == nil || info.funcs.isInit == nil { return nil } return info.funcs.isInit(p, info) } } } func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs { var once sync.Once var messageType pref.MessageType lazyInit := func() { once.Do(func() { messageName := fd.Message().FullName() messageType, _ = preg.GlobalTypes.FindMessageByName(messageName) }) } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m, ok := p.WeakFields().get(f.num) if !ok { return 0 } lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } return sizeMessage(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m, ok := p.WeakFields().get(f.num) if !ok { return b, nil } lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } return appendMessage(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { fs := p.WeakFields() m, ok := fs.get(f.num) if !ok { lazyInit() if messageType == nil { return unmarshalOutput{}, errUnknown } m = messageType.New().Interface() fs.set(f.num, m) } return consumeMessage(b, m, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m, ok := p.WeakFields().get(f.num) if !ok { return nil } return proto.CheckInitialized(m) }, merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { sm, ok := src.WeakFields().get(f.num) if !ok { return } dm, ok := dst.WeakFields().get(f.num) if !ok { lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } dm = messageType.New().Interface() dst.WeakFields().set(f.num, dm) } opts.Merge(dm, sm) }, } } func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeMessageInfo, marshal: appendMessageInfo, unmarshal: consumeMessageInfo, merge: mergeMessage, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageInfo } return funcs } else { return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m := asMessage(p.AsValueOf(ft).Elem()) return sizeMessage(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m := asMessage(p.AsValueOf(ft).Elem()) return appendMessage(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft).Elem() if mp.IsNil() { mp.Set(reflect.New(ft.Elem())) } return consumeMessage(b, asMessage(mp), wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m := asMessage(p.AsValueOf(ft).Elem()) return proto.CheckInitialized(m) }, merge: mergeMessage, } } } func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize } func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts))) return f.mi.marshalAppendPointer(b, p.Elem(), opts) } func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if p.Elem().IsNil() { p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts) if err != nil { return out, err } out.n = n out.initialized = o.initialized return out, nil } func isInitMessageInfo(p pointer, f *coderFieldInfo) error { return f.mi.checkInitializedPointer(p.Elem()) } func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int { return protowire.SizeBytes(proto.Size(m)) + tagsize } func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(proto.Size(m))) return opts.Options().MarshalAppend(b, m) } func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: m.ProtoReflect(), }) if err != nil { return out, err } out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int { m := v.Message().Interface() return sizeMessage(m, tagsize, opts) } func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { m := v.Message().Interface() return appendMessage(b, m, wiretag, opts) } func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { m := v.Message().Interface() out, err := consumeMessage(b, m, wtyp, opts) return v, out, err } func isInitMessageValue(v pref.Value) error { m := v.Message().Interface() return proto.CheckInitialized(m) } var coderMessageValue = valueCoderFuncs{ size: sizeMessageValue, marshal: appendMessageValue, unmarshal: consumeMessageValue, isInit: isInitMessageValue, merge: mergeMessageValue, } func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int { m := v.Message().Interface() return sizeGroup(m, tagsize, opts) } func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { m := v.Message().Interface() return appendGroup(b, m, wiretag, opts) } func consumeGroupValue(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { m := v.Message().Interface() out, err := consumeGroup(b, m, num, wtyp, opts) return v, out, err } var coderGroupValue = valueCoderFuncs{ size: sizeGroupValue, marshal: appendGroupValue, unmarshal: consumeGroupValue, isInit: isInitMessageValue, merge: mergeMessageValue, } func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { num := fd.Number() if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeGroupType, marshal: appendGroupType, unmarshal: consumeGroupType, merge: mergeMessage, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageInfo } return funcs } else { return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m := asMessage(p.AsValueOf(ft).Elem()) return sizeGroup(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m := asMessage(p.AsValueOf(ft).Elem()) return appendGroup(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft).Elem() if mp.IsNil() { mp.Set(reflect.New(ft.Elem())) } return consumeGroup(b, asMessage(mp), num, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m := asMessage(p.AsValueOf(ft).Elem()) return proto.CheckInitialized(m) }, merge: mergeMessage, } } } func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int { return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts) } func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, f.wiretag) // start group b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts) b = protowire.AppendVarint(b, f.wiretag+1) // end group return b, err } func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } if p.Elem().IsNil() { p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts) } func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int { return 2*tagsize + proto.Size(m) } func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) // start group b, err := opts.Options().MarshalAppend(b, m) b = protowire.AppendVarint(b, wiretag+1) // end group return b, err } func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return out, errDecode } o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: m.ProtoReflect(), }) if err != nil { return out, err } out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeMessageSliceInfo, marshal: appendMessageSliceInfo, unmarshal: consumeMessageSliceInfo, merge: mergeMessageSlice, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageSliceInfo } return funcs } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeMessageSlice(p, ft, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendMessageSlice(b, p, f.wiretag, ft, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { return consumeMessageSlice(b, p, ft, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { return isInitMessageSlice(p, ft) }, merge: mergeMessageSlice, } } func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize } return n } func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) siz := f.mi.sizePointer(v, opts) b = protowire.AppendVarint(b, uint64(siz)) b, err = f.mi.marshalAppendPointer(b, v, opts) if err != nil { return b, err } } return b, nil } func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } m := reflect.New(f.mi.GoReflectType.Elem()).Interface() mp := pointerOfIface(m) o, err := f.mi.unmarshalPointer(v, mp, 0, opts) if err != nil { return out, err } p.AppendPointerSlice(mp) out.n = n out.initialized = o.initialized return out, nil } func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error { s := p.PointerSlice() for _, v := range s { if err := f.mi.checkInitializedPointer(v); err != nil { return err } } return nil } func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) n += protowire.SizeBytes(proto.Size(m)) + tagsize } return n } func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) b = protowire.AppendVarint(b, wiretag) siz := proto.Size(m) b = protowire.AppendVarint(b, uint64(siz)) b, err = opts.Options().MarshalAppend(b, m) if err != nil { return b, err } } return b, nil } func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } mp := reflect.New(goType.Elem()) o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: asMessage(mp).ProtoReflect(), }) if err != nil { return out, err } p.AppendPointerSlice(pointerOfValue(mp)) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func isInitMessageSlice(p pointer, goType reflect.Type) error { s := p.PointerSlice() for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) if err := proto.CheckInitialized(m); err != nil { return err } } return nil } // Slices of messages func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() n += protowire.SizeBytes(proto.Size(m)) + tagsize } return n } func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() mopts := opts.Options() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() b = protowire.AppendVarint(b, wiretag) siz := proto.Size(m) b = protowire.AppendVarint(b, uint64(siz)) var err error b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } } return b, nil } func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return pref.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return pref.Value{}, out, errDecode } m := list.NewElement() o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: m.Message(), }) if err != nil { return pref.Value{}, out, err } list.Append(m) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return listv, out, nil } func isInitMessageSliceValue(listv pref.Value) error { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() if err := proto.CheckInitialized(m); err != nil { return err } } return nil } var coderMessageSliceValue = valueCoderFuncs{ size: sizeMessageSliceValue, marshal: appendMessageSliceValue, unmarshal: consumeMessageSliceValue, isInit: isInitMessageSliceValue, merge: mergeMessageListValue, } func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() n += 2*tagsize + proto.Size(m) } return n } func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() mopts := opts.Options() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() b = protowire.AppendVarint(b, wiretag) // start group var err error b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } b = protowire.AppendVarint(b, wiretag+1) // end group } return b, nil } func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.StartGroupType { return pref.Value{}, out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return pref.Value{}, out, errDecode } m := list.NewElement() o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: m.Message(), }) if err != nil { return pref.Value{}, out, err } list.Append(m) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return listv, out, nil } var coderGroupSliceValue = valueCoderFuncs{ size: sizeGroupSliceValue, marshal: appendGroupSliceValue, unmarshal: consumeGroupSliceValue, isInit: isInitMessageSliceValue, merge: mergeMessageListValue, } func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { num := fd.Number() if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeGroupSliceInfo, marshal: appendGroupSliceInfo, unmarshal: consumeGroupSliceInfo, merge: mergeMessageSlice, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageSliceInfo } return funcs } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeGroupSlice(p, ft, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendGroupSlice(b, p, f.wiretag, ft, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { return consumeGroupSlice(b, p, num, wtyp, ft, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { return isInitMessageSlice(p, ft) }, merge: mergeMessageSlice, } } func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(messageType.Elem())) n += 2*tagsize + proto.Size(m) } return n } func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { m := asMessage(v.AsValueOf(messageType.Elem())) b = protowire.AppendVarint(b, wiretag) // start group b, err = opts.Options().MarshalAppend(b, m) if err != nil { return b, err } b = protowire.AppendVarint(b, wiretag+1) // end group } return b, nil } func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return out, errDecode } mp := reflect.New(goType.Elem()) o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: asMessage(mp).ProtoReflect(), }) if err != nil { return out, err } p.AppendPointerSlice(pointerOfValue(mp)) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { n += 2*f.tagsize + f.mi.sizePointer(v, opts) } return n } func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) // start group b, err = f.mi.marshalAppendPointer(b, v, opts) if err != nil { return b, err } b = protowire.AppendVarint(b, f.wiretag+1) // end group } return b, nil } func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { if wtyp != protowire.StartGroupType { return unmarshalOutput{}, errUnknown } m := reflect.New(f.mi.GoReflectType.Elem()).Interface() mp := pointerOfIface(m) out, err := f.mi.unmarshalPointer(b, mp, f.num, opts) if err != nil { return out, err } p.AppendPointerSlice(mp) return out, nil } func asMessage(v reflect.Value) pref.ProtoMessage { if m, ok := v.Interface().(pref.ProtoMessage); ok { return m } return legacyWrapMessage(v).Interface() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/reflect/protoreflect" ) // sizeBool returns the size of wire encoding a bool pointer as a Bool. func sizeBool(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bool() return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBool wire encodes a bool pointer as a Bool. func appendBool(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bool() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } // consumeBool wire decodes a bool pointer as a Bool. func consumeBool(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Bool() = protowire.DecodeBool(v) out.n = n return out, nil } var coderBool = pointerCoderFuncs{ size: sizeBool, marshal: appendBool, unmarshal: consumeBool, merge: mergeBool, } // sizeBoolNoZero returns the size of wire encoding a bool pointer as a Bool. // The zero value is not encoded. func sizeBoolNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bool() if v == false { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBoolNoZero wire encodes a bool pointer as a Bool. // The zero value is not encoded. func appendBoolNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bool() if v == false { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } var coderBoolNoZero = pointerCoderFuncs{ size: sizeBoolNoZero, marshal: appendBoolNoZero, unmarshal: consumeBool, merge: mergeBoolNoZero, } // sizeBoolPtr returns the size of wire encoding a *bool pointer as a Bool. // It panics if the pointer is nil. func sizeBoolPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.BoolPtr() return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBoolPtr wire encodes a *bool pointer as a Bool. // It panics if the pointer is nil. func appendBoolPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.BoolPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } // consumeBoolPtr wire decodes a *bool pointer as a Bool. func consumeBoolPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.BoolPtr() if *vp == nil { *vp = new(bool) } **vp = protowire.DecodeBool(v) out.n = n return out, nil } var coderBoolPtr = pointerCoderFuncs{ size: sizeBoolPtr, marshal: appendBoolPtr, unmarshal: consumeBoolPtr, merge: mergeBoolPtr, } // sizeBoolSlice returns the size of wire encoding a []bool pointer as a repeated Bool. func sizeBoolSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BoolSlice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } return size } // appendBoolSlice encodes a []bool pointer as a repeated Bool. func appendBoolSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BoolSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) } return b, nil } // consumeBoolSlice wire decodes a []bool pointer as a repeated Bool. func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.BoolSlice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, protowire.DecodeBool(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, protowire.DecodeBool(v)) out.n = n return out, nil } var coderBoolSlice = pointerCoderFuncs{ size: sizeBoolSlice, marshal: appendBoolSlice, unmarshal: consumeBoolSlice, merge: mergeBoolSlice, } // sizeBoolPackedSlice returns the size of wire encoding a []bool pointer as a packed repeated Bool. func sizeBoolPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BoolSlice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeBool(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendBoolPackedSlice encodes a []bool pointer as a packed repeated Bool. func appendBoolPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BoolSlice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeBool(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeBool(v)) } return b, nil } var coderBoolPackedSlice = pointerCoderFuncs{ size: sizeBoolPackedSlice, marshal: appendBoolPackedSlice, unmarshal: consumeBoolSlice, merge: mergeBoolSlice, } // sizeBoolValue returns the size of wire encoding a bool value as a Bool. func sizeBoolValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } // appendBoolValue encodes a bool value as a Bool. func appendBoolValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) return b, nil } // consumeBoolValue decodes a bool value as a Bool. func consumeBoolValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfBool(protowire.DecodeBool(v)), out, nil } var coderBoolValue = valueCoderFuncs{ size: sizeBoolValue, marshal: appendBoolValue, unmarshal: consumeBoolValue, merge: mergeScalarValue, } // sizeBoolSliceValue returns the size of wire encoding a []bool value as a repeated Bool. func sizeBoolSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } return size } // appendBoolSliceValue encodes a []bool value as a repeated Bool. func appendBoolSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) } return b, nil } // consumeBoolSliceValue wire decodes a []bool value as a repeated Bool. func consumeBoolSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) out.n = n return listv, out, nil } var coderBoolSliceValue = valueCoderFuncs{ size: sizeBoolSliceValue, marshal: appendBoolSliceValue, unmarshal: consumeBoolSliceValue, merge: mergeListValue, } // sizeBoolPackedSliceValue returns the size of wire encoding a []bool value as a packed repeated Bool. func sizeBoolPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } return tagsize + protowire.SizeBytes(n) } // appendBoolPackedSliceValue encodes a []bool value as a packed repeated Bool. func appendBoolPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) } return b, nil } var coderBoolPackedSliceValue = valueCoderFuncs{ size: sizeBoolPackedSliceValue, marshal: appendBoolPackedSliceValue, unmarshal: consumeBoolSliceValue, merge: mergeListValue, } // sizeEnumValue returns the size of wire encoding a value as a Enum. func sizeEnumValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(v.Enum())) } // appendEnumValue encodes a value as a Enum. func appendEnumValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Enum())) return b, nil } // consumeEnumValue decodes a value as a Enum. func consumeEnumValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), out, nil } var coderEnumValue = valueCoderFuncs{ size: sizeEnumValue, marshal: appendEnumValue, unmarshal: consumeEnumValue, merge: mergeScalarValue, } // sizeEnumSliceValue returns the size of wire encoding a [] value as a repeated Enum. func sizeEnumSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(v.Enum())) } return size } // appendEnumSliceValue encodes a [] value as a repeated Enum. func appendEnumSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Enum())) } return b, nil } // consumeEnumSliceValue wire decodes a [] value as a repeated Enum. func consumeEnumSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) out.n = n return listv, out, nil } var coderEnumSliceValue = valueCoderFuncs{ size: sizeEnumSliceValue, marshal: appendEnumSliceValue, unmarshal: consumeEnumSliceValue, merge: mergeListValue, } // sizeEnumPackedSliceValue returns the size of wire encoding a [] value as a packed repeated Enum. func sizeEnumPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Enum())) } return tagsize + protowire.SizeBytes(n) } // appendEnumPackedSliceValue encodes a [] value as a packed repeated Enum. func appendEnumPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Enum())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(v.Enum())) } return b, nil } var coderEnumPackedSliceValue = valueCoderFuncs{ size: sizeEnumPackedSliceValue, marshal: appendEnumPackedSliceValue, unmarshal: consumeEnumSliceValue, merge: mergeListValue, } // sizeInt32 returns the size of wire encoding a int32 pointer as a Int32. func sizeInt32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32 wire encodes a int32 pointer as a Int32. func appendInt32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt32 wire decodes a int32 pointer as a Int32. func consumeInt32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int32() = int32(v) out.n = n return out, nil } var coderInt32 = pointerCoderFuncs{ size: sizeInt32, marshal: appendInt32, unmarshal: consumeInt32, merge: mergeInt32, } // sizeInt32NoZero returns the size of wire encoding a int32 pointer as a Int32. // The zero value is not encoded. func sizeInt32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32NoZero wire encodes a int32 pointer as a Int32. // The zero value is not encoded. func appendInt32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderInt32NoZero = pointerCoderFuncs{ size: sizeInt32NoZero, marshal: appendInt32NoZero, unmarshal: consumeInt32, merge: mergeInt32NoZero, } // sizeInt32Ptr returns the size of wire encoding a *int32 pointer as a Int32. // It panics if the pointer is nil. func sizeInt32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int32Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32Ptr wire encodes a *int32 pointer as a Int32. // It panics if the pointer is nil. func appendInt32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt32Ptr wire decodes a *int32 pointer as a Int32. func consumeInt32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(v) out.n = n return out, nil } var coderInt32Ptr = pointerCoderFuncs{ size: sizeInt32Ptr, marshal: appendInt32Ptr, unmarshal: consumeInt32Ptr, merge: mergeInt32Ptr, } // sizeInt32Slice returns the size of wire encoding a []int32 pointer as a repeated Int32. func sizeInt32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendInt32Slice encodes a []int32 pointer as a repeated Int32. func appendInt32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeInt32Slice wire decodes a []int32 pointer as a repeated Int32. func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int32(v)) out.n = n return out, nil } var coderInt32Slice = pointerCoderFuncs{ size: sizeInt32Slice, marshal: appendInt32Slice, unmarshal: consumeInt32Slice, merge: mergeInt32Slice, } // sizeInt32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Int32. func sizeInt32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendInt32PackedSlice encodes a []int32 pointer as a packed repeated Int32. func appendInt32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderInt32PackedSlice = pointerCoderFuncs{ size: sizeInt32PackedSlice, marshal: appendInt32PackedSlice, unmarshal: consumeInt32Slice, merge: mergeInt32Slice, } // sizeInt32Value returns the size of wire encoding a int32 value as a Int32. func sizeInt32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(int32(v.Int()))) } // appendInt32Value encodes a int32 value as a Int32. func appendInt32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) return b, nil } // consumeInt32Value decodes a int32 value as a Int32. func consumeInt32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(v)), out, nil } var coderInt32Value = valueCoderFuncs{ size: sizeInt32Value, marshal: appendInt32Value, unmarshal: consumeInt32Value, merge: mergeScalarValue, } // sizeInt32SliceValue returns the size of wire encoding a []int32 value as a repeated Int32. func sizeInt32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(int32(v.Int()))) } return size } // appendInt32SliceValue encodes a []int32 value as a repeated Int32. func appendInt32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) } return b, nil } // consumeInt32SliceValue wire decodes a []int32 value as a repeated Int32. func consumeInt32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) out.n = n return listv, out, nil } var coderInt32SliceValue = valueCoderFuncs{ size: sizeInt32SliceValue, marshal: appendInt32SliceValue, unmarshal: consumeInt32SliceValue, merge: mergeListValue, } // sizeInt32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Int32. func sizeInt32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(int32(v.Int()))) } return tagsize + protowire.SizeBytes(n) } // appendInt32PackedSliceValue encodes a []int32 value as a packed repeated Int32. func appendInt32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(int32(v.Int()))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) } return b, nil } var coderInt32PackedSliceValue = valueCoderFuncs{ size: sizeInt32PackedSliceValue, marshal: appendInt32PackedSliceValue, unmarshal: consumeInt32SliceValue, merge: mergeListValue, } // sizeSint32 returns the size of wire encoding a int32 pointer as a Sint32. func sizeSint32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32 wire encodes a int32 pointer as a Sint32. func appendSint32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } // consumeSint32 wire decodes a int32 pointer as a Sint32. func consumeSint32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int32() = int32(protowire.DecodeZigZag(v & math.MaxUint32)) out.n = n return out, nil } var coderSint32 = pointerCoderFuncs{ size: sizeSint32, marshal: appendSint32, unmarshal: consumeSint32, merge: mergeInt32, } // sizeSint32NoZero returns the size of wire encoding a int32 pointer as a Sint32. // The zero value is not encoded. func sizeSint32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32NoZero wire encodes a int32 pointer as a Sint32. // The zero value is not encoded. func appendSint32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } var coderSint32NoZero = pointerCoderFuncs{ size: sizeSint32NoZero, marshal: appendSint32NoZero, unmarshal: consumeSint32, merge: mergeInt32NoZero, } // sizeSint32Ptr returns the size of wire encoding a *int32 pointer as a Sint32. // It panics if the pointer is nil. func sizeSint32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int32Ptr() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32Ptr wire encodes a *int32 pointer as a Sint32. // It panics if the pointer is nil. func appendSint32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } // consumeSint32Ptr wire decodes a *int32 pointer as a Sint32. func consumeSint32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(protowire.DecodeZigZag(v & math.MaxUint32)) out.n = n return out, nil } var coderSint32Ptr = pointerCoderFuncs{ size: sizeSint32Ptr, marshal: appendSint32Ptr, unmarshal: consumeSint32Ptr, merge: mergeInt32Ptr, } // sizeSint32Slice returns the size of wire encoding a []int32 pointer as a repeated Sint32. func sizeSint32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } return size } // appendSint32Slice encodes a []int32 pointer as a repeated Sint32. func appendSint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) } return b, nil } // consumeSint32Slice wire decodes a []int32 pointer as a repeated Sint32. func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int32(protowire.DecodeZigZag(v&math.MaxUint32))) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int32(protowire.DecodeZigZag(v&math.MaxUint32))) out.n = n return out, nil } var coderSint32Slice = pointerCoderFuncs{ size: sizeSint32Slice, marshal: appendSint32Slice, unmarshal: consumeSint32Slice, merge: mergeInt32Slice, } // sizeSint32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sint32. func sizeSint32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } return f.tagsize + protowire.SizeBytes(n) } // appendSint32PackedSlice encodes a []int32 pointer as a packed repeated Sint32. func appendSint32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) } return b, nil } var coderSint32PackedSlice = pointerCoderFuncs{ size: sizeSint32PackedSlice, marshal: appendSint32PackedSlice, unmarshal: consumeSint32Slice, merge: mergeInt32Slice, } // sizeSint32Value returns the size of wire encoding a int32 value as a Sint32. func sizeSint32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } // appendSint32Value encodes a int32 value as a Sint32. func appendSint32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) return b, nil } // consumeSint32Value decodes a int32 value as a Sint32. func consumeSint32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), out, nil } var coderSint32Value = valueCoderFuncs{ size: sizeSint32Value, marshal: appendSint32Value, unmarshal: consumeSint32Value, merge: mergeScalarValue, } // sizeSint32SliceValue returns the size of wire encoding a []int32 value as a repeated Sint32. func sizeSint32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } return size } // appendSint32SliceValue encodes a []int32 value as a repeated Sint32. func appendSint32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) } return b, nil } // consumeSint32SliceValue wire decodes a []int32 value as a repeated Sint32. func consumeSint32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) out.n = n return listv, out, nil } var coderSint32SliceValue = valueCoderFuncs{ size: sizeSint32SliceValue, marshal: appendSint32SliceValue, unmarshal: consumeSint32SliceValue, merge: mergeListValue, } // sizeSint32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Sint32. func sizeSint32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } return tagsize + protowire.SizeBytes(n) } // appendSint32PackedSliceValue encodes a []int32 value as a packed repeated Sint32. func appendSint32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) } return b, nil } var coderSint32PackedSliceValue = valueCoderFuncs{ size: sizeSint32PackedSliceValue, marshal: appendSint32PackedSliceValue, unmarshal: consumeSint32SliceValue, merge: mergeListValue, } // sizeUint32 returns the size of wire encoding a uint32 pointer as a Uint32. func sizeUint32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32 wire encodes a uint32 pointer as a Uint32. func appendUint32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeUint32 wire decodes a uint32 pointer as a Uint32. func consumeUint32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Uint32() = uint32(v) out.n = n return out, nil } var coderUint32 = pointerCoderFuncs{ size: sizeUint32, marshal: appendUint32, unmarshal: consumeUint32, merge: mergeUint32, } // sizeUint32NoZero returns the size of wire encoding a uint32 pointer as a Uint32. // The zero value is not encoded. func sizeUint32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32NoZero wire encodes a uint32 pointer as a Uint32. // The zero value is not encoded. func appendUint32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderUint32NoZero = pointerCoderFuncs{ size: sizeUint32NoZero, marshal: appendUint32NoZero, unmarshal: consumeUint32, merge: mergeUint32NoZero, } // sizeUint32Ptr returns the size of wire encoding a *uint32 pointer as a Uint32. // It panics if the pointer is nil. func sizeUint32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Uint32Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32Ptr wire encodes a *uint32 pointer as a Uint32. // It panics if the pointer is nil. func appendUint32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeUint32Ptr wire decodes a *uint32 pointer as a Uint32. func consumeUint32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Uint32Ptr() if *vp == nil { *vp = new(uint32) } **vp = uint32(v) out.n = n return out, nil } var coderUint32Ptr = pointerCoderFuncs{ size: sizeUint32Ptr, marshal: appendUint32Ptr, unmarshal: consumeUint32Ptr, merge: mergeUint32Ptr, } // sizeUint32Slice returns the size of wire encoding a []uint32 pointer as a repeated Uint32. func sizeUint32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendUint32Slice encodes a []uint32 pointer as a repeated Uint32. func appendUint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeUint32Slice wire decodes a []uint32 pointer as a repeated Uint32. func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, uint32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, uint32(v)) out.n = n return out, nil } var coderUint32Slice = pointerCoderFuncs{ size: sizeUint32Slice, marshal: appendUint32Slice, unmarshal: consumeUint32Slice, merge: mergeUint32Slice, } // sizeUint32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Uint32. func sizeUint32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendUint32PackedSlice encodes a []uint32 pointer as a packed repeated Uint32. func appendUint32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderUint32PackedSlice = pointerCoderFuncs{ size: sizeUint32PackedSlice, marshal: appendUint32PackedSlice, unmarshal: consumeUint32Slice, merge: mergeUint32Slice, } // sizeUint32Value returns the size of wire encoding a uint32 value as a Uint32. func sizeUint32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(uint32(v.Uint()))) } // appendUint32Value encodes a uint32 value as a Uint32. func appendUint32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) return b, nil } // consumeUint32Value decodes a uint32 value as a Uint32. func consumeUint32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint32(uint32(v)), out, nil } var coderUint32Value = valueCoderFuncs{ size: sizeUint32Value, marshal: appendUint32Value, unmarshal: consumeUint32Value, merge: mergeScalarValue, } // sizeUint32SliceValue returns the size of wire encoding a []uint32 value as a repeated Uint32. func sizeUint32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(uint32(v.Uint()))) } return size } // appendUint32SliceValue encodes a []uint32 value as a repeated Uint32. func appendUint32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) } return b, nil } // consumeUint32SliceValue wire decodes a []uint32 value as a repeated Uint32. func consumeUint32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) out.n = n return listv, out, nil } var coderUint32SliceValue = valueCoderFuncs{ size: sizeUint32SliceValue, marshal: appendUint32SliceValue, unmarshal: consumeUint32SliceValue, merge: mergeListValue, } // sizeUint32PackedSliceValue returns the size of wire encoding a []uint32 value as a packed repeated Uint32. func sizeUint32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(uint32(v.Uint()))) } return tagsize + protowire.SizeBytes(n) } // appendUint32PackedSliceValue encodes a []uint32 value as a packed repeated Uint32. func appendUint32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(uint32(v.Uint()))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) } return b, nil } var coderUint32PackedSliceValue = valueCoderFuncs{ size: sizeUint32PackedSliceValue, marshal: appendUint32PackedSliceValue, unmarshal: consumeUint32SliceValue, merge: mergeListValue, } // sizeInt64 returns the size of wire encoding a int64 pointer as a Int64. func sizeInt64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64 wire encodes a int64 pointer as a Int64. func appendInt64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt64 wire decodes a int64 pointer as a Int64. func consumeInt64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int64() = int64(v) out.n = n return out, nil } var coderInt64 = pointerCoderFuncs{ size: sizeInt64, marshal: appendInt64, unmarshal: consumeInt64, merge: mergeInt64, } // sizeInt64NoZero returns the size of wire encoding a int64 pointer as a Int64. // The zero value is not encoded. func sizeInt64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64NoZero wire encodes a int64 pointer as a Int64. // The zero value is not encoded. func appendInt64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderInt64NoZero = pointerCoderFuncs{ size: sizeInt64NoZero, marshal: appendInt64NoZero, unmarshal: consumeInt64, merge: mergeInt64NoZero, } // sizeInt64Ptr returns the size of wire encoding a *int64 pointer as a Int64. // It panics if the pointer is nil. func sizeInt64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int64Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64Ptr wire encodes a *int64 pointer as a Int64. // It panics if the pointer is nil. func appendInt64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt64Ptr wire decodes a *int64 pointer as a Int64. func consumeInt64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = int64(v) out.n = n return out, nil } var coderInt64Ptr = pointerCoderFuncs{ size: sizeInt64Ptr, marshal: appendInt64Ptr, unmarshal: consumeInt64Ptr, merge: mergeInt64Ptr, } // sizeInt64Slice returns the size of wire encoding a []int64 pointer as a repeated Int64. func sizeInt64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendInt64Slice encodes a []int64 pointer as a repeated Int64. func appendInt64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeInt64Slice wire decodes a []int64 pointer as a repeated Int64. func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int64(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int64(v)) out.n = n return out, nil } var coderInt64Slice = pointerCoderFuncs{ size: sizeInt64Slice, marshal: appendInt64Slice, unmarshal: consumeInt64Slice, merge: mergeInt64Slice, } // sizeInt64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Int64. func sizeInt64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendInt64PackedSlice encodes a []int64 pointer as a packed repeated Int64. func appendInt64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderInt64PackedSlice = pointerCoderFuncs{ size: sizeInt64PackedSlice, marshal: appendInt64PackedSlice, unmarshal: consumeInt64Slice, merge: mergeInt64Slice, } // sizeInt64Value returns the size of wire encoding a int64 value as a Int64. func sizeInt64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(v.Int())) } // appendInt64Value encodes a int64 value as a Int64. func appendInt64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Int())) return b, nil } // consumeInt64Value decodes a int64 value as a Int64. func consumeInt64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(int64(v)), out, nil } var coderInt64Value = valueCoderFuncs{ size: sizeInt64Value, marshal: appendInt64Value, unmarshal: consumeInt64Value, merge: mergeScalarValue, } // sizeInt64SliceValue returns the size of wire encoding a []int64 value as a repeated Int64. func sizeInt64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(v.Int())) } return size } // appendInt64SliceValue encodes a []int64 value as a repeated Int64. func appendInt64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Int())) } return b, nil } // consumeInt64SliceValue wire decodes a []int64 value as a repeated Int64. func consumeInt64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) out.n = n return listv, out, nil } var coderInt64SliceValue = valueCoderFuncs{ size: sizeInt64SliceValue, marshal: appendInt64SliceValue, unmarshal: consumeInt64SliceValue, merge: mergeListValue, } // sizeInt64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Int64. func sizeInt64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Int())) } return tagsize + protowire.SizeBytes(n) } // appendInt64PackedSliceValue encodes a []int64 value as a packed repeated Int64. func appendInt64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(v.Int())) } return b, nil } var coderInt64PackedSliceValue = valueCoderFuncs{ size: sizeInt64PackedSliceValue, marshal: appendInt64PackedSliceValue, unmarshal: consumeInt64SliceValue, merge: mergeListValue, } // sizeSint64 returns the size of wire encoding a int64 pointer as a Sint64. func sizeSint64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64 wire encodes a int64 pointer as a Sint64. func appendSint64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } // consumeSint64 wire decodes a int64 pointer as a Sint64. func consumeSint64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int64() = protowire.DecodeZigZag(v) out.n = n return out, nil } var coderSint64 = pointerCoderFuncs{ size: sizeSint64, marshal: appendSint64, unmarshal: consumeSint64, merge: mergeInt64, } // sizeSint64NoZero returns the size of wire encoding a int64 pointer as a Sint64. // The zero value is not encoded. func sizeSint64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64NoZero wire encodes a int64 pointer as a Sint64. // The zero value is not encoded. func appendSint64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } var coderSint64NoZero = pointerCoderFuncs{ size: sizeSint64NoZero, marshal: appendSint64NoZero, unmarshal: consumeSint64, merge: mergeInt64NoZero, } // sizeSint64Ptr returns the size of wire encoding a *int64 pointer as a Sint64. // It panics if the pointer is nil. func sizeSint64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int64Ptr() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64Ptr wire encodes a *int64 pointer as a Sint64. // It panics if the pointer is nil. func appendSint64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } // consumeSint64Ptr wire decodes a *int64 pointer as a Sint64. func consumeSint64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = protowire.DecodeZigZag(v) out.n = n return out, nil } var coderSint64Ptr = pointerCoderFuncs{ size: sizeSint64Ptr, marshal: appendSint64Ptr, unmarshal: consumeSint64Ptr, merge: mergeInt64Ptr, } // sizeSint64Slice returns the size of wire encoding a []int64 pointer as a repeated Sint64. func sizeSint64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } return size } // appendSint64Slice encodes a []int64 pointer as a repeated Sint64. func appendSint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) } return b, nil } // consumeSint64Slice wire decodes a []int64 pointer as a repeated Sint64. func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, protowire.DecodeZigZag(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, protowire.DecodeZigZag(v)) out.n = n return out, nil } var coderSint64Slice = pointerCoderFuncs{ size: sizeSint64Slice, marshal: appendSint64Slice, unmarshal: consumeSint64Slice, merge: mergeInt64Slice, } // sizeSint64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sint64. func sizeSint64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendSint64PackedSlice encodes a []int64 pointer as a packed repeated Sint64. func appendSint64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) } return b, nil } var coderSint64PackedSlice = pointerCoderFuncs{ size: sizeSint64PackedSlice, marshal: appendSint64PackedSlice, unmarshal: consumeSint64Slice, merge: mergeInt64Slice, } // sizeSint64Value returns the size of wire encoding a int64 value as a Sint64. func sizeSint64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } // appendSint64Value encodes a int64 value as a Sint64. func appendSint64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) return b, nil } // consumeSint64Value decodes a int64 value as a Sint64. func consumeSint64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), out, nil } var coderSint64Value = valueCoderFuncs{ size: sizeSint64Value, marshal: appendSint64Value, unmarshal: consumeSint64Value, merge: mergeScalarValue, } // sizeSint64SliceValue returns the size of wire encoding a []int64 value as a repeated Sint64. func sizeSint64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } return size } // appendSint64SliceValue encodes a []int64 value as a repeated Sint64. func appendSint64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) } return b, nil } // consumeSint64SliceValue wire decodes a []int64 value as a repeated Sint64. func consumeSint64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) out.n = n return listv, out, nil } var coderSint64SliceValue = valueCoderFuncs{ size: sizeSint64SliceValue, marshal: appendSint64SliceValue, unmarshal: consumeSint64SliceValue, merge: mergeListValue, } // sizeSint64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Sint64. func sizeSint64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } return tagsize + protowire.SizeBytes(n) } // appendSint64PackedSliceValue encodes a []int64 value as a packed repeated Sint64. func appendSint64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) } return b, nil } var coderSint64PackedSliceValue = valueCoderFuncs{ size: sizeSint64PackedSliceValue, marshal: appendSint64PackedSliceValue, unmarshal: consumeSint64SliceValue, merge: mergeListValue, } // sizeUint64 returns the size of wire encoding a uint64 pointer as a Uint64. func sizeUint64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() return f.tagsize + protowire.SizeVarint(v) } // appendUint64 wire encodes a uint64 pointer as a Uint64. func appendUint64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } // consumeUint64 wire decodes a uint64 pointer as a Uint64. func consumeUint64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Uint64() = v out.n = n return out, nil } var coderUint64 = pointerCoderFuncs{ size: sizeUint64, marshal: appendUint64, unmarshal: consumeUint64, merge: mergeUint64, } // sizeUint64NoZero returns the size of wire encoding a uint64 pointer as a Uint64. // The zero value is not encoded. func sizeUint64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(v) } // appendUint64NoZero wire encodes a uint64 pointer as a Uint64. // The zero value is not encoded. func appendUint64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } var coderUint64NoZero = pointerCoderFuncs{ size: sizeUint64NoZero, marshal: appendUint64NoZero, unmarshal: consumeUint64, merge: mergeUint64NoZero, } // sizeUint64Ptr returns the size of wire encoding a *uint64 pointer as a Uint64. // It panics if the pointer is nil. func sizeUint64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Uint64Ptr() return f.tagsize + protowire.SizeVarint(v) } // appendUint64Ptr wire encodes a *uint64 pointer as a Uint64. // It panics if the pointer is nil. func appendUint64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } // consumeUint64Ptr wire decodes a *uint64 pointer as a Uint64. func consumeUint64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Uint64Ptr() if *vp == nil { *vp = new(uint64) } **vp = v out.n = n return out, nil } var coderUint64Ptr = pointerCoderFuncs{ size: sizeUint64Ptr, marshal: appendUint64Ptr, unmarshal: consumeUint64Ptr, merge: mergeUint64Ptr, } // sizeUint64Slice returns the size of wire encoding a []uint64 pointer as a repeated Uint64. func sizeUint64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(v) } return size } // appendUint64Slice encodes a []uint64 pointer as a repeated Uint64. func appendUint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) } return b, nil } // consumeUint64Slice wire decodes a []uint64 pointer as a repeated Uint64. func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderUint64Slice = pointerCoderFuncs{ size: sizeUint64Slice, marshal: appendUint64Slice, unmarshal: consumeUint64Slice, merge: mergeUint64Slice, } // sizeUint64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Uint64. func sizeUint64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(v) } return f.tagsize + protowire.SizeBytes(n) } // appendUint64PackedSlice encodes a []uint64 pointer as a packed repeated Uint64. func appendUint64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(v) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, v) } return b, nil } var coderUint64PackedSlice = pointerCoderFuncs{ size: sizeUint64PackedSlice, marshal: appendUint64PackedSlice, unmarshal: consumeUint64Slice, merge: mergeUint64Slice, } // sizeUint64Value returns the size of wire encoding a uint64 value as a Uint64. func sizeUint64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(v.Uint()) } // appendUint64Value encodes a uint64 value as a Uint64. func appendUint64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, v.Uint()) return b, nil } // consumeUint64Value decodes a uint64 value as a Uint64. func consumeUint64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint64(v), out, nil } var coderUint64Value = valueCoderFuncs{ size: sizeUint64Value, marshal: appendUint64Value, unmarshal: consumeUint64Value, merge: mergeScalarValue, } // sizeUint64SliceValue returns the size of wire encoding a []uint64 value as a repeated Uint64. func sizeUint64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(v.Uint()) } return size } // appendUint64SliceValue encodes a []uint64 value as a repeated Uint64. func appendUint64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, v.Uint()) } return b, nil } // consumeUint64SliceValue wire decodes a []uint64 value as a repeated Uint64. func consumeUint64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) out.n = n return listv, out, nil } var coderUint64SliceValue = valueCoderFuncs{ size: sizeUint64SliceValue, marshal: appendUint64SliceValue, unmarshal: consumeUint64SliceValue, merge: mergeListValue, } // sizeUint64PackedSliceValue returns the size of wire encoding a []uint64 value as a packed repeated Uint64. func sizeUint64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(v.Uint()) } return tagsize + protowire.SizeBytes(n) } // appendUint64PackedSliceValue encodes a []uint64 value as a packed repeated Uint64. func appendUint64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(v.Uint()) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, v.Uint()) } return b, nil } var coderUint64PackedSliceValue = valueCoderFuncs{ size: sizeUint64PackedSliceValue, marshal: appendUint64PackedSliceValue, unmarshal: consumeUint64SliceValue, merge: mergeListValue, } // sizeSfixed32 returns the size of wire encoding a int32 pointer as a Sfixed32. func sizeSfixed32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendSfixed32 wire encodes a int32 pointer as a Sfixed32. func appendSfixed32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } // consumeSfixed32 wire decodes a int32 pointer as a Sfixed32. func consumeSfixed32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Int32() = int32(v) out.n = n return out, nil } var coderSfixed32 = pointerCoderFuncs{ size: sizeSfixed32, marshal: appendSfixed32, unmarshal: consumeSfixed32, merge: mergeInt32, } // sizeSfixed32NoZero returns the size of wire encoding a int32 pointer as a Sfixed32. // The zero value is not encoded. func sizeSfixed32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendSfixed32NoZero wire encodes a int32 pointer as a Sfixed32. // The zero value is not encoded. func appendSfixed32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } var coderSfixed32NoZero = pointerCoderFuncs{ size: sizeSfixed32NoZero, marshal: appendSfixed32NoZero, unmarshal: consumeSfixed32, merge: mergeInt32NoZero, } // sizeSfixed32Ptr returns the size of wire encoding a *int32 pointer as a Sfixed32. // It panics if the pointer is nil. func sizeSfixed32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendSfixed32Ptr wire encodes a *int32 pointer as a Sfixed32. // It panics if the pointer is nil. func appendSfixed32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } // consumeSfixed32Ptr wire decodes a *int32 pointer as a Sfixed32. func consumeSfixed32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(v) out.n = n return out, nil } var coderSfixed32Ptr = pointerCoderFuncs{ size: sizeSfixed32Ptr, marshal: appendSfixed32Ptr, unmarshal: consumeSfixed32Ptr, merge: mergeInt32Ptr, } // sizeSfixed32Slice returns the size of wire encoding a []int32 pointer as a repeated Sfixed32. func sizeSfixed32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendSfixed32Slice encodes a []int32 pointer as a repeated Sfixed32. func appendSfixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) } return b, nil } // consumeSfixed32Slice wire decodes a []int32 pointer as a repeated Sfixed32. func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, int32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, int32(v)) out.n = n return out, nil } var coderSfixed32Slice = pointerCoderFuncs{ size: sizeSfixed32Slice, marshal: appendSfixed32Slice, unmarshal: consumeSfixed32Slice, merge: mergeInt32Slice, } // sizeSfixed32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sfixed32. func sizeSfixed32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendSfixed32PackedSlice encodes a []int32 pointer as a packed repeated Sfixed32. func appendSfixed32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, uint32(v)) } return b, nil } var coderSfixed32PackedSlice = pointerCoderFuncs{ size: sizeSfixed32PackedSlice, marshal: appendSfixed32PackedSlice, unmarshal: consumeSfixed32Slice, merge: mergeInt32Slice, } // sizeSfixed32Value returns the size of wire encoding a int32 value as a Sfixed32. func sizeSfixed32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendSfixed32Value encodes a int32 value as a Sfixed32. func appendSfixed32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Int())) return b, nil } // consumeSfixed32Value decodes a int32 value as a Sfixed32. func consumeSfixed32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(v)), out, nil } var coderSfixed32Value = valueCoderFuncs{ size: sizeSfixed32Value, marshal: appendSfixed32Value, unmarshal: consumeSfixed32Value, merge: mergeScalarValue, } // sizeSfixed32SliceValue returns the size of wire encoding a []int32 value as a repeated Sfixed32. func sizeSfixed32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendSfixed32SliceValue encodes a []int32 value as a repeated Sfixed32. func appendSfixed32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Int())) } return b, nil } // consumeSfixed32SliceValue wire decodes a []int32 value as a repeated Sfixed32. func consumeSfixed32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) out.n = n return listv, out, nil } var coderSfixed32SliceValue = valueCoderFuncs{ size: sizeSfixed32SliceValue, marshal: appendSfixed32SliceValue, unmarshal: consumeSfixed32SliceValue, merge: mergeListValue, } // sizeSfixed32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Sfixed32. func sizeSfixed32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendSfixed32PackedSliceValue encodes a []int32 value as a packed repeated Sfixed32. func appendSfixed32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, uint32(v.Int())) } return b, nil } var coderSfixed32PackedSliceValue = valueCoderFuncs{ size: sizeSfixed32PackedSliceValue, marshal: appendSfixed32PackedSliceValue, unmarshal: consumeSfixed32SliceValue, merge: mergeListValue, } // sizeFixed32 returns the size of wire encoding a uint32 pointer as a Fixed32. func sizeFixed32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFixed32 wire encodes a uint32 pointer as a Fixed32. func appendFixed32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } // consumeFixed32 wire decodes a uint32 pointer as a Fixed32. func consumeFixed32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Uint32() = v out.n = n return out, nil } var coderFixed32 = pointerCoderFuncs{ size: sizeFixed32, marshal: appendFixed32, unmarshal: consumeFixed32, merge: mergeUint32, } // sizeFixed32NoZero returns the size of wire encoding a uint32 pointer as a Fixed32. // The zero value is not encoded. func sizeFixed32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendFixed32NoZero wire encodes a uint32 pointer as a Fixed32. // The zero value is not encoded. func appendFixed32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } var coderFixed32NoZero = pointerCoderFuncs{ size: sizeFixed32NoZero, marshal: appendFixed32NoZero, unmarshal: consumeFixed32, merge: mergeUint32NoZero, } // sizeFixed32Ptr returns the size of wire encoding a *uint32 pointer as a Fixed32. // It panics if the pointer is nil. func sizeFixed32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFixed32Ptr wire encodes a *uint32 pointer as a Fixed32. // It panics if the pointer is nil. func appendFixed32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } // consumeFixed32Ptr wire decodes a *uint32 pointer as a Fixed32. func consumeFixed32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Uint32Ptr() if *vp == nil { *vp = new(uint32) } **vp = v out.n = n return out, nil } var coderFixed32Ptr = pointerCoderFuncs{ size: sizeFixed32Ptr, marshal: appendFixed32Ptr, unmarshal: consumeFixed32Ptr, merge: mergeUint32Ptr, } // sizeFixed32Slice returns the size of wire encoding a []uint32 pointer as a repeated Fixed32. func sizeFixed32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendFixed32Slice encodes a []uint32 pointer as a repeated Fixed32. func appendFixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) } return b, nil } // consumeFixed32Slice wire decodes a []uint32 pointer as a repeated Fixed32. func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderFixed32Slice = pointerCoderFuncs{ size: sizeFixed32Slice, marshal: appendFixed32Slice, unmarshal: consumeFixed32Slice, merge: mergeUint32Slice, } // sizeFixed32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Fixed32. func sizeFixed32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendFixed32PackedSlice encodes a []uint32 pointer as a packed repeated Fixed32. func appendFixed32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, v) } return b, nil } var coderFixed32PackedSlice = pointerCoderFuncs{ size: sizeFixed32PackedSlice, marshal: appendFixed32PackedSlice, unmarshal: consumeFixed32Slice, merge: mergeUint32Slice, } // sizeFixed32Value returns the size of wire encoding a uint32 value as a Fixed32. func sizeFixed32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendFixed32Value encodes a uint32 value as a Fixed32. func appendFixed32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Uint())) return b, nil } // consumeFixed32Value decodes a uint32 value as a Fixed32. func consumeFixed32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint32(uint32(v)), out, nil } var coderFixed32Value = valueCoderFuncs{ size: sizeFixed32Value, marshal: appendFixed32Value, unmarshal: consumeFixed32Value, merge: mergeScalarValue, } // sizeFixed32SliceValue returns the size of wire encoding a []uint32 value as a repeated Fixed32. func sizeFixed32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendFixed32SliceValue encodes a []uint32 value as a repeated Fixed32. func appendFixed32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Uint())) } return b, nil } // consumeFixed32SliceValue wire decodes a []uint32 value as a repeated Fixed32. func consumeFixed32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) out.n = n return listv, out, nil } var coderFixed32SliceValue = valueCoderFuncs{ size: sizeFixed32SliceValue, marshal: appendFixed32SliceValue, unmarshal: consumeFixed32SliceValue, merge: mergeListValue, } // sizeFixed32PackedSliceValue returns the size of wire encoding a []uint32 value as a packed repeated Fixed32. func sizeFixed32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendFixed32PackedSliceValue encodes a []uint32 value as a packed repeated Fixed32. func appendFixed32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, uint32(v.Uint())) } return b, nil } var coderFixed32PackedSliceValue = valueCoderFuncs{ size: sizeFixed32PackedSliceValue, marshal: appendFixed32PackedSliceValue, unmarshal: consumeFixed32SliceValue, merge: mergeListValue, } // sizeFloat returns the size of wire encoding a float32 pointer as a Float. func sizeFloat(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFloat wire encodes a float32 pointer as a Float. func appendFloat(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } // consumeFloat wire decodes a float32 pointer as a Float. func consumeFloat(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Float32() = math.Float32frombits(v) out.n = n return out, nil } var coderFloat = pointerCoderFuncs{ size: sizeFloat, marshal: appendFloat, unmarshal: consumeFloat, merge: mergeFloat32, } // sizeFloatNoZero returns the size of wire encoding a float32 pointer as a Float. // The zero value is not encoded. func sizeFloatNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Float32() if v == 0 && !math.Signbit(float64(v)) { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendFloatNoZero wire encodes a float32 pointer as a Float. // The zero value is not encoded. func appendFloatNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float32() if v == 0 && !math.Signbit(float64(v)) { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } var coderFloatNoZero = pointerCoderFuncs{ size: sizeFloatNoZero, marshal: appendFloatNoZero, unmarshal: consumeFloat, merge: mergeFloat32NoZero, } // sizeFloatPtr returns the size of wire encoding a *float32 pointer as a Float. // It panics if the pointer is nil. func sizeFloatPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFloatPtr wire encodes a *float32 pointer as a Float. // It panics if the pointer is nil. func appendFloatPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Float32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } // consumeFloatPtr wire decodes a *float32 pointer as a Float. func consumeFloatPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Float32Ptr() if *vp == nil { *vp = new(float32) } **vp = math.Float32frombits(v) out.n = n return out, nil } var coderFloatPtr = pointerCoderFuncs{ size: sizeFloatPtr, marshal: appendFloatPtr, unmarshal: consumeFloatPtr, merge: mergeFloat32Ptr, } // sizeFloatSlice returns the size of wire encoding a []float32 pointer as a repeated Float. func sizeFloatSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendFloatSlice encodes a []float32 pointer as a repeated Float. func appendFloatSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) } return b, nil } // consumeFloatSlice wire decodes a []float32 pointer as a repeated Float. func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Float32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, math.Float32frombits(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, math.Float32frombits(v)) out.n = n return out, nil } var coderFloatSlice = pointerCoderFuncs{ size: sizeFloatSlice, marshal: appendFloatSlice, unmarshal: consumeFloatSlice, merge: mergeFloat32Slice, } // sizeFloatPackedSlice returns the size of wire encoding a []float32 pointer as a packed repeated Float. func sizeFloatPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendFloatPackedSlice encodes a []float32 pointer as a packed repeated Float. func appendFloatPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, math.Float32bits(v)) } return b, nil } var coderFloatPackedSlice = pointerCoderFuncs{ size: sizeFloatPackedSlice, marshal: appendFloatPackedSlice, unmarshal: consumeFloatSlice, merge: mergeFloat32Slice, } // sizeFloatValue returns the size of wire encoding a float32 value as a Float. func sizeFloatValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendFloatValue encodes a float32 value as a Float. func appendFloatValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) return b, nil } // consumeFloatValue decodes a float32 value as a Float. func consumeFloatValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), out, nil } var coderFloatValue = valueCoderFuncs{ size: sizeFloatValue, marshal: appendFloatValue, unmarshal: consumeFloatValue, merge: mergeScalarValue, } // sizeFloatSliceValue returns the size of wire encoding a []float32 value as a repeated Float. func sizeFloatSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendFloatSliceValue encodes a []float32 value as a repeated Float. func appendFloatSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) } return b, nil } // consumeFloatSliceValue wire decodes a []float32 value as a repeated Float. func consumeFloatSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) out.n = n return listv, out, nil } var coderFloatSliceValue = valueCoderFuncs{ size: sizeFloatSliceValue, marshal: appendFloatSliceValue, unmarshal: consumeFloatSliceValue, merge: mergeListValue, } // sizeFloatPackedSliceValue returns the size of wire encoding a []float32 value as a packed repeated Float. func sizeFloatPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendFloatPackedSliceValue encodes a []float32 value as a packed repeated Float. func appendFloatPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) } return b, nil } var coderFloatPackedSliceValue = valueCoderFuncs{ size: sizeFloatPackedSliceValue, marshal: appendFloatPackedSliceValue, unmarshal: consumeFloatSliceValue, merge: mergeListValue, } // sizeSfixed64 returns the size of wire encoding a int64 pointer as a Sfixed64. func sizeSfixed64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendSfixed64 wire encodes a int64 pointer as a Sfixed64. func appendSfixed64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } // consumeSfixed64 wire decodes a int64 pointer as a Sfixed64. func consumeSfixed64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Int64() = int64(v) out.n = n return out, nil } var coderSfixed64 = pointerCoderFuncs{ size: sizeSfixed64, marshal: appendSfixed64, unmarshal: consumeSfixed64, merge: mergeInt64, } // sizeSfixed64NoZero returns the size of wire encoding a int64 pointer as a Sfixed64. // The zero value is not encoded. func sizeSfixed64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendSfixed64NoZero wire encodes a int64 pointer as a Sfixed64. // The zero value is not encoded. func appendSfixed64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } var coderSfixed64NoZero = pointerCoderFuncs{ size: sizeSfixed64NoZero, marshal: appendSfixed64NoZero, unmarshal: consumeSfixed64, merge: mergeInt64NoZero, } // sizeSfixed64Ptr returns the size of wire encoding a *int64 pointer as a Sfixed64. // It panics if the pointer is nil. func sizeSfixed64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendSfixed64Ptr wire encodes a *int64 pointer as a Sfixed64. // It panics if the pointer is nil. func appendSfixed64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } // consumeSfixed64Ptr wire decodes a *int64 pointer as a Sfixed64. func consumeSfixed64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = int64(v) out.n = n return out, nil } var coderSfixed64Ptr = pointerCoderFuncs{ size: sizeSfixed64Ptr, marshal: appendSfixed64Ptr, unmarshal: consumeSfixed64Ptr, merge: mergeInt64Ptr, } // sizeSfixed64Slice returns the size of wire encoding a []int64 pointer as a repeated Sfixed64. func sizeSfixed64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendSfixed64Slice encodes a []int64 pointer as a repeated Sfixed64. func appendSfixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) } return b, nil } // consumeSfixed64Slice wire decodes a []int64 pointer as a repeated Sfixed64. func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, int64(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, int64(v)) out.n = n return out, nil } var coderSfixed64Slice = pointerCoderFuncs{ size: sizeSfixed64Slice, marshal: appendSfixed64Slice, unmarshal: consumeSfixed64Slice, merge: mergeInt64Slice, } // sizeSfixed64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sfixed64. func sizeSfixed64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendSfixed64PackedSlice encodes a []int64 pointer as a packed repeated Sfixed64. func appendSfixed64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, uint64(v)) } return b, nil } var coderSfixed64PackedSlice = pointerCoderFuncs{ size: sizeSfixed64PackedSlice, marshal: appendSfixed64PackedSlice, unmarshal: consumeSfixed64Slice, merge: mergeInt64Slice, } // sizeSfixed64Value returns the size of wire encoding a int64 value as a Sfixed64. func sizeSfixed64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendSfixed64Value encodes a int64 value as a Sfixed64. func appendSfixed64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, uint64(v.Int())) return b, nil } // consumeSfixed64Value decodes a int64 value as a Sfixed64. func consumeSfixed64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(int64(v)), out, nil } var coderSfixed64Value = valueCoderFuncs{ size: sizeSfixed64Value, marshal: appendSfixed64Value, unmarshal: consumeSfixed64Value, merge: mergeScalarValue, } // sizeSfixed64SliceValue returns the size of wire encoding a []int64 value as a repeated Sfixed64. func sizeSfixed64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendSfixed64SliceValue encodes a []int64 value as a repeated Sfixed64. func appendSfixed64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, uint64(v.Int())) } return b, nil } // consumeSfixed64SliceValue wire decodes a []int64 value as a repeated Sfixed64. func consumeSfixed64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) out.n = n return listv, out, nil } var coderSfixed64SliceValue = valueCoderFuncs{ size: sizeSfixed64SliceValue, marshal: appendSfixed64SliceValue, unmarshal: consumeSfixed64SliceValue, merge: mergeListValue, } // sizeSfixed64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Sfixed64. func sizeSfixed64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendSfixed64PackedSliceValue encodes a []int64 value as a packed repeated Sfixed64. func appendSfixed64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, uint64(v.Int())) } return b, nil } var coderSfixed64PackedSliceValue = valueCoderFuncs{ size: sizeSfixed64PackedSliceValue, marshal: appendSfixed64PackedSliceValue, unmarshal: consumeSfixed64SliceValue, merge: mergeListValue, } // sizeFixed64 returns the size of wire encoding a uint64 pointer as a Fixed64. func sizeFixed64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendFixed64 wire encodes a uint64 pointer as a Fixed64. func appendFixed64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } // consumeFixed64 wire decodes a uint64 pointer as a Fixed64. func consumeFixed64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Uint64() = v out.n = n return out, nil } var coderFixed64 = pointerCoderFuncs{ size: sizeFixed64, marshal: appendFixed64, unmarshal: consumeFixed64, merge: mergeUint64, } // sizeFixed64NoZero returns the size of wire encoding a uint64 pointer as a Fixed64. // The zero value is not encoded. func sizeFixed64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendFixed64NoZero wire encodes a uint64 pointer as a Fixed64. // The zero value is not encoded. func appendFixed64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } var coderFixed64NoZero = pointerCoderFuncs{ size: sizeFixed64NoZero, marshal: appendFixed64NoZero, unmarshal: consumeFixed64, merge: mergeUint64NoZero, } // sizeFixed64Ptr returns the size of wire encoding a *uint64 pointer as a Fixed64. // It panics if the pointer is nil. func sizeFixed64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendFixed64Ptr wire encodes a *uint64 pointer as a Fixed64. // It panics if the pointer is nil. func appendFixed64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } // consumeFixed64Ptr wire decodes a *uint64 pointer as a Fixed64. func consumeFixed64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Uint64Ptr() if *vp == nil { *vp = new(uint64) } **vp = v out.n = n return out, nil } var coderFixed64Ptr = pointerCoderFuncs{ size: sizeFixed64Ptr, marshal: appendFixed64Ptr, unmarshal: consumeFixed64Ptr, merge: mergeUint64Ptr, } // sizeFixed64Slice returns the size of wire encoding a []uint64 pointer as a repeated Fixed64. func sizeFixed64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendFixed64Slice encodes a []uint64 pointer as a repeated Fixed64. func appendFixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) } return b, nil } // consumeFixed64Slice wire decodes a []uint64 pointer as a repeated Fixed64. func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderFixed64Slice = pointerCoderFuncs{ size: sizeFixed64Slice, marshal: appendFixed64Slice, unmarshal: consumeFixed64Slice, merge: mergeUint64Slice, } // sizeFixed64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Fixed64. func sizeFixed64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendFixed64PackedSlice encodes a []uint64 pointer as a packed repeated Fixed64. func appendFixed64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, v) } return b, nil } var coderFixed64PackedSlice = pointerCoderFuncs{ size: sizeFixed64PackedSlice, marshal: appendFixed64PackedSlice, unmarshal: consumeFixed64Slice, merge: mergeUint64Slice, } // sizeFixed64Value returns the size of wire encoding a uint64 value as a Fixed64. func sizeFixed64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendFixed64Value encodes a uint64 value as a Fixed64. func appendFixed64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, v.Uint()) return b, nil } // consumeFixed64Value decodes a uint64 value as a Fixed64. func consumeFixed64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint64(v), out, nil } var coderFixed64Value = valueCoderFuncs{ size: sizeFixed64Value, marshal: appendFixed64Value, unmarshal: consumeFixed64Value, merge: mergeScalarValue, } // sizeFixed64SliceValue returns the size of wire encoding a []uint64 value as a repeated Fixed64. func sizeFixed64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendFixed64SliceValue encodes a []uint64 value as a repeated Fixed64. func appendFixed64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, v.Uint()) } return b, nil } // consumeFixed64SliceValue wire decodes a []uint64 value as a repeated Fixed64. func consumeFixed64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) out.n = n return listv, out, nil } var coderFixed64SliceValue = valueCoderFuncs{ size: sizeFixed64SliceValue, marshal: appendFixed64SliceValue, unmarshal: consumeFixed64SliceValue, merge: mergeListValue, } // sizeFixed64PackedSliceValue returns the size of wire encoding a []uint64 value as a packed repeated Fixed64. func sizeFixed64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendFixed64PackedSliceValue encodes a []uint64 value as a packed repeated Fixed64. func appendFixed64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, v.Uint()) } return b, nil } var coderFixed64PackedSliceValue = valueCoderFuncs{ size: sizeFixed64PackedSliceValue, marshal: appendFixed64PackedSliceValue, unmarshal: consumeFixed64SliceValue, merge: mergeListValue, } // sizeDouble returns the size of wire encoding a float64 pointer as a Double. func sizeDouble(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendDouble wire encodes a float64 pointer as a Double. func appendDouble(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } // consumeDouble wire decodes a float64 pointer as a Double. func consumeDouble(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Float64() = math.Float64frombits(v) out.n = n return out, nil } var coderDouble = pointerCoderFuncs{ size: sizeDouble, marshal: appendDouble, unmarshal: consumeDouble, merge: mergeFloat64, } // sizeDoubleNoZero returns the size of wire encoding a float64 pointer as a Double. // The zero value is not encoded. func sizeDoubleNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Float64() if v == 0 && !math.Signbit(float64(v)) { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendDoubleNoZero wire encodes a float64 pointer as a Double. // The zero value is not encoded. func appendDoubleNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float64() if v == 0 && !math.Signbit(float64(v)) { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } var coderDoubleNoZero = pointerCoderFuncs{ size: sizeDoubleNoZero, marshal: appendDoubleNoZero, unmarshal: consumeDouble, merge: mergeFloat64NoZero, } // sizeDoublePtr returns the size of wire encoding a *float64 pointer as a Double. // It panics if the pointer is nil. func sizeDoublePtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendDoublePtr wire encodes a *float64 pointer as a Double. // It panics if the pointer is nil. func appendDoublePtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Float64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } // consumeDoublePtr wire decodes a *float64 pointer as a Double. func consumeDoublePtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Float64Ptr() if *vp == nil { *vp = new(float64) } **vp = math.Float64frombits(v) out.n = n return out, nil } var coderDoublePtr = pointerCoderFuncs{ size: sizeDoublePtr, marshal: appendDoublePtr, unmarshal: consumeDoublePtr, merge: mergeFloat64Ptr, } // sizeDoubleSlice returns the size of wire encoding a []float64 pointer as a repeated Double. func sizeDoubleSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendDoubleSlice encodes a []float64 pointer as a repeated Double. func appendDoubleSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) } return b, nil } // consumeDoubleSlice wire decodes a []float64 pointer as a repeated Double. func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Float64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, math.Float64frombits(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, math.Float64frombits(v)) out.n = n return out, nil } var coderDoubleSlice = pointerCoderFuncs{ size: sizeDoubleSlice, marshal: appendDoubleSlice, unmarshal: consumeDoubleSlice, merge: mergeFloat64Slice, } // sizeDoublePackedSlice returns the size of wire encoding a []float64 pointer as a packed repeated Double. func sizeDoublePackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendDoublePackedSlice encodes a []float64 pointer as a packed repeated Double. func appendDoublePackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, math.Float64bits(v)) } return b, nil } var coderDoublePackedSlice = pointerCoderFuncs{ size: sizeDoublePackedSlice, marshal: appendDoublePackedSlice, unmarshal: consumeDoubleSlice, merge: mergeFloat64Slice, } // sizeDoubleValue returns the size of wire encoding a float64 value as a Double. func sizeDoubleValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendDoubleValue encodes a float64 value as a Double. func appendDoubleValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) return b, nil } // consumeDoubleValue decodes a float64 value as a Double. func consumeDoubleValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfFloat64(math.Float64frombits(v)), out, nil } var coderDoubleValue = valueCoderFuncs{ size: sizeDoubleValue, marshal: appendDoubleValue, unmarshal: consumeDoubleValue, merge: mergeScalarValue, } // sizeDoubleSliceValue returns the size of wire encoding a []float64 value as a repeated Double. func sizeDoubleSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendDoubleSliceValue encodes a []float64 value as a repeated Double. func appendDoubleSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) } return b, nil } // consumeDoubleSliceValue wire decodes a []float64 value as a repeated Double. func consumeDoubleSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) out.n = n return listv, out, nil } var coderDoubleSliceValue = valueCoderFuncs{ size: sizeDoubleSliceValue, marshal: appendDoubleSliceValue, unmarshal: consumeDoubleSliceValue, merge: mergeListValue, } // sizeDoublePackedSliceValue returns the size of wire encoding a []float64 value as a packed repeated Double. func sizeDoublePackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendDoublePackedSliceValue encodes a []float64 value as a packed repeated Double. func appendDoublePackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) } return b, nil } var coderDoublePackedSliceValue = valueCoderFuncs{ size: sizeDoublePackedSliceValue, marshal: appendDoublePackedSliceValue, unmarshal: consumeDoubleSliceValue, merge: mergeListValue, } // sizeString returns the size of wire encoding a string pointer as a String. func sizeString(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.String() return f.tagsize + protowire.SizeBytes(len(v)) } // appendString wire encodes a string pointer as a String. func appendString(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } // consumeString wire decodes a string pointer as a String. func consumeString(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.String() = string(v) out.n = n return out, nil } var coderString = pointerCoderFuncs{ size: sizeString, marshal: appendString, unmarshal: consumeString, merge: mergeString, } // appendStringValidateUTF8 wire encodes a string pointer as a String. func appendStringValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } // consumeStringValidateUTF8 wire decodes a string pointer as a String. func consumeStringValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.String() = string(v) out.n = n return out, nil } var coderStringValidateUTF8 = pointerCoderFuncs{ size: sizeString, marshal: appendStringValidateUTF8, unmarshal: consumeStringValidateUTF8, merge: mergeString, } // sizeStringNoZero returns the size of wire encoding a string pointer as a String. // The zero value is not encoded. func sizeStringNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.String() if len(v) == 0 { return 0 } return f.tagsize + protowire.SizeBytes(len(v)) } // appendStringNoZero wire encodes a string pointer as a String. // The zero value is not encoded. func appendStringNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } var coderStringNoZero = pointerCoderFuncs{ size: sizeStringNoZero, marshal: appendStringNoZero, unmarshal: consumeString, merge: mergeStringNoZero, } // appendStringNoZeroValidateUTF8 wire encodes a string pointer as a String. // The zero value is not encoded. func appendStringNoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{ size: sizeStringNoZero, marshal: appendStringNoZeroValidateUTF8, unmarshal: consumeStringValidateUTF8, merge: mergeStringNoZero, } // sizeStringPtr returns the size of wire encoding a *string pointer as a String. // It panics if the pointer is nil. func sizeStringPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.StringPtr() return f.tagsize + protowire.SizeBytes(len(v)) } // appendStringPtr wire encodes a *string pointer as a String. // It panics if the pointer is nil. func appendStringPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.StringPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } // consumeStringPtr wire decodes a *string pointer as a String. func consumeStringPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } vp := p.StringPtr() if *vp == nil { *vp = new(string) } **vp = string(v) out.n = n return out, nil } var coderStringPtr = pointerCoderFuncs{ size: sizeStringPtr, marshal: appendStringPtr, unmarshal: consumeStringPtr, merge: mergeStringPtr, } // appendStringPtrValidateUTF8 wire encodes a *string pointer as a String. // It panics if the pointer is nil. func appendStringPtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.StringPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } // consumeStringPtrValidateUTF8 wire decodes a *string pointer as a String. func consumeStringPtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } vp := p.StringPtr() if *vp == nil { *vp = new(string) } **vp = string(v) out.n = n return out, nil } var coderStringPtrValidateUTF8 = pointerCoderFuncs{ size: sizeStringPtr, marshal: appendStringPtrValidateUTF8, unmarshal: consumeStringPtrValidateUTF8, merge: mergeStringPtr, } // sizeStringSlice returns the size of wire encoding a []string pointer as a repeated String. func sizeStringSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.StringSlice() for _, v := range s { size += f.tagsize + protowire.SizeBytes(len(v)) } return size } // appendStringSlice encodes a []string pointer as a repeated String. func appendStringSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.StringSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) } return b, nil } // consumeStringSlice wire decodes a []string pointer as a repeated String. func consumeStringSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.StringSlice() if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *sp = append(*sp, string(v)) out.n = n return out, nil } var coderStringSlice = pointerCoderFuncs{ size: sizeStringSlice, marshal: appendStringSlice, unmarshal: consumeStringSlice, merge: mergeStringSlice, } // appendStringSliceValidateUTF8 encodes a []string pointer as a repeated String. func appendStringSliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.StringSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } } return b, nil } // consumeStringSliceValidateUTF8 wire decodes a []string pointer as a repeated String. func consumeStringSliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } sp := p.StringSlice() *sp = append(*sp, string(v)) out.n = n return out, nil } var coderStringSliceValidateUTF8 = pointerCoderFuncs{ size: sizeStringSlice, marshal: appendStringSliceValidateUTF8, unmarshal: consumeStringSliceValidateUTF8, merge: mergeStringSlice, } // sizeStringValue returns the size of wire encoding a string value as a String. func sizeStringValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeBytes(len(v.String())) } // appendStringValue encodes a string value as a String. func appendStringValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) return b, nil } // consumeStringValue decodes a string value as a String. func consumeStringValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfString(string(v)), out, nil } var coderStringValue = valueCoderFuncs{ size: sizeStringValue, marshal: appendStringValue, unmarshal: consumeStringValue, merge: mergeScalarValue, } // appendStringValueValidateUTF8 encodes a string value as a String. func appendStringValueValidateUTF8(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) if !utf8.ValidString(v.String()) { return b, errInvalidUTF8{} } return b, nil } // consumeStringValueValidateUTF8 decodes a string value as a String. func consumeStringValueValidateUTF8(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } if !utf8.Valid(v) { return protoreflect.Value{}, out, errInvalidUTF8{} } out.n = n return protoreflect.ValueOfString(string(v)), out, nil } var coderStringValueValidateUTF8 = valueCoderFuncs{ size: sizeStringValue, marshal: appendStringValueValidateUTF8, unmarshal: consumeStringValueValidateUTF8, merge: mergeScalarValue, } // sizeStringSliceValue returns the size of wire encoding a []string value as a repeated String. func sizeStringSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeBytes(len(v.String())) } return size } // appendStringSliceValue encodes a []string value as a repeated String. func appendStringSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) } return b, nil } // consumeStringSliceValue wire decodes a []string value as a repeated String. func consumeStringSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfString(string(v))) out.n = n return listv, out, nil } var coderStringSliceValue = valueCoderFuncs{ size: sizeStringSliceValue, marshal: appendStringSliceValue, unmarshal: consumeStringSliceValue, merge: mergeListValue, } // sizeBytes returns the size of wire encoding a []byte pointer as a Bytes. func sizeBytes(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bytes() return f.tagsize + protowire.SizeBytes(len(v)) } // appendBytes wire encodes a []byte pointer as a Bytes. func appendBytes(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) return b, nil } // consumeBytes wire decodes a []byte pointer as a Bytes. func consumeBytes(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.Bytes() = append(emptyBuf[:], v...) out.n = n return out, nil } var coderBytes = pointerCoderFuncs{ size: sizeBytes, marshal: appendBytes, unmarshal: consumeBytes, merge: mergeBytes, } // appendBytesValidateUTF8 wire encodes a []byte pointer as a Bytes. func appendBytesValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } return b, nil } // consumeBytesValidateUTF8 wire decodes a []byte pointer as a Bytes. func consumeBytesValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.Bytes() = append(emptyBuf[:], v...) out.n = n return out, nil } var coderBytesValidateUTF8 = pointerCoderFuncs{ size: sizeBytes, marshal: appendBytesValidateUTF8, unmarshal: consumeBytesValidateUTF8, merge: mergeBytes, } // sizeBytesNoZero returns the size of wire encoding a []byte pointer as a Bytes. // The zero value is not encoded. func sizeBytesNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bytes() if len(v) == 0 { return 0 } return f.tagsize + protowire.SizeBytes(len(v)) } // appendBytesNoZero wire encodes a []byte pointer as a Bytes. // The zero value is not encoded. func appendBytesNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) return b, nil } // consumeBytesNoZero wire decodes a []byte pointer as a Bytes. // The zero value is not decoded. func consumeBytesNoZero(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.Bytes() = append(([]byte)(nil), v...) out.n = n return out, nil } var coderBytesNoZero = pointerCoderFuncs{ size: sizeBytesNoZero, marshal: appendBytesNoZero, unmarshal: consumeBytesNoZero, merge: mergeBytesNoZero, } // appendBytesNoZeroValidateUTF8 wire encodes a []byte pointer as a Bytes. // The zero value is not encoded. func appendBytesNoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } return b, nil } // consumeBytesNoZeroValidateUTF8 wire decodes a []byte pointer as a Bytes. func consumeBytesNoZeroValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.Bytes() = append(([]byte)(nil), v...) out.n = n return out, nil } var coderBytesNoZeroValidateUTF8 = pointerCoderFuncs{ size: sizeBytesNoZero, marshal: appendBytesNoZeroValidateUTF8, unmarshal: consumeBytesNoZeroValidateUTF8, merge: mergeBytesNoZero, } // sizeBytesSlice returns the size of wire encoding a [][]byte pointer as a repeated Bytes. func sizeBytesSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BytesSlice() for _, v := range s { size += f.tagsize + protowire.SizeBytes(len(v)) } return size } // appendBytesSlice encodes a [][]byte pointer as a repeated Bytes. func appendBytesSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BytesSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) } return b, nil } // consumeBytesSlice wire decodes a [][]byte pointer as a repeated Bytes. func consumeBytesSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.BytesSlice() if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *sp = append(*sp, append(emptyBuf[:], v...)) out.n = n return out, nil } var coderBytesSlice = pointerCoderFuncs{ size: sizeBytesSlice, marshal: appendBytesSlice, unmarshal: consumeBytesSlice, merge: mergeBytesSlice, } // appendBytesSliceValidateUTF8 encodes a [][]byte pointer as a repeated Bytes. func appendBytesSliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BytesSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } } return b, nil } // consumeBytesSliceValidateUTF8 wire decodes a [][]byte pointer as a repeated Bytes. func consumeBytesSliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } sp := p.BytesSlice() *sp = append(*sp, append(emptyBuf[:], v...)) out.n = n return out, nil } var coderBytesSliceValidateUTF8 = pointerCoderFuncs{ size: sizeBytesSlice, marshal: appendBytesSliceValidateUTF8, unmarshal: consumeBytesSliceValidateUTF8, merge: mergeBytesSlice, } // sizeBytesValue returns the size of wire encoding a []byte value as a Bytes. func sizeBytesValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeBytes(len(v.Bytes())) } // appendBytesValue encodes a []byte value as a Bytes. func appendBytesValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendBytes(b, v.Bytes()) return b, nil } // consumeBytesValue decodes a []byte value as a Bytes. func consumeBytesValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), out, nil } var coderBytesValue = valueCoderFuncs{ size: sizeBytesValue, marshal: appendBytesValue, unmarshal: consumeBytesValue, merge: mergeBytesValue, } // sizeBytesSliceValue returns the size of wire encoding a [][]byte value as a repeated Bytes. func sizeBytesSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeBytes(len(v.Bytes())) } return size } // appendBytesSliceValue encodes a [][]byte value as a repeated Bytes. func appendBytesSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendBytes(b, v.Bytes()) } return b, nil } // consumeBytesSliceValue wire decodes a [][]byte value as a repeated Bytes. func consumeBytesSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...))) out.n = n return listv, out, nil } var coderBytesSliceValue = valueCoderFuncs{ size: sizeBytesSliceValue, marshal: appendBytesSliceValue, unmarshal: consumeBytesSliceValue, merge: mergeBytesListValue, } // We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices. var emptyBuf [0]byte var wireTypes = map[protoreflect.Kind]protowire.Type{ protoreflect.BoolKind: protowire.VarintType, protoreflect.EnumKind: protowire.VarintType, protoreflect.Int32Kind: protowire.VarintType, protoreflect.Sint32Kind: protowire.VarintType, protoreflect.Uint32Kind: protowire.VarintType, protoreflect.Int64Kind: protowire.VarintType, protoreflect.Sint64Kind: protowire.VarintType, protoreflect.Uint64Kind: protowire.VarintType, protoreflect.Sfixed32Kind: protowire.Fixed32Type, protoreflect.Fixed32Kind: protowire.Fixed32Type, protoreflect.FloatKind: protowire.Fixed32Type, protoreflect.Sfixed64Kind: protowire.Fixed64Type, protoreflect.Fixed64Kind: protowire.Fixed64Type, protoreflect.DoubleKind: protowire.Fixed64Type, protoreflect.StringKind: protowire.BytesType, protoreflect.BytesKind: protowire.BytesType, protoreflect.MessageKind: protowire.BytesType, protoreflect.GroupKind: protowire.StartGroupType, } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_map.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" pref "google.golang.org/protobuf/reflect/protoreflect" ) type mapInfo struct { goType reflect.Type keyWiretag uint64 valWiretag uint64 keyFuncs valueCoderFuncs valFuncs valueCoderFuncs keyZero pref.Value keyKind pref.Kind conv *mapConverter } func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) { // TODO: Consider generating specialized map coders. keyField := fd.MapKey() valField := fd.MapValue() keyWiretag := protowire.EncodeTag(1, wireTypes[keyField.Kind()]) valWiretag := protowire.EncodeTag(2, wireTypes[valField.Kind()]) keyFuncs := encoderFuncsForValue(keyField) valFuncs := encoderFuncsForValue(valField) conv := newMapConverter(ft, fd) mapi := &mapInfo{ goType: ft, keyWiretag: keyWiretag, valWiretag: valWiretag, keyFuncs: keyFuncs, valFuncs: valFuncs, keyZero: keyField.Default(), keyKind: keyField.Kind(), conv: conv, } if valField.Kind() == pref.MessageKind { valueMessage = getMessageInfo(ft.Elem()) } funcs = pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft) if mp.Elem().IsNil() { mp.Elem().Set(reflect.MakeMap(mapi.goType)) } if f.mi == nil { return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts) } else { return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts) } }, } switch valField.Kind() { case pref.MessageKind: funcs.merge = mergeMapOfMessage case pref.BytesKind: funcs.merge = mergeMapOfBytes default: funcs.merge = mergeMap } if valFuncs.isInit != nil { funcs.isInit = func(p pointer, f *coderFieldInfo) error { return isInitMap(p.AsValueOf(ft).Elem(), mapi, f) } } return valueMessage, funcs } const ( mapKeyTagSize = 1 // field 1, tag size 1. mapValTagSize = 1 // field 2, tag size 2. ) func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int { if mapv.Len() == 0 { return 0 } n := 0 iter := mapRange(mapv) for iter.Next() { key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey() keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) var valSize int value := mapi.conv.valConv.PBValueOf(iter.Value()) if f.mi == nil { valSize = mapi.valFuncs.size(value, mapValTagSize, opts) } else { p := pointerOfValue(iter.Value()) valSize += mapValTagSize valSize += protowire.SizeBytes(f.mi.sizePointer(p, opts)) } n += f.tagsize + protowire.SizeBytes(keySize+valSize) } return n } func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var ( key = mapi.keyZero val = mapi.conv.valConv.New() ) for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return out, errDecode } if num > protowire.MaxValidNumber { return out, errDecode } b = b[n:] err := errUnknown switch num { case genid.MapEntry_Key_field_number: var v pref.Value var o unmarshalOutput v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts) if err != nil { break } key = v n = o.n case genid.MapEntry_Value_field_number: var v pref.Value var o unmarshalOutput v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts) if err != nil { break } val = v n = o.n } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } } else if err != nil { return out, err } b = b[n:] } mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), mapi.conv.valConv.GoValueOf(val)) out.n = n return out, nil } func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var ( key = mapi.keyZero val = reflect.New(f.mi.GoReflectType.Elem()) ) for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return out, errDecode } if num > protowire.MaxValidNumber { return out, errDecode } b = b[n:] err := errUnknown switch num { case 1: var v pref.Value var o unmarshalOutput v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts) if err != nil { break } key = v n = o.n case 2: if wtyp != protowire.BytesType { break } var v []byte v, n = protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var o unmarshalOutput o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts) if o.initialized { // Consider this map item initialized so long as we see // an initialized value. out.initialized = true } } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } } else if err != nil { return out, err } b = b[n:] } mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), val) out.n = n return out, nil } func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if f.mi == nil { key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey() val := mapi.conv.valConv.PBValueOf(valrv) size := 0 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) size += mapi.valFuncs.size(val, mapValTagSize, opts) b = protowire.AppendVarint(b, uint64(size)) b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts) if err != nil { return nil, err } return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts) } else { key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey() val := pointerOfValue(valrv) valSize := f.mi.sizePointer(val, opts) size := 0 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) size += mapValTagSize + protowire.SizeBytes(valSize) b = protowire.AppendVarint(b, uint64(size)) b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts) if err != nil { return nil, err } b = protowire.AppendVarint(b, mapi.valWiretag) b = protowire.AppendVarint(b, uint64(valSize)) return f.mi.marshalAppendPointer(b, val, opts) } } func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if mapv.Len() == 0 { return b, nil } if opts.Deterministic() { return appendMapDeterministic(b, mapv, mapi, f, opts) } iter := mapRange(mapv) for iter.Next() { var err error b = protowire.AppendVarint(b, f.wiretag) b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts) if err != nil { return b, err } } return b, nil } func appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { keys := mapv.MapKeys() sort.Slice(keys, func(i, j int) bool { switch keys[i].Kind() { case reflect.Bool: return !keys[i].Bool() && keys[j].Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return keys[i].Int() < keys[j].Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return keys[i].Uint() < keys[j].Uint() case reflect.Float32, reflect.Float64: return keys[i].Float() < keys[j].Float() case reflect.String: return keys[i].String() < keys[j].String() default: panic("invalid kind: " + keys[i].Kind().String()) } }) for _, key := range keys { var err error b = protowire.AppendVarint(b, f.wiretag) b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts) if err != nil { return b, err } } return b, nil } func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { if mi := f.mi; mi != nil { mi.init() if !mi.needsInitCheck { return nil } iter := mapRange(mapv) for iter.Next() { val := pointerOfValue(iter.Value()) if err := mi.checkInitializedPointer(val); err != nil { return err } } } else { iter := mapRange(mapv) for iter.Next() { val := mapi.conv.valConv.PBValueOf(iter.Value()) if err := mapi.valFuncs.isInit(val); err != nil { return err } } } return nil } func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { dstm.SetMapIndex(iter.Key(), iter.Value()) } } func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...))) } } func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { val := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { f.mi.mergePointer(pointerOfValue(val), pointerOfValue(iter.Value()), opts) } else { opts.Merge(asMessage(val), asMessage(iter.Value())) } dstm.SetMapIndex(iter.Key(), val) } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_map_go111.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !go1.12 package impl import "reflect" type mapIter struct { v reflect.Value keys []reflect.Value } // mapRange provides a less-efficient equivalent to // the Go 1.12 reflect.Value.MapRange method. func mapRange(v reflect.Value) *mapIter { return &mapIter{v: v} } func (i *mapIter) Next() bool { if i.keys == nil { i.keys = i.v.MapKeys() } else { i.keys = i.keys[1:] } return len(i.keys) > 0 } func (i *mapIter) Key() reflect.Value { return i.keys[0] } func (i *mapIter) Value() reflect.Value { return i.v.MapIndex(i.keys[0]) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_map_go112.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.12 package impl import "reflect" func mapRange(v reflect.Value) *reflect.MapIter { return v.MapRange() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_message.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/order" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // coderMessageInfo contains per-message information used by the fast-path functions. // This is a different type from MessageInfo to keep MessageInfo as general-purpose as // possible. type coderMessageInfo struct { methods piface.Methods orderedCoderFields []*coderFieldInfo denseCoderFields []*coderFieldInfo coderFields map[protowire.Number]*coderFieldInfo sizecacheOffset offset unknownOffset offset unknownPtrKind bool extensionOffset offset needsInitCheck bool isMessageSet bool numRequiredFields uint8 } type coderFieldInfo struct { funcs pointerCoderFuncs // fast-path per-field functions mi *MessageInfo // field's message ft reflect.Type validation validationInfo // information used by message validation num pref.FieldNumber // field number offset offset // struct field offset wiretag uint64 // field tag (number + wire type) tagsize int // size of the varint-encoded tag isPointer bool // true if IsNil may be called on the struct field isRequired bool // true if field is required } func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { mi.sizecacheOffset = invalidOffset mi.unknownOffset = invalidOffset mi.extensionOffset = invalidOffset if si.sizecacheOffset.IsValid() && si.sizecacheType == sizecacheType { mi.sizecacheOffset = si.sizecacheOffset } if si.unknownOffset.IsValid() && (si.unknownType == unknownFieldsAType || si.unknownType == unknownFieldsBType) { mi.unknownOffset = si.unknownOffset mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr } if si.extensionOffset.IsValid() && si.extensionType == extensionFieldsType { mi.extensionOffset = si.extensionOffset } mi.coderFields = make(map[protowire.Number]*coderFieldInfo) fields := mi.Desc.Fields() preallocFields := make([]coderFieldInfo, fields.Len()) for i := 0; i < fields.Len(); i++ { fd := fields.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } ft := fs.Type var wiretag uint64 if !fd.IsPacked() { wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()]) } else { wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType) } var fieldOffset offset var funcs pointerCoderFuncs var childMessage *MessageInfo switch { case ft == nil: // This never occurs for generated message types. // It implies that a hand-crafted type has missing Go fields // for specific protobuf message fields. funcs = pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return 0 }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return nil, nil }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { panic("missing Go struct field for " + string(fd.FullName())) }, isInit: func(p pointer, f *coderFieldInfo) error { panic("missing Go struct field for " + string(fd.FullName())) }, merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { panic("missing Go struct field for " + string(fd.FullName())) }, } case isOneof: fieldOffset = offsetOf(fs, mi.Exporter) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) default: fieldOffset = offsetOf(fs, mi.Exporter) childMessage, funcs = fieldCoder(fd, ft) } cf := &preallocFields[i] *cf = coderFieldInfo{ num: fd.Number(), offset: fieldOffset, wiretag: wiretag, ft: ft, tagsize: protowire.SizeVarint(wiretag), funcs: funcs, mi: childMessage, validation: newFieldValidationInfo(mi, si, fd, ft), isPointer: fd.Cardinality() == pref.Repeated || fd.HasPresence(), isRequired: fd.Cardinality() == pref.Required, } mi.orderedCoderFields = append(mi.orderedCoderFields, cf) mi.coderFields[cf.num] = cf } for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ { if od := oneofs.Get(i); !od.IsSynthetic() { mi.initOneofFieldCoders(od, si) } } if messageset.IsMessageSet(mi.Desc) { if !mi.extensionOffset.IsValid() { panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName())) } if !mi.unknownOffset.IsValid() { panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName())) } mi.isMessageSet = true } sort.Slice(mi.orderedCoderFields, func(i, j int) bool { return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num }) var maxDense pref.FieldNumber for _, cf := range mi.orderedCoderFields { if cf.num >= 16 && cf.num >= 2*maxDense { break } maxDense = cf.num } mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1) for _, cf := range mi.orderedCoderFields { if int(cf.num) >= len(mi.denseCoderFields) { break } mi.denseCoderFields[cf.num] = cf } // To preserve compatibility with historic wire output, marshal oneofs last. if mi.Desc.Oneofs().Len() > 0 { sort.Slice(mi.orderedCoderFields, func(i, j int) bool { fi := fields.ByNumber(mi.orderedCoderFields[i].num) fj := fields.ByNumber(mi.orderedCoderFields[j].num) return order.LegacyFieldOrder(fi, fj) }) } mi.needsInitCheck = needsInitCheck(mi.Desc) if mi.methods.Marshal == nil && mi.methods.Size == nil { mi.methods.Flags |= piface.SupportMarshalDeterministic mi.methods.Marshal = mi.marshal mi.methods.Size = mi.size } if mi.methods.Unmarshal == nil { mi.methods.Flags |= piface.SupportUnmarshalDiscardUnknown mi.methods.Unmarshal = mi.unmarshal } if mi.methods.CheckInitialized == nil { mi.methods.CheckInitialized = mi.checkInitialized } if mi.methods.Merge == nil { mi.methods.Merge = mi.merge } } // getUnknownBytes returns a *[]byte for the unknown fields. // It is the caller's responsibility to check whether the pointer is nil. // This function is specially designed to be inlineable. func (mi *MessageInfo) getUnknownBytes(p pointer) *[]byte { if mi.unknownPtrKind { return *p.Apply(mi.unknownOffset).BytesPtr() } else { return p.Apply(mi.unknownOffset).Bytes() } } // mutableUnknownBytes returns a *[]byte for the unknown fields. // The returned pointer is guaranteed to not be nil. func (mi *MessageInfo) mutableUnknownBytes(p pointer) *[]byte { if mi.unknownPtrKind { bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { *bp = new([]byte) } return *bp } else { return p.Apply(mi.unknownOffset).Bytes() } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" ) func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int) { if !flags.ProtoLegacy { return 0 } ext := *p.Apply(mi.extensionOffset).Extensions() for _, x := range ext { xi := getExtensionFieldInfo(x.Type()) if xi.funcs.size == nil { continue } num, _ := protowire.DecodeTag(xi.wiretag) size += messageset.SizeField(num) size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) } if u := mi.getUnknownBytes(p); u != nil { size += messageset.SizeUnknown(*u) } return size } func marshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts marshalOptions) ([]byte, error) { if !flags.ProtoLegacy { return b, errors.New("no support for message_set_wire_format") } ext := *p.Apply(mi.extensionOffset).Extensions() switch len(ext) { case 0: case 1: // Fast-path for one extension: Don't bother sorting the keys. for _, x := range ext { var err error b, err = marshalMessageSetField(mi, b, x, opts) if err != nil { return b, err } } default: // Sort the keys to provide a deterministic encoding. // Not sure this is required, but the old code does it. keys := make([]int, 0, len(ext)) for k := range ext { keys = append(keys, int(k)) } sort.Ints(keys) for _, k := range keys { var err error b, err = marshalMessageSetField(mi, b, ext[int32(k)], opts) if err != nil { return b, err } } } if u := mi.getUnknownBytes(p); u != nil { var err error b, err = messageset.AppendUnknown(b, *u) if err != nil { return b, err } } return b, nil } func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts marshalOptions) ([]byte, error) { xi := getExtensionFieldInfo(x.Type()) num, _ := protowire.DecodeTag(xi.wiretag) b = messageset.AppendFieldStart(b, num) b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts) if err != nil { return b, err } b = messageset.AppendFieldEnd(b) return b, nil } func unmarshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts unmarshalOptions) (out unmarshalOutput, err error) { if !flags.ProtoLegacy { return out, errors.New("no support for message_set_wire_format") } ep := p.Apply(mi.extensionOffset).Extensions() if *ep == nil { *ep = make(map[int32]ExtensionField) } ext := *ep initialized := true err = messageset.Unmarshal(b, true, func(num protowire.Number, v []byte) error { o, err := mi.unmarshalExtension(v, num, protowire.BytesType, ext, opts) if err == errUnknown { u := mi.mutableUnknownBytes(p) *u = protowire.AppendTag(*u, num, protowire.BytesType) *u = append(*u, v...) return nil } if !o.initialized { initialized = false } return err }) out.n = len(b) out.initialized = initialized return out, err } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package impl import ( "reflect" "google.golang.org/protobuf/encoding/protowire" ) func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) { v := p.v.Elem().Int() return f.tagsize + protowire.SizeVarint(uint64(v)) } func appendEnum(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := p.v.Elem().Int() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } func consumeEnum(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } p.v.Elem().SetInt(int64(v)) out.n = n return out, nil } func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { dst.v.Elem().Set(src.v.Elem()) } var coderEnum = pointerCoderFuncs{ size: sizeEnum, marshal: appendEnum, unmarshal: consumeEnum, merge: mergeEnum, } func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { if p.v.Elem().Int() == 0 { return 0 } return sizeEnum(p, f, opts) } func appendEnumNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if p.v.Elem().Int() == 0 { return b, nil } return appendEnum(b, p, f, opts) } func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { if src.v.Elem().Int() != 0 { dst.v.Elem().Set(src.v.Elem()) } } var coderEnumNoZero = pointerCoderFuncs{ size: sizeEnumNoZero, marshal: appendEnumNoZero, unmarshal: consumeEnum, merge: mergeEnumNoZero, } func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return sizeEnum(pointer{p.v.Elem()}, f, opts) } func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendEnum(b, pointer{p.v.Elem()}, f, opts) } func consumeEnumPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } if p.v.Elem().IsNil() { p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem())) } return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts) } func mergeEnumPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { if !src.v.Elem().IsNil() { v := reflect.New(dst.v.Type().Elem().Elem()) v.Elem().Set(src.v.Elem().Elem()) dst.v.Elem().Set(v) } } var coderEnumPtr = pointerCoderFuncs{ size: sizeEnumPtr, marshal: appendEnumPtr, unmarshal: consumeEnumPtr, merge: mergeEnumPtr, } func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := p.v.Elem() for i, llen := 0, s.Len(); i < llen; i++ { size += protowire.SizeVarint(uint64(s.Index(i).Int())) + f.tagsize } return size } func appendEnumSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.v.Elem() for i, llen := 0, s.Len(); i < llen; i++ { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) } return b, nil } func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { s := p.v.Elem() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } rv := reflect.New(s.Type().Elem()).Elem() rv.SetInt(int64(v)) s.Set(reflect.Append(s, rv)) b = b[n:] } out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } rv := reflect.New(s.Type().Elem()).Elem() rv.SetInt(int64(v)) s.Set(reflect.Append(s, rv)) out.n = n return out, nil } func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem())) } var coderEnumSlice = pointerCoderFuncs{ size: sizeEnumSlice, marshal: appendEnumSlice, unmarshal: consumeEnumSlice, merge: mergeEnumSlice, } func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := p.v.Elem() llen := s.Len() if llen == 0 { return 0 } n := 0 for i := 0; i < llen; i++ { n += protowire.SizeVarint(uint64(s.Index(i).Int())) } return f.tagsize + protowire.SizeBytes(n) } func appendEnumPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.v.Elem() llen := s.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for i := 0; i < llen; i++ { n += protowire.SizeVarint(uint64(s.Index(i).Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) } return b, nil } var coderEnumPackedSlice = pointerCoderFuncs{ size: sizeEnumPackedSlice, marshal: appendEnumPackedSlice, unmarshal: consumeEnumSlice, merge: mergeEnumSlice, } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_tables.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) // pointerCoderFuncs is a set of pointer encoding functions. type pointerCoderFuncs struct { mi *MessageInfo size func(p pointer, f *coderFieldInfo, opts marshalOptions) int marshal func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) unmarshal func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) isInit func(p pointer, f *coderFieldInfo) error merge func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) } // valueCoderFuncs is a set of protoreflect.Value encoding functions. type valueCoderFuncs struct { size func(v pref.Value, tagsize int, opts marshalOptions) int marshal func(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) unmarshal func(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) isInit func(v pref.Value) error merge func(dst, src pref.Value, opts mergeOptions) pref.Value } // fieldCoder returns pointer functions for a field, used for operating on // struct fields. func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointerCoderFuncs) { switch { case fd.IsMap(): return encoderFuncsForMap(fd, ft) case fd.Cardinality() == pref.Repeated && !fd.IsPacked(): // Repeated fields (not packed). if ft.Kind() != reflect.Slice { break } ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolSlice } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumSlice } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32Slice } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32Slice } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32Slice } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64Slice } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64Slice } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64Slice } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32Slice } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32Slice } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatSlice } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64Slice } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64Slice } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoubleSlice } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringSliceValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringSlice } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesSliceValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesSlice } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringSlice } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesSlice } case pref.MessageKind: return getMessageInfo(ft), makeMessageSliceFieldCoder(fd, ft) case pref.GroupKind: return getMessageInfo(ft), makeGroupSliceFieldCoder(fd, ft) } case fd.Cardinality() == pref.Repeated && fd.IsPacked(): // Packed repeated fields. // // Only repeated fields of primitive numeric types // (Varint, Fixed32, or Fixed64 wire type) can be packed. if ft.Kind() != reflect.Slice { break } ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolPackedSlice } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumPackedSlice } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32PackedSlice } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32PackedSlice } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32PackedSlice } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64PackedSlice } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64PackedSlice } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64PackedSlice } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32PackedSlice } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32PackedSlice } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatPackedSlice } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64PackedSlice } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64PackedSlice } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoublePackedSlice } } case fd.Kind() == pref.MessageKind: return getMessageInfo(ft), makeMessageFieldCoder(fd, ft) case fd.Kind() == pref.GroupKind: return getMessageInfo(ft), makeGroupFieldCoder(fd, ft) case fd.Syntax() == pref.Proto3 && fd.ContainingOneof() == nil: // Populated oneof fields always encode even if set to the zero value, // which normally are not encoded in proto3. switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolNoZero } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumNoZero } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32NoZero } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32NoZero } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32NoZero } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64NoZero } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64NoZero } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64NoZero } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32NoZero } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32NoZero } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatNoZero } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64NoZero } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64NoZero } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoubleNoZero } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringNoZeroValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringNoZero } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesNoZeroValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesNoZero } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringNoZero } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesNoZero } } case ft.Kind() == reflect.Ptr: ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolPtr } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumPtr } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32Ptr } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32Ptr } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32Ptr } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64Ptr } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64Ptr } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64Ptr } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32Ptr } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32Ptr } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatPtr } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64Ptr } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64Ptr } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoublePtr } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringPtrValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringPtr } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringPtr } } default: switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBool } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnum } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32 } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32 } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32 } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64 } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64 } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64 } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32 } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32 } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloat } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64 } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64 } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDouble } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderString } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytes } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderString } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytes } } } panic(fmt.Sprintf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft)) } // encoderFuncsForValue returns value functions for a field, used for // extension values and map encoding. func encoderFuncsForValue(fd pref.FieldDescriptor) valueCoderFuncs { switch { case fd.Cardinality() == pref.Repeated && !fd.IsPacked(): switch fd.Kind() { case pref.BoolKind: return coderBoolSliceValue case pref.EnumKind: return coderEnumSliceValue case pref.Int32Kind: return coderInt32SliceValue case pref.Sint32Kind: return coderSint32SliceValue case pref.Uint32Kind: return coderUint32SliceValue case pref.Int64Kind: return coderInt64SliceValue case pref.Sint64Kind: return coderSint64SliceValue case pref.Uint64Kind: return coderUint64SliceValue case pref.Sfixed32Kind: return coderSfixed32SliceValue case pref.Fixed32Kind: return coderFixed32SliceValue case pref.FloatKind: return coderFloatSliceValue case pref.Sfixed64Kind: return coderSfixed64SliceValue case pref.Fixed64Kind: return coderFixed64SliceValue case pref.DoubleKind: return coderDoubleSliceValue case pref.StringKind: // We don't have a UTF-8 validating coder for repeated string fields. // Value coders are used for extensions and maps. // Extensions are never proto3, and maps never contain lists. return coderStringSliceValue case pref.BytesKind: return coderBytesSliceValue case pref.MessageKind: return coderMessageSliceValue case pref.GroupKind: return coderGroupSliceValue } case fd.Cardinality() == pref.Repeated && fd.IsPacked(): switch fd.Kind() { case pref.BoolKind: return coderBoolPackedSliceValue case pref.EnumKind: return coderEnumPackedSliceValue case pref.Int32Kind: return coderInt32PackedSliceValue case pref.Sint32Kind: return coderSint32PackedSliceValue case pref.Uint32Kind: return coderUint32PackedSliceValue case pref.Int64Kind: return coderInt64PackedSliceValue case pref.Sint64Kind: return coderSint64PackedSliceValue case pref.Uint64Kind: return coderUint64PackedSliceValue case pref.Sfixed32Kind: return coderSfixed32PackedSliceValue case pref.Fixed32Kind: return coderFixed32PackedSliceValue case pref.FloatKind: return coderFloatPackedSliceValue case pref.Sfixed64Kind: return coderSfixed64PackedSliceValue case pref.Fixed64Kind: return coderFixed64PackedSliceValue case pref.DoubleKind: return coderDoublePackedSliceValue } default: switch fd.Kind() { default: case pref.BoolKind: return coderBoolValue case pref.EnumKind: return coderEnumValue case pref.Int32Kind: return coderInt32Value case pref.Sint32Kind: return coderSint32Value case pref.Uint32Kind: return coderUint32Value case pref.Int64Kind: return coderInt64Value case pref.Sint64Kind: return coderSint64Value case pref.Uint64Kind: return coderUint64Value case pref.Sfixed32Kind: return coderSfixed32Value case pref.Fixed32Kind: return coderFixed32Value case pref.FloatKind: return coderFloatValue case pref.Sfixed64Kind: return coderSfixed64Value case pref.Fixed64Kind: return coderFixed64Value case pref.DoubleKind: return coderDoubleValue case pref.StringKind: if strs.EnforceUTF8(fd) { return coderStringValueValidateUTF8 } return coderStringValue case pref.BytesKind: return coderBytesValue case pref.MessageKind: return coderMessageValue case pref.GroupKind: return coderGroupValue } } panic(fmt.Sprintf("invalid field: no encoder for %v %v %v", fd.FullName(), fd.Cardinality(), fd.Kind())) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/codec_unsafe.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package impl // When using unsafe pointers, we can just treat enum values as int32s. var ( coderEnumNoZero = coderInt32NoZero coderEnum = coderInt32 coderEnumPtr = coderInt32Ptr coderEnumSlice = coderInt32Slice coderEnumPackedSlice = coderInt32PackedSlice ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/convert.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) // unwrapper unwraps the value to the underlying value. // This is implemented by List and Map. type unwrapper interface { protoUnwrap() interface{} } // A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types. type Converter interface { // PBValueOf converts a reflect.Value to a protoreflect.Value. PBValueOf(reflect.Value) pref.Value // GoValueOf converts a protoreflect.Value to a reflect.Value. GoValueOf(pref.Value) reflect.Value // IsValidPB returns whether a protoreflect.Value is compatible with this type. IsValidPB(pref.Value) bool // IsValidGo returns whether a reflect.Value is compatible with this type. IsValidGo(reflect.Value) bool // New returns a new field value. // For scalars, it returns the default value of the field. // For composite types, it returns a new mutable value. New() pref.Value // Zero returns a new field value. // For scalars, it returns the default value of the field. // For composite types, it returns an immutable, empty value. Zero() pref.Value } // NewConverter matches a Go type with a protobuf field and returns a Converter // that converts between the two. Enums must be a named int32 kind that // implements protoreflect.Enum, and messages must be pointer to a named // struct type that implements protoreflect.ProtoMessage. // // This matcher deliberately supports a wider range of Go types than what // protoc-gen-go historically generated to be able to automatically wrap some // v1 messages generated by other forks of protoc-gen-go. func NewConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { switch { case fd.IsList(): return newListConverter(t, fd) case fd.IsMap(): return newMapConverter(t, fd) default: return newSingularConverter(t, fd) } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } var ( boolType = reflect.TypeOf(bool(false)) int32Type = reflect.TypeOf(int32(0)) int64Type = reflect.TypeOf(int64(0)) uint32Type = reflect.TypeOf(uint32(0)) uint64Type = reflect.TypeOf(uint64(0)) float32Type = reflect.TypeOf(float32(0)) float64Type = reflect.TypeOf(float64(0)) stringType = reflect.TypeOf(string("")) bytesType = reflect.TypeOf([]byte(nil)) byteType = reflect.TypeOf(byte(0)) ) var ( boolZero = pref.ValueOfBool(false) int32Zero = pref.ValueOfInt32(0) int64Zero = pref.ValueOfInt64(0) uint32Zero = pref.ValueOfUint32(0) uint64Zero = pref.ValueOfUint64(0) float32Zero = pref.ValueOfFloat32(0) float64Zero = pref.ValueOfFloat64(0) stringZero = pref.ValueOfString("") bytesZero = pref.ValueOfBytes(nil) ) func newSingularConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { defVal := func(fd pref.FieldDescriptor, zero pref.Value) pref.Value { if fd.Cardinality() == pref.Repeated { // Default isn't defined for repeated fields. return zero } return fd.Default() } switch fd.Kind() { case pref.BoolKind: if t.Kind() == reflect.Bool { return &boolConverter{t, defVal(fd, boolZero)} } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if t.Kind() == reflect.Int32 { return &int32Converter{t, defVal(fd, int32Zero)} } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if t.Kind() == reflect.Int64 { return &int64Converter{t, defVal(fd, int64Zero)} } case pref.Uint32Kind, pref.Fixed32Kind: if t.Kind() == reflect.Uint32 { return &uint32Converter{t, defVal(fd, uint32Zero)} } case pref.Uint64Kind, pref.Fixed64Kind: if t.Kind() == reflect.Uint64 { return &uint64Converter{t, defVal(fd, uint64Zero)} } case pref.FloatKind: if t.Kind() == reflect.Float32 { return &float32Converter{t, defVal(fd, float32Zero)} } case pref.DoubleKind: if t.Kind() == reflect.Float64 { return &float64Converter{t, defVal(fd, float64Zero)} } case pref.StringKind: if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) { return &stringConverter{t, defVal(fd, stringZero)} } case pref.BytesKind: if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) { return &bytesConverter{t, defVal(fd, bytesZero)} } case pref.EnumKind: // Handle enums, which must be a named int32 type. if t.Kind() == reflect.Int32 { return newEnumConverter(t, fd) } case pref.MessageKind, pref.GroupKind: return newMessageConverter(t) } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } type boolConverter struct { goType reflect.Type def pref.Value } func (c *boolConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfBool(v.Bool()) } func (c *boolConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Bool()).Convert(c.goType) } func (c *boolConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(bool) return ok } func (c *boolConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *boolConverter) New() pref.Value { return c.def } func (c *boolConverter) Zero() pref.Value { return c.def } type int32Converter struct { goType reflect.Type def pref.Value } func (c *int32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfInt32(int32(v.Int())) } func (c *int32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(int32(v.Int())).Convert(c.goType) } func (c *int32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(int32) return ok } func (c *int32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *int32Converter) New() pref.Value { return c.def } func (c *int32Converter) Zero() pref.Value { return c.def } type int64Converter struct { goType reflect.Type def pref.Value } func (c *int64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfInt64(int64(v.Int())) } func (c *int64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(int64(v.Int())).Convert(c.goType) } func (c *int64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(int64) return ok } func (c *int64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *int64Converter) New() pref.Value { return c.def } func (c *int64Converter) Zero() pref.Value { return c.def } type uint32Converter struct { goType reflect.Type def pref.Value } func (c *uint32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfUint32(uint32(v.Uint())) } func (c *uint32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(uint32(v.Uint())).Convert(c.goType) } func (c *uint32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(uint32) return ok } func (c *uint32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *uint32Converter) New() pref.Value { return c.def } func (c *uint32Converter) Zero() pref.Value { return c.def } type uint64Converter struct { goType reflect.Type def pref.Value } func (c *uint64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfUint64(uint64(v.Uint())) } func (c *uint64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(uint64(v.Uint())).Convert(c.goType) } func (c *uint64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(uint64) return ok } func (c *uint64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *uint64Converter) New() pref.Value { return c.def } func (c *uint64Converter) Zero() pref.Value { return c.def } type float32Converter struct { goType reflect.Type def pref.Value } func (c *float32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfFloat32(float32(v.Float())) } func (c *float32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(float32(v.Float())).Convert(c.goType) } func (c *float32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(float32) return ok } func (c *float32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *float32Converter) New() pref.Value { return c.def } func (c *float32Converter) Zero() pref.Value { return c.def } type float64Converter struct { goType reflect.Type def pref.Value } func (c *float64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfFloat64(float64(v.Float())) } func (c *float64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(float64(v.Float())).Convert(c.goType) } func (c *float64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(float64) return ok } func (c *float64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *float64Converter) New() pref.Value { return c.def } func (c *float64Converter) Zero() pref.Value { return c.def } type stringConverter struct { goType reflect.Type def pref.Value } func (c *stringConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfString(v.Convert(stringType).String()) } func (c *stringConverter) GoValueOf(v pref.Value) reflect.Value { // pref.Value.String never panics, so we go through an interface // conversion here to check the type. s := v.Interface().(string) if c.goType.Kind() == reflect.Slice && s == "" { return reflect.Zero(c.goType) // ensure empty string is []byte(nil) } return reflect.ValueOf(s).Convert(c.goType) } func (c *stringConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(string) return ok } func (c *stringConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *stringConverter) New() pref.Value { return c.def } func (c *stringConverter) Zero() pref.Value { return c.def } type bytesConverter struct { goType reflect.Type def pref.Value } func (c *bytesConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } if c.goType.Kind() == reflect.String && v.Len() == 0 { return pref.ValueOfBytes(nil) // ensure empty string is []byte(nil) } return pref.ValueOfBytes(v.Convert(bytesType).Bytes()) } func (c *bytesConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Bytes()).Convert(c.goType) } func (c *bytesConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().([]byte) return ok } func (c *bytesConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *bytesConverter) New() pref.Value { return c.def } func (c *bytesConverter) Zero() pref.Value { return c.def } type enumConverter struct { goType reflect.Type def pref.Value } func newEnumConverter(goType reflect.Type, fd pref.FieldDescriptor) Converter { var def pref.Value if fd.Cardinality() == pref.Repeated { def = pref.ValueOfEnum(fd.Enum().Values().Get(0).Number()) } else { def = fd.Default() } return &enumConverter{goType, def} } func (c *enumConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfEnum(pref.EnumNumber(v.Int())) } func (c *enumConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Enum()).Convert(c.goType) } func (c *enumConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(pref.EnumNumber) return ok } func (c *enumConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *enumConverter) New() pref.Value { return c.def } func (c *enumConverter) Zero() pref.Value { return c.def } type messageConverter struct { goType reflect.Type } func newMessageConverter(goType reflect.Type) Converter { return &messageConverter{goType} } func (c *messageConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } if c.isNonPointer() { if v.CanAddr() { v = v.Addr() // T => *T } else { v = reflect.Zero(reflect.PtrTo(v.Type())) } } if m, ok := v.Interface().(pref.ProtoMessage); ok { return pref.ValueOfMessage(m.ProtoReflect()) } return pref.ValueOfMessage(legacyWrapMessage(v)) } func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value { m := v.Message() var rv reflect.Value if u, ok := m.(unwrapper); ok { rv = reflect.ValueOf(u.protoUnwrap()) } else { rv = reflect.ValueOf(m.Interface()) } if c.isNonPointer() { if rv.Type() != reflect.PtrTo(c.goType) { panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), reflect.PtrTo(c.goType))) } if !rv.IsNil() { rv = rv.Elem() // *T => T } else { rv = reflect.Zero(rv.Type().Elem()) } } if rv.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType)) } return rv } func (c *messageConverter) IsValidPB(v pref.Value) bool { m := v.Message() var rv reflect.Value if u, ok := m.(unwrapper); ok { rv = reflect.ValueOf(u.protoUnwrap()) } else { rv = reflect.ValueOf(m.Interface()) } if c.isNonPointer() { return rv.Type() == reflect.PtrTo(c.goType) } return rv.Type() == c.goType } func (c *messageConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *messageConverter) New() pref.Value { if c.isNonPointer() { return c.PBValueOf(reflect.New(c.goType).Elem()) } return c.PBValueOf(reflect.New(c.goType.Elem())) } func (c *messageConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } // isNonPointer reports whether the type is a non-pointer type. // This never occurs for generated message types. func (c *messageConverter) isNonPointer() bool { return c.goType.Kind() != reflect.Ptr } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/convert_list.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) func newListConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { switch { case t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Slice: return &listPtrConverter{t, newSingularConverter(t.Elem().Elem(), fd)} case t.Kind() == reflect.Slice: return &listConverter{t, newSingularConverter(t.Elem(), fd)} } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } type listConverter struct { goType reflect.Type // []T c Converter } func (c *listConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } pv := reflect.New(c.goType) pv.Elem().Set(v) return pref.ValueOfList(&listReflect{pv, c.c}) } func (c *listConverter) GoValueOf(v pref.Value) reflect.Value { rv := v.List().(*listReflect).v if rv.IsNil() { return reflect.Zero(c.goType) } return rv.Elem() } func (c *listConverter) IsValidPB(v pref.Value) bool { list, ok := v.Interface().(*listReflect) if !ok { return false } return list.v.Type().Elem() == c.goType } func (c *listConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *listConverter) New() pref.Value { return pref.ValueOfList(&listReflect{reflect.New(c.goType), c.c}) } func (c *listConverter) Zero() pref.Value { return pref.ValueOfList(&listReflect{reflect.Zero(reflect.PtrTo(c.goType)), c.c}) } type listPtrConverter struct { goType reflect.Type // *[]T c Converter } func (c *listPtrConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfList(&listReflect{v, c.c}) } func (c *listPtrConverter) GoValueOf(v pref.Value) reflect.Value { return v.List().(*listReflect).v } func (c *listPtrConverter) IsValidPB(v pref.Value) bool { list, ok := v.Interface().(*listReflect) if !ok { return false } return list.v.Type() == c.goType } func (c *listPtrConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *listPtrConverter) New() pref.Value { return c.PBValueOf(reflect.New(c.goType.Elem())) } func (c *listPtrConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } type listReflect struct { v reflect.Value // *[]T conv Converter } func (ls *listReflect) Len() int { if ls.v.IsNil() { return 0 } return ls.v.Elem().Len() } func (ls *listReflect) Get(i int) pref.Value { return ls.conv.PBValueOf(ls.v.Elem().Index(i)) } func (ls *listReflect) Set(i int, v pref.Value) { ls.v.Elem().Index(i).Set(ls.conv.GoValueOf(v)) } func (ls *listReflect) Append(v pref.Value) { ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(v))) } func (ls *listReflect) AppendMutable() pref.Value { if _, ok := ls.conv.(*messageConverter); !ok { panic("invalid AppendMutable on list with non-message type") } v := ls.NewElement() ls.Append(v) return v } func (ls *listReflect) Truncate(i int) { ls.v.Elem().Set(ls.v.Elem().Slice(0, i)) } func (ls *listReflect) NewElement() pref.Value { return ls.conv.New() } func (ls *listReflect) IsValid() bool { return !ls.v.IsNil() } func (ls *listReflect) protoUnwrap() interface{} { return ls.v.Interface() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/convert_map.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type mapConverter struct { goType reflect.Type // map[K]V keyConv, valConv Converter } func newMapConverter(t reflect.Type, fd pref.FieldDescriptor) *mapConverter { if t.Kind() != reflect.Map { panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } return &mapConverter{ goType: t, keyConv: newSingularConverter(t.Key(), fd.MapKey()), valConv: newSingularConverter(t.Elem(), fd.MapValue()), } } func (c *mapConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfMap(&mapReflect{v, c.keyConv, c.valConv}) } func (c *mapConverter) GoValueOf(v pref.Value) reflect.Value { return v.Map().(*mapReflect).v } func (c *mapConverter) IsValidPB(v pref.Value) bool { mapv, ok := v.Interface().(*mapReflect) if !ok { return false } return mapv.v.Type() == c.goType } func (c *mapConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *mapConverter) New() pref.Value { return c.PBValueOf(reflect.MakeMap(c.goType)) } func (c *mapConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } type mapReflect struct { v reflect.Value // map[K]V keyConv Converter valConv Converter } func (ms *mapReflect) Len() int { return ms.v.Len() } func (ms *mapReflect) Has(k pref.MapKey) bool { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.v.MapIndex(rk) return rv.IsValid() } func (ms *mapReflect) Get(k pref.MapKey) pref.Value { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.v.MapIndex(rk) if !rv.IsValid() { return pref.Value{} } return ms.valConv.PBValueOf(rv) } func (ms *mapReflect) Set(k pref.MapKey, v pref.Value) { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.valConv.GoValueOf(v) ms.v.SetMapIndex(rk, rv) } func (ms *mapReflect) Clear(k pref.MapKey) { rk := ms.keyConv.GoValueOf(k.Value()) ms.v.SetMapIndex(rk, reflect.Value{}) } func (ms *mapReflect) Mutable(k pref.MapKey) pref.Value { if _, ok := ms.valConv.(*messageConverter); !ok { panic("invalid Mutable on map with non-message value type") } v := ms.Get(k) if !v.IsValid() { v = ms.NewValue() ms.Set(k, v) } return v } func (ms *mapReflect) Range(f func(pref.MapKey, pref.Value) bool) { iter := mapRange(ms.v) for iter.Next() { k := ms.keyConv.PBValueOf(iter.Key()).MapKey() v := ms.valConv.PBValueOf(iter.Value()) if !f(k, v) { return } } } func (ms *mapReflect) NewValue() pref.Value { return ms.valConv.New() } func (ms *mapReflect) IsValid() bool { return !ms.v.IsNil() } func (ms *mapReflect) protoUnwrap() interface{} { return ms.v.Interface() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/decode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "math/bits" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface" ) var errDecode = errors.New("cannot parse invalid wire-format data") type unmarshalOptions struct { flags protoiface.UnmarshalInputFlags resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } func (o unmarshalOptions) Options() proto.UnmarshalOptions { return proto.UnmarshalOptions{ Merge: true, AllowPartial: true, DiscardUnknown: o.DiscardUnknown(), Resolver: o.resolver, } } func (o unmarshalOptions) DiscardUnknown() bool { return o.flags&piface.UnmarshalDiscardUnknown != 0 } func (o unmarshalOptions) IsDefault() bool { return o.flags == 0 && o.resolver == preg.GlobalTypes } var lazyUnmarshalOptions = unmarshalOptions{ resolver: preg.GlobalTypes, } type unmarshalOutput struct { n int // number of bytes consumed initialized bool } // unmarshal is protoreflect.Methods.Unmarshal. func (mi *MessageInfo) unmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions{ flags: in.Flags, resolver: in.Resolver, }) var flags piface.UnmarshalOutputFlags if out.initialized { flags |= piface.UnmarshalInitialized } return piface.UnmarshalOutput{ Flags: flags, }, err } // errUnknown is returned during unmarshaling to indicate a parse error that // should result in a field being placed in the unknown fields section (for example, // when the wire type doesn't match) as opposed to the entire unmarshal operation // failing (for example, when a field extends past the available input). // // This is a sentinel error which should never be visible to the user. var errUnknown = errors.New("unknown") func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) { mi.init() if flags.ProtoLegacy && mi.isMessageSet { return unmarshalMessageSet(mi, b, p, opts) } initialized := true var requiredMask uint64 var exts *map[int32]ExtensionField start := len(b) for len(b) > 0 { // Parse the tag (field number and wire type). var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } b = b[n:] } var num protowire.Number if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) { return out, errDecode } else { num = protowire.Number(n) } wtyp := protowire.Type(tag & 7) if wtyp == protowire.EndGroupType { if num != groupTag { return out, errDecode } groupTag = 0 break } var f *coderFieldInfo if int(num) < len(mi.denseCoderFields) { f = mi.denseCoderFields[num] } else { f = mi.coderFields[num] } var n int err := errUnknown switch { case f != nil: if f.funcs.unmarshal == nil { break } var o unmarshalOutput o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, f, opts) n = o.n if err != nil { break } requiredMask |= f.validation.requiredBit if f.funcs.isInit != nil && !o.initialized { initialized = false } default: // Possible extension. if exts == nil && mi.extensionOffset.IsValid() { exts = p.Apply(mi.extensionOffset).Extensions() if *exts == nil { *exts = make(map[int32]ExtensionField) } } if exts == nil { break } var o unmarshalOutput o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts) if err != nil { break } n = o.n if !o.initialized { initialized = false } } if err != nil { if err != errUnknown { return out, err } n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() { u := mi.mutableUnknownBytes(p) *u = protowire.AppendTag(*u, num, wtyp) *u = append(*u, b[:n]...) } } b = b[n:] } if groupTag != 0 { return out, errDecode } if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) { initialized = false } if initialized { out.initialized = true } out.n = start - len(b) return out, nil } func (mi *MessageInfo) unmarshalExtension(b []byte, num protowire.Number, wtyp protowire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (out unmarshalOutput, err error) { x := exts[int32(num)] xt := x.Type() if xt == nil { var err error xt, err = opts.resolver.FindExtensionByNumber(mi.Desc.FullName(), num) if err != nil { if err == preg.NotFound { return out, errUnknown } return out, errors.New("%v: unable to resolve extension %v: %v", mi.Desc.FullName(), num, err) } } xi := getExtensionFieldInfo(xt) if xi.funcs.unmarshal == nil { return out, errUnknown } if flags.LazyUnmarshalExtensions { if opts.IsDefault() && x.canLazy(xt) { out, valid := skipExtension(b, xi, num, wtyp, opts) switch valid { case ValidationValid: if out.initialized { x.appendLazyBytes(xt, xi, num, wtyp, b[:out.n]) exts[int32(num)] = x return out, nil } case ValidationInvalid: return out, errDecode case ValidationUnknown: } } } ival := x.Value() if !ival.IsValid() && xi.unmarshalNeedsValue { // Create a new message, list, or map value to fill in. // For enums, create a prototype value to let the unmarshal func know the // concrete type. ival = xt.New() } v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts) if err != nil { return out, err } if xi.funcs.isInit == nil { out.initialized = true } x.Set(xt, v) exts[int32(num)] = x return out, nil } func skipExtension(b []byte, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, _ ValidationStatus) { if xi.validation.mi == nil { return out, ValidationUnknown } xi.validation.mi.init() switch xi.validation.typ { case validationTypeMessage: if wtyp != protowire.BytesType { return out, ValidationUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, ValidationUnknown } out, st := xi.validation.mi.validate(v, 0, opts) out.n = n return out, st case validationTypeGroup: if wtyp != protowire.StartGroupType { return out, ValidationUnknown } out, st := xi.validation.mi.validate(b, num, opts) return out, st default: return out, ValidationUnknown } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/encode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "math" "sort" "sync/atomic" "google.golang.org/protobuf/internal/flags" proto "google.golang.org/protobuf/proto" piface "google.golang.org/protobuf/runtime/protoiface" ) type marshalOptions struct { flags piface.MarshalInputFlags } func (o marshalOptions) Options() proto.MarshalOptions { return proto.MarshalOptions{ AllowPartial: true, Deterministic: o.Deterministic(), UseCachedSize: o.UseCachedSize(), } } func (o marshalOptions) Deterministic() bool { return o.flags&piface.MarshalDeterministic != 0 } func (o marshalOptions) UseCachedSize() bool { return o.flags&piface.MarshalUseCachedSize != 0 } // size is protoreflect.Methods.Size. func (mi *MessageInfo) size(in piface.SizeInput) piface.SizeOutput { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } size := mi.sizePointer(p, marshalOptions{ flags: in.Flags, }) return piface.SizeOutput{Size: size} } func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) { mi.init() if p.IsNil() { return 0 } if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() { if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size >= 0 { return int(size) } } return mi.sizePointerSlow(p, opts) } func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int) { if flags.ProtoLegacy && mi.isMessageSet { size = sizeMessageSet(mi, p, opts) if mi.sizecacheOffset.IsValid() { atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) } return size } if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() size += mi.sizeExtensions(e, opts) } for _, f := range mi.orderedCoderFields { if f.funcs.size == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { continue } size += f.funcs.size(fptr, f, opts) } if mi.unknownOffset.IsValid() { if u := mi.getUnknownBytes(p); u != nil { size += len(*u) } } if mi.sizecacheOffset.IsValid() { if size > math.MaxInt32 { // The size is too large for the int32 sizecache field. // We will need to recompute the size when encoding; // unfortunately expensive, but better than invalid output. atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), -1) } else { atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) } } return size } // marshal is protoreflect.Methods.Marshal. func (mi *MessageInfo) marshal(in piface.MarshalInput) (out piface.MarshalOutput, err error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } b, err := mi.marshalAppendPointer(in.Buf, p, marshalOptions{ flags: in.Flags, }) return piface.MarshalOutput{Buf: b}, err } func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOptions) ([]byte, error) { mi.init() if p.IsNil() { return b, nil } if flags.ProtoLegacy && mi.isMessageSet { return marshalMessageSet(mi, b, p, opts) } var err error // The old marshaler encodes extensions at beginning. if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() // TODO: Special handling for MessageSet? b, err = mi.appendExtensions(b, e, opts) if err != nil { return b, err } } for _, f := range mi.orderedCoderFields { if f.funcs.marshal == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { continue } b, err = f.funcs.marshal(b, fptr, f, opts) if err != nil { return b, err } } if mi.unknownOffset.IsValid() && !mi.isMessageSet { if u := mi.getUnknownBytes(p); u != nil { b = append(b, (*u)...) } } return b, nil } func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) { if ext == nil { return 0 } for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) if xi.funcs.size == nil { continue } n += xi.funcs.size(x.Value(), xi.tagsize, opts) } return n } func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) { if ext == nil { return b, nil } switch len(*ext) { case 0: return b, nil case 1: // Fast-path for one extension: Don't bother sorting the keys. var err error for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) } return b, err default: // Sort the keys to provide a deterministic encoding. // Not sure this is required, but the old code does it. keys := make([]int, 0, len(*ext)) for k := range *ext { keys = append(keys, int(k)) } sort.Ints(keys) var err error for _, k := range keys { x := (*ext)[int32(k)] xi := getExtensionFieldInfo(x.Type()) b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) if err != nil { return b, err } } return b, nil } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/enum.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type EnumInfo struct { GoReflectType reflect.Type // int32 kind Desc pref.EnumDescriptor } func (t *EnumInfo) New(n pref.EnumNumber) pref.Enum { return reflect.ValueOf(n).Convert(t.GoReflectType).Interface().(pref.Enum) } func (t *EnumInfo) Descriptor() pref.EnumDescriptor { return t.Desc } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "sync" "sync/atomic" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // ExtensionInfo implements ExtensionType. // // This type contains a number of exported fields for legacy compatibility. // The only non-deprecated use of this type is through the methods of the // ExtensionType interface. type ExtensionInfo struct { // An ExtensionInfo may exist in several stages of initialization. // // extensionInfoUninitialized: Some or all of the legacy exported // fields may be set, but none of the unexported fields have been // initialized. This is the starting state for an ExtensionInfo // in legacy generated code. // // extensionInfoDescInit: The desc field is set, but other unexported fields // may not be initialized. Legacy exported fields may or may not be set. // This is the starting state for an ExtensionInfo in newly generated code. // // extensionInfoFullInit: The ExtensionInfo is fully initialized. // This state is only entered after lazy initialization is complete. init uint32 mu sync.Mutex goType reflect.Type desc extensionTypeDescriptor conv Converter info *extensionFieldInfo // for fast-path method implementations // ExtendedType is a typed nil-pointer to the parent message type that // is being extended. It is possible for this to be unpopulated in v2 // since the message may no longer implement the MessageV1 interface. // // Deprecated: Use the ExtendedType method instead. ExtendedType piface.MessageV1 // ExtensionType is the zero value of the extension type. // // For historical reasons, reflect.TypeOf(ExtensionType) and the // type returned by InterfaceOf may not be identical. // // Deprecated: Use InterfaceOf(xt.Zero()) instead. ExtensionType interface{} // Field is the field number of the extension. // // Deprecated: Use the Descriptor().Number method instead. Field int32 // Name is the fully qualified name of extension. // // Deprecated: Use the Descriptor().FullName method instead. Name string // Tag is the protobuf struct tag used in the v1 API. // // Deprecated: Do not use. Tag string // Filename is the proto filename in which the extension is defined. // // Deprecated: Use Descriptor().ParentFile().Path() instead. Filename string } // Stages of initialization: See the ExtensionInfo.init field. const ( extensionInfoUninitialized = 0 extensionInfoDescInit = 1 extensionInfoFullInit = 2 ) func InitExtensionInfo(xi *ExtensionInfo, xd pref.ExtensionDescriptor, goType reflect.Type) { xi.goType = goType xi.desc = extensionTypeDescriptor{xd, xi} xi.init = extensionInfoDescInit } func (xi *ExtensionInfo) New() pref.Value { return xi.lazyInit().New() } func (xi *ExtensionInfo) Zero() pref.Value { return xi.lazyInit().Zero() } func (xi *ExtensionInfo) ValueOf(v interface{}) pref.Value { return xi.lazyInit().PBValueOf(reflect.ValueOf(v)) } func (xi *ExtensionInfo) InterfaceOf(v pref.Value) interface{} { return xi.lazyInit().GoValueOf(v).Interface() } func (xi *ExtensionInfo) IsValidValue(v pref.Value) bool { return xi.lazyInit().IsValidPB(v) } func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool { return xi.lazyInit().IsValidGo(reflect.ValueOf(v)) } func (xi *ExtensionInfo) TypeDescriptor() pref.ExtensionTypeDescriptor { if atomic.LoadUint32(&xi.init) < extensionInfoDescInit { xi.lazyInitSlow() } return &xi.desc } func (xi *ExtensionInfo) lazyInit() Converter { if atomic.LoadUint32(&xi.init) < extensionInfoFullInit { xi.lazyInitSlow() } return xi.conv } func (xi *ExtensionInfo) lazyInitSlow() { xi.mu.Lock() defer xi.mu.Unlock() if xi.init == extensionInfoFullInit { return } defer atomic.StoreUint32(&xi.init, extensionInfoFullInit) if xi.desc.ExtensionDescriptor == nil { xi.initFromLegacy() } if !xi.desc.ExtensionDescriptor.IsPlaceholder() { if xi.ExtensionType == nil { xi.initToLegacy() } xi.conv = NewConverter(xi.goType, xi.desc.ExtensionDescriptor) xi.info = makeExtensionFieldInfo(xi.desc.ExtensionDescriptor) xi.info.validation = newValidationInfo(xi.desc.ExtensionDescriptor, xi.goType) } } type extensionTypeDescriptor struct { pref.ExtensionDescriptor xi *ExtensionInfo } func (xtd *extensionTypeDescriptor) Type() pref.ExtensionType { return xtd.xi } func (xtd *extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor { return xtd.ExtensionDescriptor } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/legacy_enum.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strings" "sync" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) // legacyEnumName returns the name of enums used in legacy code. // It is neither the protobuf full name nor the qualified Go name, // but rather an odd hybrid of both. func legacyEnumName(ed pref.EnumDescriptor) string { var protoPkg string enumName := string(ed.FullName()) if fd := ed.ParentFile(); fd != nil { protoPkg = string(fd.Package()) enumName = strings.TrimPrefix(enumName, protoPkg+".") } if protoPkg == "" { return strs.GoCamelCase(enumName) } return protoPkg + "." + strs.GoCamelCase(enumName) } // legacyWrapEnum wraps v as a protoreflect.Enum, // where v must be a int32 kind and not implement the v2 API already. func legacyWrapEnum(v reflect.Value) pref.Enum { et := legacyLoadEnumType(v.Type()) return et.New(pref.EnumNumber(v.Int())) } var legacyEnumTypeCache sync.Map // map[reflect.Type]protoreflect.EnumType // legacyLoadEnumType dynamically loads a protoreflect.EnumType for t, // where t must be an int32 kind and not implement the v2 API already. func legacyLoadEnumType(t reflect.Type) pref.EnumType { // Fast-path: check if a EnumType is cached for this concrete type. if et, ok := legacyEnumTypeCache.Load(t); ok { return et.(pref.EnumType) } // Slow-path: derive enum descriptor and initialize EnumType. var et pref.EnumType ed := LegacyLoadEnumDesc(t) et = &legacyEnumType{ desc: ed, goType: t, } if et, ok := legacyEnumTypeCache.LoadOrStore(t, et); ok { return et.(pref.EnumType) } return et } type legacyEnumType struct { desc pref.EnumDescriptor goType reflect.Type m sync.Map // map[protoreflect.EnumNumber]proto.Enum } func (t *legacyEnumType) New(n pref.EnumNumber) pref.Enum { if e, ok := t.m.Load(n); ok { return e.(pref.Enum) } e := &legacyEnumWrapper{num: n, pbTyp: t, goTyp: t.goType} t.m.Store(n, e) return e } func (t *legacyEnumType) Descriptor() pref.EnumDescriptor { return t.desc } type legacyEnumWrapper struct { num pref.EnumNumber pbTyp pref.EnumType goTyp reflect.Type } func (e *legacyEnumWrapper) Descriptor() pref.EnumDescriptor { return e.pbTyp.Descriptor() } func (e *legacyEnumWrapper) Type() pref.EnumType { return e.pbTyp } func (e *legacyEnumWrapper) Number() pref.EnumNumber { return e.num } func (e *legacyEnumWrapper) ProtoReflect() pref.Enum { return e } func (e *legacyEnumWrapper) protoUnwrap() interface{} { v := reflect.New(e.goTyp).Elem() v.SetInt(int64(e.num)) return v.Interface() } var ( _ pref.Enum = (*legacyEnumWrapper)(nil) _ unwrapper = (*legacyEnumWrapper)(nil) ) var legacyEnumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor // LegacyLoadEnumDesc returns an EnumDescriptor derived from the Go type, // which must be an int32 kind and not implement the v2 API already. // // This is exported for testing purposes. func LegacyLoadEnumDesc(t reflect.Type) pref.EnumDescriptor { // Fast-path: check if an EnumDescriptor is cached for this concrete type. if ed, ok := legacyEnumDescCache.Load(t); ok { return ed.(pref.EnumDescriptor) } // Slow-path: initialize EnumDescriptor from the raw descriptor. ev := reflect.Zero(t).Interface() if _, ok := ev.(pref.Enum); ok { panic(fmt.Sprintf("%v already implements proto.Enum", t)) } edV1, ok := ev.(enumV1) if !ok { return aberrantLoadEnumDesc(t) } b, idxs := edV1.EnumDescriptor() var ed pref.EnumDescriptor if len(idxs) == 1 { ed = legacyLoadFileDesc(b).Enums().Get(idxs[0]) } else { md := legacyLoadFileDesc(b).Messages().Get(idxs[0]) for _, i := range idxs[1 : len(idxs)-1] { md = md.Messages().Get(i) } ed = md.Enums().Get(idxs[len(idxs)-1]) } if ed, ok := legacyEnumDescCache.LoadOrStore(t, ed); ok { return ed.(protoreflect.EnumDescriptor) } return ed } var aberrantEnumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor // aberrantLoadEnumDesc returns an EnumDescriptor derived from the Go type, // which must not implement protoreflect.Enum or enumV1. // // If the type does not implement enumV1, then there is no reliable // way to derive the original protobuf type information. // We are unable to use the global enum registry since it is // unfortunately keyed by the protobuf full name, which we also do not know. // Thus, this produces some bogus enum descriptor based on the Go type name. func aberrantLoadEnumDesc(t reflect.Type) pref.EnumDescriptor { // Fast-path: check if an EnumDescriptor is cached for this concrete type. if ed, ok := aberrantEnumDescCache.Load(t); ok { return ed.(pref.EnumDescriptor) } // Slow-path: construct a bogus, but unique EnumDescriptor. ed := &filedesc.Enum{L2: new(filedesc.EnumL2)} ed.L0.FullName = AberrantDeriveFullName(t) // e.g., github_com.user.repo.MyEnum ed.L0.ParentFile = filedesc.SurrogateProto3 ed.L2.Values.List = append(ed.L2.Values.List, filedesc.EnumValue{}) // TODO: Use the presence of a UnmarshalJSON method to determine proto2? vd := &ed.L2.Values.List[0] vd.L0.FullName = ed.L0.FullName + "_UNKNOWN" // e.g., github_com.user.repo.MyEnum_UNKNOWN vd.L0.ParentFile = ed.L0.ParentFile vd.L0.Parent = ed // TODO: We could use the String method to obtain some enum value names by // starting at 0 and print the enum until it produces invalid identifiers. // An exhaustive query is clearly impractical, but can be best-effort. if ed, ok := aberrantEnumDescCache.LoadOrStore(t, ed); ok { return ed.(pref.EnumDescriptor) } return ed } // AberrantDeriveFullName derives a fully qualified protobuf name for the given Go type // The provided name is not guaranteed to be stable nor universally unique. // It should be sufficiently unique within a program. // // This is exported for testing purposes. func AberrantDeriveFullName(t reflect.Type) pref.FullName { sanitize := func(r rune) rune { switch { case r == '/': return '.' case 'a' <= r && r <= 'z', 'A' <= r && r <= 'Z', '0' <= r && r <= '9': return r default: return '_' } } prefix := strings.Map(sanitize, t.PkgPath()) suffix := strings.Map(sanitize, t.Name()) if suffix == "" { suffix = fmt.Sprintf("UnknownX%X", reflect.ValueOf(t).Pointer()) } ss := append(strings.Split(prefix, "."), suffix) for i, s := range ss { if s == "" || ('0' <= s[0] && s[0] <= '9') { ss[i] = "x" + s } } return pref.FullName(strings.Join(ss, ".")) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/legacy_export.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "encoding/binary" "encoding/json" "hash/crc32" "math" "reflect" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // These functions exist to support exported APIs in generated protobufs. // While these are deprecated, they cannot be removed for compatibility reasons. // LegacyEnumName returns the name of enums used in legacy code. func (Export) LegacyEnumName(ed pref.EnumDescriptor) string { return legacyEnumName(ed) } // LegacyMessageTypeOf returns the protoreflect.MessageType for m, // with name used as the message name if necessary. func (Export) LegacyMessageTypeOf(m piface.MessageV1, name pref.FullName) pref.MessageType { if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Type() } return legacyLoadMessageType(reflect.TypeOf(m), name) } // UnmarshalJSONEnum unmarshals an enum from a JSON-encoded input. // The input can either be a string representing the enum value by name, // or a number representing the enum number itself. func (Export) UnmarshalJSONEnum(ed pref.EnumDescriptor, b []byte) (pref.EnumNumber, error) { if b[0] == '"' { var name pref.Name if err := json.Unmarshal(b, &name); err != nil { return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) } ev := ed.Values().ByName(name) if ev == nil { return 0, errors.New("invalid value for enum %v: %s", ed.FullName(), name) } return ev.Number(), nil } else { var num pref.EnumNumber if err := json.Unmarshal(b, &num); err != nil { return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) } return num, nil } } // CompressGZIP compresses the input as a GZIP-encoded file. // The current implementation does no compression. func (Export) CompressGZIP(in []byte) (out []byte) { // RFC 1952, section 2.3.1. var gzipHeader = [10]byte{0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff} // RFC 1951, section 3.2.4. var blockHeader [5]byte const maxBlockSize = math.MaxUint16 numBlocks := 1 + len(in)/maxBlockSize // RFC 1952, section 2.3.1. var gzipFooter [8]byte binary.LittleEndian.PutUint32(gzipFooter[0:4], crc32.ChecksumIEEE(in)) binary.LittleEndian.PutUint32(gzipFooter[4:8], uint32(len(in))) // Encode the input without compression using raw DEFLATE blocks. out = make([]byte, 0, len(gzipHeader)+len(blockHeader)*numBlocks+len(in)+len(gzipFooter)) out = append(out, gzipHeader[:]...) for blockHeader[0] == 0 { blockSize := maxBlockSize if blockSize > len(in) { blockHeader[0] = 0x01 // final bit per RFC 1951, section 3.2.3. blockSize = len(in) } binary.LittleEndian.PutUint16(blockHeader[1:3], uint16(blockSize)^0x0000) binary.LittleEndian.PutUint16(blockHeader[3:5], uint16(blockSize)^0xffff) out = append(out, blockHeader[:]...) out = append(out, in[:blockSize]...) in = in[blockSize:] } out = append(out, gzipFooter[:]...) return out } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/legacy_extension.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/encoding/messageset" ptag "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) func (xi *ExtensionInfo) initToLegacy() { xd := xi.desc var parent piface.MessageV1 messageName := xd.ContainingMessage().FullName() if mt, _ := preg.GlobalTypes.FindMessageByName(messageName); mt != nil { // Create a new parent message and unwrap it if possible. mv := mt.New().Interface() t := reflect.TypeOf(mv) if mv, ok := mv.(unwrapper); ok { t = reflect.TypeOf(mv.protoUnwrap()) } // Check whether the message implements the legacy v1 Message interface. mz := reflect.Zero(t).Interface() if mz, ok := mz.(piface.MessageV1); ok { parent = mz } } // Determine the v1 extension type, which is unfortunately not the same as // the v2 ExtensionType.GoType. extType := xi.goType switch extType.Kind() { case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields } // Reconstruct the legacy enum full name. var enumName string if xd.Kind() == pref.EnumKind { enumName = legacyEnumName(xd.Enum()) } // Derive the proto file that the extension was declared within. var filename string if fd := xd.ParentFile(); fd != nil { filename = fd.Path() } // For MessageSet extensions, the name used is the parent message. name := xd.FullName() if messageset.IsMessageSetExtension(xd) { name = name.Parent() } xi.ExtendedType = parent xi.ExtensionType = reflect.Zero(extType).Interface() xi.Field = int32(xd.Number()) xi.Name = string(name) xi.Tag = ptag.Marshal(xd, enumName) xi.Filename = filename } // initFromLegacy initializes an ExtensionInfo from // the contents of the deprecated exported fields of the type. func (xi *ExtensionInfo) initFromLegacy() { // The v1 API returns "type incomplete" descriptors where only the // field number is specified. In such a case, use a placeholder. if xi.ExtendedType == nil || xi.ExtensionType == nil { xd := placeholderExtension{ name: pref.FullName(xi.Name), number: pref.FieldNumber(xi.Field), } xi.desc = extensionTypeDescriptor{xd, xi} return } // Resolve enum or message dependencies. var ed pref.EnumDescriptor var md pref.MessageDescriptor t := reflect.TypeOf(xi.ExtensionType) isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 if isOptional || isRepeated { t = t.Elem() } switch v := reflect.Zero(t).Interface().(type) { case pref.Enum: ed = v.Descriptor() case enumV1: ed = LegacyLoadEnumDesc(t) case pref.ProtoMessage: md = v.ProtoReflect().Descriptor() case messageV1: md = LegacyLoadMessageDesc(t) } // Derive basic field information from the struct tag. var evs pref.EnumValueDescriptors if ed != nil { evs = ed.Values() } fd := ptag.Unmarshal(xi.Tag, t, evs).(*filedesc.Field) // Construct a v2 ExtensionType. xd := &filedesc.Extension{L2: new(filedesc.ExtensionL2)} xd.L0.ParentFile = filedesc.SurrogateProto2 xd.L0.FullName = pref.FullName(xi.Name) xd.L1.Number = pref.FieldNumber(xi.Field) xd.L1.Cardinality = fd.L1.Cardinality xd.L1.Kind = fd.L1.Kind xd.L2.IsPacked = fd.L1.IsPacked xd.L2.Default = fd.L1.Default xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType) xd.L2.Enum = ed xd.L2.Message = md // Derive real extension field name for MessageSets. if messageset.IsMessageSet(xd.L1.Extendee) && md.FullName() == xd.L0.FullName { xd.L0.FullName = xd.L0.FullName.Append(messageset.ExtensionName) } tt := reflect.TypeOf(xi.ExtensionType) if isOptional { tt = tt.Elem() } xi.goType = tt xi.desc = extensionTypeDescriptor{xd, xi} } type placeholderExtension struct { name pref.FullName number pref.FieldNumber } func (x placeholderExtension) ParentFile() pref.FileDescriptor { return nil } func (x placeholderExtension) Parent() pref.Descriptor { return nil } func (x placeholderExtension) Index() int { return 0 } func (x placeholderExtension) Syntax() pref.Syntax { return 0 } func (x placeholderExtension) Name() pref.Name { return x.name.Name() } func (x placeholderExtension) FullName() pref.FullName { return x.name } func (x placeholderExtension) IsPlaceholder() bool { return true } func (x placeholderExtension) Options() pref.ProtoMessage { return descopts.Field } func (x placeholderExtension) Number() pref.FieldNumber { return x.number } func (x placeholderExtension) Cardinality() pref.Cardinality { return 0 } func (x placeholderExtension) Kind() pref.Kind { return 0 } func (x placeholderExtension) HasJSONName() bool { return false } func (x placeholderExtension) JSONName() string { return "[" + string(x.name) + "]" } func (x placeholderExtension) TextName() string { return "[" + string(x.name) + "]" } func (x placeholderExtension) HasPresence() bool { return false } func (x placeholderExtension) HasOptionalKeyword() bool { return false } func (x placeholderExtension) IsExtension() bool { return true } func (x placeholderExtension) IsWeak() bool { return false } func (x placeholderExtension) IsPacked() bool { return false } func (x placeholderExtension) IsList() bool { return false } func (x placeholderExtension) IsMap() bool { return false } func (x placeholderExtension) MapKey() pref.FieldDescriptor { return nil } func (x placeholderExtension) MapValue() pref.FieldDescriptor { return nil } func (x placeholderExtension) HasDefault() bool { return false } func (x placeholderExtension) Default() pref.Value { return pref.Value{} } func (x placeholderExtension) DefaultEnumValue() pref.EnumValueDescriptor { return nil } func (x placeholderExtension) ContainingOneof() pref.OneofDescriptor { return nil } func (x placeholderExtension) ContainingMessage() pref.MessageDescriptor { return nil } func (x placeholderExtension) Enum() pref.EnumDescriptor { return nil } func (x placeholderExtension) Message() pref.MessageDescriptor { return nil } func (x placeholderExtension) ProtoType(pref.FieldDescriptor) { return } func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement) { return } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/legacy_file.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "bytes" "compress/gzip" "io/ioutil" "sync" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // Every enum and message type generated by protoc-gen-go since commit 2fc053c5 // on February 25th, 2016 has had a method to get the raw descriptor. // Types that were not generated by protoc-gen-go or were generated prior // to that version are not supported. // // The []byte returned is the encoded form of a FileDescriptorProto message // compressed using GZIP. The []int is the path from the top-level file // to the specific message or enum declaration. type ( enumV1 interface { EnumDescriptor() ([]byte, []int) } messageV1 interface { Descriptor() ([]byte, []int) } ) var legacyFileDescCache sync.Map // map[*byte]protoreflect.FileDescriptor // legacyLoadFileDesc unmarshals b as a compressed FileDescriptorProto message. // // This assumes that b is immutable and that b does not refer to part of a // concatenated series of GZIP files (which would require shenanigans that // rely on the concatenation properties of both protobufs and GZIP). // File descriptors generated by protoc-gen-go do not rely on that property. func legacyLoadFileDesc(b []byte) protoreflect.FileDescriptor { // Fast-path: check whether we already have a cached file descriptor. if fd, ok := legacyFileDescCache.Load(&b[0]); ok { return fd.(protoreflect.FileDescriptor) } // Slow-path: decompress and unmarshal the file descriptor proto. zr, err := gzip.NewReader(bytes.NewReader(b)) if err != nil { panic(err) } b2, err := ioutil.ReadAll(zr) if err != nil { panic(err) } fd := filedesc.Builder{ RawDescriptor: b2, FileRegistry: resolverOnly{protoregistry.GlobalFiles}, // do not register back to global registry }.Build().File if fd, ok := legacyFileDescCache.LoadOrStore(&b[0], fd); ok { return fd.(protoreflect.FileDescriptor) } return fd } type resolverOnly struct { reg *protoregistry.Files } func (r resolverOnly) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { return r.reg.FindFileByPath(path) } func (r resolverOnly) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { return r.reg.FindDescriptorByName(name) } func (resolverOnly) RegisterFile(protoreflect.FileDescriptor) error { return nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/legacy_message.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strings" "sync" "google.golang.org/protobuf/internal/descopts" ptag "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface" ) // legacyWrapMessage wraps v as a protoreflect.Message, // where v must be a *struct kind and not implement the v2 API already. func legacyWrapMessage(v reflect.Value) pref.Message { t := v.Type() if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return aberrantMessage{v: v} } mt := legacyLoadMessageInfo(t, "") return mt.MessageOf(v.Interface()) } // legacyLoadMessageType dynamically loads a protoreflect.Type for t, // where t must be not implement the v2 API already. // The provided name is used if it cannot be determined from the message. func legacyLoadMessageType(t reflect.Type, name pref.FullName) protoreflect.MessageType { if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return aberrantMessageType{t} } return legacyLoadMessageInfo(t, name) } var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo // legacyLoadMessageInfo dynamically loads a *MessageInfo for t, // where t must be a *struct kind and not implement the v2 API already. // The provided name is used if it cannot be determined from the message. func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo { // Fast-path: check if a MessageInfo is cached for this concrete type. if mt, ok := legacyMessageTypeCache.Load(t); ok { return mt.(*MessageInfo) } // Slow-path: derive message descriptor and initialize MessageInfo. mi := &MessageInfo{ Desc: legacyLoadMessageDesc(t, name), GoReflectType: t, } var hasMarshal, hasUnmarshal bool v := reflect.Zero(t).Interface() if _, hasMarshal = v.(legacyMarshaler); hasMarshal { mi.methods.Marshal = legacyMarshal // We have no way to tell whether the type's Marshal method // supports deterministic serialization or not, but this // preserves the v1 implementation's behavior of always // calling Marshal methods when present. mi.methods.Flags |= piface.SupportMarshalDeterministic } if _, hasUnmarshal = v.(legacyUnmarshaler); hasUnmarshal { mi.methods.Unmarshal = legacyUnmarshal } if _, hasMerge := v.(legacyMerger); hasMerge || (hasMarshal && hasUnmarshal) { mi.methods.Merge = legacyMerge } if mi, ok := legacyMessageTypeCache.LoadOrStore(t, mi); ok { return mi.(*MessageInfo) } return mi } var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor // LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type, // which should be a *struct kind and must not implement the v2 API already. // // This is exported for testing purposes. func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor { return legacyLoadMessageDesc(t, "") } func legacyLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { // Fast-path: check if a MessageDescriptor is cached for this concrete type. if mi, ok := legacyMessageDescCache.Load(t); ok { return mi.(pref.MessageDescriptor) } // Slow-path: initialize MessageDescriptor from the raw descriptor. mv := reflect.Zero(t).Interface() if _, ok := mv.(pref.ProtoMessage); ok { panic(fmt.Sprintf("%v already implements proto.Message", t)) } mdV1, ok := mv.(messageV1) if !ok { return aberrantLoadMessageDesc(t, name) } // If this is a dynamic message type where there isn't a 1-1 mapping between // Go and protobuf types, calling the Descriptor method on the zero value of // the message type isn't likely to work. If it panics, swallow the panic and // continue as if the Descriptor method wasn't present. b, idxs := func() ([]byte, []int) { defer func() { recover() }() return mdV1.Descriptor() }() if b == nil { return aberrantLoadMessageDesc(t, name) } // If the Go type has no fields, then this might be a proto3 empty message // from before the size cache was added. If there are any fields, check to // see that at least one of them looks like something we generated. if t.Elem().Kind() == reflect.Struct { if nfield := t.Elem().NumField(); nfield > 0 { hasProtoField := false for i := 0; i < nfield; i++ { f := t.Elem().Field(i) if f.Tag.Get("protobuf") != "" || f.Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(f.Name, "XXX_") { hasProtoField = true break } } if !hasProtoField { return aberrantLoadMessageDesc(t, name) } } } md := legacyLoadFileDesc(b).Messages().Get(idxs[0]) for _, i := range idxs[1:] { md = md.Messages().Get(i) } if name != "" && md.FullName() != name { panic(fmt.Sprintf("mismatching message name: got %v, want %v", md.FullName(), name)) } if md, ok := legacyMessageDescCache.LoadOrStore(t, md); ok { return md.(protoreflect.MessageDescriptor) } return md } var ( aberrantMessageDescLock sync.Mutex aberrantMessageDescCache map[reflect.Type]protoreflect.MessageDescriptor ) // aberrantLoadMessageDesc returns an MessageDescriptor derived from the Go type, // which must not implement protoreflect.ProtoMessage or messageV1. // // This is a best-effort derivation of the message descriptor using the protobuf // tags on the struct fields. func aberrantLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { aberrantMessageDescLock.Lock() defer aberrantMessageDescLock.Unlock() if aberrantMessageDescCache == nil { aberrantMessageDescCache = make(map[reflect.Type]protoreflect.MessageDescriptor) } return aberrantLoadMessageDescReentrant(t, name) } func aberrantLoadMessageDescReentrant(t reflect.Type, name pref.FullName) pref.MessageDescriptor { // Fast-path: check if an MessageDescriptor is cached for this concrete type. if md, ok := aberrantMessageDescCache[t]; ok { return md } // Slow-path: construct a descriptor from the Go struct type (best-effort). // Cache the MessageDescriptor early on so that we can resolve internal // cyclic references. md := &filedesc.Message{L2: new(filedesc.MessageL2)} md.L0.FullName = aberrantDeriveMessageName(t, name) md.L0.ParentFile = filedesc.SurrogateProto2 aberrantMessageDescCache[t] = md if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return md } // Try to determine if the message is using proto3 by checking scalars. for i := 0; i < t.Elem().NumField(); i++ { f := t.Elem().Field(i) if tag := f.Tag.Get("protobuf"); tag != "" { switch f.Type.Kind() { case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: md.L0.ParentFile = filedesc.SurrogateProto3 } for _, s := range strings.Split(tag, ",") { if s == "proto3" { md.L0.ParentFile = filedesc.SurrogateProto3 } } } } // Obtain a list of oneof wrapper types. var oneofWrappers []reflect.Type for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { if fn, ok := t.MethodByName(method); ok { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { if vs, ok := v.Interface().([]interface{}); ok { for _, v := range vs { oneofWrappers = append(oneofWrappers, reflect.TypeOf(v)) } } } } } // Obtain a list of the extension ranges. if fn, ok := t.MethodByName("ExtensionRangeArray"); ok { vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0] for i := 0; i < vs.Len(); i++ { v := vs.Index(i) md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, [2]pref.FieldNumber{ pref.FieldNumber(v.FieldByName("Start").Int()), pref.FieldNumber(v.FieldByName("End").Int() + 1), }) md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, nil) } } // Derive the message fields by inspecting the struct fields. for i := 0; i < t.Elem().NumField(); i++ { f := t.Elem().Field(i) if tag := f.Tag.Get("protobuf"); tag != "" { tagKey := f.Tag.Get("protobuf_key") tagVal := f.Tag.Get("protobuf_val") aberrantAppendField(md, f.Type, tag, tagKey, tagVal) } if tag := f.Tag.Get("protobuf_oneof"); tag != "" { n := len(md.L2.Oneofs.List) md.L2.Oneofs.List = append(md.L2.Oneofs.List, filedesc.Oneof{}) od := &md.L2.Oneofs.List[n] od.L0.FullName = md.FullName().Append(pref.Name(tag)) od.L0.ParentFile = md.L0.ParentFile od.L0.Parent = md od.L0.Index = n for _, t := range oneofWrappers { if t.Implements(f.Type) { f := t.Elem().Field(0) if tag := f.Tag.Get("protobuf"); tag != "" { aberrantAppendField(md, f.Type, tag, "", "") fd := &md.L2.Fields.List[len(md.L2.Fields.List)-1] fd.L1.ContainingOneof = od od.L1.Fields.List = append(od.L1.Fields.List, fd) } } } } } return md } func aberrantDeriveMessageName(t reflect.Type, name pref.FullName) pref.FullName { if name.IsValid() { return name } func() { defer func() { recover() }() // swallow possible nil panics if m, ok := reflect.Zero(t).Interface().(interface{ XXX_MessageName() string }); ok { name = pref.FullName(m.XXX_MessageName()) } }() if name.IsValid() { return name } if t.Kind() == reflect.Ptr { t = t.Elem() } return AberrantDeriveFullName(t) } func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey, tagVal string) { t := goType isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 if isOptional || isRepeated { t = t.Elem() } fd := ptag.Unmarshal(tag, t, placeholderEnumValues{}).(*filedesc.Field) // Append field descriptor to the message. n := len(md.L2.Fields.List) md.L2.Fields.List = append(md.L2.Fields.List, *fd) fd = &md.L2.Fields.List[n] fd.L0.FullName = md.FullName().Append(fd.Name()) fd.L0.ParentFile = md.L0.ParentFile fd.L0.Parent = md fd.L0.Index = n if fd.L1.IsWeak || fd.L1.HasPacked { fd.L1.Options = func() pref.ProtoMessage { opts := descopts.Field.ProtoReflect().New() if fd.L1.IsWeak { opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true)) } if fd.L1.HasPacked { opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.IsPacked)) } return opts.Interface() } } // Populate Enum and Message. if fd.Enum() == nil && fd.Kind() == pref.EnumKind { switch v := reflect.Zero(t).Interface().(type) { case pref.Enum: fd.L1.Enum = v.Descriptor() default: fd.L1.Enum = LegacyLoadEnumDesc(t) } } if fd.Message() == nil && (fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind) { switch v := reflect.Zero(t).Interface().(type) { case pref.ProtoMessage: fd.L1.Message = v.ProtoReflect().Descriptor() case messageV1: fd.L1.Message = LegacyLoadMessageDesc(t) default: if t.Kind() == reflect.Map { n := len(md.L1.Messages.List) md.L1.Messages.List = append(md.L1.Messages.List, filedesc.Message{L2: new(filedesc.MessageL2)}) md2 := &md.L1.Messages.List[n] md2.L0.FullName = md.FullName().Append(pref.Name(strs.MapEntryName(string(fd.Name())))) md2.L0.ParentFile = md.L0.ParentFile md2.L0.Parent = md md2.L0.Index = n md2.L1.IsMapEntry = true md2.L2.Options = func() pref.ProtoMessage { opts := descopts.Message.ProtoReflect().New() opts.Set(opts.Descriptor().Fields().ByName("map_entry"), protoreflect.ValueOfBool(true)) return opts.Interface() } aberrantAppendField(md2, t.Key(), tagKey, "", "") aberrantAppendField(md2, t.Elem(), tagVal, "", "") fd.L1.Message = md2 break } fd.L1.Message = aberrantLoadMessageDescReentrant(t, "") } } } type placeholderEnumValues struct { protoreflect.EnumValueDescriptors } func (placeholderEnumValues) ByNumber(n pref.EnumNumber) pref.EnumValueDescriptor { return filedesc.PlaceholderEnumValue(pref.FullName(fmt.Sprintf("UNKNOWN_%d", n))) } // legacyMarshaler is the proto.Marshaler interface superseded by protoiface.Methoder. type legacyMarshaler interface { Marshal() ([]byte, error) } // legacyUnmarshaler is the proto.Unmarshaler interface superseded by protoiface.Methoder. type legacyUnmarshaler interface { Unmarshal([]byte) error } // legacyMerger is the proto.Merger interface superseded by protoiface.Methoder. type legacyMerger interface { Merge(protoiface.MessageV1) } var aberrantProtoMethods = &piface.Methods{ Marshal: legacyMarshal, Unmarshal: legacyUnmarshal, Merge: legacyMerge, // We have no way to tell whether the type's Marshal method // supports deterministic serialization or not, but this // preserves the v1 implementation's behavior of always // calling Marshal methods when present. Flags: piface.SupportMarshalDeterministic, } func legacyMarshal(in piface.MarshalInput) (piface.MarshalOutput, error) { v := in.Message.(unwrapper).protoUnwrap() marshaler, ok := v.(legacyMarshaler) if !ok { return piface.MarshalOutput{}, errors.New("%T does not implement Marshal", v) } out, err := marshaler.Marshal() if in.Buf != nil { out = append(in.Buf, out...) } return piface.MarshalOutput{ Buf: out, }, err } func legacyUnmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) { v := in.Message.(unwrapper).protoUnwrap() unmarshaler, ok := v.(legacyUnmarshaler) if !ok { return piface.UnmarshalOutput{}, errors.New("%T does not implement Unmarshal", v) } return piface.UnmarshalOutput{}, unmarshaler.Unmarshal(in.Buf) } func legacyMerge(in piface.MergeInput) piface.MergeOutput { // Check whether this supports the legacy merger. dstv := in.Destination.(unwrapper).protoUnwrap() merger, ok := dstv.(legacyMerger) if ok { merger.Merge(Export{}.ProtoMessageV1Of(in.Source)) return piface.MergeOutput{Flags: piface.MergeComplete} } // If legacy merger is unavailable, implement merge in terms of // a marshal and unmarshal operation. srcv := in.Source.(unwrapper).protoUnwrap() marshaler, ok := srcv.(legacyMarshaler) if !ok { return piface.MergeOutput{} } dstv = in.Destination.(unwrapper).protoUnwrap() unmarshaler, ok := dstv.(legacyUnmarshaler) if !ok { return piface.MergeOutput{} } b, err := marshaler.Marshal() if err != nil { return piface.MergeOutput{} } err = unmarshaler.Unmarshal(b) if err != nil { return piface.MergeOutput{} } return piface.MergeOutput{Flags: piface.MergeComplete} } // aberrantMessageType implements MessageType for all types other than pointer-to-struct. type aberrantMessageType struct { t reflect.Type } func (mt aberrantMessageType) New() pref.Message { if mt.t.Kind() == reflect.Ptr { return aberrantMessage{reflect.New(mt.t.Elem())} } return aberrantMessage{reflect.Zero(mt.t)} } func (mt aberrantMessageType) Zero() pref.Message { return aberrantMessage{reflect.Zero(mt.t)} } func (mt aberrantMessageType) GoType() reflect.Type { return mt.t } func (mt aberrantMessageType) Descriptor() pref.MessageDescriptor { return LegacyLoadMessageDesc(mt.t) } // aberrantMessage implements Message for all types other than pointer-to-struct. // // When the underlying type implements legacyMarshaler or legacyUnmarshaler, // the aberrant Message can be marshaled or unmarshaled. Otherwise, there is // not much that can be done with values of this type. type aberrantMessage struct { v reflect.Value } // Reset implements the v1 proto.Message.Reset method. func (m aberrantMessage) Reset() { if mr, ok := m.v.Interface().(interface{ Reset() }); ok { mr.Reset() return } if m.v.Kind() == reflect.Ptr && !m.v.IsNil() { m.v.Elem().Set(reflect.Zero(m.v.Type().Elem())) } } func (m aberrantMessage) ProtoReflect() pref.Message { return m } func (m aberrantMessage) Descriptor() pref.MessageDescriptor { return LegacyLoadMessageDesc(m.v.Type()) } func (m aberrantMessage) Type() pref.MessageType { return aberrantMessageType{m.v.Type()} } func (m aberrantMessage) New() pref.Message { if m.v.Type().Kind() == reflect.Ptr { return aberrantMessage{reflect.New(m.v.Type().Elem())} } return aberrantMessage{reflect.Zero(m.v.Type())} } func (m aberrantMessage) Interface() pref.ProtoMessage { return m } func (m aberrantMessage) Range(f func(pref.FieldDescriptor, pref.Value) bool) { return } func (m aberrantMessage) Has(pref.FieldDescriptor) bool { return false } func (m aberrantMessage) Clear(pref.FieldDescriptor) { panic("invalid Message.Clear on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Get(fd pref.FieldDescriptor) pref.Value { if fd.Default().IsValid() { return fd.Default() } panic("invalid Message.Get on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Set(pref.FieldDescriptor, pref.Value) { panic("invalid Message.Set on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Mutable(pref.FieldDescriptor) pref.Value { panic("invalid Message.Mutable on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) NewField(pref.FieldDescriptor) pref.Value { panic("invalid Message.NewField on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) WhichOneof(pref.OneofDescriptor) pref.FieldDescriptor { panic("invalid Message.WhichOneof descriptor on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) GetUnknown() pref.RawFields { return nil } func (m aberrantMessage) SetUnknown(pref.RawFields) { // SetUnknown discards its input on messages which don't support unknown field storage. } func (m aberrantMessage) IsValid() bool { if m.v.Kind() == reflect.Ptr { return !m.v.IsNil() } return false } func (m aberrantMessage) ProtoMethods() *piface.Methods { return aberrantProtoMethods } func (m aberrantMessage) protoUnwrap() interface{} { return m.v.Interface() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/merge.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) type mergeOptions struct{} func (o mergeOptions) Merge(dst, src proto.Message) { proto.Merge(dst, src) } // merge is protoreflect.Methods.Merge. func (mi *MessageInfo) merge(in piface.MergeInput) piface.MergeOutput { dp, ok := mi.getPointer(in.Destination) if !ok { return piface.MergeOutput{} } sp, ok := mi.getPointer(in.Source) if !ok { return piface.MergeOutput{} } mi.mergePointer(dp, sp, mergeOptions{}) return piface.MergeOutput{Flags: piface.MergeComplete} } func (mi *MessageInfo) mergePointer(dst, src pointer, opts mergeOptions) { mi.init() if dst.IsNil() { panic(fmt.Sprintf("invalid value: merging into nil message")) } if src.IsNil() { return } for _, f := range mi.orderedCoderFields { if f.funcs.merge == nil { continue } sfptr := src.Apply(f.offset) if f.isPointer && sfptr.Elem().IsNil() { continue } f.funcs.merge(dst.Apply(f.offset), sfptr, f, opts) } if mi.extensionOffset.IsValid() { sext := src.Apply(mi.extensionOffset).Extensions() dext := dst.Apply(mi.extensionOffset).Extensions() if *dext == nil { *dext = make(map[int32]ExtensionField) } for num, sx := range *sext { xt := sx.Type() xi := getExtensionFieldInfo(xt) if xi.funcs.merge == nil { continue } dx := (*dext)[num] var dv pref.Value if dx.Type() == sx.Type() { dv = dx.Value() } if !dv.IsValid() && xi.unmarshalNeedsValue { dv = xt.New() } dv = xi.funcs.merge(dv, sx.Value(), opts) dx.Set(sx.Type(), dv) (*dext)[num] = dx } } if mi.unknownOffset.IsValid() { su := mi.getUnknownBytes(src) if su != nil && len(*su) > 0 { du := mi.mutableUnknownBytes(dst) *du = append(*du, *su...) } } } func mergeScalarValue(dst, src pref.Value, opts mergeOptions) pref.Value { return src } func mergeBytesValue(dst, src pref.Value, opts mergeOptions) pref.Value { return pref.ValueOfBytes(append(emptyBuf[:], src.Bytes()...)) } func mergeListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { dstl.Append(srcl.Get(i)) } return dst } func mergeBytesListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { sb := srcl.Get(i).Bytes() db := append(emptyBuf[:], sb...) dstl.Append(pref.ValueOfBytes(db)) } return dst } func mergeMessageListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { sm := srcl.Get(i).Message() dm := proto.Clone(sm.Interface()).ProtoReflect() dstl.Append(pref.ValueOfMessage(dm)) } return dst } func mergeMessageValue(dst, src pref.Value, opts mergeOptions) pref.Value { opts.Merge(dst.Message().Interface(), src.Message().Interface()) return dst } func mergeMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if f.mi != nil { if dst.Elem().IsNil() { dst.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } f.mi.mergePointer(dst.Elem(), src.Elem(), opts) } else { dm := dst.AsValueOf(f.ft).Elem() sm := src.AsValueOf(f.ft).Elem() if dm.IsNil() { dm.Set(reflect.New(f.ft.Elem())) } opts.Merge(asMessage(dm), asMessage(sm)) } } func mergeMessageSlice(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { for _, sp := range src.PointerSlice() { dm := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { f.mi.mergePointer(pointerOfValue(dm), sp, opts) } else { opts.Merge(asMessage(dm), asMessage(sp.AsValueOf(f.ft.Elem().Elem()))) } dst.AppendPointerSlice(pointerOfValue(dm)) } } func mergeBytes(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Bytes() = append(emptyBuf[:], *src.Bytes()...) } func mergeBytesNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Bytes() if len(v) > 0 { *dst.Bytes() = append(emptyBuf[:], v...) } } func mergeBytesSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.BytesSlice() for _, v := range *src.BytesSlice() { *ds = append(*ds, append(emptyBuf[:], v...)) } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/merge_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import () func mergeBool(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Bool() = *src.Bool() } func mergeBoolNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Bool() if v != false { *dst.Bool() = v } } func mergeBoolPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.BoolPtr() if p != nil { v := *p *dst.BoolPtr() = &v } } func mergeBoolSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.BoolSlice() ss := src.BoolSlice() *ds = append(*ds, *ss...) } func mergeInt32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Int32() = *src.Int32() } func mergeInt32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Int32() if v != 0 { *dst.Int32() = v } } func mergeInt32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Int32Ptr() if p != nil { v := *p *dst.Int32Ptr() = &v } } func mergeInt32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Int32Slice() ss := src.Int32Slice() *ds = append(*ds, *ss...) } func mergeUint32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Uint32() = *src.Uint32() } func mergeUint32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Uint32() if v != 0 { *dst.Uint32() = v } } func mergeUint32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Uint32Ptr() if p != nil { v := *p *dst.Uint32Ptr() = &v } } func mergeUint32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Uint32Slice() ss := src.Uint32Slice() *ds = append(*ds, *ss...) } func mergeInt64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Int64() = *src.Int64() } func mergeInt64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Int64() if v != 0 { *dst.Int64() = v } } func mergeInt64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Int64Ptr() if p != nil { v := *p *dst.Int64Ptr() = &v } } func mergeInt64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Int64Slice() ss := src.Int64Slice() *ds = append(*ds, *ss...) } func mergeUint64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Uint64() = *src.Uint64() } func mergeUint64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Uint64() if v != 0 { *dst.Uint64() = v } } func mergeUint64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Uint64Ptr() if p != nil { v := *p *dst.Uint64Ptr() = &v } } func mergeUint64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Uint64Slice() ss := src.Uint64Slice() *ds = append(*ds, *ss...) } func mergeFloat32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Float32() = *src.Float32() } func mergeFloat32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Float32() if v != 0 { *dst.Float32() = v } } func mergeFloat32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Float32Ptr() if p != nil { v := *p *dst.Float32Ptr() = &v } } func mergeFloat32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Float32Slice() ss := src.Float32Slice() *ds = append(*ds, *ss...) } func mergeFloat64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Float64() = *src.Float64() } func mergeFloat64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Float64() if v != 0 { *dst.Float64() = v } } func mergeFloat64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Float64Ptr() if p != nil { v := *p *dst.Float64Ptr() = &v } } func mergeFloat64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Float64Slice() ss := src.Float64Slice() *ds = append(*ds, *ss...) } func mergeString(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.String() = *src.String() } func mergeStringNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.String() if v != "" { *dst.String() = v } } func mergeStringPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.StringPtr() if p != nil { v := *p *dst.StringPtr() = &v } } func mergeStringSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.StringSlice() ss := src.StringSlice() *ds = append(*ds, *ss...) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/message.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strconv" "strings" "sync" "sync/atomic" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // MessageInfo provides protobuf related functionality for a given Go type // that represents a message. A given instance of MessageInfo is tied to // exactly one Go type, which must be a pointer to a struct type. // // The exported fields must be populated before any methods are called // and cannot be mutated after set. type MessageInfo struct { // GoReflectType is the underlying message Go type and must be populated. GoReflectType reflect.Type // pointer to struct // Desc is the underlying message descriptor type and must be populated. Desc pref.MessageDescriptor // Exporter must be provided in a purego environment in order to provide // access to unexported fields. Exporter exporter // OneofWrappers is list of pointers to oneof wrapper struct types. OneofWrappers []interface{} initMu sync.Mutex // protects all unexported fields initDone uint32 reflectMessageInfo // for reflection implementation coderMessageInfo // for fast-path method implementations } // exporter is a function that returns a reference to the ith field of v, // where v is a pointer to a struct. It returns nil if it does not support // exporting the requested field (e.g., already exported). type exporter func(v interface{}, i int) interface{} // getMessageInfo returns the MessageInfo for any message type that // is generated by our implementation of protoc-gen-go (for v2 and on). // If it is unable to obtain a MessageInfo, it returns nil. func getMessageInfo(mt reflect.Type) *MessageInfo { m, ok := reflect.Zero(mt).Interface().(pref.ProtoMessage) if !ok { return nil } mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo }) if !ok { return nil } return mr.ProtoMessageInfo() } func (mi *MessageInfo) init() { // This function is called in the hot path. Inline the sync.Once logic, // since allocating a closure for Once.Do is expensive. // Keep init small to ensure that it can be inlined. if atomic.LoadUint32(&mi.initDone) == 0 { mi.initOnce() } } func (mi *MessageInfo) initOnce() { mi.initMu.Lock() defer mi.initMu.Unlock() if mi.initDone == 1 { return } t := mi.GoReflectType if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct { panic(fmt.Sprintf("got %v, want *struct kind", t)) } t = t.Elem() si := mi.makeStructInfo(t) mi.makeReflectFuncs(t, si) mi.makeCoderMethods(t, si) atomic.StoreUint32(&mi.initDone, 1) } // getPointer returns the pointer for a message, which should be of // the type of the MessageInfo. If the message is of a different type, // it returns ok==false. func (mi *MessageInfo) getPointer(m pref.Message) (p pointer, ok bool) { switch m := m.(type) { case *messageState: return m.pointer(), m.messageInfo() == mi case *messageReflectWrapper: return m.pointer(), m.messageInfo() == mi } return pointer{}, false } type ( SizeCache = int32 WeakFields = map[int32]protoreflect.ProtoMessage UnknownFields = unknownFieldsA // TODO: switch to unknownFieldsB unknownFieldsA = []byte unknownFieldsB = *[]byte ExtensionFields = map[int32]ExtensionField ) var ( sizecacheType = reflect.TypeOf(SizeCache(0)) weakFieldsType = reflect.TypeOf(WeakFields(nil)) unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil)) unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil)) extensionFieldsType = reflect.TypeOf(ExtensionFields(nil)) ) type structInfo struct { sizecacheOffset offset sizecacheType reflect.Type weakOffset offset weakType reflect.Type unknownOffset offset unknownType reflect.Type extensionOffset offset extensionType reflect.Type fieldsByNumber map[pref.FieldNumber]reflect.StructField oneofsByName map[pref.Name]reflect.StructField oneofWrappersByType map[reflect.Type]pref.FieldNumber oneofWrappersByNumber map[pref.FieldNumber]reflect.Type } func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo { si := structInfo{ sizecacheOffset: invalidOffset, weakOffset: invalidOffset, unknownOffset: invalidOffset, extensionOffset: invalidOffset, fieldsByNumber: map[pref.FieldNumber]reflect.StructField{}, oneofsByName: map[pref.Name]reflect.StructField{}, oneofWrappersByType: map[reflect.Type]pref.FieldNumber{}, oneofWrappersByNumber: map[pref.FieldNumber]reflect.Type{}, } fieldLoop: for i := 0; i < t.NumField(); i++ { switch f := t.Field(i); f.Name { case genid.SizeCache_goname, genid.SizeCacheA_goname: if f.Type == sizecacheType { si.sizecacheOffset = offsetOf(f, mi.Exporter) si.sizecacheType = f.Type } case genid.WeakFields_goname, genid.WeakFieldsA_goname: if f.Type == weakFieldsType { si.weakOffset = offsetOf(f, mi.Exporter) si.weakType = f.Type } case genid.UnknownFields_goname, genid.UnknownFieldsA_goname: if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType { si.unknownOffset = offsetOf(f, mi.Exporter) si.unknownType = f.Type } case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname: if f.Type == extensionFieldsType { si.extensionOffset = offsetOf(f, mi.Exporter) si.extensionType = f.Type } default: for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { n, _ := strconv.ParseUint(s, 10, 64) si.fieldsByNumber[pref.FieldNumber(n)] = f continue fieldLoop } } if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 { si.oneofsByName[pref.Name(s)] = f continue fieldLoop } } } // Derive a mapping of oneof wrappers to fields. oneofWrappers := mi.OneofWrappers for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { if fn, ok := reflect.PtrTo(t).MethodByName(method); ok { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { if vs, ok := v.Interface().([]interface{}); ok { oneofWrappers = vs } } } } for _, v := range oneofWrappers { tf := reflect.TypeOf(v).Elem() f := tf.Field(0) for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { n, _ := strconv.ParseUint(s, 10, 64) si.oneofWrappersByType[tf] = pref.FieldNumber(n) si.oneofWrappersByNumber[pref.FieldNumber(n)] = tf break } } } return si } func (mi *MessageInfo) New() protoreflect.Message { return mi.MessageOf(reflect.New(mi.GoReflectType.Elem()).Interface()) } func (mi *MessageInfo) Zero() protoreflect.Message { return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) } func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { return mi.Desc } func (mi *MessageInfo) Enum(i int) protoreflect.EnumType { mi.init() fd := mi.Desc.Fields().Get(i) return Export{}.EnumTypeOf(mi.fieldTypes[fd.Number()]) } func (mi *MessageInfo) Message(i int) protoreflect.MessageType { mi.init() fd := mi.Desc.Fields().Get(i) switch { case fd.IsWeak(): mt, _ := preg.GlobalTypes.FindMessageByName(fd.Message().FullName()) return mt case fd.IsMap(): return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]} default: return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()]) } } type mapEntryType struct { desc protoreflect.MessageDescriptor valType interface{} // zero value of enum or message type } func (mt mapEntryType) New() protoreflect.Message { return nil } func (mt mapEntryType) Zero() protoreflect.Message { return nil } func (mt mapEntryType) Descriptor() protoreflect.MessageDescriptor { return mt.desc } func (mt mapEntryType) Enum(i int) protoreflect.EnumType { fd := mt.desc.Fields().Get(i) if fd.Enum() == nil { return nil } return Export{}.EnumTypeOf(mt.valType) } func (mt mapEntryType) Message(i int) protoreflect.MessageType { fd := mt.desc.Fields().Get(i) if fd.Message() == nil { return nil } return Export{}.MessageTypeOf(mt.valType) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/message_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) type reflectMessageInfo struct { fields map[pref.FieldNumber]*fieldInfo oneofs map[pref.Name]*oneofInfo // fieldTypes contains the zero value of an enum or message field. // For lists, it contains the element type. // For maps, it contains the entry value type. fieldTypes map[pref.FieldNumber]interface{} // denseFields is a subset of fields where: // 0 < fieldDesc.Number() < len(denseFields) // It provides faster access to the fieldInfo, but may be incomplete. denseFields []*fieldInfo // rangeInfos is a list of all fields (not belonging to a oneof) and oneofs. rangeInfos []interface{} // either *fieldInfo or *oneofInfo getUnknown func(pointer) pref.RawFields setUnknown func(pointer, pref.RawFields) extensionMap func(pointer) *extensionMap nilMessage atomicNilMessage } // makeReflectFuncs generates the set of functions to support reflection. func (mi *MessageInfo) makeReflectFuncs(t reflect.Type, si structInfo) { mi.makeKnownFieldsFunc(si) mi.makeUnknownFieldsFunc(t, si) mi.makeExtensionFieldsFunc(t, si) mi.makeFieldTypes(si) } // makeKnownFieldsFunc generates functions for operations that can be performed // on each protobuf message field. It takes in a reflect.Type representing the // Go struct and matches message fields with struct fields. // // This code assumes that the struct is well-formed and panics if there are // any discrepancies. func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) { mi.fields = map[pref.FieldNumber]*fieldInfo{} md := mi.Desc fds := md.Fields() for i := 0; i < fds.Len(); i++ { fd := fds.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } var fi fieldInfo switch { case fs.Type == nil: fi = fieldInfoForMissing(fd) // never occurs for officially generated message types case isOneof: fi = fieldInfoForOneof(fd, fs, mi.Exporter, si.oneofWrappersByNumber[fd.Number()]) case fd.IsMap(): fi = fieldInfoForMap(fd, fs, mi.Exporter) case fd.IsList(): fi = fieldInfoForList(fd, fs, mi.Exporter) case fd.IsWeak(): fi = fieldInfoForWeakMessage(fd, si.weakOffset) case fd.Message() != nil: fi = fieldInfoForMessage(fd, fs, mi.Exporter) default: fi = fieldInfoForScalar(fd, fs, mi.Exporter) } mi.fields[fd.Number()] = &fi } mi.oneofs = map[pref.Name]*oneofInfo{} for i := 0; i < md.Oneofs().Len(); i++ { od := md.Oneofs().Get(i) mi.oneofs[od.Name()] = makeOneofInfo(od, si, mi.Exporter) } mi.denseFields = make([]*fieldInfo, fds.Len()*2) for i := 0; i < fds.Len(); i++ { if fd := fds.Get(i); int(fd.Number()) < len(mi.denseFields) { mi.denseFields[fd.Number()] = mi.fields[fd.Number()] } } for i := 0; i < fds.Len(); { fd := fds.Get(i) if od := fd.ContainingOneof(); od != nil && !od.IsSynthetic() { mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()]) i += od.Fields().Len() } else { mi.rangeInfos = append(mi.rangeInfos, mi.fields[fd.Number()]) i++ } } // Introduce instability to iteration order, but keep it deterministic. if len(mi.rangeInfos) > 1 && detrand.Bool() { i := detrand.Intn(len(mi.rangeInfos) - 1) mi.rangeInfos[i], mi.rangeInfos[i+1] = mi.rangeInfos[i+1], mi.rangeInfos[i] } } func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) { switch { case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsAType: // Handle as []byte. mi.getUnknown = func(p pointer) pref.RawFields { if p.IsNil() { return nil } return *p.Apply(mi.unknownOffset).Bytes() } mi.setUnknown = func(p pointer, b pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } *p.Apply(mi.unknownOffset).Bytes() = b } case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsBType: // Handle as *[]byte. mi.getUnknown = func(p pointer) pref.RawFields { if p.IsNil() { return nil } bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { return nil } return **bp } mi.setUnknown = func(p pointer, b pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { *bp = new([]byte) } **bp = b } default: mi.getUnknown = func(pointer) pref.RawFields { return nil } mi.setUnknown = func(p pointer, _ pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } } } } func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type, si structInfo) { if si.extensionOffset.IsValid() { mi.extensionMap = func(p pointer) *extensionMap { if p.IsNil() { return (*extensionMap)(nil) } v := p.Apply(si.extensionOffset).AsValueOf(extensionFieldsType) return (*extensionMap)(v.Interface().(*map[int32]ExtensionField)) } } else { mi.extensionMap = func(pointer) *extensionMap { return (*extensionMap)(nil) } } } func (mi *MessageInfo) makeFieldTypes(si structInfo) { md := mi.Desc fds := md.Fields() for i := 0; i < fds.Len(); i++ { var ft reflect.Type fd := fds.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } var isMessage bool switch { case fs.Type == nil: continue // never occurs for officially generated message types case isOneof: if fd.Enum() != nil || fd.Message() != nil { ft = si.oneofWrappersByNumber[fd.Number()].Field(0).Type } case fd.IsMap(): if fd.MapValue().Enum() != nil || fd.MapValue().Message() != nil { ft = fs.Type.Elem() } isMessage = fd.MapValue().Message() != nil case fd.IsList(): if fd.Enum() != nil || fd.Message() != nil { ft = fs.Type.Elem() } isMessage = fd.Message() != nil case fd.Enum() != nil: ft = fs.Type if fd.HasPresence() && ft.Kind() == reflect.Ptr { ft = ft.Elem() } case fd.Message() != nil: ft = fs.Type if fd.IsWeak() { ft = nil } isMessage = true } if isMessage && ft != nil && ft.Kind() != reflect.Ptr { ft = reflect.PtrTo(ft) // never occurs for officially generated message types } if ft != nil { if mi.fieldTypes == nil { mi.fieldTypes = make(map[pref.FieldNumber]interface{}) } mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface() } } } type extensionMap map[int32]ExtensionField func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) { if m != nil { for _, x := range *m { xd := x.Type().TypeDescriptor() v := x.Value() if xd.IsList() && v.List().Len() == 0 { continue } if !f(xd, v) { return } } } } func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) { if m == nil { return false } xd := xt.TypeDescriptor() x, ok := (*m)[int32(xd.Number())] if !ok { return false } switch { case xd.IsList(): return x.Value().List().Len() > 0 case xd.IsMap(): return x.Value().Map().Len() > 0 case xd.Message() != nil: return x.Value().Message().IsValid() } return true } func (m *extensionMap) Clear(xt pref.ExtensionType) { delete(*m, int32(xt.TypeDescriptor().Number())) } func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value { xd := xt.TypeDescriptor() if m != nil { if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } } return xt.Zero() } func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) { xd := xt.TypeDescriptor() isValid := true switch { case !xt.IsValidValue(v): isValid = false case xd.IsList(): isValid = v.List().IsValid() case xd.IsMap(): isValid = v.Map().IsValid() case xd.Message() != nil: isValid = v.Message().IsValid() } if !isValid { panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName())) } if *m == nil { *m = make(map[int32]ExtensionField) } var x ExtensionField x.Set(xt, v) (*m)[int32(xd.Number())] = x } func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value { xd := xt.TypeDescriptor() if xd.Kind() != pref.MessageKind && xd.Kind() != pref.GroupKind && !xd.IsList() && !xd.IsMap() { panic("invalid Mutable on field with non-composite type") } if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } v := xt.New() m.Set(xt, v) return v } // MessageState is a data structure that is nested as the first field in a // concrete message. It provides a way to implement the ProtoReflect method // in an allocation-free way without needing to have a shadow Go type generated // for every message type. This technique only works using unsafe. // // // Example generated code: // // type M struct { // state protoimpl.MessageState // // Field1 int32 // Field2 string // Field3 *BarMessage // ... // } // // func (m *M) ProtoReflect() protoreflect.Message { // mi := &file_fizz_buzz_proto_msgInfos[5] // if protoimpl.UnsafeEnabled && m != nil { // ms := protoimpl.X.MessageStateOf(Pointer(m)) // if ms.LoadMessageInfo() == nil { // ms.StoreMessageInfo(mi) // } // return ms // } // return mi.MessageOf(m) // } // // The MessageState type holds a *MessageInfo, which must be atomically set to // the message info associated with a given message instance. // By unsafely converting a *M into a *MessageState, the MessageState object // has access to all the information needed to implement protobuf reflection. // It has access to the message info as its first field, and a pointer to the // MessageState is identical to a pointer to the concrete message value. // // // Requirements: // • The type M must implement protoreflect.ProtoMessage. // • The address of m must not be nil. // • The address of m and the address of m.state must be equal, // even though they are different Go types. type MessageState struct { pragma.NoUnkeyedLiterals pragma.DoNotCompare pragma.DoNotCopy atomicMessageInfo *MessageInfo } type messageState MessageState var ( _ pref.Message = (*messageState)(nil) _ unwrapper = (*messageState)(nil) ) // messageDataType is a tuple of a pointer to the message data and // a pointer to the message type. It is a generalized way of providing a // reflective view over a message instance. The disadvantage of this approach // is the need to allocate this tuple of 16B. type messageDataType struct { p pointer mi *MessageInfo } type ( messageReflectWrapper messageDataType messageIfaceWrapper messageDataType ) var ( _ pref.Message = (*messageReflectWrapper)(nil) _ unwrapper = (*messageReflectWrapper)(nil) _ pref.ProtoMessage = (*messageIfaceWrapper)(nil) _ unwrapper = (*messageIfaceWrapper)(nil) ) // MessageOf returns a reflective view over a message. The input must be a // pointer to a named Go struct. If the provided type has a ProtoReflect method, // it must be implemented by calling this method. func (mi *MessageInfo) MessageOf(m interface{}) pref.Message { if reflect.TypeOf(m) != mi.GoReflectType { panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType)) } p := pointerOfIface(m) if p.IsNil() { return mi.nilMessage.Init(mi) } return &messageReflectWrapper{p, mi} } func (m *messageReflectWrapper) pointer() pointer { return m.p } func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi } // Reset implements the v1 proto.Message.Reset method. func (m *messageIfaceWrapper) Reset() { if mr, ok := m.protoUnwrap().(interface{ Reset() }); ok { mr.Reset() return } rv := reflect.ValueOf(m.protoUnwrap()) if rv.Kind() == reflect.Ptr && !rv.IsNil() { rv.Elem().Set(reflect.Zero(rv.Type().Elem())) } } func (m *messageIfaceWrapper) ProtoReflect() pref.Message { return (*messageReflectWrapper)(m) } func (m *messageIfaceWrapper) protoUnwrap() interface{} { return m.p.AsIfaceOf(m.mi.GoReflectType.Elem()) } // checkField verifies that the provided field descriptor is valid. // Exactly one of the returned values is populated. func (mi *MessageInfo) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.ExtensionType) { var fi *fieldInfo if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) { fi = mi.denseFields[n] } else { fi = mi.fields[n] } if fi != nil { if fi.fieldDesc != fd { if got, want := fd.FullName(), fi.fieldDesc.FullName(); got != want { panic(fmt.Sprintf("mismatching field: got %v, want %v", got, want)) } panic(fmt.Sprintf("mismatching field: %v", fd.FullName())) } return fi, nil } if fd.IsExtension() { if got, want := fd.ContainingMessage().FullName(), mi.Desc.FullName(); got != want { // TODO: Should this be exact containing message descriptor match? panic(fmt.Sprintf("extension %v has mismatching containing message: got %v, want %v", fd.FullName(), got, want)) } if !mi.Desc.ExtensionRanges().Has(fd.Number()) { panic(fmt.Sprintf("extension %v extends %v outside the extension range", fd.FullName(), mi.Desc.FullName())) } xtd, ok := fd.(pref.ExtensionTypeDescriptor) if !ok { panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName())) } return nil, xtd.Type() } panic(fmt.Sprintf("field %v is invalid", fd.FullName())) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/message_reflect_field.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "math" "reflect" "sync" "google.golang.org/protobuf/internal/flags" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) type fieldInfo struct { fieldDesc pref.FieldDescriptor // These fields are used for protobuf reflection support. has func(pointer) bool clear func(pointer) get func(pointer) pref.Value set func(pointer, pref.Value) mutable func(pointer) pref.Value newMessage func() pref.Message newField func() pref.Value } func fieldInfoForMissing(fd pref.FieldDescriptor) fieldInfo { // This never occurs for generated message types. // It implies that a hand-crafted type has missing Go fields // for specific protobuf message fields. return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { return false }, clear: func(p pointer) { panic("missing Go struct field for " + string(fd.FullName())) }, get: func(p pointer) pref.Value { return fd.Default() }, set: func(p pointer, v pref.Value) { panic("missing Go struct field for " + string(fd.FullName())) }, mutable: func(p pointer) pref.Value { panic("missing Go struct field for " + string(fd.FullName())) }, newMessage: func() pref.Message { panic("missing Go struct field for " + string(fd.FullName())) }, newField: func() pref.Value { if v := fd.Default(); v.IsValid() { return v } panic("missing Go struct field for " + string(fd.FullName())) }, } } func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Interface { panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", fd.FullName(), ft)) } if ot.Kind() != reflect.Struct { panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", fd.FullName(), ot)) } if !reflect.PtrTo(ot).Implements(ft) { panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", fd.FullName(), ot, ft)) } conv := NewConverter(ot.Field(0).Type, fd) isMessage := fd.Message() != nil // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ // NOTE: The logic below intentionally assumes that oneof fields are // well-formatted. That is, the oneof interface never contains a // typed nil pointer to one of the wrapper structs. fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { return false } return true }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot { // NOTE: We intentionally don't check for rv.Elem().IsNil() // so that (*OneofWrapperType)(nil) gets cleared to nil. return } rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { return conv.Zero() } rv = rv.Elem().Elem().Field(0) return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { rv.Set(reflect.New(ot)) } rv = rv.Elem().Elem().Field(0) rv.Set(conv.GoValueOf(v)) }, mutable: func(p pointer) pref.Value { if !isMessage { panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", fd.FullName())) } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { rv.Set(reflect.New(ot)) } rv = rv.Elem().Elem().Field(0) if rv.Kind() == reflect.Ptr && rv.IsNil() { rv.Set(conv.GoValueOf(pref.ValueOfMessage(conv.New().Message()))) } return conv.PBValueOf(rv) }, newMessage: func() pref.Message { return conv.New().Message() }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Map { panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", fd.FullName(), ft)) } conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return rv.Len() > 0 }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.Len() == 0 { return conv.Zero() } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() pv := conv.GoValueOf(v) if pv.IsNil() { panic(fmt.Sprintf("map field %v cannot be set with read-only value", fd.FullName())) } rv.Set(pv) }, mutable: func(p pointer) pref.Value { v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if v.IsNil() { v.Set(reflect.MakeMap(fs.Type)) } return conv.PBValueOf(v) }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Slice { panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", fd.FullName(), ft)) } conv := NewConverter(reflect.PtrTo(ft), fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return rv.Len() > 0 }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type) if rv.Elem().Len() == 0 { return conv.Zero() } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() pv := conv.GoValueOf(v) if pv.IsNil() { panic(fmt.Sprintf("list field %v cannot be set with read-only value", fd.FullName())) } rv.Set(pv.Elem()) }, mutable: func(p pointer) pref.Value { v := p.Apply(fieldOffset).AsValueOf(fs.Type) return conv.PBValueOf(v) }, newField: func() pref.Value { return conv.New() }, } } var ( nilBytes = reflect.ValueOf([]byte(nil)) emptyBytes = reflect.ValueOf([]byte{}) ) func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type nullable := fd.HasPresence() isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 if nullable { if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice { // This never occurs for generated message types. // Despite the protobuf type system specifying presence, // the Go field type cannot represent it. nullable = false } if ft.Kind() == reflect.Ptr { ft = ft.Elem() } } conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable { return !rv.IsNil() } switch rv.Kind() { case reflect.Bool: return rv.Bool() case reflect.Int32, reflect.Int64: return rv.Int() != 0 case reflect.Uint32, reflect.Uint64: return rv.Uint() != 0 case reflect.Float32, reflect.Float64: return rv.Float() != 0 || math.Signbit(rv.Float()) case reflect.String, reflect.Slice: return rv.Len() > 0 default: panic(fmt.Sprintf("field %v has invalid type: %v", fd.FullName(), rv.Type())) // should never happen } }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable { if rv.IsNil() { return conv.Zero() } if rv.Kind() == reflect.Ptr { rv = rv.Elem() } } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable && rv.Kind() == reflect.Ptr { if rv.IsNil() { rv.Set(reflect.New(ft)) } rv = rv.Elem() } rv.Set(conv.GoValueOf(v)) if isBytes && rv.Len() == 0 { if nullable { rv.Set(emptyBytes) // preserve presence } else { rv.Set(nilBytes) // do not preserve presence } } }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldInfo { if !flags.ProtoLegacy { panic("no support for proto1 weak fields") } var once sync.Once var messageType pref.MessageType lazyInit := func() { once.Do(func() { messageName := fd.Message().FullName() messageType, _ = preg.GlobalTypes.FindMessageByName(messageName) if messageType == nil { panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName())) } }) } num := fd.Number() return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } _, ok := p.Apply(weakOffset).WeakFields().get(num) return ok }, clear: func(p pointer) { p.Apply(weakOffset).WeakFields().clear(num) }, get: func(p pointer) pref.Value { lazyInit() if p.IsNil() { return pref.ValueOfMessage(messageType.Zero()) } m, ok := p.Apply(weakOffset).WeakFields().get(num) if !ok { return pref.ValueOfMessage(messageType.Zero()) } return pref.ValueOfMessage(m.ProtoReflect()) }, set: func(p pointer, v pref.Value) { lazyInit() m := v.Message() if m.Descriptor() != messageType.Descriptor() { if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want { panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want)) } panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName())) } p.Apply(weakOffset).WeakFields().set(num, m.Interface()) }, mutable: func(p pointer) pref.Value { lazyInit() fs := p.Apply(weakOffset).WeakFields() m, ok := fs.get(num) if !ok { m = messageType.New().Interface() fs.set(num, m) } return pref.ValueOfMessage(m.ProtoReflect()) }, newMessage: func() pref.Message { lazyInit() return messageType.New() }, newField: func() pref.Value { lazyInit() return pref.ValueOfMessage(messageType.New()) }, } } func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() != reflect.Ptr { return !isZero(rv) } return !rv.IsNil() }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(conv.GoValueOf(v)) if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName())) } }, mutable: func(p pointer) pref.Value { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { rv.Set(conv.GoValueOf(conv.New())) } return conv.PBValueOf(rv) }, newMessage: func() pref.Message { return conv.New().Message() }, newField: func() pref.Value { return conv.New() }, } } type oneofInfo struct { oneofDesc pref.OneofDescriptor which func(pointer) pref.FieldNumber } func makeOneofInfo(od pref.OneofDescriptor, si structInfo, x exporter) *oneofInfo { oi := &oneofInfo{oneofDesc: od} if od.IsSynthetic() { fs := si.fieldsByNumber[od.Fields().Get(0).Number()] fieldOffset := offsetOf(fs, x) oi.which = func(p pointer) pref.FieldNumber { if p.IsNil() { return 0 } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() { // valid on either *T or []byte return 0 } return od.Fields().Get(0).Number() } } else { fs := si.oneofsByName[od.Name()] fieldOffset := offsetOf(fs, x) oi.which = func(p pointer) pref.FieldNumber { if p.IsNil() { return 0 } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() { return 0 } rv = rv.Elem() if rv.IsNil() { return 0 } return si.oneofWrappersByType[rv.Type().Elem()] } } return oi } // isZero is identical to reflect.Value.IsZero. // TODO: Remove this when Go1.13 is the minimally supported Go version. func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return math.Float64bits(v.Float()) == 0 case reflect.Complex64, reflect.Complex128: c := v.Complex() return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 case reflect.Array: for i := 0; i < v.Len(); i++ { if !isZero(v.Index(i)) { return false } } return true case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: return v.IsNil() case reflect.String: return v.Len() == 0 case reflect.Struct: for i := 0; i < v.NumField(); i++ { if !isZero(v.Field(i)) { return false } } return true default: panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()}) } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/message_reflect_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) func (m *messageState) Descriptor() protoreflect.MessageDescriptor { return m.messageInfo().Desc } func (m *messageState) Type() protoreflect.MessageType { return m.messageInfo() } func (m *messageState) New() protoreflect.Message { return m.messageInfo().New() } func (m *messageState) Interface() protoreflect.ProtoMessage { return m.protoUnwrap().(protoreflect.ProtoMessage) } func (m *messageState) protoUnwrap() interface{} { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageState) ProtoMethods() *protoiface.Methods { m.messageInfo().init() return &m.messageInfo().methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code // to be able to retrieve a v2 MessageInfo struct. // // WARNING: This method is exempt from the compatibility promise and // may be removed in the future without warning. func (m *messageState) ProtoMessageInfo() *MessageInfo { return m.messageInfo() } func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { m.messageInfo().init() for _, ri := range m.messageInfo().rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { if !f(ri.fieldDesc, ri.get(m.pointer())) { return } } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { fi := m.messageInfo().fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } m.messageInfo().extensionMap(m.pointer()).Range(f) } func (m *messageState) Has(fd protoreflect.FieldDescriptor) bool { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.has(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Has(xt) } } func (m *messageState) Clear(fd protoreflect.FieldDescriptor) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.clear(m.pointer()) } else { m.messageInfo().extensionMap(m.pointer()).Clear(xt) } } func (m *messageState) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.get(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Get(xt) } } func (m *messageState) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { m.messageInfo().extensionMap(m.pointer()).Set(xt, v) } } func (m *messageState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) } } func (m *messageState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.newField() } else { return xt.New() } } func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { m.messageInfo().init() if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageState) GetUnknown() protoreflect.RawFields { m.messageInfo().init() return m.messageInfo().getUnknown(m.pointer()) } func (m *messageState) SetUnknown(b protoreflect.RawFields) { m.messageInfo().init() m.messageInfo().setUnknown(m.pointer(), b) } func (m *messageState) IsValid() bool { return !m.pointer().IsNil() } func (m *messageReflectWrapper) Descriptor() protoreflect.MessageDescriptor { return m.messageInfo().Desc } func (m *messageReflectWrapper) Type() protoreflect.MessageType { return m.messageInfo() } func (m *messageReflectWrapper) New() protoreflect.Message { return m.messageInfo().New() } func (m *messageReflectWrapper) Interface() protoreflect.ProtoMessage { if m, ok := m.protoUnwrap().(protoreflect.ProtoMessage); ok { return m } return (*messageIfaceWrapper)(m) } func (m *messageReflectWrapper) protoUnwrap() interface{} { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageReflectWrapper) ProtoMethods() *protoiface.Methods { m.messageInfo().init() return &m.messageInfo().methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code // to be able to retrieve a v2 MessageInfo struct. // // WARNING: This method is exempt from the compatibility promise and // may be removed in the future without warning. func (m *messageReflectWrapper) ProtoMessageInfo() *MessageInfo { return m.messageInfo() } func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { m.messageInfo().init() for _, ri := range m.messageInfo().rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { if !f(ri.fieldDesc, ri.get(m.pointer())) { return } } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { fi := m.messageInfo().fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } m.messageInfo().extensionMap(m.pointer()).Range(f) } func (m *messageReflectWrapper) Has(fd protoreflect.FieldDescriptor) bool { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.has(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Has(xt) } } func (m *messageReflectWrapper) Clear(fd protoreflect.FieldDescriptor) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.clear(m.pointer()) } else { m.messageInfo().extensionMap(m.pointer()).Clear(xt) } } func (m *messageReflectWrapper) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.get(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Get(xt) } } func (m *messageReflectWrapper) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { m.messageInfo().extensionMap(m.pointer()).Set(xt, v) } } func (m *messageReflectWrapper) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) } } func (m *messageReflectWrapper) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.newField() } else { return xt.New() } } func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { m.messageInfo().init() if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageReflectWrapper) GetUnknown() protoreflect.RawFields { m.messageInfo().init() return m.messageInfo().getUnknown(m.pointer()) } func (m *messageReflectWrapper) SetUnknown(b protoreflect.RawFields) { m.messageInfo().init() m.messageInfo().setUnknown(m.pointer(), b) } func (m *messageReflectWrapper) IsValid() bool { return !m.pointer().IsNil() } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/pointer_reflect.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package impl import ( "fmt" "reflect" "sync" ) const UnsafeEnabled = false // Pointer is an opaque pointer type. type Pointer interface{} // offset represents the offset to a struct field, accessible from a pointer. // The offset is the field index into a struct. type offset struct { index int export exporter } // offsetOf returns a field offset for the struct field. func offsetOf(f reflect.StructField, x exporter) offset { if len(f.Index) != 1 { panic("embedded structs are not supported") } if f.PkgPath == "" { return offset{index: f.Index[0]} // field is already exported } if x == nil { panic("exporter must be provided for unexported field") } return offset{index: f.Index[0], export: x} } // IsValid reports whether the offset is valid. func (f offset) IsValid() bool { return f.index >= 0 } // invalidOffset is an invalid field offset. var invalidOffset = offset{index: -1} // zeroOffset is a noop when calling pointer.Apply. var zeroOffset = offset{index: 0} // pointer is an abstract representation of a pointer to a struct or field. type pointer struct{ v reflect.Value } // pointerOf returns p as a pointer. func pointerOf(p Pointer) pointer { return pointerOfIface(p) } // pointerOfValue returns v as a pointer. func pointerOfValue(v reflect.Value) pointer { return pointer{v: v} } // pointerOfIface returns the pointer portion of an interface. func pointerOfIface(v interface{}) pointer { return pointer{v: reflect.ValueOf(v)} } // IsNil reports whether the pointer is nil. func (p pointer) IsNil() bool { return p.v.IsNil() } // Apply adds an offset to the pointer to derive a new pointer // to a specified field. The current pointer must be pointing at a struct. func (p pointer) Apply(f offset) pointer { if f.export != nil { if v := reflect.ValueOf(f.export(p.v.Interface(), f.index)); v.IsValid() { return pointer{v: v} } } return pointer{v: p.v.Elem().Field(f.index).Addr()} } // AsValueOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) func (p pointer) AsValueOf(t reflect.Type) reflect.Value { if got := p.v.Type().Elem(); got != t { panic(fmt.Sprintf("invalid type: got %v, want %v", got, t)) } return p.v } // AsIfaceOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to p.AsValueOf(t).Interface() func (p pointer) AsIfaceOf(t reflect.Type) interface{} { return p.AsValueOf(t).Interface() } func (p pointer) Bool() *bool { return p.v.Interface().(*bool) } func (p pointer) BoolPtr() **bool { return p.v.Interface().(**bool) } func (p pointer) BoolSlice() *[]bool { return p.v.Interface().(*[]bool) } func (p pointer) Int32() *int32 { return p.v.Interface().(*int32) } func (p pointer) Int32Ptr() **int32 { return p.v.Interface().(**int32) } func (p pointer) Int32Slice() *[]int32 { return p.v.Interface().(*[]int32) } func (p pointer) Int64() *int64 { return p.v.Interface().(*int64) } func (p pointer) Int64Ptr() **int64 { return p.v.Interface().(**int64) } func (p pointer) Int64Slice() *[]int64 { return p.v.Interface().(*[]int64) } func (p pointer) Uint32() *uint32 { return p.v.Interface().(*uint32) } func (p pointer) Uint32Ptr() **uint32 { return p.v.Interface().(**uint32) } func (p pointer) Uint32Slice() *[]uint32 { return p.v.Interface().(*[]uint32) } func (p pointer) Uint64() *uint64 { return p.v.Interface().(*uint64) } func (p pointer) Uint64Ptr() **uint64 { return p.v.Interface().(**uint64) } func (p pointer) Uint64Slice() *[]uint64 { return p.v.Interface().(*[]uint64) } func (p pointer) Float32() *float32 { return p.v.Interface().(*float32) } func (p pointer) Float32Ptr() **float32 { return p.v.Interface().(**float32) } func (p pointer) Float32Slice() *[]float32 { return p.v.Interface().(*[]float32) } func (p pointer) Float64() *float64 { return p.v.Interface().(*float64) } func (p pointer) Float64Ptr() **float64 { return p.v.Interface().(**float64) } func (p pointer) Float64Slice() *[]float64 { return p.v.Interface().(*[]float64) } func (p pointer) String() *string { return p.v.Interface().(*string) } func (p pointer) StringPtr() **string { return p.v.Interface().(**string) } func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) } func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) } func (p pointer) BytesPtr() **[]byte { return p.v.Interface().(**[]byte) } func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) } func (p pointer) Extensions() *map[int32]ExtensionField { return p.v.Interface().(*map[int32]ExtensionField) } func (p pointer) Elem() pointer { return pointer{v: p.v.Elem()} } // PointerSlice copies []*T from p as a new []pointer. // This behavior differs from the implementation in pointer_unsafe.go. func (p pointer) PointerSlice() []pointer { // TODO: reconsider this if p.v.IsNil() { return nil } n := p.v.Elem().Len() s := make([]pointer, n) for i := 0; i < n; i++ { s[i] = pointer{v: p.v.Elem().Index(i)} } return s } // AppendPointerSlice appends v to p, which must be a []*T. func (p pointer) AppendPointerSlice(v pointer) { sp := p.v.Elem() sp.Set(reflect.Append(sp, v.v)) } // SetPointer sets *p to v. func (p pointer) SetPointer(v pointer) { p.v.Elem().Set(v.v) } func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } func (ms *messageState) pointer() pointer { panic("not supported") } func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) LoadMessageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) StoreMessageInfo(mi *MessageInfo) { panic("not supported") } type atomicNilMessage struct { once sync.Once m messageReflectWrapper } func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { m.once.Do(func() { m.m.p = pointerOfIface(reflect.Zero(mi.GoReflectType).Interface()) m.m.mi = mi }) return &m.m } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/pointer_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package impl import ( "reflect" "sync/atomic" "unsafe" ) const UnsafeEnabled = true // Pointer is an opaque pointer type. type Pointer unsafe.Pointer // offset represents the offset to a struct field, accessible from a pointer. // The offset is the byte offset to the field from the start of the struct. type offset uintptr // offsetOf returns a field offset for the struct field. func offsetOf(f reflect.StructField, x exporter) offset { return offset(f.Offset) } // IsValid reports whether the offset is valid. func (f offset) IsValid() bool { return f != invalidOffset } // invalidOffset is an invalid field offset. var invalidOffset = ^offset(0) // zeroOffset is a noop when calling pointer.Apply. var zeroOffset = offset(0) // pointer is a pointer to a message struct or field. type pointer struct{ p unsafe.Pointer } // pointerOf returns p as a pointer. func pointerOf(p Pointer) pointer { return pointer{p: unsafe.Pointer(p)} } // pointerOfValue returns v as a pointer. func pointerOfValue(v reflect.Value) pointer { return pointer{p: unsafe.Pointer(v.Pointer())} } // pointerOfIface returns the pointer portion of an interface. func pointerOfIface(v interface{}) pointer { type ifaceHeader struct { Type unsafe.Pointer Data unsafe.Pointer } return pointer{p: (*ifaceHeader)(unsafe.Pointer(&v)).Data} } // IsNil reports whether the pointer is nil. func (p pointer) IsNil() bool { return p.p == nil } // Apply adds an offset to the pointer to derive a new pointer // to a specified field. The pointer must be valid and pointing at a struct. func (p pointer) Apply(f offset) pointer { if p.IsNil() { panic("invalid nil pointer") } return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} } // AsValueOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) func (p pointer) AsValueOf(t reflect.Type) reflect.Value { return reflect.NewAt(t, p.p) } // AsIfaceOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to p.AsValueOf(t).Interface() func (p pointer) AsIfaceOf(t reflect.Type) interface{} { // TODO: Use tricky unsafe magic to directly create ifaceHeader. return p.AsValueOf(t).Interface() } func (p pointer) Bool() *bool { return (*bool)(p.p) } func (p pointer) BoolPtr() **bool { return (**bool)(p.p) } func (p pointer) BoolSlice() *[]bool { return (*[]bool)(p.p) } func (p pointer) Int32() *int32 { return (*int32)(p.p) } func (p pointer) Int32Ptr() **int32 { return (**int32)(p.p) } func (p pointer) Int32Slice() *[]int32 { return (*[]int32)(p.p) } func (p pointer) Int64() *int64 { return (*int64)(p.p) } func (p pointer) Int64Ptr() **int64 { return (**int64)(p.p) } func (p pointer) Int64Slice() *[]int64 { return (*[]int64)(p.p) } func (p pointer) Uint32() *uint32 { return (*uint32)(p.p) } func (p pointer) Uint32Ptr() **uint32 { return (**uint32)(p.p) } func (p pointer) Uint32Slice() *[]uint32 { return (*[]uint32)(p.p) } func (p pointer) Uint64() *uint64 { return (*uint64)(p.p) } func (p pointer) Uint64Ptr() **uint64 { return (**uint64)(p.p) } func (p pointer) Uint64Slice() *[]uint64 { return (*[]uint64)(p.p) } func (p pointer) Float32() *float32 { return (*float32)(p.p) } func (p pointer) Float32Ptr() **float32 { return (**float32)(p.p) } func (p pointer) Float32Slice() *[]float32 { return (*[]float32)(p.p) } func (p pointer) Float64() *float64 { return (*float64)(p.p) } func (p pointer) Float64Ptr() **float64 { return (**float64)(p.p) } func (p pointer) Float64Slice() *[]float64 { return (*[]float64)(p.p) } func (p pointer) String() *string { return (*string)(p.p) } func (p pointer) StringPtr() **string { return (**string)(p.p) } func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) } func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) } func (p pointer) BytesPtr() **[]byte { return (**[]byte)(p.p) } func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.p) } func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) } func (p pointer) Elem() pointer { return pointer{p: *(*unsafe.Pointer)(p.p)} } // PointerSlice loads []*T from p as a []pointer. // The value returned is aliased with the original slice. // This behavior differs from the implementation in pointer_reflect.go. func (p pointer) PointerSlice() []pointer { // Super-tricky - p should point to a []*T where T is a // message type. We load it as []pointer. return *(*[]pointer)(p.p) } // AppendPointerSlice appends v to p, which must be a []*T. func (p pointer) AppendPointerSlice(v pointer) { *(*[]pointer)(p.p) = append(*(*[]pointer)(p.p), v) } // SetPointer sets *p to v. func (p pointer) SetPointer(v pointer) { *(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p) } // Static check that MessageState does not exceed the size of a pointer. const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{})) func (Export) MessageStateOf(p Pointer) *messageState { // Super-tricky - see documentation on MessageState. return (*messageState)(unsafe.Pointer(p)) } func (ms *messageState) pointer() pointer { // Super-tricky - see documentation on MessageState. return pointer{p: unsafe.Pointer(ms)} } func (ms *messageState) messageInfo() *MessageInfo { mi := ms.LoadMessageInfo() if mi == nil { panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct") } return mi } func (ms *messageState) LoadMessageInfo() *MessageInfo { return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)))) } func (ms *messageState) StoreMessageInfo(mi *MessageInfo) { atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)), unsafe.Pointer(mi)) } type atomicNilMessage struct{ p unsafe.Pointer } // p is a *messageReflectWrapper func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { if p := atomic.LoadPointer(&m.p); p != nil { return (*messageReflectWrapper)(p) } w := &messageReflectWrapper{mi: mi} atomic.CompareAndSwapPointer(&m.p, nil, (unsafe.Pointer)(w)) return (*messageReflectWrapper)(atomic.LoadPointer(&m.p)) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/validate.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "math" "math/bits" "reflect" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) // ValidationStatus is the result of validating the wire-format encoding of a message. type ValidationStatus int const ( // ValidationUnknown indicates that unmarshaling the message might succeed or fail. // The validator was unable to render a judgement. // // The only causes of this status are an aberrant message type appearing somewhere // in the message or a failure in the extension resolver. ValidationUnknown ValidationStatus = iota + 1 // ValidationInvalid indicates that unmarshaling the message will fail. ValidationInvalid // ValidationValid indicates that unmarshaling the message will succeed. ValidationValid ) func (v ValidationStatus) String() string { switch v { case ValidationUnknown: return "ValidationUnknown" case ValidationInvalid: return "ValidationInvalid" case ValidationValid: return "ValidationValid" default: return fmt.Sprintf("ValidationStatus(%d)", int(v)) } } // Validate determines whether the contents of the buffer are a valid wire encoding // of the message type. // // This function is exposed for testing. func Validate(mt pref.MessageType, in piface.UnmarshalInput) (out piface.UnmarshalOutput, _ ValidationStatus) { mi, ok := mt.(*MessageInfo) if !ok { return out, ValidationUnknown } if in.Resolver == nil { in.Resolver = preg.GlobalTypes } o, st := mi.validate(in.Buf, 0, unmarshalOptions{ flags: in.Flags, resolver: in.Resolver, }) if o.initialized { out.Flags |= piface.UnmarshalInitialized } return out, st } type validationInfo struct { mi *MessageInfo typ validationType keyType, valType validationType // For non-required fields, requiredBit is 0. // // For required fields, requiredBit's nth bit is set, where n is a // unique index in the range [0, MessageInfo.numRequiredFields). // // If there are more than 64 required fields, requiredBit is 0. requiredBit uint64 } type validationType uint8 const ( validationTypeOther validationType = iota validationTypeMessage validationTypeGroup validationTypeMap validationTypeRepeatedVarint validationTypeRepeatedFixed32 validationTypeRepeatedFixed64 validationTypeVarint validationTypeFixed32 validationTypeFixed64 validationTypeBytes validationTypeUTF8String validationTypeMessageSetItem ) func newFieldValidationInfo(mi *MessageInfo, si structInfo, fd pref.FieldDescriptor, ft reflect.Type) validationInfo { var vi validationInfo switch { case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic(): switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok { vi.mi = getMessageInfo(ot.Field(0).Type) } case pref.GroupKind: vi.typ = validationTypeGroup if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok { vi.mi = getMessageInfo(ot.Field(0).Type) } case pref.StringKind: if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } } default: vi = newValidationInfo(fd, ft) } if fd.Cardinality() == pref.Required { // Avoid overflow. The required field check is done with a 64-bit mask, with // any message containing more than 64 required fields always reported as // potentially uninitialized, so it is not important to get a precise count // of the required fields past 64. if mi.numRequiredFields < math.MaxUint8 { mi.numRequiredFields++ vi.requiredBit = 1 << (mi.numRequiredFields - 1) } } return vi } func newValidationInfo(fd pref.FieldDescriptor, ft reflect.Type) validationInfo { var vi validationInfo switch { case fd.IsList(): switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if ft.Kind() == reflect.Slice { vi.mi = getMessageInfo(ft.Elem()) } case pref.GroupKind: vi.typ = validationTypeGroup if ft.Kind() == reflect.Slice { vi.mi = getMessageInfo(ft.Elem()) } case pref.StringKind: vi.typ = validationTypeBytes if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } default: switch wireTypes[fd.Kind()] { case protowire.VarintType: vi.typ = validationTypeRepeatedVarint case protowire.Fixed32Type: vi.typ = validationTypeRepeatedFixed32 case protowire.Fixed64Type: vi.typ = validationTypeRepeatedFixed64 } } case fd.IsMap(): vi.typ = validationTypeMap switch fd.MapKey().Kind() { case pref.StringKind: if strs.EnforceUTF8(fd) { vi.keyType = validationTypeUTF8String } } switch fd.MapValue().Kind() { case pref.MessageKind: vi.valType = validationTypeMessage if ft.Kind() == reflect.Map { vi.mi = getMessageInfo(ft.Elem()) } case pref.StringKind: if strs.EnforceUTF8(fd) { vi.valType = validationTypeUTF8String } } default: switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if !fd.IsWeak() { vi.mi = getMessageInfo(ft) } case pref.GroupKind: vi.typ = validationTypeGroup vi.mi = getMessageInfo(ft) case pref.StringKind: vi.typ = validationTypeBytes if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } default: switch wireTypes[fd.Kind()] { case protowire.VarintType: vi.typ = validationTypeVarint case protowire.Fixed32Type: vi.typ = validationTypeFixed32 case protowire.Fixed64Type: vi.typ = validationTypeFixed64 case protowire.BytesType: vi.typ = validationTypeBytes } } } return vi } func (mi *MessageInfo) validate(b []byte, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, result ValidationStatus) { mi.init() type validationState struct { typ validationType keyType, valType validationType endGroup protowire.Number mi *MessageInfo tail []byte requiredMask uint64 } // Pre-allocate some slots to avoid repeated slice reallocation. states := make([]validationState, 0, 16) states = append(states, validationState{ typ: validationTypeMessage, mi: mi, }) if groupTag > 0 { states[0].typ = validationTypeGroup states[0].endGroup = groupTag } initialized := true start := len(b) State: for len(states) > 0 { st := &states[len(states)-1] for len(b) > 0 { // Parse the tag (field number and wire type). var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { return out, ValidationInvalid } b = b[n:] } var num protowire.Number if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) { return out, ValidationInvalid } else { num = protowire.Number(n) } wtyp := protowire.Type(tag & 7) if wtyp == protowire.EndGroupType { if st.endGroup == num { goto PopState } return out, ValidationInvalid } var vi validationInfo switch { case st.typ == validationTypeMap: switch num { case genid.MapEntry_Key_field_number: vi.typ = st.keyType case genid.MapEntry_Value_field_number: vi.typ = st.valType vi.mi = st.mi vi.requiredBit = 1 } case flags.ProtoLegacy && st.mi.isMessageSet: switch num { case messageset.FieldItem: vi.typ = validationTypeMessageSetItem } default: var f *coderFieldInfo if int(num) < len(st.mi.denseCoderFields) { f = st.mi.denseCoderFields[num] } else { f = st.mi.coderFields[num] } if f != nil { vi = f.validation if vi.typ == validationTypeMessage && vi.mi == nil { // Probable weak field. // // TODO: Consider storing the results of this lookup somewhere // rather than recomputing it on every validation. fd := st.mi.Desc.Fields().ByNumber(num) if fd == nil || !fd.IsWeak() { break } messageName := fd.Message().FullName() messageType, err := preg.GlobalTypes.FindMessageByName(messageName) switch err { case nil: vi.mi, _ = messageType.(*MessageInfo) case preg.NotFound: vi.typ = validationTypeBytes default: return out, ValidationUnknown } } break } // Possible extension field. // // TODO: We should return ValidationUnknown when: // 1. The resolver is not frozen. (More extensions may be added to it.) // 2. The resolver returns preg.NotFound. // In this case, a type added to the resolver in the future could cause // unmarshaling to begin failing. Supporting this requires some way to // determine if the resolver is frozen. xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), num) if err != nil && err != preg.NotFound { return out, ValidationUnknown } if err == nil { vi = getExtensionFieldInfo(xt).validation } } if vi.requiredBit != 0 { // Check that the field has a compatible wire type. // We only need to consider non-repeated field types, // since repeated fields (and maps) can never be required. ok := false switch vi.typ { case validationTypeVarint: ok = wtyp == protowire.VarintType case validationTypeFixed32: ok = wtyp == protowire.Fixed32Type case validationTypeFixed64: ok = wtyp == protowire.Fixed64Type case validationTypeBytes, validationTypeUTF8String, validationTypeMessage: ok = wtyp == protowire.BytesType case validationTypeGroup: ok = wtyp == protowire.StartGroupType } if ok { st.requiredMask |= vi.requiredBit } } switch wtyp { case protowire.VarintType: if len(b) >= 10 { switch { case b[0] < 0x80: b = b[1:] case b[1] < 0x80: b = b[2:] case b[2] < 0x80: b = b[3:] case b[3] < 0x80: b = b[4:] case b[4] < 0x80: b = b[5:] case b[5] < 0x80: b = b[6:] case b[6] < 0x80: b = b[7:] case b[7] < 0x80: b = b[8:] case b[8] < 0x80: b = b[9:] case b[9] < 0x80 && b[9] < 2: b = b[10:] default: return out, ValidationInvalid } } else { switch { case len(b) > 0 && b[0] < 0x80: b = b[1:] case len(b) > 1 && b[1] < 0x80: b = b[2:] case len(b) > 2 && b[2] < 0x80: b = b[3:] case len(b) > 3 && b[3] < 0x80: b = b[4:] case len(b) > 4 && b[4] < 0x80: b = b[5:] case len(b) > 5 && b[5] < 0x80: b = b[6:] case len(b) > 6 && b[6] < 0x80: b = b[7:] case len(b) > 7 && b[7] < 0x80: b = b[8:] case len(b) > 8 && b[8] < 0x80: b = b[9:] case len(b) > 9 && b[9] < 2: b = b[10:] default: return out, ValidationInvalid } } continue State case protowire.BytesType: var size uint64 if len(b) >= 1 && b[0] < 0x80 { size = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { size = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int size, n = protowire.ConsumeVarint(b) if n < 0 { return out, ValidationInvalid } b = b[n:] } if size > uint64(len(b)) { return out, ValidationInvalid } v := b[:size] b = b[size:] switch vi.typ { case validationTypeMessage: if vi.mi == nil { return out, ValidationUnknown } vi.mi.init() fallthrough case validationTypeMap: if vi.mi != nil { vi.mi.init() } states = append(states, validationState{ typ: vi.typ, keyType: vi.keyType, valType: vi.valType, mi: vi.mi, tail: b, }) b = v continue State case validationTypeRepeatedVarint: // Packed field. for len(v) > 0 { _, n := protowire.ConsumeVarint(v) if n < 0 { return out, ValidationInvalid } v = v[n:] } case validationTypeRepeatedFixed32: // Packed field. if len(v)%4 != 0 { return out, ValidationInvalid } case validationTypeRepeatedFixed64: // Packed field. if len(v)%8 != 0 { return out, ValidationInvalid } case validationTypeUTF8String: if !utf8.Valid(v) { return out, ValidationInvalid } } case protowire.Fixed32Type: if len(b) < 4 { return out, ValidationInvalid } b = b[4:] case protowire.Fixed64Type: if len(b) < 8 { return out, ValidationInvalid } b = b[8:] case protowire.StartGroupType: switch { case vi.typ == validationTypeGroup: if vi.mi == nil { return out, ValidationUnknown } vi.mi.init() states = append(states, validationState{ typ: validationTypeGroup, mi: vi.mi, endGroup: num, }) continue State case flags.ProtoLegacy && vi.typ == validationTypeMessageSetItem: typeid, v, n, err := messageset.ConsumeFieldValue(b, false) if err != nil { return out, ValidationInvalid } xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), typeid) switch { case err == preg.NotFound: b = b[n:] case err != nil: return out, ValidationUnknown default: xvi := getExtensionFieldInfo(xt).validation if xvi.mi != nil { xvi.mi.init() } states = append(states, validationState{ typ: xvi.typ, mi: xvi.mi, tail: b[n:], }) b = v continue State } default: n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, ValidationInvalid } b = b[n:] } default: return out, ValidationInvalid } } if st.endGroup != 0 { return out, ValidationInvalid } if len(b) != 0 { return out, ValidationInvalid } b = st.tail PopState: numRequiredFields := 0 switch st.typ { case validationTypeMessage, validationTypeGroup: numRequiredFields = int(st.mi.numRequiredFields) case validationTypeMap: // If this is a map field with a message value that contains // required fields, require that the value be present. if st.mi != nil && st.mi.numRequiredFields > 0 { numRequiredFields = 1 } } // If there are more than 64 required fields, this check will // always fail and we will report that the message is potentially // uninitialized. if numRequiredFields > 0 && bits.OnesCount64(st.requiredMask) != numRequiredFields { initialized = false } states = states[:len(states)-1] } out.n = start - len(b) if initialized { out.initialized = true } return out, ValidationValid } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/impl/weak.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // weakFields adds methods to the exported WeakFields type for internal use. // // The exported type is an alias to an unnamed type, so methods can't be // defined directly on it. type weakFields WeakFields func (w weakFields) get(num pref.FieldNumber) (pref.ProtoMessage, bool) { m, ok := w[int32(num)] return m, ok } func (w *weakFields) set(num pref.FieldNumber, m pref.ProtoMessage) { if *w == nil { *w = make(weakFields) } (*w)[int32(num)] = m } func (w *weakFields) clear(num pref.FieldNumber) { delete(*w, int32(num)) } func (Export) HasWeak(w WeakFields, num pref.FieldNumber) bool { _, ok := w[int32(num)] return ok } func (Export) ClearWeak(w *WeakFields, num pref.FieldNumber) { delete(*w, int32(num)) } func (Export) GetWeak(w WeakFields, num pref.FieldNumber, name pref.FullName) pref.ProtoMessage { if m, ok := w[int32(num)]; ok { return m } mt, _ := protoregistry.GlobalTypes.FindMessageByName(name) if mt == nil { panic(fmt.Sprintf("message %v for weak field is not linked in", name)) } return mt.Zero().Interface() } func (Export) SetWeak(w *WeakFields, num pref.FieldNumber, name pref.FullName, m pref.ProtoMessage) { if m != nil { mt, _ := protoregistry.GlobalTypes.FindMessageByName(name) if mt == nil { panic(fmt.Sprintf("message %v for weak field is not linked in", name)) } if mt != m.ProtoReflect().Type() { panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface())) } } if m == nil || !m.ProtoReflect().IsValid() { delete(*w, int32(num)) return } if *w == nil { *w = make(weakFields) } (*w)[int32(num)] = m } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/order/order.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package order import ( pref "google.golang.org/protobuf/reflect/protoreflect" ) // FieldOrder specifies the ordering to visit message fields. // It is a function that reports whether x is ordered before y. type FieldOrder func(x, y pref.FieldDescriptor) bool var ( // AnyFieldOrder specifies no specific field ordering. AnyFieldOrder FieldOrder = nil // LegacyFieldOrder sorts fields in the same ordering as emitted by // wire serialization in the github.com/golang/protobuf implementation. LegacyFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { ox, oy := x.ContainingOneof(), y.ContainingOneof() inOneof := func(od pref.OneofDescriptor) bool { return od != nil && !od.IsSynthetic() } // Extension fields sort before non-extension fields. if x.IsExtension() != y.IsExtension() { return x.IsExtension() && !y.IsExtension() } // Fields not within a oneof sort before those within a oneof. if inOneof(ox) != inOneof(oy) { return !inOneof(ox) && inOneof(oy) } // Fields in disjoint oneof sets are sorted by declaration index. if ox != nil && oy != nil && ox != oy { return ox.Index() < oy.Index() } // Fields sorted by field number. return x.Number() < y.Number() } // NumberFieldOrder sorts fields by their field number. NumberFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { return x.Number() < y.Number() } // IndexNameFieldOrder sorts non-extension fields before extension fields. // Non-extensions are sorted according to their declaration index. // Extensions are sorted according to their full name. IndexNameFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { // Non-extension fields sort before extension fields. if x.IsExtension() != y.IsExtension() { return !x.IsExtension() && y.IsExtension() } // Extensions sorted by fullname. if x.IsExtension() && y.IsExtension() { return x.FullName() < y.FullName() } // Non-extensions sorted by declaration index. return x.Index() < y.Index() } ) // KeyOrder specifies the ordering to visit map entries. // It is a function that reports whether x is ordered before y. type KeyOrder func(x, y pref.MapKey) bool var ( // AnyKeyOrder specifies no specific key ordering. AnyKeyOrder KeyOrder = nil // GenericKeyOrder sorts false before true, numeric keys in ascending order, // and strings in lexicographical ordering according to UTF-8 codepoints. GenericKeyOrder KeyOrder = func(x, y pref.MapKey) bool { switch x.Interface().(type) { case bool: return !x.Bool() && y.Bool() case int32, int64: return x.Int() < y.Int() case uint32, uint64: return x.Uint() < y.Uint() case string: return x.String() < y.String() default: panic("invalid map key type") } } ) ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/order/range.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package order provides ordered access to messages and maps. package order import ( "sort" "sync" pref "google.golang.org/protobuf/reflect/protoreflect" ) type messageField struct { fd pref.FieldDescriptor v pref.Value } var messageFieldPool = sync.Pool{ New: func() interface{} { return new([]messageField) }, } type ( // FieldRnger is an interface for visiting all fields in a message. // The protoreflect.Message type implements this interface. FieldRanger interface{ Range(VisitField) } // VisitField is called everytime a message field is visited. VisitField = func(pref.FieldDescriptor, pref.Value) bool ) // RangeFields iterates over the fields of fs according to the specified order. func RangeFields(fs FieldRanger, less FieldOrder, fn VisitField) { if less == nil { fs.Range(fn) return } // Obtain a pre-allocated scratch buffer. p := messageFieldPool.Get().(*[]messageField) fields := (*p)[:0] defer func() { if cap(fields) < 1024 { *p = fields messageFieldPool.Put(p) } }() // Collect all fields in the message and sort them. fs.Range(func(fd pref.FieldDescriptor, v pref.Value) bool { fields = append(fields, messageField{fd, v}) return true }) sort.Slice(fields, func(i, j int) bool { return less(fields[i].fd, fields[j].fd) }) // Visit the fields in the specified ordering. for _, f := range fields { if !fn(f.fd, f.v) { return } } } type mapEntry struct { k pref.MapKey v pref.Value } var mapEntryPool = sync.Pool{ New: func() interface{} { return new([]mapEntry) }, } type ( // EntryRanger is an interface for visiting all fields in a message. // The protoreflect.Map type implements this interface. EntryRanger interface{ Range(VisitEntry) } // VisitEntry is called everytime a map entry is visited. VisitEntry = func(pref.MapKey, pref.Value) bool ) // RangeEntries iterates over the entries of es according to the specified order. func RangeEntries(es EntryRanger, less KeyOrder, fn VisitEntry) { if less == nil { es.Range(fn) return } // Obtain a pre-allocated scratch buffer. p := mapEntryPool.Get().(*[]mapEntry) entries := (*p)[:0] defer func() { if cap(entries) < 1024 { *p = entries mapEntryPool.Put(p) } }() // Collect all entries in the map and sort them. es.Range(func(k pref.MapKey, v pref.Value) bool { entries = append(entries, mapEntry{k, v}) return true }) sort.Slice(entries, func(i, j int) bool { return less(entries[i].k, entries[j].k) }) // Visit the entries in the specified ordering. for _, e := range entries { if !fn(e.k, e.v) { return } } } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/pragma/pragma.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package pragma provides types that can be embedded into a struct to // statically enforce or prevent certain language properties. package pragma import "sync" // NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals. type NoUnkeyedLiterals struct{} // DoNotImplement can be embedded in an interface to prevent trivial // implementations of the interface. // // This is useful to prevent unauthorized implementations of an interface // so that it can be extended in the future for any protobuf language changes. type DoNotImplement interface{ ProtoInternal(DoNotImplement) } // DoNotCompare can be embedded in a struct to prevent comparability. type DoNotCompare [0]func() // DoNotCopy can be embedded in a struct to help prevent shallow copies. // This does not rely on a Go language feature, but rather a special case // within the vet checker. // // See https://golang.org/issues/8005. type DoNotCopy [0]sync.Mutex ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/set/ints.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package set provides simple set data structures for uint64s. package set import "math/bits" // int64s represents a set of integers within the range of 0..63. type int64s uint64 func (bs *int64s) Len() int { return bits.OnesCount64(uint64(*bs)) } func (bs *int64s) Has(n uint64) bool { return uint64(*bs)&(uint64(1)< 0 } func (bs *int64s) Set(n uint64) { *(*uint64)(bs) |= uint64(1) << n } func (bs *int64s) Clear(n uint64) { *(*uint64)(bs) &^= uint64(1) << n } // Ints represents a set of integers within the range of 0..math.MaxUint64. type Ints struct { lo int64s hi map[uint64]struct{} } func (bs *Ints) Len() int { return bs.lo.Len() + len(bs.hi) } func (bs *Ints) Has(n uint64) bool { if n < 64 { return bs.lo.Has(n) } _, ok := bs.hi[n] return ok } func (bs *Ints) Set(n uint64) { if n < 64 { bs.lo.Set(n) return } if bs.hi == nil { bs.hi = make(map[uint64]struct{}) } bs.hi[n] = struct{}{} } func (bs *Ints) Clear(n uint64) { if n < 64 { bs.lo.Clear(n) return } delete(bs.hi, n) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/strs/strings.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package strs provides string manipulation functionality specific to protobuf. package strs import ( "go/token" "strings" "unicode" "unicode/utf8" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/reflect/protoreflect" ) // EnforceUTF8 reports whether to enforce strict UTF-8 validation. func EnforceUTF8(fd protoreflect.FieldDescriptor) bool { if flags.ProtoLegacy { if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok { return fd.EnforceUTF8() } } return fd.Syntax() == protoreflect.Proto3 } // GoCamelCase camel-cases a protobuf name for use as a Go identifier. // // If there is an interior underscore followed by a lower case letter, // drop the underscore and convert the letter to upper case. func GoCamelCase(s string) string { // Invariant: if the next letter is lower case, it must be converted // to upper case. // That is, we process a word at a time, where words are marked by _ or // upper case letter. Digits are treated as words. var b []byte for i := 0; i < len(s); i++ { c := s[i] switch { case c == '.' && i+1 < len(s) && isASCIILower(s[i+1]): // Skip over '.' in ".{{lowercase}}". case c == '.': b = append(b, '_') // convert '.' to '_' case c == '_' && (i == 0 || s[i-1] == '.'): // Convert initial '_' to ensure we start with a capital letter. // Do the same for '_' after '.' to match historic behavior. b = append(b, 'X') // convert '_' to 'X' case c == '_' && i+1 < len(s) && isASCIILower(s[i+1]): // Skip over '_' in "_{{lowercase}}". case isASCIIDigit(c): b = append(b, c) default: // Assume we have a letter now - if not, it's a bogus identifier. // The next word is a sequence of characters that must start upper case. if isASCIILower(c) { c -= 'a' - 'A' // convert lowercase to uppercase } b = append(b, c) // Accept lower case sequence that follows. for ; i+1 < len(s) && isASCIILower(s[i+1]); i++ { b = append(b, s[i+1]) } } } return string(b) } // GoSanitized converts a string to a valid Go identifier. func GoSanitized(s string) string { // Sanitize the input to the set of valid characters, // which must be '_' or be in the Unicode L or N categories. s = strings.Map(func(r rune) rune { if unicode.IsLetter(r) || unicode.IsDigit(r) { return r } return '_' }, s) // Prepend '_' in the event of a Go keyword conflict or if // the identifier is invalid (does not start in the Unicode L category). r, _ := utf8.DecodeRuneInString(s) if token.Lookup(s).IsKeyword() || !unicode.IsLetter(r) { return "_" + s } return s } // JSONCamelCase converts a snake_case identifier to a camelCase identifier, // according to the protobuf JSON specification. func JSONCamelCase(s string) string { var b []byte var wasUnderscore bool for i := 0; i < len(s); i++ { // proto identifiers are always ASCII c := s[i] if c != '_' { if wasUnderscore && isASCIILower(c) { c -= 'a' - 'A' // convert to uppercase } b = append(b, c) } wasUnderscore = c == '_' } return string(b) } // JSONSnakeCase converts a camelCase identifier to a snake_case identifier, // according to the protobuf JSON specification. func JSONSnakeCase(s string) string { var b []byte for i := 0; i < len(s); i++ { // proto identifiers are always ASCII c := s[i] if isASCIIUpper(c) { b = append(b, '_') c += 'a' - 'A' // convert to lowercase } b = append(b, c) } return string(b) } // MapEntryName derives the name of the map entry message given the field name. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:254-276,6057 func MapEntryName(s string) string { var b []byte upperNext := true for _, c := range s { switch { case c == '_': upperNext = true case upperNext: b = append(b, byte(unicode.ToUpper(c))) upperNext = false default: b = append(b, byte(c)) } } b = append(b, "Entry"...) return string(b) } // EnumValueName derives the camel-cased enum value name. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:297-313 func EnumValueName(s string) string { var b []byte upperNext := true for _, c := range s { switch { case c == '_': upperNext = true case upperNext: b = append(b, byte(unicode.ToUpper(c))) upperNext = false default: b = append(b, byte(unicode.ToLower(c))) upperNext = false } } return string(b) } // TrimEnumPrefix trims the enum name prefix from an enum value name, // where the prefix is all lowercase without underscores. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:330-375 func TrimEnumPrefix(s, prefix string) string { s0 := s // original input for len(s) > 0 && len(prefix) > 0 { if s[0] == '_' { s = s[1:] continue } if unicode.ToLower(rune(s[0])) != rune(prefix[0]) { return s0 // no prefix match } s, prefix = s[1:], prefix[1:] } if len(prefix) > 0 { return s0 // no prefix match } s = strings.TrimLeft(s, "_") if len(s) == 0 { return s0 // avoid returning empty string } return s } func isASCIILower(c byte) bool { return 'a' <= c && c <= 'z' } func isASCIIUpper(c byte) bool { return 'A' <= c && c <= 'Z' } func isASCIIDigit(c byte) bool { return '0' <= c && c <= '9' } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/strs/strings_pure.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package strs import pref "google.golang.org/protobuf/reflect/protoreflect" func UnsafeString(b []byte) string { return string(b) } func UnsafeBytes(s string) []byte { return []byte(s) } type Builder struct{} func (*Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName { return prefix.Append(name) } func (*Builder) MakeString(b []byte) string { return string(b) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/strs/strings_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package strs import ( "unsafe" pref "google.golang.org/protobuf/reflect/protoreflect" ) type ( stringHeader struct { Data unsafe.Pointer Len int } sliceHeader struct { Data unsafe.Pointer Len int Cap int } ) // UnsafeString returns an unsafe string reference of b. // The caller must treat the input slice as immutable. // // WARNING: Use carefully. The returned result must not leak to the end user // unless the input slice is provably immutable. func UnsafeString(b []byte) (s string) { src := (*sliceHeader)(unsafe.Pointer(&b)) dst := (*stringHeader)(unsafe.Pointer(&s)) dst.Data = src.Data dst.Len = src.Len return s } // UnsafeBytes returns an unsafe bytes slice reference of s. // The caller must treat returned slice as immutable. // // WARNING: Use carefully. The returned result must not leak to the end user. func UnsafeBytes(s string) (b []byte) { src := (*stringHeader)(unsafe.Pointer(&s)) dst := (*sliceHeader)(unsafe.Pointer(&b)) dst.Data = src.Data dst.Len = src.Len dst.Cap = src.Len return b } // Builder builds a set of strings with shared lifetime. // This differs from strings.Builder, which is for building a single string. type Builder struct { buf []byte } // AppendFullName is equivalent to protoreflect.FullName.Append, // but optimized for large batches where each name has a shared lifetime. func (sb *Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName { n := len(prefix) + len(".") + len(name) if len(prefix) == 0 { n -= len(".") } sb.grow(n) sb.buf = append(sb.buf, prefix...) sb.buf = append(sb.buf, '.') sb.buf = append(sb.buf, name...) return pref.FullName(sb.last(n)) } // MakeString is equivalent to string(b), but optimized for large batches // with a shared lifetime. func (sb *Builder) MakeString(b []byte) string { sb.grow(len(b)) sb.buf = append(sb.buf, b...) return sb.last(len(b)) } func (sb *Builder) grow(n int) { if cap(sb.buf)-len(sb.buf) >= n { return } // Unlike strings.Builder, we do not need to copy over the contents // of the old buffer since our builder provides no API for // retrieving previously created strings. sb.buf = make([]byte, 2*(cap(sb.buf)+n)) } func (sb *Builder) last(n int) string { return UnsafeString(sb.buf[len(sb.buf)-n:]) } ================================================ FILE: _tools/src/google.golang.org/protobuf/internal/version/version.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package version records versioning information about this module. package version import ( "fmt" "strings" ) // These constants determine the current version of this module. // // // For our release process, we enforce the following rules: // * Tagged releases use a tag that is identical to String. // * Tagged releases never reference a commit where the String // contains "devel". // * The set of all commits in this repository where String // does not contain "devel" must have a unique String. // // // Steps for tagging a new release: // 1. Create a new CL. // // 2. Update Minor, Patch, and/or PreRelease as necessary. // PreRelease must not contain the string "devel". // // 3. Since the last released minor version, have there been any changes to // generator that relies on new functionality in the runtime? // If yes, then increment RequiredGenerated. // // 4. Since the last released minor version, have there been any changes to // the runtime that removes support for old .pb.go source code? // If yes, then increment SupportMinimum. // // 5. Send out the CL for review and submit it. // Note that the next CL in step 8 must be submitted after this CL // without any other CLs in-between. // // 6. Tag a new version, where the tag is is the current String. // // 7. Write release notes for all notable changes // between this release and the last release. // // 8. Create a new CL. // // 9. Update PreRelease to include the string "devel". // For example: "" -> "devel" or "rc.1" -> "rc.1.devel" // // 10. Send out the CL for review and submit it. const ( Major = 1 Minor = 26 Patch = 0 PreRelease = "devel" ) // String formats the version string for this module in semver format. // // Examples: // v1.20.1 // v1.21.0-rc.1 func String() string { v := fmt.Sprintf("v%d.%d.%d", Major, Minor, Patch) if PreRelease != "" { v += "-" + PreRelease // TODO: Add metadata about the commit or build hash. // See https://golang.org/issue/29814 // See https://golang.org/issue/33533 var metadata string if strings.Contains(PreRelease, "devel") && metadata != "" { v += "+" + metadata } } return v } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/checkinit.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // CheckInitialized returns an error if any required fields in m are not set. func CheckInitialized(m Message) error { // Treat a nil message interface as an "untyped" empty message, // which we assume to have no required fields. if m == nil { return nil } return checkInitialized(m.ProtoReflect()) } // CheckInitialized returns an error if any required fields in m are not set. func checkInitialized(m protoreflect.Message) error { if methods := protoMethods(m); methods != nil && methods.CheckInitialized != nil { _, err := methods.CheckInitialized(protoiface.CheckInitializedInput{ Message: m, }) return err } return checkInitializedSlow(m) } func checkInitializedSlow(m protoreflect.Message) error { md := m.Descriptor() fds := md.Fields() for i, nums := 0, md.RequiredNumbers(); i < nums.Len(); i++ { fd := fds.ByNumber(nums.Get(i)) if !m.Has(fd) { return errors.RequiredNotSet(string(fd.FullName())) } } var err error m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { switch { case fd.IsList(): if fd.Message() == nil { return true } for i, list := 0, v.List(); i < list.Len() && err == nil; i++ { err = checkInitialized(list.Get(i).Message()) } case fd.IsMap(): if fd.MapValue().Message() == nil { return true } v.Map().Range(func(key protoreflect.MapKey, v protoreflect.Value) bool { err = checkInitialized(v.Message()) return err == nil }) default: if fd.Message() == nil { return true } err = checkInitialized(v.Message()) } return err == nil }) return err } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/runtime/protoiface" ) // UnmarshalOptions configures the unmarshaler. // // Example usage: // err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m) type UnmarshalOptions struct { pragma.NoUnkeyedLiterals // Merge merges the input into the destination message. // The default behavior is to always reset the message before unmarshaling, // unless Merge is specified. Merge bool // AllowPartial accepts input for messages that will result in missing // required fields. If AllowPartial is false (the default), Unmarshal will // return an error if there are any missing required fields. AllowPartial bool // If DiscardUnknown is set, unknown fields are ignored. DiscardUnknown bool // Resolver is used for looking up types when unmarshaling extension fields. // If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } // Unmarshal parses the wire-format message in b and places the result in m. // The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m Message) error { _, err := UnmarshalOptions{}.unmarshal(b, m.ProtoReflect()) return err } // Unmarshal parses the wire-format message in b and places the result in m. // The provided message must be mutable (e.g., a non-nil pointer to a message). func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error { _, err := o.unmarshal(b, m.ProtoReflect()) return err } // UnmarshalState parses a wire-format message and places the result in m. // // This method permits fine-grained control over the unmarshaler. // Most users should use Unmarshal instead. func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { return o.unmarshal(in.Buf, in.Message) } // unmarshal is a centralized function that all unmarshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m protoreflect.Message) (out protoiface.UnmarshalOutput, err error) { if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } if !o.Merge { Reset(m.Interface()) } allowPartial := o.AllowPartial o.Merge = true o.AllowPartial = true methods := protoMethods(m) if methods != nil && methods.Unmarshal != nil && !(o.DiscardUnknown && methods.Flags&protoiface.SupportUnmarshalDiscardUnknown == 0) { in := protoiface.UnmarshalInput{ Message: m, Buf: b, Resolver: o.Resolver, } if o.DiscardUnknown { in.Flags |= protoiface.UnmarshalDiscardUnknown } out, err = methods.Unmarshal(in) } else { err = o.unmarshalMessageSlow(b, m) } if err != nil { return out, err } if allowPartial || (out.Flags&protoiface.UnmarshalInitialized != 0) { return out, nil } return out, checkInitialized(m) } func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error { _, err := o.unmarshal(b, m) return err } func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error { md := m.Descriptor() if messageset.IsMessageSet(md) { return o.unmarshalMessageSet(b, m) } fields := md.Fields() for len(b) > 0 { // Parse the tag (field number and wire type). num, wtyp, tagLen := protowire.ConsumeTag(b) if tagLen < 0 { return errDecode } if num > protowire.MaxValidNumber { return errDecode } // Find the field descriptor for this field number. fd := fields.ByNumber(num) if fd == nil && md.ExtensionRanges().Has(num) { extType, err := o.Resolver.FindExtensionByNumber(md.FullName(), num) if err != nil && err != protoregistry.NotFound { return errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err) } if extType != nil { fd = extType.TypeDescriptor() } } var err error if fd == nil { err = errUnknown } else if flags.ProtoLegacy { if fd.IsWeak() && fd.Message().IsPlaceholder() { err = errUnknown // weak referent is not linked in } } // Parse the field value. var valLen int switch { case err != nil: case fd.IsList(): valLen, err = o.unmarshalList(b[tagLen:], wtyp, m.Mutable(fd).List(), fd) case fd.IsMap(): valLen, err = o.unmarshalMap(b[tagLen:], wtyp, m.Mutable(fd).Map(), fd) default: valLen, err = o.unmarshalSingular(b[tagLen:], wtyp, m, fd) } if err != nil { if err != errUnknown { return err } valLen = protowire.ConsumeFieldValue(num, wtyp, b[tagLen:]) if valLen < 0 { return errDecode } if !o.DiscardUnknown { m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...)) } } b = b[tagLen+valLen:] } return nil } func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp protowire.Type, m protoreflect.Message, fd protoreflect.FieldDescriptor) (n int, err error) { v, n, err := o.unmarshalScalar(b, wtyp, fd) if err != nil { return 0, err } switch fd.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: m2 := m.Mutable(fd).Message() if err := o.unmarshalMessage(v.Bytes(), m2); err != nil { return n, err } default: // Non-message scalars replace the previous value. m.Set(fd, v) } return n, nil } func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) { if wtyp != protowire.BytesType { return 0, errUnknown } b, n = protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } var ( keyField = fd.MapKey() valField = fd.MapValue() key protoreflect.Value val protoreflect.Value haveKey bool haveVal bool ) switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: val = mapv.NewValue() } // Map entries are represented as a two-element message with fields // containing the key and value. for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return 0, errDecode } if num > protowire.MaxValidNumber { return 0, errDecode } b = b[n:] err = errUnknown switch num { case genid.MapEntry_Key_field_number: key, n, err = o.unmarshalScalar(b, wtyp, keyField) if err != nil { break } haveKey = true case genid.MapEntry_Value_field_number: var v protoreflect.Value v, n, err = o.unmarshalScalar(b, wtyp, valField) if err != nil { break } switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil { return 0, err } default: val = v } haveVal = true } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return 0, errDecode } } else if err != nil { return 0, err } b = b[n:] } // Every map entry should have entries for key and value, but this is not strictly required. if !haveKey { key = keyField.Default() } if !haveVal { switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: default: val = valField.Default() } } mapv.Set(key.MapKey(), val) return n, nil } // errUnknown is used internally to indicate fields which should be added // to the unknown field set of a message. It is never returned from an exported // function. var errUnknown = errors.New("BUG: internal error (unknown)") var errDecode = errors.New("cannot parse invalid wire-format data") ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/decode_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" ) // unmarshalScalar decodes a value of the given kind. // // Message values are decoded into a []byte which aliases the input data. func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd protoreflect.FieldDescriptor) (val protoreflect.Value, n int, err error) { switch fd.Kind() { case protoreflect.BoolKind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBool(protowire.DecodeBool(v)), n, nil case protoreflect.EnumKind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), n, nil case protoreflect.Int32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(v)), n, nil case protoreflect.Sint32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), n, nil case protoreflect.Uint32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint32(uint32(v)), n, nil case protoreflect.Int64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(int64(v)), n, nil case protoreflect.Sint64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), n, nil case protoreflect.Uint64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint64(v), n, nil case protoreflect.Sfixed32Kind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(v)), n, nil case protoreflect.Fixed32Kind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint32(uint32(v)), n, nil case protoreflect.FloatKind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), n, nil case protoreflect.Sfixed64Kind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(int64(v)), n, nil case protoreflect.Fixed64Kind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint64(v), n, nil case protoreflect.DoubleKind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfFloat64(math.Float64frombits(v)), n, nil case protoreflect.StringKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } if strs.EnforceUTF8(fd) && !utf8.Valid(v) { return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName())) } return protoreflect.ValueOfString(string(v)), n, nil case protoreflect.BytesKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), n, nil case protoreflect.MessageKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(v), n, nil case protoreflect.GroupKind: if wtyp != protowire.StartGroupType { return val, 0, errUnknown } v, n := protowire.ConsumeGroup(fd.Number(), b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(v), n, nil default: return val, 0, errUnknown } } func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list protoreflect.List, fd protoreflect.FieldDescriptor) (n int, err error) { switch fd.Kind() { case protoreflect.BoolKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) return n, nil case protoreflect.EnumKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) return n, nil case protoreflect.Int32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) return n, nil case protoreflect.Sint32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) return n, nil case protoreflect.Uint32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint32(uint32(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) return n, nil case protoreflect.Int64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(int64(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) return n, nil case protoreflect.Sint64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) return n, nil case protoreflect.Uint64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint64(v)) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint64(v)) return n, nil case protoreflect.Sfixed32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(v))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) return n, nil case protoreflect.Fixed32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint32(uint32(v))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) return n, nil case protoreflect.FloatKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) return n, nil case protoreflect.Sfixed64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(int64(v))) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) return n, nil case protoreflect.Fixed64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint64(v)) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint64(v)) return n, nil case protoreflect.DoubleKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) return n, nil case protoreflect.StringKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } if strs.EnforceUTF8(fd) && !utf8.Valid(v) { return 0, errors.InvalidUTF8(string(fd.FullName())) } list.Append(protoreflect.ValueOfString(string(v))) return n, nil case protoreflect.BytesKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...))) return n, nil case protoreflect.MessageKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } m := list.NewElement() if err := o.unmarshalMessage(v, m.Message()); err != nil { return 0, err } list.Append(m) return n, nil case protoreflect.GroupKind: if wtyp != protowire.StartGroupType { return 0, errUnknown } v, n := protowire.ConsumeGroup(fd.Number(), b) if n < 0 { return 0, errDecode } m := list.NewElement() if err := o.unmarshalMessage(v, m.Message()); err != nil { return 0, err } list.Append(m) return n, nil default: return 0, errUnknown } } // We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices. var emptyBuf [0]byte ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package proto provides functions operating on protocol buffer messages. // // For documentation on protocol buffers in general, see: // // https://developers.google.com/protocol-buffers // // For a tutorial on using protocol buffers with Go, see: // // https://developers.google.com/protocol-buffers/docs/gotutorial // // For a guide to generated Go protocol buffer code, see: // // https://developers.google.com/protocol-buffers/docs/reference/go-generated // // // Binary serialization // // This package contains functions to convert to and from the wire format, // an efficient binary serialization of protocol buffers. // // • Size reports the size of a message in the wire format. // // • Marshal converts a message to the wire format. // The MarshalOptions type provides more control over wire marshaling. // // • Unmarshal converts a message from the wire format. // The UnmarshalOptions type provides more control over wire unmarshaling. // // // Basic message operations // // • Clone makes a deep copy of a message. // // • Merge merges the content of a message into another. // // • Equal compares two messages. For more control over comparisons // and detailed reporting of differences, see package // "google.golang.org/protobuf/testing/protocmp". // // • Reset clears the content of a message. // // • CheckInitialized reports whether all required fields in a message are set. // // // Optional scalar constructors // // The API for some generated messages represents optional scalar fields // as pointers to a value. For example, an optional string field has the // Go type *string. // // • Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, and String // take a value and return a pointer to a new instance of it, // to simplify construction of optional field values. // // Generated enum types usually have an Enum method which performs the // same operation. // // Optional scalar fields are only supported in proto2. // // // Extension accessors // // • HasExtension, GetExtension, SetExtension, and ClearExtension // access extension field values in a protocol buffer message. // // Extension fields are only supported in proto2. // // // Related packages // // • Package "google.golang.org/protobuf/encoding/protojson" converts messages to // and from JSON. // // • Package "google.golang.org/protobuf/encoding/prototext" converts messages to // and from the text format. // // • Package "google.golang.org/protobuf/reflect/protoreflect" provides a // reflection interface for protocol buffer data types. // // • Package "google.golang.org/protobuf/testing/protocmp" provides features // to compare protocol buffer messages with the "github.com/google/go-cmp/cmp" // package. // // • Package "google.golang.org/protobuf/types/dynamicpb" provides a dynamic // message type, suitable for working with messages where the protocol buffer // type is only known at runtime. // // This module contains additional packages for more specialized use cases. // Consult the individual package documentation for details. package proto ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/encode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // MarshalOptions configures the marshaler. // // Example usage: // b, err := MarshalOptions{Deterministic: true}.Marshal(m) type MarshalOptions struct { pragma.NoUnkeyedLiterals // AllowPartial allows messages that have missing required fields to marshal // without returning an error. If AllowPartial is false (the default), // Marshal will return an error if there are any missing required fields. AllowPartial bool // Deterministic controls whether the same message will always be // serialized to the same bytes within the same binary. // // Setting this option guarantees that repeated serialization of // the same message will return the same bytes, and that different // processes of the same binary (which may be executing on different // machines) will serialize equal messages to the same bytes. // It has no effect on the resulting size of the encoded message compared // to a non-deterministic marshal. // // Note that the deterministic serialization is NOT canonical across // languages. It is not guaranteed to remain stable over time. It is // unstable across different builds with schema changes due to unknown // fields. Users who need canonical serialization (e.g., persistent // storage in a canonical form, fingerprinting, etc.) must define // their own canonicalization specification and implement their own // serializer rather than relying on this API. // // If deterministic serialization is requested, map entries will be // sorted by keys in lexographical order. This is an implementation // detail and subject to change. Deterministic bool // UseCachedSize indicates that the result of a previous Size call // may be reused. // // Setting this option asserts that: // // 1. Size has previously been called on this message with identical // options (except for UseCachedSize itself). // // 2. The message and all its submessages have not changed in any // way since the Size call. // // If either of these invariants is violated, // the results are undefined and may include panics or corrupted output. // // Implementations MAY take this option into account to provide // better performance, but there is no guarantee that they will do so. // There is absolutely no guarantee that Size followed by Marshal with // UseCachedSize set will perform equivalently to Marshal alone. UseCachedSize bool } // Marshal returns the wire-format encoding of m. func Marshal(m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to output. if m == nil { return nil, nil } out, err := MarshalOptions{}.marshal(nil, m.ProtoReflect()) if len(out.Buf) == 0 && err == nil { out.Buf = emptyBytesForMessage(m) } return out.Buf, err } // Marshal returns the wire-format encoding of m. func (o MarshalOptions) Marshal(m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to output. if m == nil { return nil, nil } out, err := o.marshal(nil, m.ProtoReflect()) if len(out.Buf) == 0 && err == nil { out.Buf = emptyBytesForMessage(m) } return out.Buf, err } // emptyBytesForMessage returns a nil buffer if and only if m is invalid, // otherwise it returns a non-nil empty buffer. // // This is to assist the edge-case where user-code does the following: // m1.OptionalBytes, _ = proto.Marshal(m2) // where they expect the proto2 "optional_bytes" field to be populated // if any only if m2 is a valid message. func emptyBytesForMessage(m Message) []byte { if m == nil || !m.ProtoReflect().IsValid() { return nil } return emptyBuf[:] } // MarshalAppend appends the wire-format encoding of m to b, // returning the result. func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to append. if m == nil { return b, nil } out, err := o.marshal(b, m.ProtoReflect()) return out.Buf, err } // MarshalState returns the wire-format encoding of a message. // // This method permits fine-grained control over the marshaler. // Most users should use Marshal instead. func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) { return o.marshal(in.Buf, in.Message) } // marshal is a centralized function that all marshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for marshal that do not go through this. func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoiface.MarshalOutput, err error) { allowPartial := o.AllowPartial o.AllowPartial = true if methods := protoMethods(m); methods != nil && methods.Marshal != nil && !(o.Deterministic && methods.Flags&protoiface.SupportMarshalDeterministic == 0) { in := protoiface.MarshalInput{ Message: m, Buf: b, } if o.Deterministic { in.Flags |= protoiface.MarshalDeterministic } if o.UseCachedSize { in.Flags |= protoiface.MarshalUseCachedSize } if methods.Size != nil { sout := methods.Size(protoiface.SizeInput{ Message: m, Flags: in.Flags, }) if cap(b) < len(b)+sout.Size { in.Buf = make([]byte, len(b), growcap(cap(b), len(b)+sout.Size)) copy(in.Buf, b) } in.Flags |= protoiface.MarshalUseCachedSize } out, err = methods.Marshal(in) } else { out.Buf, err = o.marshalMessageSlow(b, m) } if err != nil { return out, err } if allowPartial { return out, nil } return out, checkInitialized(m) } func (o MarshalOptions) marshalMessage(b []byte, m protoreflect.Message) ([]byte, error) { out, err := o.marshal(b, m) return out.Buf, err } // growcap scales up the capacity of a slice. // // Given a slice with a current capacity of oldcap and a desired // capacity of wantcap, growcap returns a new capacity >= wantcap. // // The algorithm is mostly identical to the one used by append as of Go 1.14. func growcap(oldcap, wantcap int) (newcap int) { if wantcap > oldcap*2 { newcap = wantcap } else if oldcap < 1024 { // The Go 1.14 runtime takes this case when len(s) < 1024, // not when cap(s) < 1024. The difference doesn't seem // significant here. newcap = oldcap * 2 } else { newcap = oldcap for 0 < newcap && newcap < wantcap { newcap += newcap / 4 } if newcap <= 0 { newcap = wantcap } } return newcap } func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]byte, error) { if messageset.IsMessageSet(m.Descriptor()) { return o.marshalMessageSet(b, m) } fieldOrder := order.AnyFieldOrder if o.Deterministic { // TODO: This should use a more natural ordering like NumberFieldOrder, // but doing so breaks golden tests that make invalid assumption about // output stability of this implementation. fieldOrder = order.LegacyFieldOrder } var err error order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { b, err = o.marshalField(b, fd, v) return err == nil }) if err != nil { return b, err } b = append(b, m.GetUnknown()...) return b, nil } func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { switch { case fd.IsList(): return o.marshalList(b, fd, value.List()) case fd.IsMap(): return o.marshalMap(b, fd, value.Map()) default: b = protowire.AppendTag(b, fd.Number(), wireTypes[fd.Kind()]) return o.marshalSingular(b, fd, value) } } func (o MarshalOptions) marshalList(b []byte, fd protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) { if fd.IsPacked() && list.Len() > 0 { b = protowire.AppendTag(b, fd.Number(), protowire.BytesType) b, pos := appendSpeculativeLength(b) for i, llen := 0, list.Len(); i < llen; i++ { var err error b, err = o.marshalSingular(b, fd, list.Get(i)) if err != nil { return b, err } } b = finishSpeculativeLength(b, pos) return b, nil } kind := fd.Kind() for i, llen := 0, list.Len(); i < llen; i++ { var err error b = protowire.AppendTag(b, fd.Number(), wireTypes[kind]) b, err = o.marshalSingular(b, fd, list.Get(i)) if err != nil { return b, err } } return b, nil } func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) { keyf := fd.MapKey() valf := fd.MapValue() keyOrder := order.AnyKeyOrder if o.Deterministic { keyOrder = order.GenericKeyOrder } var err error order.RangeEntries(mapv, keyOrder, func(key protoreflect.MapKey, value protoreflect.Value) bool { b = protowire.AppendTag(b, fd.Number(), protowire.BytesType) var pos int b, pos = appendSpeculativeLength(b) b, err = o.marshalField(b, keyf, key.Value()) if err != nil { return false } b, err = o.marshalField(b, valf, value) if err != nil { return false } b = finishSpeculativeLength(b, pos) return true }) return b, err } // When encoding length-prefixed fields, we speculatively set aside some number of bytes // for the length, encode the data, and then encode the length (shifting the data if necessary // to make room). const speculativeLength = 1 func appendSpeculativeLength(b []byte) ([]byte, int) { pos := len(b) b = append(b, "\x00\x00\x00\x00"[:speculativeLength]...) return b, pos } func finishSpeculativeLength(b []byte, pos int) []byte { mlen := len(b) - pos - speculativeLength msiz := protowire.SizeVarint(uint64(mlen)) if msiz != speculativeLength { for i := 0; i < msiz-speculativeLength; i++ { b = append(b, 0) } copy(b[pos+msiz:], b[pos+speculativeLength:]) b = b[:pos+msiz+mlen] } protowire.AppendVarint(b[:pos], uint64(mlen)) return b } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/encode_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" ) var wireTypes = map[protoreflect.Kind]protowire.Type{ protoreflect.BoolKind: protowire.VarintType, protoreflect.EnumKind: protowire.VarintType, protoreflect.Int32Kind: protowire.VarintType, protoreflect.Sint32Kind: protowire.VarintType, protoreflect.Uint32Kind: protowire.VarintType, protoreflect.Int64Kind: protowire.VarintType, protoreflect.Sint64Kind: protowire.VarintType, protoreflect.Uint64Kind: protowire.VarintType, protoreflect.Sfixed32Kind: protowire.Fixed32Type, protoreflect.Fixed32Kind: protowire.Fixed32Type, protoreflect.FloatKind: protowire.Fixed32Type, protoreflect.Sfixed64Kind: protowire.Fixed64Type, protoreflect.Fixed64Kind: protowire.Fixed64Type, protoreflect.DoubleKind: protowire.Fixed64Type, protoreflect.StringKind: protowire.BytesType, protoreflect.BytesKind: protowire.BytesType, protoreflect.MessageKind: protowire.BytesType, protoreflect.GroupKind: protowire.StartGroupType, } func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescriptor, v protoreflect.Value) ([]byte, error) { switch fd.Kind() { case protoreflect.BoolKind: b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) case protoreflect.EnumKind: b = protowire.AppendVarint(b, uint64(v.Enum())) case protoreflect.Int32Kind: b = protowire.AppendVarint(b, uint64(int32(v.Int()))) case protoreflect.Sint32Kind: b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) case protoreflect.Uint32Kind: b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) case protoreflect.Int64Kind: b = protowire.AppendVarint(b, uint64(v.Int())) case protoreflect.Sint64Kind: b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) case protoreflect.Uint64Kind: b = protowire.AppendVarint(b, v.Uint()) case protoreflect.Sfixed32Kind: b = protowire.AppendFixed32(b, uint32(v.Int())) case protoreflect.Fixed32Kind: b = protowire.AppendFixed32(b, uint32(v.Uint())) case protoreflect.FloatKind: b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) case protoreflect.Sfixed64Kind: b = protowire.AppendFixed64(b, uint64(v.Int())) case protoreflect.Fixed64Kind: b = protowire.AppendFixed64(b, v.Uint()) case protoreflect.DoubleKind: b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) case protoreflect.StringKind: if strs.EnforceUTF8(fd) && !utf8.ValidString(v.String()) { return b, errors.InvalidUTF8(string(fd.FullName())) } b = protowire.AppendString(b, v.String()) case protoreflect.BytesKind: b = protowire.AppendBytes(b, v.Bytes()) case protoreflect.MessageKind: var pos int var err error b, pos = appendSpeculativeLength(b) b, err = o.marshalMessage(b, v.Message()) if err != nil { return b, err } b = finishSpeculativeLength(b, pos) case protoreflect.GroupKind: var err error b, err = o.marshalMessage(b, v.Message()) if err != nil { return b, err } b = protowire.AppendVarint(b, protowire.EncodeTag(fd.Number(), protowire.EndGroupType)) default: return b, errors.New("invalid kind %v", fd.Kind()) } return b, nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/equal.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "bytes" "math" "reflect" "google.golang.org/protobuf/encoding/protowire" pref "google.golang.org/protobuf/reflect/protoreflect" ) // Equal reports whether two messages are equal. // If two messages marshal to the same bytes under deterministic serialization, // then Equal is guaranteed to report true. // // Two messages are equal if they belong to the same message descriptor, // have the same set of populated known and extension field values, // and the same set of unknown fields values. If either of the top-level // messages are invalid, then Equal reports true only if both are invalid. // // Scalar values are compared with the equivalent of the == operator in Go, // except bytes values which are compared using bytes.Equal and // floating point values which specially treat NaNs as equal. // Message values are compared by recursively calling Equal. // Lists are equal if each element value is also equal. // Maps are equal if they have the same set of keys, where the pair of values // for each key is also equal. func Equal(x, y Message) bool { if x == nil || y == nil { return x == nil && y == nil } mx := x.ProtoReflect() my := y.ProtoReflect() if mx.IsValid() != my.IsValid() { return false } return equalMessage(mx, my) } // equalMessage compares two messages. func equalMessage(mx, my pref.Message) bool { if mx.Descriptor() != my.Descriptor() { return false } nx := 0 equal := true mx.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { nx++ vy := my.Get(fd) equal = my.Has(fd) && equalField(fd, vx, vy) return equal }) if !equal { return false } ny := 0 my.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { ny++ return true }) if nx != ny { return false } return equalUnknown(mx.GetUnknown(), my.GetUnknown()) } // equalField compares two fields. func equalField(fd pref.FieldDescriptor, x, y pref.Value) bool { switch { case fd.IsList(): return equalList(fd, x.List(), y.List()) case fd.IsMap(): return equalMap(fd, x.Map(), y.Map()) default: return equalValue(fd, x, y) } } // equalMap compares two maps. func equalMap(fd pref.FieldDescriptor, x, y pref.Map) bool { if x.Len() != y.Len() { return false } equal := true x.Range(func(k pref.MapKey, vx pref.Value) bool { vy := y.Get(k) equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) return equal }) return equal } // equalList compares two lists. func equalList(fd pref.FieldDescriptor, x, y pref.List) bool { if x.Len() != y.Len() { return false } for i := x.Len() - 1; i >= 0; i-- { if !equalValue(fd, x.Get(i), y.Get(i)) { return false } } return true } // equalValue compares two singular values. func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool { switch fd.Kind() { case pref.BoolKind: return x.Bool() == y.Bool() case pref.EnumKind: return x.Enum() == y.Enum() case pref.Int32Kind, pref.Sint32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: return x.Int() == y.Int() case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: return x.Uint() == y.Uint() case pref.FloatKind, pref.DoubleKind: fx := x.Float() fy := y.Float() if math.IsNaN(fx) || math.IsNaN(fy) { return math.IsNaN(fx) && math.IsNaN(fy) } return fx == fy case pref.StringKind: return x.String() == y.String() case pref.BytesKind: return bytes.Equal(x.Bytes(), y.Bytes()) case pref.MessageKind, pref.GroupKind: return equalMessage(x.Message(), y.Message()) default: return x.Interface() == y.Interface() } } // equalUnknown compares unknown fields by direct comparison on the raw bytes // of each individual field number. func equalUnknown(x, y pref.RawFields) bool { if len(x) != len(y) { return false } if bytes.Equal([]byte(x), []byte(y)) { return true } mx := make(map[pref.FieldNumber]pref.RawFields) my := make(map[pref.FieldNumber]pref.RawFields) for len(x) > 0 { fnum, _, n := protowire.ConsumeField(x) mx[fnum] = append(mx[fnum], x[:n]...) x = x[n:] } for len(y) > 0 { fnum, _, n := protowire.ConsumeField(y) my[fnum] = append(my[fnum], y[:n]...) y = y[n:] } return reflect.DeepEqual(mx, my) } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/reflect/protoreflect" ) // HasExtension reports whether an extension field is populated. // It returns false if m is invalid or if xt does not extend m. func HasExtension(m Message, xt protoreflect.ExtensionType) bool { // Treat nil message interface as an empty message; no populated fields. if m == nil { return false } // As a special-case, we reports invalid or mismatching descriptors // as always not being populated (since they aren't). if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() { return false } return m.ProtoReflect().Has(xt.TypeDescriptor()) } // ClearExtension clears an extension field such that subsequent // HasExtension calls return false. // It panics if m is invalid or if xt does not extend m. func ClearExtension(m Message, xt protoreflect.ExtensionType) { m.ProtoReflect().Clear(xt.TypeDescriptor()) } // GetExtension retrieves the value for an extension field. // If the field is unpopulated, it returns the default value for // scalars and an immutable, empty value for lists or messages. // It panics if xt does not extend m. func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} { // Treat nil message interface as an empty message; return the default. if m == nil { return xt.InterfaceOf(xt.Zero()) } return xt.InterfaceOf(m.ProtoReflect().Get(xt.TypeDescriptor())) } // SetExtension stores the value of an extension field. // It panics if m is invalid, xt does not extend m, or if type of v // is invalid for the specified extension field. func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) { xd := xt.TypeDescriptor() pv := xt.ValueOf(v) // Specially treat an invalid list, map, or message as clear. isValid := true switch { case xd.IsList(): isValid = pv.List().IsValid() case xd.IsMap(): isValid = pv.Map().IsValid() case xd.Message() != nil: isValid = pv.Message().IsValid() } if !isValid { m.ProtoReflect().Clear(xd) return } m.ProtoReflect().Set(xd, pv) } // RangeExtensions iterates over every populated extension field in m in an // undefined order, calling f for each extension type and value encountered. // It returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current extension field. func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) { // Treat nil message interface as an empty message; nothing to range over. if m == nil { return } m.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { if fd.IsExtension() { xt := fd.(protoreflect.ExtensionTypeDescriptor).Type() vi := xt.InterfaceOf(v) return f(xt, vi) } return true }) } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/merge.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // Merge merges src into dst, which must be a message with the same descriptor. // // Populated scalar fields in src are copied to dst, while populated // singular messages in src are merged into dst by recursively calling Merge. // The elements of every list field in src is appended to the corresponded // list fields in dst. The entries of every map field in src is copied into // the corresponding map field in dst, possibly replacing existing entries. // The unknown fields of src are appended to the unknown fields of dst. // // It is semantically equivalent to unmarshaling the encoded form of src // into dst with the UnmarshalOptions.Merge option specified. func Merge(dst, src Message) { // TODO: Should nil src be treated as semantically equivalent to a // untyped, read-only, empty message? What about a nil dst? dstMsg, srcMsg := dst.ProtoReflect(), src.ProtoReflect() if dstMsg.Descriptor() != srcMsg.Descriptor() { if got, want := dstMsg.Descriptor().FullName(), srcMsg.Descriptor().FullName(); got != want { panic(fmt.Sprintf("descriptor mismatch: %v != %v", got, want)) } panic("descriptor mismatch") } mergeOptions{}.mergeMessage(dstMsg, srcMsg) } // Clone returns a deep copy of m. // If the top-level message is invalid, it returns an invalid message as well. func Clone(m Message) Message { // NOTE: Most usages of Clone assume the following properties: // t := reflect.TypeOf(m) // t == reflect.TypeOf(m.ProtoReflect().New().Interface()) // t == reflect.TypeOf(m.ProtoReflect().Type().Zero().Interface()) // // Embedding protobuf messages breaks this since the parent type will have // a forwarded ProtoReflect method, but the Interface method will return // the underlying embedded message type. if m == nil { return nil } src := m.ProtoReflect() if !src.IsValid() { return src.Type().Zero().Interface() } dst := src.New() mergeOptions{}.mergeMessage(dst, src) return dst.Interface() } // mergeOptions provides a namespace for merge functions, and can be // exported in the future if we add user-visible merge options. type mergeOptions struct{} func (o mergeOptions) mergeMessage(dst, src protoreflect.Message) { methods := protoMethods(dst) if methods != nil && methods.Merge != nil { in := protoiface.MergeInput{ Destination: dst, Source: src, } out := methods.Merge(in) if out.Flags&protoiface.MergeComplete != 0 { return } } if !dst.IsValid() { panic(fmt.Sprintf("cannot merge into invalid %v message", dst.Descriptor().FullName())) } src.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { switch { case fd.IsList(): o.mergeList(dst.Mutable(fd).List(), v.List(), fd) case fd.IsMap(): o.mergeMap(dst.Mutable(fd).Map(), v.Map(), fd.MapValue()) case fd.Message() != nil: o.mergeMessage(dst.Mutable(fd).Message(), v.Message()) case fd.Kind() == protoreflect.BytesKind: dst.Set(fd, o.cloneBytes(v)) default: dst.Set(fd, v) } return true }) if len(src.GetUnknown()) > 0 { dst.SetUnknown(append(dst.GetUnknown(), src.GetUnknown()...)) } } func (o mergeOptions) mergeList(dst, src protoreflect.List, fd protoreflect.FieldDescriptor) { // Merge semantics appends to the end of the existing list. for i, n := 0, src.Len(); i < n; i++ { switch v := src.Get(i); { case fd.Message() != nil: dstv := dst.NewElement() o.mergeMessage(dstv.Message(), v.Message()) dst.Append(dstv) case fd.Kind() == protoreflect.BytesKind: dst.Append(o.cloneBytes(v)) default: dst.Append(v) } } } func (o mergeOptions) mergeMap(dst, src protoreflect.Map, fd protoreflect.FieldDescriptor) { // Merge semantics replaces, rather than merges into existing entries. src.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { switch { case fd.Message() != nil: dstv := dst.NewValue() o.mergeMessage(dstv.Message(), v.Message()) dst.Set(k, dstv) case fd.Kind() == protoreflect.BytesKind: dst.Set(k, o.cloneBytes(v)) default: dst.Set(k, v) } return true }) } func (o mergeOptions) cloneBytes(v protoreflect.Value) protoreflect.Value { return protoreflect.ValueOfBytes(append([]byte{}, v.Bytes()...)) } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) func (o MarshalOptions) sizeMessageSet(m protoreflect.Message) (size int) { m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { size += messageset.SizeField(fd.Number()) size += protowire.SizeTag(messageset.FieldMessage) size += protowire.SizeBytes(o.size(v.Message())) return true }) size += messageset.SizeUnknown(m.GetUnknown()) return size } func (o MarshalOptions) marshalMessageSet(b []byte, m protoreflect.Message) ([]byte, error) { if !flags.ProtoLegacy { return b, errors.New("no support for message_set_wire_format") } fieldOrder := order.AnyFieldOrder if o.Deterministic { fieldOrder = order.NumberFieldOrder } var err error order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { b, err = o.marshalMessageSetField(b, fd, v) return err == nil }) if err != nil { return b, err } return messageset.AppendUnknown(b, m.GetUnknown()) } func (o MarshalOptions) marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { b = messageset.AppendFieldStart(b, fd.Number()) b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType) b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface()))) b, err := o.marshalMessage(b, value.Message()) if err != nil { return b, err } b = messageset.AppendFieldEnd(b) return b, nil } func (o UnmarshalOptions) unmarshalMessageSet(b []byte, m protoreflect.Message) error { if !flags.ProtoLegacy { return errors.New("no support for message_set_wire_format") } return messageset.Unmarshal(b, false, func(num protowire.Number, v []byte) error { err := o.unmarshalMessageSetField(m, num, v) if err == errUnknown { unknown := m.GetUnknown() unknown = protowire.AppendTag(unknown, num, protowire.BytesType) unknown = protowire.AppendBytes(unknown, v) m.SetUnknown(unknown) return nil } return err }) } func (o UnmarshalOptions) unmarshalMessageSetField(m protoreflect.Message, num protowire.Number, v []byte) error { md := m.Descriptor() if !md.ExtensionRanges().Has(num) { return errUnknown } xt, err := o.Resolver.FindExtensionByNumber(md.FullName(), num) if err == protoregistry.NotFound { return errUnknown } if err != nil { return errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err) } xd := xt.TypeDescriptor() if err := o.unmarshalMessage(v, m.Mutable(xd).Message()); err != nil { return err } return nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/proto.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/reflect/protoreflect" ) // Message is the top-level interface that all messages must implement. // It provides access to a reflective view of a message. // Any implementation of this interface may be used with all functions in the // protobuf module that accept a Message, except where otherwise specified. // // This is the v2 interface definition for protobuf messages. // The v1 interface definition is "github.com/golang/protobuf/proto".Message. // // To convert a v1 message to a v2 message, // use "github.com/golang/protobuf/proto".MessageV2. // To convert a v2 message to a v1 message, // use "github.com/golang/protobuf/proto".MessageV1. type Message = protoreflect.ProtoMessage // Error matches all errors produced by packages in the protobuf module. // // That is, errors.Is(err, Error) reports whether an error is produced // by this module. var Error error func init() { Error = errors.Error } // MessageName returns the full name of m. // If m is nil, it returns an empty string. func MessageName(m Message) protoreflect.FullName { if m == nil { return "" } return m.ProtoReflect().Descriptor().FullName() } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/proto_methods.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The protoreflect build tag disables use of fast-path methods. // +build !protoreflect package proto import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) const hasProtoMethods = true func protoMethods(m protoreflect.Message) *protoiface.Methods { return m.ProtoMethods() } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/proto_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The protoreflect build tag disables use of fast-path methods. // +build protoreflect package proto import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) const hasProtoMethods = false func protoMethods(m protoreflect.Message) *protoiface.Methods { return nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/reset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" ) // Reset clears every field in the message. // The resulting message shares no observable memory with its previous state // other than the memory for the message itself. func Reset(m Message) { if mr, ok := m.(interface{ Reset() }); ok && hasProtoMethods { mr.Reset() return } resetMessage(m.ProtoReflect()) } func resetMessage(m protoreflect.Message) { if !m.IsValid() { panic(fmt.Sprintf("cannot reset invalid %v message", m.Descriptor().FullName())) } // Clear all known fields. fds := m.Descriptor().Fields() for i := 0; i < fds.Len(); i++ { m.Clear(fds.Get(i)) } // Clear extension fields. m.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool { m.Clear(fd) return true }) // Clear unknown fields. m.SetUnknown(nil) } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/size.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // Size returns the size in bytes of the wire-format encoding of m. func Size(m Message) int { return MarshalOptions{}.Size(m) } // Size returns the size in bytes of the wire-format encoding of m. func (o MarshalOptions) Size(m Message) int { // Treat a nil message interface as an empty message; nothing to output. if m == nil { return 0 } return o.size(m.ProtoReflect()) } // size is a centralized function that all size operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for size that do not go through this. func (o MarshalOptions) size(m protoreflect.Message) (size int) { methods := protoMethods(m) if methods != nil && methods.Size != nil { out := methods.Size(protoiface.SizeInput{ Message: m, }) return out.Size } if methods != nil && methods.Marshal != nil { // This is not efficient, but we don't have any choice. // This case is mainly used for legacy types with a Marshal method. out, _ := methods.Marshal(protoiface.MarshalInput{ Message: m, }) return len(out.Buf) } return o.sizeMessageSlow(m) } func (o MarshalOptions) sizeMessageSlow(m protoreflect.Message) (size int) { if messageset.IsMessageSet(m.Descriptor()) { return o.sizeMessageSet(m) } m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { size += o.sizeField(fd, v) return true }) size += len(m.GetUnknown()) return size } func (o MarshalOptions) sizeField(fd protoreflect.FieldDescriptor, value protoreflect.Value) (size int) { num := fd.Number() switch { case fd.IsList(): return o.sizeList(num, fd, value.List()) case fd.IsMap(): return o.sizeMap(num, fd, value.Map()) default: return protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), value) } } func (o MarshalOptions) sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) { if fd.IsPacked() && list.Len() > 0 { content := 0 for i, llen := 0, list.Len(); i < llen; i++ { content += o.sizeSingular(num, fd.Kind(), list.Get(i)) } return protowire.SizeTag(num) + protowire.SizeBytes(content) } for i, llen := 0, list.Len(); i < llen; i++ { size += protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), list.Get(i)) } return size } func (o MarshalOptions) sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) { mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool { size += protowire.SizeTag(num) size += protowire.SizeBytes(o.sizeField(fd.MapKey(), key.Value()) + o.sizeField(fd.MapValue(), value)) return true }) return size } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/size_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/reflect/protoreflect" ) func (o MarshalOptions) sizeSingular(num protowire.Number, kind protoreflect.Kind, v protoreflect.Value) int { switch kind { case protoreflect.BoolKind: return protowire.SizeVarint(protowire.EncodeBool(v.Bool())) case protoreflect.EnumKind: return protowire.SizeVarint(uint64(v.Enum())) case protoreflect.Int32Kind: return protowire.SizeVarint(uint64(int32(v.Int()))) case protoreflect.Sint32Kind: return protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) case protoreflect.Uint32Kind: return protowire.SizeVarint(uint64(uint32(v.Uint()))) case protoreflect.Int64Kind: return protowire.SizeVarint(uint64(v.Int())) case protoreflect.Sint64Kind: return protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) case protoreflect.Uint64Kind: return protowire.SizeVarint(v.Uint()) case protoreflect.Sfixed32Kind: return protowire.SizeFixed32() case protoreflect.Fixed32Kind: return protowire.SizeFixed32() case protoreflect.FloatKind: return protowire.SizeFixed32() case protoreflect.Sfixed64Kind: return protowire.SizeFixed64() case protoreflect.Fixed64Kind: return protowire.SizeFixed64() case protoreflect.DoubleKind: return protowire.SizeFixed64() case protoreflect.StringKind: return protowire.SizeBytes(len(v.String())) case protoreflect.BytesKind: return protowire.SizeBytes(len(v.Bytes())) case protoreflect.MessageKind: return protowire.SizeBytes(o.size(v.Message())) case protoreflect.GroupKind: return protowire.SizeGroup(num, o.size(v.Message())) default: return 0 } } ================================================ FILE: _tools/src/google.golang.org/protobuf/proto/wrappers.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto // Bool stores v in a new bool value and returns a pointer to it. func Bool(v bool) *bool { return &v } // Int32 stores v in a new int32 value and returns a pointer to it. func Int32(v int32) *int32 { return &v } // Int64 stores v in a new int64 value and returns a pointer to it. func Int64(v int64) *int64 { return &v } // Float32 stores v in a new float32 value and returns a pointer to it. func Float32(v float32) *float32 { return &v } // Float64 stores v in a new float64 value and returns a pointer to it. func Float64(v float64) *float64 { return &v } // Uint32 stores v in a new uint32 value and returns a pointer to it. func Uint32(v uint32) *uint32 { return &v } // Uint64 stores v in a new uint64 value and returns a pointer to it. func Uint64(v uint64) *uint64 { return &v } // String stores v in a new string value and returns a pointer to it. func String(v string) *string { return &v } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protodesc/desc.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protodesc provides functionality for converting // FileDescriptorProto messages to/from protoreflect.FileDescriptor values. // // The google.protobuf.FileDescriptorProto is a protobuf message that describes // the type information for a .proto file in a form that is easily serializable. // The protoreflect.FileDescriptor is a more structured representation of // the FileDescriptorProto message where references and remote dependencies // can be directly followed. package protodesc import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" ) // Resolver is the resolver used by NewFile to resolve dependencies. // The enums and messages provided must belong to some parent file, // which is also registered. // // It is implemented by protoregistry.Files. type Resolver interface { FindFileByPath(string) (protoreflect.FileDescriptor, error) FindDescriptorByName(protoreflect.FullName) (protoreflect.Descriptor, error) } // FileOptions configures the construction of file descriptors. type FileOptions struct { pragma.NoUnkeyedLiterals // AllowUnresolvable configures New to permissively allow unresolvable // file, enum, or message dependencies. Unresolved dependencies are replaced // by placeholder equivalents. // // The following dependencies may be left unresolved: // • Resolving an imported file. // • Resolving the type for a message field or extension field. // If the kind of the field is unknown, then a placeholder is used for both // the Enum and Message accessors on the protoreflect.FieldDescriptor. // • Resolving an enum value set as the default for an optional enum field. // If unresolvable, the protoreflect.FieldDescriptor.Default is set to the // first value in the associated enum (or zero if the also enum dependency // is also unresolvable). The protoreflect.FieldDescriptor.DefaultEnumValue // is populated with a placeholder. // • Resolving the extended message type for an extension field. // • Resolving the input or output message type for a service method. // // If the unresolved dependency uses a relative name, // then the placeholder will contain an invalid FullName with a "*." prefix, // indicating that the starting prefix of the full name is unknown. AllowUnresolvable bool } // NewFile creates a new protoreflect.FileDescriptor from the provided // file descriptor message. See FileOptions.New for more information. func NewFile(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { return FileOptions{}.New(fd, r) } // NewFiles creates a new protoregistry.Files from the provided // FileDescriptorSet message. See FileOptions.NewFiles for more information. func NewFiles(fd *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { return FileOptions{}.NewFiles(fd) } // New creates a new protoreflect.FileDescriptor from the provided // file descriptor message. The file must represent a valid proto file according // to protobuf semantics. The returned descriptor is a deep copy of the input. // // Any imported files, enum types, or message types referenced in the file are // resolved using the provided registry. When looking up an import file path, // the path must be unique. The newly created file descriptor is not registered // back into the provided file registry. func (o FileOptions) New(fd *descriptorpb.FileDescriptorProto, r Resolver) (protoreflect.FileDescriptor, error) { if r == nil { r = (*protoregistry.Files)(nil) // empty resolver } // Handle the file descriptor content. f := &filedesc.File{L2: &filedesc.FileL2{}} switch fd.GetSyntax() { case "proto2", "": f.L1.Syntax = protoreflect.Proto2 case "proto3": f.L1.Syntax = protoreflect.Proto3 default: return nil, errors.New("invalid syntax: %q", fd.GetSyntax()) } f.L1.Path = fd.GetName() if f.L1.Path == "" { return nil, errors.New("file path must be populated") } f.L1.Package = protoreflect.FullName(fd.GetPackage()) if !f.L1.Package.IsValid() && f.L1.Package != "" { return nil, errors.New("invalid package: %q", f.L1.Package) } if opts := fd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.FileOptions) f.L2.Options = func() protoreflect.ProtoMessage { return opts } } f.L2.Imports = make(filedesc.FileImports, len(fd.GetDependency())) for _, i := range fd.GetPublicDependency() { if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsPublic { return nil, errors.New("invalid or duplicate public import index: %d", i) } f.L2.Imports[i].IsPublic = true } for _, i := range fd.GetWeakDependency() { if !(0 <= i && int(i) < len(f.L2.Imports)) || f.L2.Imports[i].IsWeak { return nil, errors.New("invalid or duplicate weak import index: %d", i) } f.L2.Imports[i].IsWeak = true } imps := importSet{f.Path(): true} for i, path := range fd.GetDependency() { imp := &f.L2.Imports[i] f, err := r.FindFileByPath(path) if err == protoregistry.NotFound && (o.AllowUnresolvable || imp.IsWeak) { f = filedesc.PlaceholderFile(path) } else if err != nil { return nil, errors.New("could not resolve import %q: %v", path, err) } imp.FileDescriptor = f if imps[imp.Path()] { return nil, errors.New("already imported %q", path) } imps[imp.Path()] = true } for i := range fd.GetDependency() { imp := &f.L2.Imports[i] imps.importPublic(imp.Imports()) } // Handle source locations. f.L2.Locations.File = f for _, loc := range fd.GetSourceCodeInfo().GetLocation() { var l protoreflect.SourceLocation // TODO: Validate that the path points to an actual declaration? l.Path = protoreflect.SourcePath(loc.GetPath()) s := loc.GetSpan() switch len(s) { case 3: l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[0]), int(s[2]) case 4: l.StartLine, l.StartColumn, l.EndLine, l.EndColumn = int(s[0]), int(s[1]), int(s[2]), int(s[3]) default: return nil, errors.New("invalid span: %v", s) } // TODO: Validate that the span information is sensible? // See https://github.com/protocolbuffers/protobuf/issues/6378. if false && (l.EndLine < l.StartLine || l.StartLine < 0 || l.StartColumn < 0 || l.EndColumn < 0 || (l.StartLine == l.EndLine && l.EndColumn <= l.StartColumn)) { return nil, errors.New("invalid span: %v", s) } l.LeadingDetachedComments = loc.GetLeadingDetachedComments() l.LeadingComments = loc.GetLeadingComments() l.TrailingComments = loc.GetTrailingComments() f.L2.Locations.List = append(f.L2.Locations.List, l) } // Step 1: Allocate and derive the names for all declarations. // This copies all fields from the descriptor proto except: // google.protobuf.FieldDescriptorProto.type_name // google.protobuf.FieldDescriptorProto.default_value // google.protobuf.FieldDescriptorProto.oneof_index // google.protobuf.FieldDescriptorProto.extendee // google.protobuf.MethodDescriptorProto.input // google.protobuf.MethodDescriptorProto.output var err error sb := new(strs.Builder) r1 := make(descsByName) if f.L1.Enums.List, err = r1.initEnumDeclarations(fd.GetEnumType(), f, sb); err != nil { return nil, err } if f.L1.Messages.List, err = r1.initMessagesDeclarations(fd.GetMessageType(), f, sb); err != nil { return nil, err } if f.L1.Extensions.List, err = r1.initExtensionDeclarations(fd.GetExtension(), f, sb); err != nil { return nil, err } if f.L1.Services.List, err = r1.initServiceDeclarations(fd.GetService(), f, sb); err != nil { return nil, err } // Step 2: Resolve every dependency reference not handled by step 1. r2 := &resolver{local: r1, remote: r, imports: imps, allowUnresolvable: o.AllowUnresolvable} if err := r2.resolveMessageDependencies(f.L1.Messages.List, fd.GetMessageType()); err != nil { return nil, err } if err := r2.resolveExtensionDependencies(f.L1.Extensions.List, fd.GetExtension()); err != nil { return nil, err } if err := r2.resolveServiceDependencies(f.L1.Services.List, fd.GetService()); err != nil { return nil, err } // Step 3: Validate every enum, message, and extension declaration. if err := validateEnumDeclarations(f.L1.Enums.List, fd.GetEnumType()); err != nil { return nil, err } if err := validateMessageDeclarations(f.L1.Messages.List, fd.GetMessageType()); err != nil { return nil, err } if err := validateExtensionDeclarations(f.L1.Extensions.List, fd.GetExtension()); err != nil { return nil, err } return f, nil } type importSet map[string]bool func (is importSet) importPublic(imps protoreflect.FileImports) { for i := 0; i < imps.Len(); i++ { if imp := imps.Get(i); imp.IsPublic { is[imp.Path()] = true is.importPublic(imp.Imports()) } } } // NewFiles creates a new protoregistry.Files from the provided // FileDescriptorSet message. The descriptor set must include only // valid files according to protobuf semantics. The returned descriptors // are a deep copy of the input. func (o FileOptions) NewFiles(fds *descriptorpb.FileDescriptorSet) (*protoregistry.Files, error) { files := make(map[string]*descriptorpb.FileDescriptorProto) for _, fd := range fds.File { if _, ok := files[fd.GetName()]; ok { return nil, errors.New("file appears multiple times: %q", fd.GetName()) } files[fd.GetName()] = fd } r := &protoregistry.Files{} for _, fd := range files { if err := o.addFileDeps(r, fd, files); err != nil { return nil, err } } return r, nil } func (o FileOptions) addFileDeps(r *protoregistry.Files, fd *descriptorpb.FileDescriptorProto, files map[string]*descriptorpb.FileDescriptorProto) error { // Set the entry to nil while descending into a file's dependencies to detect cycles. files[fd.GetName()] = nil for _, dep := range fd.Dependency { depfd, ok := files[dep] if depfd == nil { if ok { return errors.New("import cycle in file: %q", dep) } continue } if err := o.addFileDeps(r, depfd, files); err != nil { return err } } // Delete the entry once dependencies are processed. delete(files, fd.GetName()) f, err := o.New(fd, r) if err != nil { return err } return r.RegisterFile(f) } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protodesc/desc_init.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protodesc import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/descriptorpb" ) type descsByName map[protoreflect.FullName]protoreflect.Descriptor func (r descsByName) initEnumDeclarations(eds []*descriptorpb.EnumDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (es []filedesc.Enum, err error) { es = make([]filedesc.Enum, len(eds)) // allocate up-front to ensure stable pointers for i, ed := range eds { e := &es[i] e.L2 = new(filedesc.EnumL2) if e.L0, err = r.makeBase(e, parent, ed.GetName(), i, sb); err != nil { return nil, err } if opts := ed.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.EnumOptions) e.L2.Options = func() protoreflect.ProtoMessage { return opts } } for _, s := range ed.GetReservedName() { e.L2.ReservedNames.List = append(e.L2.ReservedNames.List, protoreflect.Name(s)) } for _, rr := range ed.GetReservedRange() { e.L2.ReservedRanges.List = append(e.L2.ReservedRanges.List, [2]protoreflect.EnumNumber{ protoreflect.EnumNumber(rr.GetStart()), protoreflect.EnumNumber(rr.GetEnd()), }) } if e.L2.Values.List, err = r.initEnumValuesFromDescriptorProto(ed.GetValue(), e, sb); err != nil { return nil, err } } return es, nil } func (r descsByName) initEnumValuesFromDescriptorProto(vds []*descriptorpb.EnumValueDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (vs []filedesc.EnumValue, err error) { vs = make([]filedesc.EnumValue, len(vds)) // allocate up-front to ensure stable pointers for i, vd := range vds { v := &vs[i] if v.L0, err = r.makeBase(v, parent, vd.GetName(), i, sb); err != nil { return nil, err } if opts := vd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.EnumValueOptions) v.L1.Options = func() protoreflect.ProtoMessage { return opts } } v.L1.Number = protoreflect.EnumNumber(vd.GetNumber()) } return vs, nil } func (r descsByName) initMessagesDeclarations(mds []*descriptorpb.DescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Message, err error) { ms = make([]filedesc.Message, len(mds)) // allocate up-front to ensure stable pointers for i, md := range mds { m := &ms[i] m.L2 = new(filedesc.MessageL2) if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { return nil, err } if opts := md.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.MessageOptions) m.L2.Options = func() protoreflect.ProtoMessage { return opts } m.L1.IsMapEntry = opts.GetMapEntry() m.L1.IsMessageSet = opts.GetMessageSetWireFormat() } for _, s := range md.GetReservedName() { m.L2.ReservedNames.List = append(m.L2.ReservedNames.List, protoreflect.Name(s)) } for _, rr := range md.GetReservedRange() { m.L2.ReservedRanges.List = append(m.L2.ReservedRanges.List, [2]protoreflect.FieldNumber{ protoreflect.FieldNumber(rr.GetStart()), protoreflect.FieldNumber(rr.GetEnd()), }) } for _, xr := range md.GetExtensionRange() { m.L2.ExtensionRanges.List = append(m.L2.ExtensionRanges.List, [2]protoreflect.FieldNumber{ protoreflect.FieldNumber(xr.GetStart()), protoreflect.FieldNumber(xr.GetEnd()), }) var optsFunc func() protoreflect.ProtoMessage if opts := xr.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.ExtensionRangeOptions) optsFunc = func() protoreflect.ProtoMessage { return opts } } m.L2.ExtensionRangeOptions = append(m.L2.ExtensionRangeOptions, optsFunc) } if m.L2.Fields.List, err = r.initFieldsFromDescriptorProto(md.GetField(), m, sb); err != nil { return nil, err } if m.L2.Oneofs.List, err = r.initOneofsFromDescriptorProto(md.GetOneofDecl(), m, sb); err != nil { return nil, err } if m.L1.Enums.List, err = r.initEnumDeclarations(md.GetEnumType(), m, sb); err != nil { return nil, err } if m.L1.Messages.List, err = r.initMessagesDeclarations(md.GetNestedType(), m, sb); err != nil { return nil, err } if m.L1.Extensions.List, err = r.initExtensionDeclarations(md.GetExtension(), m, sb); err != nil { return nil, err } } return ms, nil } func (r descsByName) initFieldsFromDescriptorProto(fds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (fs []filedesc.Field, err error) { fs = make([]filedesc.Field, len(fds)) // allocate up-front to ensure stable pointers for i, fd := range fds { f := &fs[i] if f.L0, err = r.makeBase(f, parent, fd.GetName(), i, sb); err != nil { return nil, err } f.L1.IsProto3Optional = fd.GetProto3Optional() if opts := fd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.FieldOptions) f.L1.Options = func() protoreflect.ProtoMessage { return opts } f.L1.IsWeak = opts.GetWeak() f.L1.HasPacked = opts.Packed != nil f.L1.IsPacked = opts.GetPacked() } f.L1.Number = protoreflect.FieldNumber(fd.GetNumber()) f.L1.Cardinality = protoreflect.Cardinality(fd.GetLabel()) if fd.Type != nil { f.L1.Kind = protoreflect.Kind(fd.GetType()) } if fd.JsonName != nil { f.L1.StringName.InitJSON(fd.GetJsonName()) } } return fs, nil } func (r descsByName) initOneofsFromDescriptorProto(ods []*descriptorpb.OneofDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (os []filedesc.Oneof, err error) { os = make([]filedesc.Oneof, len(ods)) // allocate up-front to ensure stable pointers for i, od := range ods { o := &os[i] if o.L0, err = r.makeBase(o, parent, od.GetName(), i, sb); err != nil { return nil, err } if opts := od.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.OneofOptions) o.L1.Options = func() protoreflect.ProtoMessage { return opts } } } return os, nil } func (r descsByName) initExtensionDeclarations(xds []*descriptorpb.FieldDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (xs []filedesc.Extension, err error) { xs = make([]filedesc.Extension, len(xds)) // allocate up-front to ensure stable pointers for i, xd := range xds { x := &xs[i] x.L2 = new(filedesc.ExtensionL2) if x.L0, err = r.makeBase(x, parent, xd.GetName(), i, sb); err != nil { return nil, err } if opts := xd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.FieldOptions) x.L2.Options = func() protoreflect.ProtoMessage { return opts } x.L2.IsPacked = opts.GetPacked() } x.L1.Number = protoreflect.FieldNumber(xd.GetNumber()) x.L1.Cardinality = protoreflect.Cardinality(xd.GetLabel()) if xd.Type != nil { x.L1.Kind = protoreflect.Kind(xd.GetType()) } if xd.JsonName != nil { x.L2.StringName.InitJSON(xd.GetJsonName()) } } return xs, nil } func (r descsByName) initServiceDeclarations(sds []*descriptorpb.ServiceDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ss []filedesc.Service, err error) { ss = make([]filedesc.Service, len(sds)) // allocate up-front to ensure stable pointers for i, sd := range sds { s := &ss[i] s.L2 = new(filedesc.ServiceL2) if s.L0, err = r.makeBase(s, parent, sd.GetName(), i, sb); err != nil { return nil, err } if opts := sd.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.ServiceOptions) s.L2.Options = func() protoreflect.ProtoMessage { return opts } } if s.L2.Methods.List, err = r.initMethodsFromDescriptorProto(sd.GetMethod(), s, sb); err != nil { return nil, err } } return ss, nil } func (r descsByName) initMethodsFromDescriptorProto(mds []*descriptorpb.MethodDescriptorProto, parent protoreflect.Descriptor, sb *strs.Builder) (ms []filedesc.Method, err error) { ms = make([]filedesc.Method, len(mds)) // allocate up-front to ensure stable pointers for i, md := range mds { m := &ms[i] if m.L0, err = r.makeBase(m, parent, md.GetName(), i, sb); err != nil { return nil, err } if opts := md.GetOptions(); opts != nil { opts = proto.Clone(opts).(*descriptorpb.MethodOptions) m.L1.Options = func() protoreflect.ProtoMessage { return opts } } m.L1.IsStreamingClient = md.GetClientStreaming() m.L1.IsStreamingServer = md.GetServerStreaming() } return ms, nil } func (r descsByName) makeBase(child, parent protoreflect.Descriptor, name string, idx int, sb *strs.Builder) (filedesc.BaseL0, error) { if !protoreflect.Name(name).IsValid() { return filedesc.BaseL0{}, errors.New("descriptor %q has an invalid nested name: %q", parent.FullName(), name) } // Derive the full name of the child. // Note that enum values are a sibling to the enum parent in the namespace. var fullName protoreflect.FullName if _, ok := parent.(protoreflect.EnumDescriptor); ok { fullName = sb.AppendFullName(parent.FullName().Parent(), protoreflect.Name(name)) } else { fullName = sb.AppendFullName(parent.FullName(), protoreflect.Name(name)) } if _, ok := r[fullName]; ok { return filedesc.BaseL0{}, errors.New("descriptor %q already declared", fullName) } r[fullName] = child // TODO: Verify that the full name does not already exist in the resolver? // This is not as critical since most usages of NewFile will register // the created file back into the registry, which will perform this check. return filedesc.BaseL0{ FullName: fullName, ParentFile: parent.ParentFile().(*filedesc.File), Parent: parent, Index: idx, }, nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protodesc import ( "google.golang.org/protobuf/internal/encoding/defval" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/types/descriptorpb" ) // resolver is a wrapper around a local registry of declarations within the file // and the remote resolver. The remote resolver is restricted to only return // descriptors that have been imported. type resolver struct { local descsByName remote Resolver imports importSet allowUnresolvable bool } func (r *resolver) resolveMessageDependencies(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) (err error) { for i, md := range mds { m := &ms[i] for j, fd := range md.GetField() { f := &m.L2.Fields.List[j] if f.L1.Cardinality == protoreflect.Required { m.L2.RequiredNumbers.List = append(m.L2.RequiredNumbers.List, f.L1.Number) } if fd.OneofIndex != nil { k := int(fd.GetOneofIndex()) if !(0 <= k && k < len(md.GetOneofDecl())) { return errors.New("message field %q has an invalid oneof index: %d", f.FullName(), k) } o := &m.L2.Oneofs.List[k] f.L1.ContainingOneof = o o.L1.Fields.List = append(o.L1.Fields.List, f) } if f.L1.Kind, f.L1.Enum, f.L1.Message, err = r.findTarget(f.Kind(), f.Parent().FullName(), partialName(fd.GetTypeName()), f.IsWeak()); err != nil { return errors.New("message field %q cannot resolve type: %v", f.FullName(), err) } if fd.DefaultValue != nil { v, ev, err := unmarshalDefault(fd.GetDefaultValue(), f, r.allowUnresolvable) if err != nil { return errors.New("message field %q has invalid default: %v", f.FullName(), err) } f.L1.Default = filedesc.DefaultValue(v, ev) } } if err := r.resolveMessageDependencies(m.L1.Messages.List, md.GetNestedType()); err != nil { return err } if err := r.resolveExtensionDependencies(m.L1.Extensions.List, md.GetExtension()); err != nil { return err } } return nil } func (r *resolver) resolveExtensionDependencies(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) (err error) { for i, xd := range xds { x := &xs[i] if x.L1.Extendee, err = r.findMessageDescriptor(x.Parent().FullName(), partialName(xd.GetExtendee()), false); err != nil { return errors.New("extension field %q cannot resolve extendee: %v", x.FullName(), err) } if x.L1.Kind, x.L2.Enum, x.L2.Message, err = r.findTarget(x.Kind(), x.Parent().FullName(), partialName(xd.GetTypeName()), false); err != nil { return errors.New("extension field %q cannot resolve type: %v", x.FullName(), err) } if xd.DefaultValue != nil { v, ev, err := unmarshalDefault(xd.GetDefaultValue(), x, r.allowUnresolvable) if err != nil { return errors.New("extension field %q has invalid default: %v", x.FullName(), err) } x.L2.Default = filedesc.DefaultValue(v, ev) } } return nil } func (r *resolver) resolveServiceDependencies(ss []filedesc.Service, sds []*descriptorpb.ServiceDescriptorProto) (err error) { for i, sd := range sds { s := &ss[i] for j, md := range sd.GetMethod() { m := &s.L2.Methods.List[j] m.L1.Input, err = r.findMessageDescriptor(m.Parent().FullName(), partialName(md.GetInputType()), false) if err != nil { return errors.New("service method %q cannot resolve input: %v", m.FullName(), err) } m.L1.Output, err = r.findMessageDescriptor(s.FullName(), partialName(md.GetOutputType()), false) if err != nil { return errors.New("service method %q cannot resolve output: %v", m.FullName(), err) } } } return nil } // findTarget finds an enum or message descriptor if k is an enum, message, // group, or unknown. If unknown, and the name could be resolved, the kind // returned kind is set based on the type of the resolved descriptor. func (r *resolver) findTarget(k protoreflect.Kind, scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.Kind, protoreflect.EnumDescriptor, protoreflect.MessageDescriptor, error) { switch k { case protoreflect.EnumKind: ed, err := r.findEnumDescriptor(scope, ref, isWeak) if err != nil { return 0, nil, nil, err } return k, ed, nil, nil case protoreflect.MessageKind, protoreflect.GroupKind: md, err := r.findMessageDescriptor(scope, ref, isWeak) if err != nil { return 0, nil, nil, err } return k, nil, md, nil case 0: // Handle unspecified kinds (possible with parsers that operate // on a per-file basis without knowledge of dependencies). d, err := r.findDescriptor(scope, ref) if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) { return k, filedesc.PlaceholderEnum(ref.FullName()), filedesc.PlaceholderMessage(ref.FullName()), nil } else if err == protoregistry.NotFound { return 0, nil, nil, errors.New("%q not found", ref.FullName()) } else if err != nil { return 0, nil, nil, err } switch d := d.(type) { case protoreflect.EnumDescriptor: return protoreflect.EnumKind, d, nil, nil case protoreflect.MessageDescriptor: return protoreflect.MessageKind, nil, d, nil default: return 0, nil, nil, errors.New("unknown kind") } default: if ref != "" { return 0, nil, nil, errors.New("target name cannot be specified for %v", k) } if !k.IsValid() { return 0, nil, nil, errors.New("invalid kind: %d", k) } return k, nil, nil, nil } } // findDescriptor finds the descriptor by name, // which may be a relative name within some scope. // // Suppose the scope was "fizz.buzz" and the reference was "Foo.Bar", // then the following full names are searched: // * fizz.buzz.Foo.Bar // * fizz.Foo.Bar // * Foo.Bar func (r *resolver) findDescriptor(scope protoreflect.FullName, ref partialName) (protoreflect.Descriptor, error) { if !ref.IsValid() { return nil, errors.New("invalid name reference: %q", ref) } if ref.IsFull() { scope, ref = "", ref[1:] } var foundButNotImported protoreflect.Descriptor for { // Derive the full name to search. s := protoreflect.FullName(ref) if scope != "" { s = scope + "." + s } // Check the current file for the descriptor. if d, ok := r.local[s]; ok { return d, nil } // Check the remote registry for the descriptor. d, err := r.remote.FindDescriptorByName(s) if err == nil { // Only allow descriptors covered by one of the imports. if r.imports[d.ParentFile().Path()] { return d, nil } foundButNotImported = d } else if err != protoregistry.NotFound { return nil, errors.Wrap(err, "%q", s) } // Continue on at a higher level of scoping. if scope == "" { if d := foundButNotImported; d != nil { return nil, errors.New("resolved %q, but %q is not imported", d.FullName(), d.ParentFile().Path()) } return nil, protoregistry.NotFound } scope = scope.Parent() } } func (r *resolver) findEnumDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.EnumDescriptor, error) { d, err := r.findDescriptor(scope, ref) if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) { return filedesc.PlaceholderEnum(ref.FullName()), nil } else if err == protoregistry.NotFound { return nil, errors.New("%q not found", ref.FullName()) } else if err != nil { return nil, err } ed, ok := d.(protoreflect.EnumDescriptor) if !ok { return nil, errors.New("resolved %q, but it is not an enum", d.FullName()) } return ed, nil } func (r *resolver) findMessageDescriptor(scope protoreflect.FullName, ref partialName, isWeak bool) (protoreflect.MessageDescriptor, error) { d, err := r.findDescriptor(scope, ref) if err == protoregistry.NotFound && (r.allowUnresolvable || isWeak) { return filedesc.PlaceholderMessage(ref.FullName()), nil } else if err == protoregistry.NotFound { return nil, errors.New("%q not found", ref.FullName()) } else if err != nil { return nil, err } md, ok := d.(protoreflect.MessageDescriptor) if !ok { return nil, errors.New("resolved %q, but it is not an message", d.FullName()) } return md, nil } // partialName is the partial name. A leading dot means that the name is full, // otherwise the name is relative to some current scope. // See google.protobuf.FieldDescriptorProto.type_name. type partialName string func (s partialName) IsFull() bool { return len(s) > 0 && s[0] == '.' } func (s partialName) IsValid() bool { if s.IsFull() { return protoreflect.FullName(s[1:]).IsValid() } return protoreflect.FullName(s).IsValid() } const unknownPrefix = "*." // FullName converts the partial name to a full name on a best-effort basis. // If relative, it creates an invalid full name, using a "*." prefix // to indicate that the start of the full name is unknown. func (s partialName) FullName() protoreflect.FullName { if s.IsFull() { return protoreflect.FullName(s[1:]) } return protoreflect.FullName(unknownPrefix + s) } func unmarshalDefault(s string, fd protoreflect.FieldDescriptor, allowUnresolvable bool) (protoreflect.Value, protoreflect.EnumValueDescriptor, error) { var evs protoreflect.EnumValueDescriptors if fd.Enum() != nil { evs = fd.Enum().Values() } v, ev, err := defval.Unmarshal(s, fd.Kind(), evs, defval.Descriptor) if err != nil && allowUnresolvable && evs != nil && protoreflect.Name(s).IsValid() { v = protoreflect.ValueOfEnum(0) if evs.Len() > 0 { v = protoreflect.ValueOfEnum(evs.Get(0).Number()) } ev = filedesc.PlaceholderEnumValue(fd.Enum().FullName().Parent().Append(protoreflect.Name(s))) } else if err != nil { return v, ev, err } if fd.Syntax() == protoreflect.Proto3 { return v, ev, errors.New("cannot be specified under proto3 semantics") } if fd.Kind() == protoreflect.MessageKind || fd.Kind() == protoreflect.GroupKind || fd.Cardinality() == protoreflect.Repeated { return v, ev, errors.New("cannot be specified on composite types") } return v, ev, nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protodesc/desc_validate.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protodesc import ( "strings" "unicode" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/descriptorpb" ) func validateEnumDeclarations(es []filedesc.Enum, eds []*descriptorpb.EnumDescriptorProto) error { for i, ed := range eds { e := &es[i] if err := e.L2.ReservedNames.CheckValid(); err != nil { return errors.New("enum %q reserved names has %v", e.FullName(), err) } if err := e.L2.ReservedRanges.CheckValid(); err != nil { return errors.New("enum %q reserved ranges has %v", e.FullName(), err) } if len(ed.GetValue()) == 0 { return errors.New("enum %q must contain at least one value declaration", e.FullName()) } allowAlias := ed.GetOptions().GetAllowAlias() foundAlias := false for i := 0; i < e.Values().Len(); i++ { v1 := e.Values().Get(i) if v2 := e.Values().ByNumber(v1.Number()); v1 != v2 { foundAlias = true if !allowAlias { return errors.New("enum %q has conflicting non-aliased values on number %d: %q with %q", e.FullName(), v1.Number(), v1.Name(), v2.Name()) } } } if allowAlias && !foundAlias { return errors.New("enum %q allows aliases, but none were found", e.FullName()) } if e.Syntax() == protoreflect.Proto3 { if v := e.Values().Get(0); v.Number() != 0 { return errors.New("enum %q using proto3 semantics must have zero number for the first value", v.FullName()) } // Verify that value names in proto3 do not conflict if the // case-insensitive prefix is removed. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:4991-5055 names := map[string]protoreflect.EnumValueDescriptor{} prefix := strings.Replace(strings.ToLower(string(e.Name())), "_", "", -1) for i := 0; i < e.Values().Len(); i++ { v1 := e.Values().Get(i) s := strs.EnumValueName(strs.TrimEnumPrefix(string(v1.Name()), prefix)) if v2, ok := names[s]; ok && v1.Number() != v2.Number() { return errors.New("enum %q using proto3 semantics has conflict: %q with %q", e.FullName(), v1.Name(), v2.Name()) } names[s] = v1 } } for j, vd := range ed.GetValue() { v := &e.L2.Values.List[j] if vd.Number == nil { return errors.New("enum value %q must have a specified number", v.FullName()) } if e.L2.ReservedNames.Has(v.Name()) { return errors.New("enum value %q must not use reserved name", v.FullName()) } if e.L2.ReservedRanges.Has(v.Number()) { return errors.New("enum value %q must not use reserved number %d", v.FullName(), v.Number()) } } } return nil } func validateMessageDeclarations(ms []filedesc.Message, mds []*descriptorpb.DescriptorProto) error { for i, md := range mds { m := &ms[i] // Handle the message descriptor itself. isMessageSet := md.GetOptions().GetMessageSetWireFormat() if err := m.L2.ReservedNames.CheckValid(); err != nil { return errors.New("message %q reserved names has %v", m.FullName(), err) } if err := m.L2.ReservedRanges.CheckValid(isMessageSet); err != nil { return errors.New("message %q reserved ranges has %v", m.FullName(), err) } if err := m.L2.ExtensionRanges.CheckValid(isMessageSet); err != nil { return errors.New("message %q extension ranges has %v", m.FullName(), err) } if err := (*filedesc.FieldRanges).CheckOverlap(&m.L2.ReservedRanges, &m.L2.ExtensionRanges); err != nil { return errors.New("message %q reserved and extension ranges has %v", m.FullName(), err) } for i := 0; i < m.Fields().Len(); i++ { f1 := m.Fields().Get(i) if f2 := m.Fields().ByNumber(f1.Number()); f1 != f2 { return errors.New("message %q has conflicting fields: %q with %q", m.FullName(), f1.Name(), f2.Name()) } } if isMessageSet && !flags.ProtoLegacy { return errors.New("message %q is a MessageSet, which is a legacy proto1 feature that is no longer supported", m.FullName()) } if isMessageSet && (m.Syntax() != protoreflect.Proto2 || m.Fields().Len() > 0 || m.ExtensionRanges().Len() == 0) { return errors.New("message %q is an invalid proto1 MessageSet", m.FullName()) } if m.Syntax() == protoreflect.Proto3 { if m.ExtensionRanges().Len() > 0 { return errors.New("message %q using proto3 semantics cannot have extension ranges", m.FullName()) } // Verify that field names in proto3 do not conflict if lowercased // with all underscores removed. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:5830-5847 names := map[string]protoreflect.FieldDescriptor{} for i := 0; i < m.Fields().Len(); i++ { f1 := m.Fields().Get(i) s := strings.Replace(strings.ToLower(string(f1.Name())), "_", "", -1) if f2, ok := names[s]; ok { return errors.New("message %q using proto3 semantics has conflict: %q with %q", m.FullName(), f1.Name(), f2.Name()) } names[s] = f1 } } for j, fd := range md.GetField() { f := &m.L2.Fields.List[j] if m.L2.ReservedNames.Has(f.Name()) { return errors.New("message field %q must not use reserved name", f.FullName()) } if !f.Number().IsValid() { return errors.New("message field %q has an invalid number: %d", f.FullName(), f.Number()) } if !f.Cardinality().IsValid() { return errors.New("message field %q has an invalid cardinality: %d", f.FullName(), f.Cardinality()) } if m.L2.ReservedRanges.Has(f.Number()) { return errors.New("message field %q must not use reserved number %d", f.FullName(), f.Number()) } if m.L2.ExtensionRanges.Has(f.Number()) { return errors.New("message field %q with number %d in extension range", f.FullName(), f.Number()) } if fd.Extendee != nil { return errors.New("message field %q may not have extendee: %q", f.FullName(), fd.GetExtendee()) } if f.L1.IsProto3Optional { if f.Syntax() != protoreflect.Proto3 { return errors.New("message field %q under proto3 optional semantics must be specified in the proto3 syntax", f.FullName()) } if f.Cardinality() != protoreflect.Optional { return errors.New("message field %q under proto3 optional semantics must have optional cardinality", f.FullName()) } if f.ContainingOneof() != nil && f.ContainingOneof().Fields().Len() != 1 { return errors.New("message field %q under proto3 optional semantics must be within a single element oneof", f.FullName()) } } if f.IsWeak() && !flags.ProtoLegacy { return errors.New("message field %q is a weak field, which is a legacy proto1 feature that is no longer supported", f.FullName()) } if f.IsWeak() && (f.Syntax() != protoreflect.Proto2 || !isOptionalMessage(f) || f.ContainingOneof() != nil) { return errors.New("message field %q may only be weak for an optional message", f.FullName()) } if f.IsPacked() && !isPackable(f) { return errors.New("message field %q is not packable", f.FullName()) } if err := checkValidGroup(f); err != nil { return errors.New("message field %q is an invalid group: %v", f.FullName(), err) } if err := checkValidMap(f); err != nil { return errors.New("message field %q is an invalid map: %v", f.FullName(), err) } if f.Syntax() == protoreflect.Proto3 { if f.Cardinality() == protoreflect.Required { return errors.New("message field %q using proto3 semantics cannot be required", f.FullName()) } if f.Enum() != nil && !f.Enum().IsPlaceholder() && f.Enum().Syntax() != protoreflect.Proto3 { return errors.New("message field %q using proto3 semantics may only depend on a proto3 enum", f.FullName()) } } } seenSynthetic := false // synthetic oneofs for proto3 optional must come after real oneofs for j := range md.GetOneofDecl() { o := &m.L2.Oneofs.List[j] if o.Fields().Len() == 0 { return errors.New("message oneof %q must contain at least one field declaration", o.FullName()) } if n := o.Fields().Len(); n-1 != (o.Fields().Get(n-1).Index() - o.Fields().Get(0).Index()) { return errors.New("message oneof %q must have consecutively declared fields", o.FullName()) } if o.IsSynthetic() { seenSynthetic = true continue } if !o.IsSynthetic() && seenSynthetic { return errors.New("message oneof %q must be declared before synthetic oneofs", o.FullName()) } for i := 0; i < o.Fields().Len(); i++ { f := o.Fields().Get(i) if f.Cardinality() != protoreflect.Optional { return errors.New("message field %q belongs in a oneof and must be optional", f.FullName()) } if f.IsWeak() { return errors.New("message field %q belongs in a oneof and must not be a weak reference", f.FullName()) } } } if err := validateEnumDeclarations(m.L1.Enums.List, md.GetEnumType()); err != nil { return err } if err := validateMessageDeclarations(m.L1.Messages.List, md.GetNestedType()); err != nil { return err } if err := validateExtensionDeclarations(m.L1.Extensions.List, md.GetExtension()); err != nil { return err } } return nil } func validateExtensionDeclarations(xs []filedesc.Extension, xds []*descriptorpb.FieldDescriptorProto) error { for i, xd := range xds { x := &xs[i] // NOTE: Avoid using the IsValid method since extensions to MessageSet // may have a field number higher than normal. This check only verifies // that the number is not negative or reserved. We check again later // if we know that the extendee is definitely not a MessageSet. if n := x.Number(); n < 0 || (protowire.FirstReservedNumber <= n && n <= protowire.LastReservedNumber) { return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number()) } if !x.Cardinality().IsValid() || x.Cardinality() == protoreflect.Required { return errors.New("extension field %q has an invalid cardinality: %d", x.FullName(), x.Cardinality()) } if xd.JsonName != nil { // A bug in older versions of protoc would always populate the // "json_name" option for extensions when it is meaningless. // When it did so, it would always use the camel-cased field name. if xd.GetJsonName() != strs.JSONCamelCase(string(x.Name())) { return errors.New("extension field %q may not have an explicitly set JSON name: %q", x.FullName(), xd.GetJsonName()) } } if xd.OneofIndex != nil { return errors.New("extension field %q may not be part of a oneof", x.FullName()) } if md := x.ContainingMessage(); !md.IsPlaceholder() { if !md.ExtensionRanges().Has(x.Number()) { return errors.New("extension field %q extends %q with non-extension field number: %d", x.FullName(), md.FullName(), x.Number()) } isMessageSet := md.Options().(*descriptorpb.MessageOptions).GetMessageSetWireFormat() if isMessageSet && !isOptionalMessage(x) { return errors.New("extension field %q extends MessageSet and must be an optional message", x.FullName()) } if !isMessageSet && !x.Number().IsValid() { return errors.New("extension field %q has an invalid number: %d", x.FullName(), x.Number()) } } if xd.GetOptions().GetWeak() { return errors.New("extension field %q cannot be a weak reference", x.FullName()) } if x.IsPacked() && !isPackable(x) { return errors.New("extension field %q is not packable", x.FullName()) } if err := checkValidGroup(x); err != nil { return errors.New("extension field %q is an invalid group: %v", x.FullName(), err) } if md := x.Message(); md != nil && md.IsMapEntry() { return errors.New("extension field %q cannot be a map entry", x.FullName()) } if x.Syntax() == protoreflect.Proto3 { switch x.ContainingMessage().FullName() { case (*descriptorpb.FileOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.EnumOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.EnumValueOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.MessageOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.FieldOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.OneofOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.ExtensionRangeOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.ServiceOptions)(nil).ProtoReflect().Descriptor().FullName(): case (*descriptorpb.MethodOptions)(nil).ProtoReflect().Descriptor().FullName(): default: return errors.New("extension field %q cannot be declared in proto3 unless extended descriptor options", x.FullName()) } } } return nil } // isOptionalMessage reports whether this is an optional message. // If the kind is unknown, it is assumed to be a message. func isOptionalMessage(fd protoreflect.FieldDescriptor) bool { return (fd.Kind() == 0 || fd.Kind() == protoreflect.MessageKind) && fd.Cardinality() == protoreflect.Optional } // isPackable checks whether the pack option can be specified. func isPackable(fd protoreflect.FieldDescriptor) bool { switch fd.Kind() { case protoreflect.StringKind, protoreflect.BytesKind, protoreflect.MessageKind, protoreflect.GroupKind: return false } return fd.IsList() } // checkValidGroup reports whether fd is a valid group according to the same // rules that protoc imposes. func checkValidGroup(fd protoreflect.FieldDescriptor) error { md := fd.Message() switch { case fd.Kind() != protoreflect.GroupKind: return nil case fd.Syntax() != protoreflect.Proto2: return errors.New("invalid under proto2 semantics") case md == nil || md.IsPlaceholder(): return errors.New("message must be resolvable") case fd.FullName().Parent() != md.FullName().Parent(): return errors.New("message and field must be declared in the same scope") case !unicode.IsUpper(rune(md.Name()[0])): return errors.New("message name must start with an uppercase") case fd.Name() != protoreflect.Name(strings.ToLower(string(md.Name()))): return errors.New("field name must be lowercased form of the message name") } return nil } // checkValidMap checks whether the field is a valid map according to the same // rules that protoc imposes. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:6045-6115 func checkValidMap(fd protoreflect.FieldDescriptor) error { md := fd.Message() switch { case md == nil || !md.IsMapEntry(): return nil case fd.FullName().Parent() != md.FullName().Parent(): return errors.New("message and field must be declared in the same scope") case md.Name() != protoreflect.Name(strs.MapEntryName(string(fd.Name()))): return errors.New("incorrect implicit map entry name") case fd.Cardinality() != protoreflect.Repeated: return errors.New("field must be repeated") case md.Fields().Len() != 2: return errors.New("message must have exactly two fields") case md.ExtensionRanges().Len() > 0: return errors.New("message must not have any extension ranges") case md.Enums().Len()+md.Messages().Len()+md.Extensions().Len() > 0: return errors.New("message must not have any nested declarations") } kf := md.Fields().Get(0) vf := md.Fields().Get(1) switch { case kf.Name() != genid.MapEntry_Key_field_name || kf.Number() != genid.MapEntry_Key_field_number || kf.Cardinality() != protoreflect.Optional || kf.ContainingOneof() != nil || kf.HasDefault(): return errors.New("invalid key field") case vf.Name() != genid.MapEntry_Value_field_name || vf.Number() != genid.MapEntry_Value_field_number || vf.Cardinality() != protoreflect.Optional || vf.ContainingOneof() != nil || vf.HasDefault(): return errors.New("invalid value field") } switch kf.Kind() { case protoreflect.BoolKind: // bool case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind: // int32 case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind: // int64 case protoreflect.Uint32Kind, protoreflect.Fixed32Kind: // uint32 case protoreflect.Uint64Kind, protoreflect.Fixed64Kind: // uint64 case protoreflect.StringKind: // string default: return errors.New("invalid key kind: %v", kf.Kind()) } if e := vf.Enum(); e != nil && e.Values().Len() > 0 && e.Values().Get(0).Number() != 0 { return errors.New("map enum value must have zero number for the first value") } return nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protodesc/proto.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protodesc import ( "fmt" "strings" "google.golang.org/protobuf/internal/encoding/defval" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/types/descriptorpb" ) // ToFileDescriptorProto copies a protoreflect.FileDescriptor into a // google.protobuf.FileDescriptorProto message. func ToFileDescriptorProto(file protoreflect.FileDescriptor) *descriptorpb.FileDescriptorProto { p := &descriptorpb.FileDescriptorProto{ Name: proto.String(file.Path()), Options: proto.Clone(file.Options()).(*descriptorpb.FileOptions), } if file.Package() != "" { p.Package = proto.String(string(file.Package())) } for i, imports := 0, file.Imports(); i < imports.Len(); i++ { imp := imports.Get(i) p.Dependency = append(p.Dependency, imp.Path()) if imp.IsPublic { p.PublicDependency = append(p.PublicDependency, int32(i)) } if imp.IsWeak { p.WeakDependency = append(p.WeakDependency, int32(i)) } } for i, locs := 0, file.SourceLocations(); i < locs.Len(); i++ { loc := locs.Get(i) l := &descriptorpb.SourceCodeInfo_Location{} l.Path = append(l.Path, loc.Path...) if loc.StartLine == loc.EndLine { l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndColumn)} } else { l.Span = []int32{int32(loc.StartLine), int32(loc.StartColumn), int32(loc.EndLine), int32(loc.EndColumn)} } l.LeadingDetachedComments = append([]string(nil), loc.LeadingDetachedComments...) if loc.LeadingComments != "" { l.LeadingComments = proto.String(loc.LeadingComments) } if loc.TrailingComments != "" { l.TrailingComments = proto.String(loc.TrailingComments) } if p.SourceCodeInfo == nil { p.SourceCodeInfo = &descriptorpb.SourceCodeInfo{} } p.SourceCodeInfo.Location = append(p.SourceCodeInfo.Location, l) } for i, messages := 0, file.Messages(); i < messages.Len(); i++ { p.MessageType = append(p.MessageType, ToDescriptorProto(messages.Get(i))) } for i, enums := 0, file.Enums(); i < enums.Len(); i++ { p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i))) } for i, services := 0, file.Services(); i < services.Len(); i++ { p.Service = append(p.Service, ToServiceDescriptorProto(services.Get(i))) } for i, exts := 0, file.Extensions(); i < exts.Len(); i++ { p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) } if syntax := file.Syntax(); syntax != protoreflect.Proto2 { p.Syntax = proto.String(file.Syntax().String()) } return p } // ToDescriptorProto copies a protoreflect.MessageDescriptor into a // google.protobuf.DescriptorProto message. func ToDescriptorProto(message protoreflect.MessageDescriptor) *descriptorpb.DescriptorProto { p := &descriptorpb.DescriptorProto{ Name: proto.String(string(message.Name())), Options: proto.Clone(message.Options()).(*descriptorpb.MessageOptions), } for i, fields := 0, message.Fields(); i < fields.Len(); i++ { p.Field = append(p.Field, ToFieldDescriptorProto(fields.Get(i))) } for i, exts := 0, message.Extensions(); i < exts.Len(); i++ { p.Extension = append(p.Extension, ToFieldDescriptorProto(exts.Get(i))) } for i, messages := 0, message.Messages(); i < messages.Len(); i++ { p.NestedType = append(p.NestedType, ToDescriptorProto(messages.Get(i))) } for i, enums := 0, message.Enums(); i < enums.Len(); i++ { p.EnumType = append(p.EnumType, ToEnumDescriptorProto(enums.Get(i))) } for i, xranges := 0, message.ExtensionRanges(); i < xranges.Len(); i++ { xrange := xranges.Get(i) p.ExtensionRange = append(p.ExtensionRange, &descriptorpb.DescriptorProto_ExtensionRange{ Start: proto.Int32(int32(xrange[0])), End: proto.Int32(int32(xrange[1])), Options: proto.Clone(message.ExtensionRangeOptions(i)).(*descriptorpb.ExtensionRangeOptions), }) } for i, oneofs := 0, message.Oneofs(); i < oneofs.Len(); i++ { p.OneofDecl = append(p.OneofDecl, ToOneofDescriptorProto(oneofs.Get(i))) } for i, ranges := 0, message.ReservedRanges(); i < ranges.Len(); i++ { rrange := ranges.Get(i) p.ReservedRange = append(p.ReservedRange, &descriptorpb.DescriptorProto_ReservedRange{ Start: proto.Int32(int32(rrange[0])), End: proto.Int32(int32(rrange[1])), }) } for i, names := 0, message.ReservedNames(); i < names.Len(); i++ { p.ReservedName = append(p.ReservedName, string(names.Get(i))) } return p } // ToFieldDescriptorProto copies a protoreflect.FieldDescriptor into a // google.protobuf.FieldDescriptorProto message. func ToFieldDescriptorProto(field protoreflect.FieldDescriptor) *descriptorpb.FieldDescriptorProto { p := &descriptorpb.FieldDescriptorProto{ Name: proto.String(string(field.Name())), Number: proto.Int32(int32(field.Number())), Label: descriptorpb.FieldDescriptorProto_Label(field.Cardinality()).Enum(), Options: proto.Clone(field.Options()).(*descriptorpb.FieldOptions), } if field.IsExtension() { p.Extendee = fullNameOf(field.ContainingMessage()) } if field.Kind().IsValid() { p.Type = descriptorpb.FieldDescriptorProto_Type(field.Kind()).Enum() } if field.Enum() != nil { p.TypeName = fullNameOf(field.Enum()) } if field.Message() != nil { p.TypeName = fullNameOf(field.Message()) } if field.HasJSONName() { // A bug in older versions of protoc would always populate the // "json_name" option for extensions when it is meaningless. // When it did so, it would always use the camel-cased field name. if field.IsExtension() { p.JsonName = proto.String(strs.JSONCamelCase(string(field.Name()))) } else { p.JsonName = proto.String(field.JSONName()) } } if field.Syntax() == protoreflect.Proto3 && field.HasOptionalKeyword() { p.Proto3Optional = proto.Bool(true) } if field.HasDefault() { def, err := defval.Marshal(field.Default(), field.DefaultEnumValue(), field.Kind(), defval.Descriptor) if err != nil && field.DefaultEnumValue() != nil { def = string(field.DefaultEnumValue().Name()) // occurs for unresolved enum values } else if err != nil { panic(fmt.Sprintf("%v: %v", field.FullName(), err)) } p.DefaultValue = proto.String(def) } if oneof := field.ContainingOneof(); oneof != nil { p.OneofIndex = proto.Int32(int32(oneof.Index())) } return p } // ToOneofDescriptorProto copies a protoreflect.OneofDescriptor into a // google.protobuf.OneofDescriptorProto message. func ToOneofDescriptorProto(oneof protoreflect.OneofDescriptor) *descriptorpb.OneofDescriptorProto { return &descriptorpb.OneofDescriptorProto{ Name: proto.String(string(oneof.Name())), Options: proto.Clone(oneof.Options()).(*descriptorpb.OneofOptions), } } // ToEnumDescriptorProto copies a protoreflect.EnumDescriptor into a // google.protobuf.EnumDescriptorProto message. func ToEnumDescriptorProto(enum protoreflect.EnumDescriptor) *descriptorpb.EnumDescriptorProto { p := &descriptorpb.EnumDescriptorProto{ Name: proto.String(string(enum.Name())), Options: proto.Clone(enum.Options()).(*descriptorpb.EnumOptions), } for i, values := 0, enum.Values(); i < values.Len(); i++ { p.Value = append(p.Value, ToEnumValueDescriptorProto(values.Get(i))) } for i, ranges := 0, enum.ReservedRanges(); i < ranges.Len(); i++ { rrange := ranges.Get(i) p.ReservedRange = append(p.ReservedRange, &descriptorpb.EnumDescriptorProto_EnumReservedRange{ Start: proto.Int32(int32(rrange[0])), End: proto.Int32(int32(rrange[1])), }) } for i, names := 0, enum.ReservedNames(); i < names.Len(); i++ { p.ReservedName = append(p.ReservedName, string(names.Get(i))) } return p } // ToEnumValueDescriptorProto copies a protoreflect.EnumValueDescriptor into a // google.protobuf.EnumValueDescriptorProto message. func ToEnumValueDescriptorProto(value protoreflect.EnumValueDescriptor) *descriptorpb.EnumValueDescriptorProto { return &descriptorpb.EnumValueDescriptorProto{ Name: proto.String(string(value.Name())), Number: proto.Int32(int32(value.Number())), Options: proto.Clone(value.Options()).(*descriptorpb.EnumValueOptions), } } // ToServiceDescriptorProto copies a protoreflect.ServiceDescriptor into a // google.protobuf.ServiceDescriptorProto message. func ToServiceDescriptorProto(service protoreflect.ServiceDescriptor) *descriptorpb.ServiceDescriptorProto { p := &descriptorpb.ServiceDescriptorProto{ Name: proto.String(string(service.Name())), Options: proto.Clone(service.Options()).(*descriptorpb.ServiceOptions), } for i, methods := 0, service.Methods(); i < methods.Len(); i++ { p.Method = append(p.Method, ToMethodDescriptorProto(methods.Get(i))) } return p } // ToMethodDescriptorProto copies a protoreflect.MethodDescriptor into a // google.protobuf.MethodDescriptorProto message. func ToMethodDescriptorProto(method protoreflect.MethodDescriptor) *descriptorpb.MethodDescriptorProto { p := &descriptorpb.MethodDescriptorProto{ Name: proto.String(string(method.Name())), InputType: fullNameOf(method.Input()), OutputType: fullNameOf(method.Output()), Options: proto.Clone(method.Options()).(*descriptorpb.MethodOptions), } if method.IsStreamingClient() { p.ClientStreaming = proto.Bool(true) } if method.IsStreamingServer() { p.ServerStreaming = proto.Bool(true) } return p } func fullNameOf(d protoreflect.Descriptor) *string { if d == nil { return nil } if strings.HasPrefix(string(d.FullName()), unknownPrefix) { return proto.String(string(d.FullName()[len(unknownPrefix):])) } return proto.String("." + string(d.FullName())) } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/methods.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "google.golang.org/protobuf/internal/pragma" ) // The following types are used by the fast-path Message.ProtoMethods method. // // To avoid polluting the public protoreflect API with types used only by // low-level implementations, the canonical definitions of these types are // in the runtime/protoiface package. The definitions here and in protoiface // must be kept in sync. type ( methods = struct { pragma.NoUnkeyedLiterals Flags supportFlags Size func(sizeInput) sizeOutput Marshal func(marshalInput) (marshalOutput, error) Unmarshal func(unmarshalInput) (unmarshalOutput, error) Merge func(mergeInput) mergeOutput CheckInitialized func(checkInitializedInput) (checkInitializedOutput, error) } supportFlags = uint64 sizeInput = struct { pragma.NoUnkeyedLiterals Message Message Flags uint8 } sizeOutput = struct { pragma.NoUnkeyedLiterals Size int } marshalInput = struct { pragma.NoUnkeyedLiterals Message Message Buf []byte Flags uint8 } marshalOutput = struct { pragma.NoUnkeyedLiterals Buf []byte } unmarshalInput = struct { pragma.NoUnkeyedLiterals Message Message Buf []byte Flags uint8 Resolver interface { FindExtensionByName(field FullName) (ExtensionType, error) FindExtensionByNumber(message FullName, field FieldNumber) (ExtensionType, error) } } unmarshalOutput = struct { pragma.NoUnkeyedLiterals Flags uint8 } mergeInput = struct { pragma.NoUnkeyedLiterals Source Message Destination Message } mergeOutput = struct { pragma.NoUnkeyedLiterals Flags uint8 } checkInitializedInput = struct { pragma.NoUnkeyedLiterals Message Message } checkInitializedOutput = struct { pragma.NoUnkeyedLiterals } ) ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/proto.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoreflect provides interfaces to dynamically manipulate messages. // // This package includes type descriptors which describe the structure of types // defined in proto source files and value interfaces which provide the // ability to examine and manipulate the contents of messages. // // // Protocol Buffer Descriptors // // Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor) // are immutable objects that represent protobuf type information. // They are wrappers around the messages declared in descriptor.proto. // Protobuf descriptors alone lack any information regarding Go types. // // Enums and messages generated by this module implement Enum and ProtoMessage, // where the Descriptor and ProtoReflect.Descriptor accessors respectively // return the protobuf descriptor for the values. // // The protobuf descriptor interfaces are not meant to be implemented by // user code since they might need to be extended in the future to support // additions to the protobuf language. // The "google.golang.org/protobuf/reflect/protodesc" package converts between // google.protobuf.DescriptorProto messages and protobuf descriptors. // // // Go Type Descriptors // // A type descriptor (e.g., EnumType or MessageType) is a constructor for // a concrete Go type that represents the associated protobuf descriptor. // There is commonly a one-to-one relationship between protobuf descriptors and // Go type descriptors, but it can potentially be a one-to-many relationship. // // Enums and messages generated by this module implement Enum and ProtoMessage, // where the Type and ProtoReflect.Type accessors respectively // return the protobuf descriptor for the values. // // The "google.golang.org/protobuf/types/dynamicpb" package can be used to // create Go type descriptors from protobuf descriptors. // // // Value Interfaces // // The Enum and Message interfaces provide a reflective view over an // enum or message instance. For enums, it provides the ability to retrieve // the enum value number for any concrete enum type. For messages, it provides // the ability to access or manipulate fields of the message. // // To convert a proto.Message to a protoreflect.Message, use the // former's ProtoReflect method. Since the ProtoReflect method is new to the // v2 message interface, it may not be present on older message implementations. // The "github.com/golang/protobuf/proto".MessageReflect function can be used // to obtain a reflective view on older messages. // // // Relationships // // The following diagrams demonstrate the relationships between // various types declared in this package. // // // ┌───────────────────────────────────┐ // V │ // ┌────────────── New(n) ─────────────┐ │ // │ │ │ // │ ┌──── Descriptor() ──┐ │ ┌── Number() ──┐ │ // │ │ V V │ V │ // ╔════════════╗ ╔════════════════╗ ╔════════╗ ╔════════════╗ // ║ EnumType ║ ║ EnumDescriptor ║ ║ Enum ║ ║ EnumNumber ║ // ╚════════════╝ ╚════════════════╝ ╚════════╝ ╚════════════╝ // Λ Λ │ │ // │ └─── Descriptor() ──┘ │ // │ │ // └────────────────── Type() ───────┘ // // • An EnumType describes a concrete Go enum type. // It has an EnumDescriptor and can construct an Enum instance. // // • An EnumDescriptor describes an abstract protobuf enum type. // // • An Enum is a concrete enum instance. Generated enums implement Enum. // // // ┌──────────────── New() ─────────────────┐ // │ │ // │ ┌─── Descriptor() ─────┐ │ ┌── Interface() ───┐ // │ │ V V │ V // ╔═════════════╗ ╔═══════════════════╗ ╔═════════╗ ╔══════════════╗ // ║ MessageType ║ ║ MessageDescriptor ║ ║ Message ║ ║ ProtoMessage ║ // ╚═════════════╝ ╚═══════════════════╝ ╚═════════╝ ╚══════════════╝ // Λ Λ │ │ Λ │ // │ └──── Descriptor() ────┘ │ └─ ProtoReflect() ─┘ // │ │ // └─────────────────── Type() ─────────┘ // // • A MessageType describes a concrete Go message type. // It has a MessageDescriptor and can construct a Message instance. // // • A MessageDescriptor describes an abstract protobuf message type. // // • A Message is a concrete message instance. Generated messages implement // ProtoMessage, which can convert to/from a Message. // // // ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ // │ V │ V // ╔═══════════════╗ ╔═════════════════════════╗ ╔═════════════════════╗ // ║ ExtensionType ║ ║ ExtensionTypeDescriptor ║ ║ ExtensionDescriptor ║ // ╚═══════════════╝ ╚═════════════════════════╝ ╚═════════════════════╝ // Λ │ │ Λ │ Λ // └─────── Type() ───────┘ │ └─── may implement ────┘ │ // │ │ // └────── implements ────────┘ // // • An ExtensionType describes a concrete Go implementation of an extension. // It has an ExtensionTypeDescriptor and can convert to/from // abstract Values and Go values. // // • An ExtensionTypeDescriptor is an ExtensionDescriptor // which also has an ExtensionType. // // • An ExtensionDescriptor describes an abstract protobuf extension field and // may not always be an ExtensionTypeDescriptor. package protoreflect import ( "fmt" "strings" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/pragma" ) type doNotImplement pragma.DoNotImplement // ProtoMessage is the top-level interface that all proto messages implement. // This is declared in the protoreflect package to avoid a cyclic dependency; // use the proto.Message type instead, which aliases this type. type ProtoMessage interface{ ProtoReflect() Message } // Syntax is the language version of the proto file. type Syntax syntax type syntax int8 // keep exact type opaque as the int type may change const ( Proto2 Syntax = 2 Proto3 Syntax = 3 ) // IsValid reports whether the syntax is valid. func (s Syntax) IsValid() bool { switch s { case Proto2, Proto3: return true default: return false } } // String returns s as a proto source identifier (e.g., "proto2"). func (s Syntax) String() string { switch s { case Proto2: return "proto2" case Proto3: return "proto3" default: return fmt.Sprintf("", s) } } // GoString returns s as a Go source identifier (e.g., "Proto2"). func (s Syntax) GoString() string { switch s { case Proto2: return "Proto2" case Proto3: return "Proto3" default: return fmt.Sprintf("Syntax(%d)", s) } } // Cardinality determines whether a field is optional, required, or repeated. type Cardinality cardinality type cardinality int8 // keep exact type opaque as the int type may change // Constants as defined by the google.protobuf.Cardinality enumeration. const ( Optional Cardinality = 1 // appears zero or one times Required Cardinality = 2 // appears exactly one time; invalid with Proto3 Repeated Cardinality = 3 // appears zero or more times ) // IsValid reports whether the cardinality is valid. func (c Cardinality) IsValid() bool { switch c { case Optional, Required, Repeated: return true default: return false } } // String returns c as a proto source identifier (e.g., "optional"). func (c Cardinality) String() string { switch c { case Optional: return "optional" case Required: return "required" case Repeated: return "repeated" default: return fmt.Sprintf("", c) } } // GoString returns c as a Go source identifier (e.g., "Optional"). func (c Cardinality) GoString() string { switch c { case Optional: return "Optional" case Required: return "Required" case Repeated: return "Repeated" default: return fmt.Sprintf("Cardinality(%d)", c) } } // Kind indicates the basic proto kind of a field. type Kind kind type kind int8 // keep exact type opaque as the int type may change // Constants as defined by the google.protobuf.Field.Kind enumeration. const ( BoolKind Kind = 8 EnumKind Kind = 14 Int32Kind Kind = 5 Sint32Kind Kind = 17 Uint32Kind Kind = 13 Int64Kind Kind = 3 Sint64Kind Kind = 18 Uint64Kind Kind = 4 Sfixed32Kind Kind = 15 Fixed32Kind Kind = 7 FloatKind Kind = 2 Sfixed64Kind Kind = 16 Fixed64Kind Kind = 6 DoubleKind Kind = 1 StringKind Kind = 9 BytesKind Kind = 12 MessageKind Kind = 11 GroupKind Kind = 10 ) // IsValid reports whether the kind is valid. func (k Kind) IsValid() bool { switch k { case BoolKind, EnumKind, Int32Kind, Sint32Kind, Uint32Kind, Int64Kind, Sint64Kind, Uint64Kind, Sfixed32Kind, Fixed32Kind, FloatKind, Sfixed64Kind, Fixed64Kind, DoubleKind, StringKind, BytesKind, MessageKind, GroupKind: return true default: return false } } // String returns k as a proto source identifier (e.g., "bool"). func (k Kind) String() string { switch k { case BoolKind: return "bool" case EnumKind: return "enum" case Int32Kind: return "int32" case Sint32Kind: return "sint32" case Uint32Kind: return "uint32" case Int64Kind: return "int64" case Sint64Kind: return "sint64" case Uint64Kind: return "uint64" case Sfixed32Kind: return "sfixed32" case Fixed32Kind: return "fixed32" case FloatKind: return "float" case Sfixed64Kind: return "sfixed64" case Fixed64Kind: return "fixed64" case DoubleKind: return "double" case StringKind: return "string" case BytesKind: return "bytes" case MessageKind: return "message" case GroupKind: return "group" default: return fmt.Sprintf("", k) } } // GoString returns k as a Go source identifier (e.g., "BoolKind"). func (k Kind) GoString() string { switch k { case BoolKind: return "BoolKind" case EnumKind: return "EnumKind" case Int32Kind: return "Int32Kind" case Sint32Kind: return "Sint32Kind" case Uint32Kind: return "Uint32Kind" case Int64Kind: return "Int64Kind" case Sint64Kind: return "Sint64Kind" case Uint64Kind: return "Uint64Kind" case Sfixed32Kind: return "Sfixed32Kind" case Fixed32Kind: return "Fixed32Kind" case FloatKind: return "FloatKind" case Sfixed64Kind: return "Sfixed64Kind" case Fixed64Kind: return "Fixed64Kind" case DoubleKind: return "DoubleKind" case StringKind: return "StringKind" case BytesKind: return "BytesKind" case MessageKind: return "MessageKind" case GroupKind: return "GroupKind" default: return fmt.Sprintf("Kind(%d)", k) } } // FieldNumber is the field number in a message. type FieldNumber = protowire.Number // FieldNumbers represent a list of field numbers. type FieldNumbers interface { // Len reports the number of fields in the list. Len() int // Get returns the ith field number. It panics if out of bounds. Get(i int) FieldNumber // Has reports whether n is within the list of fields. Has(n FieldNumber) bool doNotImplement } // FieldRanges represent a list of field number ranges. type FieldRanges interface { // Len reports the number of ranges in the list. Len() int // Get returns the ith range. It panics if out of bounds. Get(i int) [2]FieldNumber // start inclusive; end exclusive // Has reports whether n is within any of the ranges. Has(n FieldNumber) bool doNotImplement } // EnumNumber is the numeric value for an enum. type EnumNumber int32 // EnumRanges represent a list of enum number ranges. type EnumRanges interface { // Len reports the number of ranges in the list. Len() int // Get returns the ith range. It panics if out of bounds. Get(i int) [2]EnumNumber // start inclusive; end inclusive // Has reports whether n is within any of the ranges. Has(n EnumNumber) bool doNotImplement } // Name is the short name for a proto declaration. This is not the name // as used in Go source code, which might not be identical to the proto name. type Name string // e.g., "Kind" // IsValid reports whether s is a syntactically valid name. // An empty name is invalid. func (s Name) IsValid() bool { return consumeIdent(string(s)) == len(s) } // Names represent a list of names. type Names interface { // Len reports the number of names in the list. Len() int // Get returns the ith name. It panics if out of bounds. Get(i int) Name // Has reports whether s matches any names in the list. Has(s Name) bool doNotImplement } // FullName is a qualified name that uniquely identifies a proto declaration. // A qualified name is the concatenation of the proto package along with the // fully-declared name (i.e., name of parent preceding the name of the child), // with a '.' delimiter placed between each Name. // // This should not have any leading or trailing dots. type FullName string // e.g., "google.protobuf.Field.Kind" // IsValid reports whether s is a syntactically valid full name. // An empty full name is invalid. func (s FullName) IsValid() bool { i := consumeIdent(string(s)) if i < 0 { return false } for len(s) > i { if s[i] != '.' { return false } i++ n := consumeIdent(string(s[i:])) if n < 0 { return false } i += n } return true } func consumeIdent(s string) (i int) { if len(s) == 0 || !isLetter(s[i]) { return -1 } i++ for len(s) > i && isLetterDigit(s[i]) { i++ } return i } func isLetter(c byte) bool { return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') } func isLetterDigit(c byte) bool { return isLetter(c) || ('0' <= c && c <= '9') } // Name returns the short name, which is the last identifier segment. // A single segment FullName is the Name itself. func (n FullName) Name() Name { if i := strings.LastIndexByte(string(n), '.'); i >= 0 { return Name(n[i+1:]) } return Name(n) } // Parent returns the full name with the trailing identifier removed. // A single segment FullName has no parent. func (n FullName) Parent() FullName { if i := strings.LastIndexByte(string(n), '.'); i >= 0 { return n[:i] } return "" } // Append returns the qualified name appended with the provided short name. // // Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid func (n FullName) Append(s Name) FullName { if n == "" { return FullName(s) } return n + "." + FullName(s) } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/source.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "strconv" ) // SourceLocations is a list of source locations. type SourceLocations interface { // Len reports the number of source locations in the proto file. Len() int // Get returns the ith SourceLocation. It panics if out of bounds. Get(int) SourceLocation // ByPath returns the SourceLocation for the given path, // returning the first location if multiple exist for the same path. // If multiple locations exist for the same path, // then SourceLocation.Next index can be used to identify the // index of the next SourceLocation. // If no location exists for this path, it returns the zero value. ByPath(path SourcePath) SourceLocation // ByDescriptor returns the SourceLocation for the given descriptor, // returning the first location if multiple exist for the same path. // If no location exists for this descriptor, it returns the zero value. ByDescriptor(desc Descriptor) SourceLocation doNotImplement } // SourceLocation describes a source location and // corresponds with the google.protobuf.SourceCodeInfo.Location message. type SourceLocation struct { // Path is the path to the declaration from the root file descriptor. // The contents of this slice must not be mutated. Path SourcePath // StartLine and StartColumn are the zero-indexed starting location // in the source file for the declaration. StartLine, StartColumn int // EndLine and EndColumn are the zero-indexed ending location // in the source file for the declaration. // In the descriptor.proto, the end line may be omitted if it is identical // to the start line. Here, it is always populated. EndLine, EndColumn int // LeadingDetachedComments are the leading detached comments // for the declaration. The contents of this slice must not be mutated. LeadingDetachedComments []string // LeadingComments is the leading attached comment for the declaration. LeadingComments string // TrailingComments is the trailing attached comment for the declaration. TrailingComments string // Next is an index into SourceLocations for the next source location that // has the same Path. It is zero if there is no next location. Next int } // SourcePath identifies part of a file descriptor for a source location. // The SourcePath is a sequence of either field numbers or indexes into // a repeated field that form a path starting from the root file descriptor. // // See google.protobuf.SourceCodeInfo.Location.path. type SourcePath []int32 // Equal reports whether p1 equals p2. func (p1 SourcePath) Equal(p2 SourcePath) bool { if len(p1) != len(p2) { return false } for i := range p1 { if p1[i] != p2[i] { return false } } return true } // String formats the path in a humanly readable manner. // The output is guaranteed to be deterministic, // making it suitable for use as a key into a Go map. // It is not guaranteed to be stable as the exact output could change // in a future version of this module. // // Example output: // .message_type[6].nested_type[15].field[3] func (p SourcePath) String() string { b := p.appendFileDescriptorProto(nil) for _, i := range p { b = append(b, '.') b = strconv.AppendInt(b, int64(i), 10) } return string(b) } type appendFunc func(*SourcePath, []byte) []byte func (p *SourcePath) appendSingularField(b []byte, name string, f appendFunc) []byte { if len(*p) == 0 { return b } b = append(b, '.') b = append(b, name...) *p = (*p)[1:] if f != nil { b = f(p, b) } return b } func (p *SourcePath) appendRepeatedField(b []byte, name string, f appendFunc) []byte { b = p.appendSingularField(b, name, nil) if len(*p) == 0 || (*p)[0] < 0 { return b } b = append(b, '[') b = strconv.AppendUint(b, uint64((*p)[0]), 10) b = append(b, ']') *p = (*p)[1:] if f != nil { b = f(p, b) } return b } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/source_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package protoreflect func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "package", nil) case 3: b = p.appendRepeatedField(b, "dependency", nil) case 10: b = p.appendRepeatedField(b, "public_dependency", nil) case 11: b = p.appendRepeatedField(b, "weak_dependency", nil) case 4: b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto) case 5: b = p.appendRepeatedField(b, "enum_type", (*SourcePath).appendEnumDescriptorProto) case 6: b = p.appendRepeatedField(b, "service", (*SourcePath).appendServiceDescriptorProto) case 7: b = p.appendRepeatedField(b, "extension", (*SourcePath).appendFieldDescriptorProto) case 8: b = p.appendSingularField(b, "options", (*SourcePath).appendFileOptions) case 9: b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo) case 12: b = p.appendSingularField(b, "syntax", nil) } return b } func (p *SourcePath) appendDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "field", (*SourcePath).appendFieldDescriptorProto) case 6: b = p.appendRepeatedField(b, "extension", (*SourcePath).appendFieldDescriptorProto) case 3: b = p.appendRepeatedField(b, "nested_type", (*SourcePath).appendDescriptorProto) case 4: b = p.appendRepeatedField(b, "enum_type", (*SourcePath).appendEnumDescriptorProto) case 5: b = p.appendRepeatedField(b, "extension_range", (*SourcePath).appendDescriptorProto_ExtensionRange) case 8: b = p.appendRepeatedField(b, "oneof_decl", (*SourcePath).appendOneofDescriptorProto) case 7: b = p.appendSingularField(b, "options", (*SourcePath).appendMessageOptions) case 9: b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange) case 10: b = p.appendRepeatedField(b, "reserved_name", nil) } return b } func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "value", (*SourcePath).appendEnumValueDescriptorProto) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendEnumOptions) case 4: b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange) case 5: b = p.appendRepeatedField(b, "reserved_name", nil) } return b } func (p *SourcePath) appendServiceDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "method", (*SourcePath).appendMethodDescriptorProto) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendServiceOptions) } return b } func (p *SourcePath) appendFieldDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 3: b = p.appendSingularField(b, "number", nil) case 4: b = p.appendSingularField(b, "label", nil) case 5: b = p.appendSingularField(b, "type", nil) case 6: b = p.appendSingularField(b, "type_name", nil) case 2: b = p.appendSingularField(b, "extendee", nil) case 7: b = p.appendSingularField(b, "default_value", nil) case 9: b = p.appendSingularField(b, "oneof_index", nil) case 10: b = p.appendSingularField(b, "json_name", nil) case 8: b = p.appendSingularField(b, "options", (*SourcePath).appendFieldOptions) case 17: b = p.appendSingularField(b, "proto3_optional", nil) } return b } func (p *SourcePath) appendFileOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "java_package", nil) case 8: b = p.appendSingularField(b, "java_outer_classname", nil) case 10: b = p.appendSingularField(b, "java_multiple_files", nil) case 20: b = p.appendSingularField(b, "java_generate_equals_and_hash", nil) case 27: b = p.appendSingularField(b, "java_string_check_utf8", nil) case 9: b = p.appendSingularField(b, "optimize_for", nil) case 11: b = p.appendSingularField(b, "go_package", nil) case 16: b = p.appendSingularField(b, "cc_generic_services", nil) case 17: b = p.appendSingularField(b, "java_generic_services", nil) case 18: b = p.appendSingularField(b, "py_generic_services", nil) case 42: b = p.appendSingularField(b, "php_generic_services", nil) case 23: b = p.appendSingularField(b, "deprecated", nil) case 31: b = p.appendSingularField(b, "cc_enable_arenas", nil) case 36: b = p.appendSingularField(b, "objc_class_prefix", nil) case 37: b = p.appendSingularField(b, "csharp_namespace", nil) case 39: b = p.appendSingularField(b, "swift_prefix", nil) case 40: b = p.appendSingularField(b, "php_class_prefix", nil) case 41: b = p.appendSingularField(b, "php_namespace", nil) case 44: b = p.appendSingularField(b, "php_metadata_namespace", nil) case 45: b = p.appendSingularField(b, "ruby_package", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendSourceCodeInfo(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendRepeatedField(b, "location", (*SourcePath).appendSourceCodeInfo_Location) } return b } func (p *SourcePath) appendDescriptorProto_ExtensionRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendExtensionRangeOptions) } return b } func (p *SourcePath) appendOneofDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "options", (*SourcePath).appendOneofOptions) } return b } func (p *SourcePath) appendMessageOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "message_set_wire_format", nil) case 2: b = p.appendSingularField(b, "no_standard_descriptor_accessor", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 7: b = p.appendSingularField(b, "map_entry", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendDescriptorProto_ReservedRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) } return b } func (p *SourcePath) appendEnumValueDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "number", nil) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendEnumValueOptions) } return b } func (p *SourcePath) appendEnumOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 2: b = p.appendSingularField(b, "allow_alias", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendEnumDescriptorProto_EnumReservedRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) } return b } func (p *SourcePath) appendMethodDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "input_type", nil) case 3: b = p.appendSingularField(b, "output_type", nil) case 4: b = p.appendSingularField(b, "options", (*SourcePath).appendMethodOptions) case 5: b = p.appendSingularField(b, "client_streaming", nil) case 6: b = p.appendSingularField(b, "server_streaming", nil) } return b } func (p *SourcePath) appendServiceOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 33: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendFieldOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "ctype", nil) case 2: b = p.appendSingularField(b, "packed", nil) case 6: b = p.appendSingularField(b, "jstype", nil) case 5: b = p.appendSingularField(b, "lazy", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 10: b = p.appendSingularField(b, "weak", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendUninterpretedOption(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 2: b = p.appendRepeatedField(b, "name", (*SourcePath).appendUninterpretedOption_NamePart) case 3: b = p.appendSingularField(b, "identifier_value", nil) case 4: b = p.appendSingularField(b, "positive_int_value", nil) case 5: b = p.appendSingularField(b, "negative_int_value", nil) case 6: b = p.appendSingularField(b, "double_value", nil) case 7: b = p.appendSingularField(b, "string_value", nil) case 8: b = p.appendSingularField(b, "aggregate_value", nil) } return b } func (p *SourcePath) appendSourceCodeInfo_Location(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendRepeatedField(b, "path", nil) case 2: b = p.appendRepeatedField(b, "span", nil) case 3: b = p.appendSingularField(b, "leading_comments", nil) case 4: b = p.appendSingularField(b, "trailing_comments", nil) case 6: b = p.appendRepeatedField(b, "leading_detached_comments", nil) } return b } func (p *SourcePath) appendExtensionRangeOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendOneofOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendEnumValueOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendMethodOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 33: b = p.appendSingularField(b, "deprecated", nil) case 34: b = p.appendSingularField(b, "idempotency_level", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name_part", nil) case 2: b = p.appendSingularField(b, "is_extension", nil) } return b } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/type.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect // Descriptor provides a set of accessors that are common to every descriptor. // Each descriptor type wraps the equivalent google.protobuf.XXXDescriptorProto, // but provides efficient lookup and immutability. // // Each descriptor is comparable. Equality implies that the two types are // exactly identical. However, it is possible for the same semantically // identical proto type to be represented by multiple type descriptors. // // For example, suppose we have t1 and t2 which are both MessageDescriptors. // If t1 == t2, then the types are definitely equal and all accessors return // the same information. However, if t1 != t2, then it is still possible that // they still represent the same proto type (e.g., t1.FullName == t2.FullName). // This can occur if a descriptor type is created dynamically, or multiple // versions of the same proto type are accidentally linked into the Go binary. type Descriptor interface { // ParentFile returns the parent file descriptor that this descriptor // is declared within. The parent file for the file descriptor is itself. // // Support for this functionality is optional and may return nil. ParentFile() FileDescriptor // Parent returns the parent containing this descriptor declaration. // The following shows the mapping from child type to possible parent types: // // ╔═════════════════════╤═══════════════════════════════════╗ // ║ Child type │ Possible parent types ║ // ╠═════════════════════╪═══════════════════════════════════╣ // ║ FileDescriptor │ nil ║ // ║ MessageDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ FieldDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ OneofDescriptor │ MessageDescriptor ║ // ║ EnumDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ EnumValueDescriptor │ EnumDescriptor ║ // ║ ServiceDescriptor │ FileDescriptor ║ // ║ MethodDescriptor │ ServiceDescriptor ║ // ╚═════════════════════╧═══════════════════════════════════╝ // // Support for this functionality is optional and may return nil. Parent() Descriptor // Index returns the index of this descriptor within its parent. // It returns 0 if the descriptor does not have a parent or if the parent // is unknown. Index() int // Syntax is the protobuf syntax. Syntax() Syntax // e.g., Proto2 or Proto3 // Name is the short name of the declaration (i.e., FullName.Name). Name() Name // e.g., "Any" // FullName is the fully-qualified name of the declaration. // // The FullName is a concatenation of the full name of the type that this // type is declared within and the declaration name. For example, // field "foo_field" in message "proto.package.MyMessage" is // uniquely identified as "proto.package.MyMessage.foo_field". // Enum values are an exception to the rule (see EnumValueDescriptor). FullName() FullName // e.g., "google.protobuf.Any" // IsPlaceholder reports whether type information is missing since a // dependency is not resolved, in which case only name information is known. // // Placeholder types may only be returned by the following accessors // as a result of unresolved dependencies or weak imports: // // ╔═══════════════════════════════════╤═════════════════════╗ // ║ Accessor │ Descriptor ║ // ╠═══════════════════════════════════╪═════════════════════╣ // ║ FileImports.FileDescriptor │ FileDescriptor ║ // ║ FieldDescriptor.Enum │ EnumDescriptor ║ // ║ FieldDescriptor.Message │ MessageDescriptor ║ // ║ FieldDescriptor.DefaultEnumValue │ EnumValueDescriptor ║ // ║ FieldDescriptor.ContainingMessage │ MessageDescriptor ║ // ║ MethodDescriptor.Input │ MessageDescriptor ║ // ║ MethodDescriptor.Output │ MessageDescriptor ║ // ╚═══════════════════════════════════╧═════════════════════╝ // // If true, only Name and FullName are valid. // For FileDescriptor, the Path is also valid. IsPlaceholder() bool // Options returns the descriptor options. The caller must not modify // the returned value. // // To avoid a dependency cycle, this function returns a proto.Message value. // The proto message type returned for each descriptor type is as follows: // ╔═════════════════════╤══════════════════════════════════════════╗ // ║ Go type │ Protobuf message type ║ // ╠═════════════════════╪══════════════════════════════════════════╣ // ║ FileDescriptor │ google.protobuf.FileOptions ║ // ║ EnumDescriptor │ google.protobuf.EnumOptions ║ // ║ EnumValueDescriptor │ google.protobuf.EnumValueOptions ║ // ║ MessageDescriptor │ google.protobuf.MessageOptions ║ // ║ FieldDescriptor │ google.protobuf.FieldOptions ║ // ║ OneofDescriptor │ google.protobuf.OneofOptions ║ // ║ ServiceDescriptor │ google.protobuf.ServiceOptions ║ // ║ MethodDescriptor │ google.protobuf.MethodOptions ║ // ╚═════════════════════╧══════════════════════════════════════════╝ // // This method returns a typed nil-pointer if no options are present. // The caller must import the descriptorpb package to use this. Options() ProtoMessage doNotImplement } // FileDescriptor describes the types in a complete proto file and // corresponds with the google.protobuf.FileDescriptorProto message. // // Top-level declarations: // EnumDescriptor, MessageDescriptor, FieldDescriptor, and/or ServiceDescriptor. type FileDescriptor interface { Descriptor // Descriptor.FullName is identical to Package // Path returns the file name, relative to the source tree root. Path() string // e.g., "path/to/file.proto" // Package returns the protobuf package namespace. Package() FullName // e.g., "google.protobuf" // Imports is a list of imported proto files. Imports() FileImports // Enums is a list of the top-level enum declarations. Enums() EnumDescriptors // Messages is a list of the top-level message declarations. Messages() MessageDescriptors // Extensions is a list of the top-level extension declarations. Extensions() ExtensionDescriptors // Services is a list of the top-level service declarations. Services() ServiceDescriptors // SourceLocations is a list of source locations. SourceLocations() SourceLocations isFileDescriptor } type isFileDescriptor interface{ ProtoType(FileDescriptor) } // FileImports is a list of file imports. type FileImports interface { // Len reports the number of files imported by this proto file. Len() int // Get returns the ith FileImport. It panics if out of bounds. Get(i int) FileImport doNotImplement } // FileImport is the declaration for a proto file import. type FileImport struct { // FileDescriptor is the file type for the given import. // It is a placeholder descriptor if IsWeak is set or if a dependency has // not been regenerated to implement the new reflection APIs. FileDescriptor // IsPublic reports whether this is a public import, which causes this file // to alias declarations within the imported file. The intended use cases // for this feature is the ability to move proto files without breaking // existing dependencies. // // The current file and the imported file must be within proto package. IsPublic bool // IsWeak reports whether this is a weak import, which does not impose // a direct dependency on the target file. // // Weak imports are a legacy proto1 feature. Equivalent behavior is // achieved using proto2 extension fields or proto3 Any messages. IsWeak bool } // MessageDescriptor describes a message and // corresponds with the google.protobuf.DescriptorProto message. // // Nested declarations: // FieldDescriptor, OneofDescriptor, FieldDescriptor, EnumDescriptor, // and/or MessageDescriptor. type MessageDescriptor interface { Descriptor // IsMapEntry indicates that this is an auto-generated message type to // represent the entry type for a map field. // // Map entry messages have only two fields: // • a "key" field with a field number of 1 // • a "value" field with a field number of 2 // The key and value types are determined by these two fields. // // If IsMapEntry is true, it implies that FieldDescriptor.IsMap is true // for some field with this message type. IsMapEntry() bool // Fields is a list of nested field declarations. Fields() FieldDescriptors // Oneofs is a list of nested oneof declarations. Oneofs() OneofDescriptors // ReservedNames is a list of reserved field names. ReservedNames() Names // ReservedRanges is a list of reserved ranges of field numbers. ReservedRanges() FieldRanges // RequiredNumbers is a list of required field numbers. // In Proto3, it is always an empty list. RequiredNumbers() FieldNumbers // ExtensionRanges is the field ranges used for extension fields. // In Proto3, it is always an empty ranges. ExtensionRanges() FieldRanges // ExtensionRangeOptions returns the ith extension range options. // // To avoid a dependency cycle, this method returns a proto.Message value, // which always contains a google.protobuf.ExtensionRangeOptions message. // This method returns a typed nil-pointer if no options are present. // The caller must import the descriptorpb package to use this. ExtensionRangeOptions(i int) ProtoMessage // Enums is a list of nested enum declarations. Enums() EnumDescriptors // Messages is a list of nested message declarations. Messages() MessageDescriptors // Extensions is a list of nested extension declarations. Extensions() ExtensionDescriptors isMessageDescriptor } type isMessageDescriptor interface{ ProtoType(MessageDescriptor) } // MessageType encapsulates a MessageDescriptor with a concrete Go implementation. // It is recommended that implementations of this interface also implement the // MessageFieldTypes interface. type MessageType interface { // New returns a newly allocated empty message. // It may return nil for synthetic messages representing a map entry. New() Message // Zero returns an empty, read-only message. // It may return nil for synthetic messages representing a map entry. Zero() Message // Descriptor returns the message descriptor. // // Invariant: t.Descriptor() == t.New().Descriptor() Descriptor() MessageDescriptor } // MessageFieldTypes extends a MessageType by providing type information // regarding enums and messages referenced by the message fields. type MessageFieldTypes interface { MessageType // Enum returns the EnumType for the ith field in Descriptor.Fields. // It returns nil if the ith field is not an enum kind. // It panics if out of bounds. // // Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum() Enum(i int) EnumType // Message returns the MessageType for the ith field in Descriptor.Fields. // It returns nil if the ith field is not a message or group kind. // It panics if out of bounds. // // Invariant: mt.Message(i).Descriptor() == mt.Descriptor().Fields(i).Message() Message(i int) MessageType } // MessageDescriptors is a list of message declarations. type MessageDescriptors interface { // Len reports the number of messages. Len() int // Get returns the ith MessageDescriptor. It panics if out of bounds. Get(i int) MessageDescriptor // ByName returns the MessageDescriptor for a message named s. // It returns nil if not found. ByName(s Name) MessageDescriptor doNotImplement } // FieldDescriptor describes a field within a message and // corresponds with the google.protobuf.FieldDescriptorProto message. // // It is used for both normal fields defined within the parent message // (e.g., MessageDescriptor.Fields) and fields that extend some remote message // (e.g., FileDescriptor.Extensions or MessageDescriptor.Extensions). type FieldDescriptor interface { Descriptor // Number reports the unique number for this field. Number() FieldNumber // Cardinality reports the cardinality for this field. Cardinality() Cardinality // Kind reports the basic kind for this field. Kind() Kind // HasJSONName reports whether this field has an explicitly set JSON name. HasJSONName() bool // JSONName reports the name used for JSON serialization. // It is usually the camel-cased form of the field name. // Extension fields are represented by the full name surrounded by brackets. JSONName() string // TextName reports the name used for text serialization. // It is usually the name of the field, except that groups use the name // of the inlined message, and extension fields are represented by the // full name surrounded by brackets. TextName() string // HasPresence reports whether the field distinguishes between unpopulated // and default values. HasPresence() bool // IsExtension reports whether this is an extension field. If false, // then Parent and ContainingMessage refer to the same message. // Otherwise, ContainingMessage and Parent likely differ. IsExtension() bool // HasOptionalKeyword reports whether the "optional" keyword was explicitly // specified in the source .proto file. HasOptionalKeyword() bool // IsWeak reports whether this is a weak field, which does not impose a // direct dependency on the target type. // If true, then Message returns a placeholder type. IsWeak() bool // IsPacked reports whether repeated primitive numeric kinds should be // serialized using a packed encoding. // If true, then it implies Cardinality is Repeated. IsPacked() bool // IsList reports whether this field represents a list, // where the value type for the associated field is a List. // It is equivalent to checking whether Cardinality is Repeated and // that IsMap reports false. IsList() bool // IsMap reports whether this field represents a map, // where the value type for the associated field is a Map. // It is equivalent to checking whether Cardinality is Repeated, // that the Kind is MessageKind, and that Message.IsMapEntry reports true. IsMap() bool // MapKey returns the field descriptor for the key in the map entry. // It returns nil if IsMap reports false. MapKey() FieldDescriptor // MapValue returns the field descriptor for the value in the map entry. // It returns nil if IsMap reports false. MapValue() FieldDescriptor // HasDefault reports whether this field has a default value. HasDefault() bool // Default returns the default value for scalar fields. // For proto2, it is the default value as specified in the proto file, // or the zero value if unspecified. // For proto3, it is always the zero value of the scalar. // The Value type is determined by the Kind. Default() Value // DefaultEnumValue returns the enum value descriptor for the default value // of an enum field, and is nil for any other kind of field. DefaultEnumValue() EnumValueDescriptor // ContainingOneof is the containing oneof that this field belongs to, // and is nil if this field is not part of a oneof. ContainingOneof() OneofDescriptor // ContainingMessage is the containing message that this field belongs to. // For extension fields, this may not necessarily be the parent message // that the field is declared within. ContainingMessage() MessageDescriptor // Enum is the enum descriptor if Kind is EnumKind. // It returns nil for any other Kind. Enum() EnumDescriptor // Message is the message descriptor if Kind is // MessageKind or GroupKind. It returns nil for any other Kind. Message() MessageDescriptor isFieldDescriptor } type isFieldDescriptor interface{ ProtoType(FieldDescriptor) } // FieldDescriptors is a list of field declarations. type FieldDescriptors interface { // Len reports the number of fields. Len() int // Get returns the ith FieldDescriptor. It panics if out of bounds. Get(i int) FieldDescriptor // ByName returns the FieldDescriptor for a field named s. // It returns nil if not found. ByName(s Name) FieldDescriptor // ByJSONName returns the FieldDescriptor for a field with s as the JSON name. // It returns nil if not found. ByJSONName(s string) FieldDescriptor // ByTextName returns the FieldDescriptor for a field with s as the text name. // It returns nil if not found. ByTextName(s string) FieldDescriptor // ByNumber returns the FieldDescriptor for a field numbered n. // It returns nil if not found. ByNumber(n FieldNumber) FieldDescriptor doNotImplement } // OneofDescriptor describes a oneof field set within a given message and // corresponds with the google.protobuf.OneofDescriptorProto message. type OneofDescriptor interface { Descriptor // IsSynthetic reports whether this is a synthetic oneof created to support // proto3 optional semantics. If true, Fields contains exactly one field // with HasOptionalKeyword specified. IsSynthetic() bool // Fields is a list of fields belonging to this oneof. Fields() FieldDescriptors isOneofDescriptor } type isOneofDescriptor interface{ ProtoType(OneofDescriptor) } // OneofDescriptors is a list of oneof declarations. type OneofDescriptors interface { // Len reports the number of oneof fields. Len() int // Get returns the ith OneofDescriptor. It panics if out of bounds. Get(i int) OneofDescriptor // ByName returns the OneofDescriptor for a oneof named s. // It returns nil if not found. ByName(s Name) OneofDescriptor doNotImplement } // ExtensionDescriptor is an alias of FieldDescriptor for documentation. type ExtensionDescriptor = FieldDescriptor // ExtensionTypeDescriptor is an ExtensionDescriptor with an associated ExtensionType. type ExtensionTypeDescriptor interface { ExtensionDescriptor // Type returns the associated ExtensionType. Type() ExtensionType // Descriptor returns the plain ExtensionDescriptor without the // associated ExtensionType. Descriptor() ExtensionDescriptor } // ExtensionDescriptors is a list of field declarations. type ExtensionDescriptors interface { // Len reports the number of fields. Len() int // Get returns the ith ExtensionDescriptor. It panics if out of bounds. Get(i int) ExtensionDescriptor // ByName returns the ExtensionDescriptor for a field named s. // It returns nil if not found. ByName(s Name) ExtensionDescriptor doNotImplement } // ExtensionType encapsulates an ExtensionDescriptor with a concrete // Go implementation. The nested field descriptor must be for a extension field. // // While a normal field is a member of the parent message that it is declared // within (see Descriptor.Parent), an extension field is a member of some other // target message (see ExtensionDescriptor.Extendee) and may have no // relationship with the parent. However, the full name of an extension field is // relative to the parent that it is declared within. // // For example: // syntax = "proto2"; // package example; // message FooMessage { // extensions 100 to max; // } // message BarMessage { // extends FooMessage { optional BarMessage bar_field = 100; } // } // // Field "bar_field" is an extension of FooMessage, but its full name is // "example.BarMessage.bar_field" instead of "example.FooMessage.bar_field". type ExtensionType interface { // New returns a new value for the field. // For scalars, this returns the default value in native Go form. New() Value // Zero returns a new value for the field. // For scalars, this returns the default value in native Go form. // For composite types, this returns an empty, read-only message, list, or map. Zero() Value // TypeDescriptor returns the extension type descriptor. TypeDescriptor() ExtensionTypeDescriptor // ValueOf wraps the input and returns it as a Value. // ValueOf panics if the input value is invalid or not the appropriate type. // // ValueOf is more extensive than protoreflect.ValueOf for a given field's // value as it has more type information available. ValueOf(interface{}) Value // InterfaceOf completely unwraps the Value to the underlying Go type. // InterfaceOf panics if the input is nil or does not represent the // appropriate underlying Go type. For composite types, it panics if the // value is not mutable. // // InterfaceOf is able to unwrap the Value further than Value.Interface // as it has more type information available. InterfaceOf(Value) interface{} // IsValidValue reports whether the Value is valid to assign to the field. IsValidValue(Value) bool // IsValidInterface reports whether the input is valid to assign to the field. IsValidInterface(interface{}) bool } // EnumDescriptor describes an enum and // corresponds with the google.protobuf.EnumDescriptorProto message. // // Nested declarations: // EnumValueDescriptor. type EnumDescriptor interface { Descriptor // Values is a list of nested enum value declarations. Values() EnumValueDescriptors // ReservedNames is a list of reserved enum names. ReservedNames() Names // ReservedRanges is a list of reserved ranges of enum numbers. ReservedRanges() EnumRanges isEnumDescriptor } type isEnumDescriptor interface{ ProtoType(EnumDescriptor) } // EnumType encapsulates an EnumDescriptor with a concrete Go implementation. type EnumType interface { // New returns an instance of this enum type with its value set to n. New(n EnumNumber) Enum // Descriptor returns the enum descriptor. // // Invariant: t.Descriptor() == t.New(0).Descriptor() Descriptor() EnumDescriptor } // EnumDescriptors is a list of enum declarations. type EnumDescriptors interface { // Len reports the number of enum types. Len() int // Get returns the ith EnumDescriptor. It panics if out of bounds. Get(i int) EnumDescriptor // ByName returns the EnumDescriptor for an enum named s. // It returns nil if not found. ByName(s Name) EnumDescriptor doNotImplement } // EnumValueDescriptor describes an enum value and // corresponds with the google.protobuf.EnumValueDescriptorProto message. // // All other proto declarations are in the namespace of the parent. // However, enum values do not follow this rule and are within the namespace // of the parent's parent (i.e., they are a sibling of the containing enum). // Thus, a value named "FOO_VALUE" declared within an enum uniquely identified // as "proto.package.MyEnum" has a full name of "proto.package.FOO_VALUE". type EnumValueDescriptor interface { Descriptor // Number returns the enum value as an integer. Number() EnumNumber isEnumValueDescriptor } type isEnumValueDescriptor interface{ ProtoType(EnumValueDescriptor) } // EnumValueDescriptors is a list of enum value declarations. type EnumValueDescriptors interface { // Len reports the number of enum values. Len() int // Get returns the ith EnumValueDescriptor. It panics if out of bounds. Get(i int) EnumValueDescriptor // ByName returns the EnumValueDescriptor for the enum value named s. // It returns nil if not found. ByName(s Name) EnumValueDescriptor // ByNumber returns the EnumValueDescriptor for the enum value numbered n. // If multiple have the same number, the first one defined is returned // It returns nil if not found. ByNumber(n EnumNumber) EnumValueDescriptor doNotImplement } // ServiceDescriptor describes a service and // corresponds with the google.protobuf.ServiceDescriptorProto message. // // Nested declarations: MethodDescriptor. type ServiceDescriptor interface { Descriptor // Methods is a list of nested message declarations. Methods() MethodDescriptors isServiceDescriptor } type isServiceDescriptor interface{ ProtoType(ServiceDescriptor) } // ServiceDescriptors is a list of service declarations. type ServiceDescriptors interface { // Len reports the number of services. Len() int // Get returns the ith ServiceDescriptor. It panics if out of bounds. Get(i int) ServiceDescriptor // ByName returns the ServiceDescriptor for a service named s. // It returns nil if not found. ByName(s Name) ServiceDescriptor doNotImplement } // MethodDescriptor describes a method and // corresponds with the google.protobuf.MethodDescriptorProto message. type MethodDescriptor interface { Descriptor // Input is the input message descriptor. Input() MessageDescriptor // Output is the output message descriptor. Output() MessageDescriptor // IsStreamingClient reports whether the client streams multiple messages. IsStreamingClient() bool // IsStreamingServer reports whether the server streams multiple messages. IsStreamingServer() bool isMethodDescriptor } type isMethodDescriptor interface{ ProtoType(MethodDescriptor) } // MethodDescriptors is a list of method declarations. type MethodDescriptors interface { // Len reports the number of methods. Len() int // Get returns the ith MethodDescriptor. It panics if out of bounds. Get(i int) MethodDescriptor // ByName returns the MethodDescriptor for a service method named s. // It returns nil if not found. ByName(s Name) MethodDescriptor doNotImplement } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/value.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import "google.golang.org/protobuf/encoding/protowire" // Enum is a reflection interface for a concrete enum value, // which provides type information and a getter for the enum number. // Enum does not provide a mutable API since enums are commonly backed by // Go constants, which are not addressable. type Enum interface { // Descriptor returns enum descriptor, which contains only the protobuf // type information for the enum. Descriptor() EnumDescriptor // Type returns the enum type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the enum descriptor be used instead. Type() EnumType // Number returns the enum value as an integer. Number() EnumNumber } // Message is a reflective interface for a concrete message value, // encapsulating both type and value information for the message. // // Accessor/mutators for individual fields are keyed by FieldDescriptor. // For non-extension fields, the descriptor must exactly match the // field known by the parent message. // For extension fields, the descriptor must implement ExtensionTypeDescriptor, // extend the parent message (i.e., have the same message FullName), and // be within the parent's extension range. // // Each field Value can be a scalar or a composite type (Message, List, or Map). // See Value for the Go types associated with a FieldDescriptor. // Providing a Value that is invalid or of an incorrect type panics. type Message interface { // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. Descriptor() MessageDescriptor // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. Type() MessageType // New returns a newly allocated and mutable empty message. New() Message // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. Interface() ProtoMessage // Range iterates over every populated field in an undefined order, // calling f for each field descriptor and value encountered. // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. Range(f func(FieldDescriptor, Value) bool) // Has reports whether a field is populated. // // Some fields have the property of nullability where it is possible to // distinguish between the default value of a field and whether the field // was explicitly populated with the default value. Singular message fields, // member fields of a oneof, and proto2 scalar fields are nullable. Such // fields are populated only if explicitly set. // // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. Has(FieldDescriptor) bool // Clear clears the field such that a subsequent Has call reports false. // // Clearing an extension field clears both the extension type and value // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. Clear(FieldDescriptor) // Get retrieves the value for a field. // // For unpopulated scalars, it returns the default value, where // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. Get(FieldDescriptor) Value // Set stores the value for a field. // // For a field belonging to a oneof, it implicitly clears any other field // that may be currently set within the same oneof. // For extension fields, it implicitly stores the provided ExtensionType. // When setting a composite type, it is unspecified whether the stored value // aliases the source's memory in any way. If the composite value is an // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. Set(FieldDescriptor, Value) // Mutable returns a mutable reference to a composite type. // // If the field is unpopulated, it may allocate a composite value. // For a field belonging to a oneof, it implicitly clears any other field // that may be currently set within the same oneof. // For extension fields, it implicitly stores the provided ExtensionType // if not already stored. // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. Mutable(FieldDescriptor) Value // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. NewField(FieldDescriptor) Value // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. WhichOneof(OneofDescriptor) FieldDescriptor // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. GetUnknown() RawFields // SetUnknown stores an entire list of unknown fields. // The raw fields must be syntactically valid according to the wire format. // An implementation may panic if this is not the case. // Once stored, the caller must not mutate the content of the RawFields. // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. SetUnknown(RawFields) // IsValid reports whether the message is valid. // // An invalid message is an empty, read-only value. // // An invalid message often corresponds to a nil pointer of the concrete // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool // ProtoMethods returns optional fast-path implementions of various operations. // This method may return nil. // // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. ProtoMethods() *methods } // RawFields is the raw bytes for an ordered sequence of fields. // Each field contains both the tag (representing field number and wire type), // and also the wire data itself. type RawFields []byte // IsValid reports whether b is syntactically correct wire format. func (b RawFields) IsValid() bool { for len(b) > 0 { _, _, n := protowire.ConsumeField(b) if n < 0 { return false } b = b[n:] } return true } // List is a zero-indexed, ordered list. // The element Value type is determined by FieldDescriptor.Kind. // Providing a Value that is invalid or of an incorrect type panics. type List interface { // Len reports the number of entries in the List. // Get, Set, and Truncate panic with out of bound indexes. Len() int // Get retrieves the value at the given index. // It never returns an invalid value. Get(int) Value // Set stores a value for the given index. // When setting a composite type, it is unspecified whether the set // value aliases the source's memory in any way. // // Set is a mutating operation and unsafe for concurrent use. Set(int, Value) // Append appends the provided value to the end of the list. // When appending a composite type, it is unspecified whether the appended // value aliases the source's memory in any way. // // Append is a mutating operation and unsafe for concurrent use. Append(Value) // AppendMutable appends a new, empty, mutable message value to the end // of the list and returns it. // It panics if the list does not contain a message type. AppendMutable() Value // Truncate truncates the list to a smaller length. // // Truncate is a mutating operation and unsafe for concurrent use. Truncate(int) // NewElement returns a new value for a list element. // For enums, this returns the first enum value. // For other scalars, this returns the zero value. // For messages, this returns a new, empty, mutable value. NewElement() Value // IsValid reports whether the list is valid. // // An invalid list is an empty, read-only value. // // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool } // Map is an unordered, associative map. // The entry MapKey type is determined by FieldDescriptor.MapKey.Kind. // The entry Value type is determined by FieldDescriptor.MapValue.Kind. // Providing a MapKey or Value that is invalid or of an incorrect type panics. type Map interface { // Len reports the number of elements in the map. Len() int // Range iterates over every map entry in an undefined order, // calling f for each key and value encountered. // Range calls f Len times unless f returns false, which stops iteration. // While iterating, mutating operations may only be performed // on the current map key. Range(f func(MapKey, Value) bool) // Has reports whether an entry with the given key is in the map. Has(MapKey) bool // Clear clears the entry associated with they given key. // The operation does nothing if there is no entry associated with the key. // // Clear is a mutating operation and unsafe for concurrent use. Clear(MapKey) // Get retrieves the value for an entry with the given key. // It returns an invalid value for non-existent entries. Get(MapKey) Value // Set stores the value for an entry with the given key. // It panics when given a key or value that is invalid or the wrong type. // When setting a composite type, it is unspecified whether the set // value aliases the source's memory in any way. // // Set is a mutating operation and unsafe for concurrent use. Set(MapKey, Value) // Mutable retrieves a mutable reference to the entry for the given key. // If no entry exists for the key, it creates a new, empty, mutable value // and stores it as the entry for the key. // It panics if the map value is not a message. Mutable(MapKey) Value // NewValue returns a new value assignable as a map value. // For enums, this returns the first enum value. // For other scalars, this returns the zero value. // For messages, this returns a new, empty, mutable value. NewValue() Value // IsValid reports whether the map is valid. // // An invalid map is an empty, read-only value. // // An invalid message often corresponds to a nil Go map value, // but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/value_pure.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package protoreflect import "google.golang.org/protobuf/internal/pragma" type valueType int const ( nilType valueType = iota boolType int32Type int64Type uint32Type uint64Type float32Type float64Type stringType bytesType enumType ifaceType ) // value is a union where only one type can be represented at a time. // This uses a distinct field for each type. This is type safe in Go, but // occupies more memory than necessary (72B). type value struct { pragma.DoNotCompare // 0B typ valueType // 8B num uint64 // 8B str string // 16B bin []byte // 24B iface interface{} // 16B } func valueOfString(v string) Value { return Value{typ: stringType, str: v} } func valueOfBytes(v []byte) Value { return Value{typ: bytesType, bin: v} } func valueOfIface(v interface{}) Value { return Value{typ: ifaceType, iface: v} } func (v Value) getString() string { return v.str } func (v Value) getBytes() []byte { return v.bin } func (v Value) getIface() interface{} { return v.iface } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/value_union.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "fmt" "math" ) // Value is a union where only one Go type may be set at a time. // The Value is used to represent all possible values a field may take. // The following shows which Go type is used to represent each proto Kind: // // ╔════════════╤═════════════════════════════════════╗ // ║ Go type │ Protobuf kind ║ // ╠════════════╪═════════════════════════════════════╣ // ║ bool │ BoolKind ║ // ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ // ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ // ║ uint32 │ Uint32Kind, Fixed32Kind ║ // ║ uint64 │ Uint64Kind, Fixed64Kind ║ // ║ float32 │ FloatKind ║ // ║ float64 │ DoubleKind ║ // ║ string │ StringKind ║ // ║ []byte │ BytesKind ║ // ║ EnumNumber │ EnumKind ║ // ║ Message │ MessageKind, GroupKind ║ // ╚════════════╧═════════════════════════════════════╝ // // Multiple protobuf Kinds may be represented by a single Go type if the type // can losslessly represent the information for the proto kind. For example, // Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64, // but use different integer encoding methods. // // The List or Map types are used if the field cardinality is repeated. // A field is a List if FieldDescriptor.IsList reports true. // A field is a Map if FieldDescriptor.IsMap reports true. // // Converting to/from a Value and a concrete Go value panics on type mismatch. // For example, ValueOf("hello").Int() panics because this attempts to // retrieve an int64 from a string. type Value value // The protoreflect API uses a custom Value union type instead of interface{} // to keep the future open for performance optimizations. Using an interface{} // always incurs an allocation for primitives (e.g., int64) since it needs to // be boxed on the heap (as interfaces can only contain pointers natively). // Instead, we represent the Value union as a flat struct that internally keeps // track of which type is set. Using unsafe, the Value union can be reduced // down to 24B, which is identical in size to a slice. // // The latest compiler (Go1.11) currently suffers from some limitations: // • With inlining, the compiler should be able to statically prove that // only one of these switch cases are taken and inline one specific case. // See https://golang.org/issue/22310. // ValueOf returns a Value initialized with the concrete value stored in v. // This panics if the type does not match one of the allowed types in the // Value union. func ValueOf(v interface{}) Value { switch v := v.(type) { case nil: return Value{} case bool: return ValueOfBool(v) case int32: return ValueOfInt32(v) case int64: return ValueOfInt64(v) case uint32: return ValueOfUint32(v) case uint64: return ValueOfUint64(v) case float32: return ValueOfFloat32(v) case float64: return ValueOfFloat64(v) case string: return ValueOfString(v) case []byte: return ValueOfBytes(v) case EnumNumber: return ValueOfEnum(v) case Message, List, Map: return valueOfIface(v) case ProtoMessage: panic(fmt.Sprintf("invalid proto.Message(%T) type, expected a protoreflect.Message type", v)) default: panic(fmt.Sprintf("invalid type: %T", v)) } } // ValueOfBool returns a new boolean value. func ValueOfBool(v bool) Value { if v { return Value{typ: boolType, num: 1} } else { return Value{typ: boolType, num: 0} } } // ValueOfInt32 returns a new int32 value. func ValueOfInt32(v int32) Value { return Value{typ: int32Type, num: uint64(v)} } // ValueOfInt64 returns a new int64 value. func ValueOfInt64(v int64) Value { return Value{typ: int64Type, num: uint64(v)} } // ValueOfUint32 returns a new uint32 value. func ValueOfUint32(v uint32) Value { return Value{typ: uint32Type, num: uint64(v)} } // ValueOfUint64 returns a new uint64 value. func ValueOfUint64(v uint64) Value { return Value{typ: uint64Type, num: v} } // ValueOfFloat32 returns a new float32 value. func ValueOfFloat32(v float32) Value { return Value{typ: float32Type, num: uint64(math.Float64bits(float64(v)))} } // ValueOfFloat64 returns a new float64 value. func ValueOfFloat64(v float64) Value { return Value{typ: float64Type, num: uint64(math.Float64bits(float64(v)))} } // ValueOfString returns a new string value. func ValueOfString(v string) Value { return valueOfString(v) } // ValueOfBytes returns a new bytes value. func ValueOfBytes(v []byte) Value { return valueOfBytes(v[:len(v):len(v)]) } // ValueOfEnum returns a new enum value. func ValueOfEnum(v EnumNumber) Value { return Value{typ: enumType, num: uint64(v)} } // ValueOfMessage returns a new Message value. func ValueOfMessage(v Message) Value { return valueOfIface(v) } // ValueOfList returns a new List value. func ValueOfList(v List) Value { return valueOfIface(v) } // ValueOfMap returns a new Map value. func ValueOfMap(v Map) Value { return valueOfIface(v) } // IsValid reports whether v is populated with a value. func (v Value) IsValid() bool { return v.typ != nilType } // Interface returns v as an interface{}. // // Invariant: v == ValueOf(v).Interface() func (v Value) Interface() interface{} { switch v.typ { case nilType: return nil case boolType: return v.Bool() case int32Type: return int32(v.Int()) case int64Type: return int64(v.Int()) case uint32Type: return uint32(v.Uint()) case uint64Type: return uint64(v.Uint()) case float32Type: return float32(v.Float()) case float64Type: return float64(v.Float()) case stringType: return v.String() case bytesType: return v.Bytes() case enumType: return v.Enum() default: return v.getIface() } } func (v Value) typeName() string { switch v.typ { case nilType: return "nil" case boolType: return "bool" case int32Type: return "int32" case int64Type: return "int64" case uint32Type: return "uint32" case uint64Type: return "uint64" case float32Type: return "float32" case float64Type: return "float64" case stringType: return "string" case bytesType: return "bytes" case enumType: return "enum" default: switch v := v.getIface().(type) { case Message: return "message" case List: return "list" case Map: return "map" default: return fmt.Sprintf("", v) } } } func (v Value) panicMessage(what string) string { return fmt.Sprintf("type mismatch: cannot convert %v to %s", v.typeName(), what) } // Bool returns v as a bool and panics if the type is not a bool. func (v Value) Bool() bool { switch v.typ { case boolType: return v.num > 0 default: panic(v.panicMessage("bool")) } } // Int returns v as a int64 and panics if the type is not a int32 or int64. func (v Value) Int() int64 { switch v.typ { case int32Type, int64Type: return int64(v.num) default: panic(v.panicMessage("int")) } } // Uint returns v as a uint64 and panics if the type is not a uint32 or uint64. func (v Value) Uint() uint64 { switch v.typ { case uint32Type, uint64Type: return uint64(v.num) default: panic(v.panicMessage("uint")) } } // Float returns v as a float64 and panics if the type is not a float32 or float64. func (v Value) Float() float64 { switch v.typ { case float32Type, float64Type: return math.Float64frombits(uint64(v.num)) default: panic(v.panicMessage("float")) } } // String returns v as a string. Since this method implements fmt.Stringer, // this returns the formatted string value for any non-string type. func (v Value) String() string { switch v.typ { case stringType: return v.getString() default: return fmt.Sprint(v.Interface()) } } // Bytes returns v as a []byte and panics if the type is not a []byte. func (v Value) Bytes() []byte { switch v.typ { case bytesType: return v.getBytes() default: panic(v.panicMessage("bytes")) } } // Enum returns v as a EnumNumber and panics if the type is not a EnumNumber. func (v Value) Enum() EnumNumber { switch v.typ { case enumType: return EnumNumber(v.num) default: panic(v.panicMessage("enum")) } } // Message returns v as a Message and panics if the type is not a Message. func (v Value) Message() Message { switch vi := v.getIface().(type) { case Message: return vi default: panic(v.panicMessage("message")) } } // List returns v as a List and panics if the type is not a List. func (v Value) List() List { switch vi := v.getIface().(type) { case List: return vi default: panic(v.panicMessage("list")) } } // Map returns v as a Map and panics if the type is not a Map. func (v Value) Map() Map { switch vi := v.getIface().(type) { case Map: return vi default: panic(v.panicMessage("map")) } } // MapKey returns v as a MapKey and panics for invalid MapKey types. func (v Value) MapKey() MapKey { switch v.typ { case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType: return MapKey(v) default: panic(v.panicMessage("map key")) } } // MapKey is used to index maps, where the Go type of the MapKey must match // the specified key Kind (see MessageDescriptor.IsMapEntry). // The following shows what Go type is used to represent each proto Kind: // // ╔═════════╤═════════════════════════════════════╗ // ║ Go type │ Protobuf kind ║ // ╠═════════╪═════════════════════════════════════╣ // ║ bool │ BoolKind ║ // ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ // ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ // ║ uint32 │ Uint32Kind, Fixed32Kind ║ // ║ uint64 │ Uint64Kind, Fixed64Kind ║ // ║ string │ StringKind ║ // ╚═════════╧═════════════════════════════════════╝ // // A MapKey is constructed and accessed through a Value: // k := ValueOf("hash").MapKey() // convert string to MapKey // s := k.String() // convert MapKey to string // // The MapKey is a strict subset of valid types used in Value; // converting a Value to a MapKey with an invalid type panics. type MapKey value // IsValid reports whether k is populated with a value. func (k MapKey) IsValid() bool { return Value(k).IsValid() } // Interface returns k as an interface{}. func (k MapKey) Interface() interface{} { return Value(k).Interface() } // Bool returns k as a bool and panics if the type is not a bool. func (k MapKey) Bool() bool { return Value(k).Bool() } // Int returns k as a int64 and panics if the type is not a int32 or int64. func (k MapKey) Int() int64 { return Value(k).Int() } // Uint returns k as a uint64 and panics if the type is not a uint32 or uint64. func (k MapKey) Uint() uint64 { return Value(k).Uint() } // String returns k as a string. Since this method implements fmt.Stringer, // this returns the formatted string value for any non-string type. func (k MapKey) String() string { return Value(k).String() } // Value returns k as a Value. func (k MapKey) Value() Value { return Value(k) } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package protoreflect import ( "unsafe" "google.golang.org/protobuf/internal/pragma" ) type ( stringHeader struct { Data unsafe.Pointer Len int } sliceHeader struct { Data unsafe.Pointer Len int Cap int } ifaceHeader struct { Type unsafe.Pointer Data unsafe.Pointer } ) var ( nilType = typeOf(nil) boolType = typeOf(*new(bool)) int32Type = typeOf(*new(int32)) int64Type = typeOf(*new(int64)) uint32Type = typeOf(*new(uint32)) uint64Type = typeOf(*new(uint64)) float32Type = typeOf(*new(float32)) float64Type = typeOf(*new(float64)) stringType = typeOf(*new(string)) bytesType = typeOf(*new([]byte)) enumType = typeOf(*new(EnumNumber)) ) // typeOf returns a pointer to the Go type information. // The pointer is comparable and equal if and only if the types are identical. func typeOf(t interface{}) unsafe.Pointer { return (*ifaceHeader)(unsafe.Pointer(&t)).Type } // value is a union where only one type can be represented at a time. // The struct is 24B large on 64-bit systems and requires the minimum storage // necessary to represent each possible type. // // The Go GC needs to be able to scan variables containing pointers. // As such, pointers and non-pointers cannot be intermixed. type value struct { pragma.DoNotCompare // 0B // typ stores the type of the value as a pointer to the Go type. typ unsafe.Pointer // 8B // ptr stores the data pointer for a String, Bytes, or interface value. ptr unsafe.Pointer // 8B // num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or // Enum value as a raw uint64. // // It is also used to store the length of a String or Bytes value; // the capacity is ignored. num uint64 // 8B } func valueOfString(v string) Value { p := (*stringHeader)(unsafe.Pointer(&v)) return Value{typ: stringType, ptr: p.Data, num: uint64(len(v))} } func valueOfBytes(v []byte) Value { p := (*sliceHeader)(unsafe.Pointer(&v)) return Value{typ: bytesType, ptr: p.Data, num: uint64(len(v))} } func valueOfIface(v interface{}) Value { p := (*ifaceHeader)(unsafe.Pointer(&v)) return Value{typ: p.Type, ptr: p.Data} } func (v Value) getString() (x string) { *(*stringHeader)(unsafe.Pointer(&x)) = stringHeader{Data: v.ptr, Len: int(v.num)} return x } func (v Value) getBytes() (x []byte) { *(*sliceHeader)(unsafe.Pointer(&x)) = sliceHeader{Data: v.ptr, Len: int(v.num), Cap: int(v.num)} return x } func (v Value) getIface() (x interface{}) { *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr} return x } ================================================ FILE: _tools/src/google.golang.org/protobuf/reflect/protoregistry/registry.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoregistry provides data structures to register and lookup // protobuf descriptor types. // // The Files registry contains file descriptors and provides the ability // to iterate over the files or lookup a specific descriptor within the files. // Files only contains protobuf descriptors and has no understanding of Go // type information that may be associated with each descriptor. // // The Types registry contains descriptor types for which there is a known // Go type associated with that descriptor. It provides the ability to iterate // over the registered types or lookup a type by name. package protoregistry import ( "fmt" "os" "strings" "sync" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/reflect/protoreflect" ) // conflictPolicy configures the policy for handling registration conflicts. // // It can be over-written at compile time with a linker-initialized variable: // go build -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn" // // It can be over-written at program execution with an environment variable: // GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn ./main // // Neither of the above are covered by the compatibility promise and // may be removed in a future release of this module. var conflictPolicy = "panic" // "panic" | "warn" | "ignore" // ignoreConflict reports whether to ignore a registration conflict // given the descriptor being registered and the error. // It is a variable so that the behavior is easily overridden in another file. var ignoreConflict = func(d protoreflect.Descriptor, err error) bool { const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT" const faq = "https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict" policy := conflictPolicy if v := os.Getenv(env); v != "" { policy = v } switch policy { case "panic": panic(fmt.Sprintf("%v\nSee %v\n", err, faq)) case "warn": fmt.Fprintf(os.Stderr, "WARNING: %v\nSee %v\n\n", err, faq) return true case "ignore": return true default: panic("invalid " + env + " value: " + os.Getenv(env)) } } var globalMutex sync.RWMutex // GlobalFiles is a global registry of file descriptors. var GlobalFiles *Files = new(Files) // GlobalTypes is the registry used by default for type lookups // unless a local registry is provided by the user. var GlobalTypes *Types = new(Types) // NotFound is a sentinel error value to indicate that the type was not found. // // Since registry lookup can happen in the critical performance path, resolvers // must return this exact error value, not an error wrapping it. var NotFound = errors.New("not found") // Files is a registry for looking up or iterating over files and the // descriptors contained within them. // The Find and Range methods are safe for concurrent use. type Files struct { // The map of descsByName contains: // EnumDescriptor // EnumValueDescriptor // MessageDescriptor // ExtensionDescriptor // ServiceDescriptor // *packageDescriptor // // Note that files are stored as a slice, since a package may contain // multiple files. Only top-level declarations are registered. // Note that enum values are in the top-level since that are in the same // scope as the parent enum. descsByName map[protoreflect.FullName]interface{} filesByPath map[string]protoreflect.FileDescriptor } type packageDescriptor struct { files []protoreflect.FileDescriptor } // RegisterFile registers the provided file descriptor. // // If any descriptor within the file conflicts with the descriptor of any // previously registered file (e.g., two enums with the same full name), // then the file is not registered and an error is returned. // // It is permitted for multiple files to have the same file path. func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error { if r == GlobalFiles { globalMutex.Lock() defer globalMutex.Unlock() } if r.descsByName == nil { r.descsByName = map[protoreflect.FullName]interface{}{ "": &packageDescriptor{}, } r.filesByPath = make(map[string]protoreflect.FileDescriptor) } path := file.Path() if prev := r.filesByPath[path]; prev != nil { r.checkGenProtoConflict(path) err := errors.New("file %q is already registered", file.Path()) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(file, err) { err = nil } return err } for name := file.Package(); name != ""; name = name.Parent() { switch prev := r.descsByName[name]; prev.(type) { case nil, *packageDescriptor: default: err := errors.New("file %q has a package name conflict over %v", file.Path(), name) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(file, err) { err = nil } return err } } var err error var hasConflict bool rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) { if prev := r.descsByName[d.FullName()]; prev != nil { hasConflict = true err = errors.New("file %q has a name conflict over %v", file.Path(), d.FullName()) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(d, err) { err = nil } } }) if hasConflict { return err } for name := file.Package(); name != ""; name = name.Parent() { if r.descsByName[name] == nil { r.descsByName[name] = &packageDescriptor{} } } p := r.descsByName[file.Package()].(*packageDescriptor) p.files = append(p.files, file) rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) { r.descsByName[d.FullName()] = d }) r.filesByPath[path] = file return nil } // Several well-known types were hosted in the google.golang.org/genproto module // but were later moved to this module. To avoid a weak dependency on the // genproto module (and its relatively large set of transitive dependencies), // we rely on a registration conflict to determine whether the genproto version // is too old (i.e., does not contain aliases to the new type declarations). func (r *Files) checkGenProtoConflict(path string) { if r != GlobalFiles { return } var prevPath string const prevModule = "google.golang.org/genproto" const prevVersion = "cb27e3aa (May 26th, 2020)" switch path { case "google/protobuf/field_mask.proto": prevPath = prevModule + "/protobuf/field_mask" case "google/protobuf/api.proto": prevPath = prevModule + "/protobuf/api" case "google/protobuf/type.proto": prevPath = prevModule + "/protobuf/ptype" case "google/protobuf/source_context.proto": prevPath = prevModule + "/protobuf/source_context" default: return } pkgName := strings.TrimSuffix(strings.TrimPrefix(path, "google/protobuf/"), ".proto") pkgName = strings.Replace(pkgName, "_", "", -1) + "pb" // e.g., "field_mask" => "fieldmaskpb" currPath := "google.golang.org/protobuf/types/known/" + pkgName panic(fmt.Sprintf(""+ "duplicate registration of %q\n"+ "\n"+ "The generated definition for this file has moved:\n"+ "\tfrom: %q\n"+ "\tto: %q\n"+ "A dependency on the %q module must\n"+ "be at version %v or higher.\n"+ "\n"+ "Upgrade the dependency by running:\n"+ "\tgo get -u %v\n", path, prevPath, currPath, prevModule, prevVersion, prevPath)) } // FindDescriptorByName looks up a descriptor by the full name. // // This returns (nil, NotFound) if not found. func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { if r == nil { return nil, NotFound } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } prefix := name suffix := nameSuffix("") for prefix != "" { if d, ok := r.descsByName[prefix]; ok { switch d := d.(type) { case protoreflect.EnumDescriptor: if d.FullName() == name { return d, nil } case protoreflect.EnumValueDescriptor: if d.FullName() == name { return d, nil } case protoreflect.MessageDescriptor: if d.FullName() == name { return d, nil } if d := findDescriptorInMessage(d, suffix); d != nil && d.FullName() == name { return d, nil } case protoreflect.ExtensionDescriptor: if d.FullName() == name { return d, nil } case protoreflect.ServiceDescriptor: if d.FullName() == name { return d, nil } if d := d.Methods().ByName(suffix.Pop()); d != nil && d.FullName() == name { return d, nil } } return nil, NotFound } prefix = prefix.Parent() suffix = nameSuffix(name[len(prefix)+len("."):]) } return nil, NotFound } func findDescriptorInMessage(md protoreflect.MessageDescriptor, suffix nameSuffix) protoreflect.Descriptor { name := suffix.Pop() if suffix == "" { if ed := md.Enums().ByName(name); ed != nil { return ed } for i := md.Enums().Len() - 1; i >= 0; i-- { if vd := md.Enums().Get(i).Values().ByName(name); vd != nil { return vd } } if xd := md.Extensions().ByName(name); xd != nil { return xd } if fd := md.Fields().ByName(name); fd != nil { return fd } if od := md.Oneofs().ByName(name); od != nil { return od } } if md := md.Messages().ByName(name); md != nil { if suffix == "" { return md } return findDescriptorInMessage(md, suffix) } return nil } type nameSuffix string func (s *nameSuffix) Pop() (name protoreflect.Name) { if i := strings.IndexByte(string(*s), '.'); i >= 0 { name, *s = protoreflect.Name((*s)[:i]), (*s)[i+1:] } else { name, *s = protoreflect.Name((*s)), "" } return name } // FindFileByPath looks up a file by the path. // // This returns (nil, NotFound) if not found. func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { if r == nil { return nil, NotFound } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } if fd, ok := r.filesByPath[path]; ok { return fd, nil } return nil, NotFound } // NumFiles reports the number of registered files. func (r *Files) NumFiles() int { if r == nil { return 0 } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } return len(r.filesByPath) } // RangeFiles iterates over all registered files while f returns true. // The iteration order is undefined. func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) { if r == nil { return } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } for _, file := range r.filesByPath { if !f(file) { return } } } // NumFilesByPackage reports the number of registered files in a proto package. func (r *Files) NumFilesByPackage(name protoreflect.FullName) int { if r == nil { return 0 } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } p, ok := r.descsByName[name].(*packageDescriptor) if !ok { return 0 } return len(p.files) } // RangeFilesByPackage iterates over all registered files in a given proto package // while f returns true. The iteration order is undefined. func (r *Files) RangeFilesByPackage(name protoreflect.FullName, f func(protoreflect.FileDescriptor) bool) { if r == nil { return } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } p, ok := r.descsByName[name].(*packageDescriptor) if !ok { return } for _, file := range p.files { if !f(file) { return } } } // rangeTopLevelDescriptors iterates over all top-level descriptors in a file // which will be directly entered into the registry. func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflect.Descriptor)) { eds := fd.Enums() for i := eds.Len() - 1; i >= 0; i-- { f(eds.Get(i)) vds := eds.Get(i).Values() for i := vds.Len() - 1; i >= 0; i-- { f(vds.Get(i)) } } mds := fd.Messages() for i := mds.Len() - 1; i >= 0; i-- { f(mds.Get(i)) } xds := fd.Extensions() for i := xds.Len() - 1; i >= 0; i-- { f(xds.Get(i)) } sds := fd.Services() for i := sds.Len() - 1; i >= 0; i-- { f(sds.Get(i)) } } // MessageTypeResolver is an interface for looking up messages. // // A compliant implementation must deterministically return the same type // if no error is encountered. // // The Types type implements this interface. type MessageTypeResolver interface { // FindMessageByName looks up a message by its full name. // E.g., "google.protobuf.Any" // // This return (nil, NotFound) if not found. FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) // FindMessageByURL looks up a message by a URL identifier. // See documentation on google.protobuf.Any.type_url for the URL format. // // This returns (nil, NotFound) if not found. FindMessageByURL(url string) (protoreflect.MessageType, error) } // ExtensionTypeResolver is an interface for looking up extensions. // // A compliant implementation must deterministically return the same type // if no error is encountered. // // The Types type implements this interface. type ExtensionTypeResolver interface { // FindExtensionByName looks up a extension field by the field's full name. // Note that this is the full name of the field as determined by // where the extension is declared and is unrelated to the full name of the // message being extended. // // This returns (nil, NotFound) if not found. FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) // FindExtensionByNumber looks up a extension field by the field number // within some parent message, identified by full name. // // This returns (nil, NotFound) if not found. FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } var ( _ MessageTypeResolver = (*Types)(nil) _ ExtensionTypeResolver = (*Types)(nil) ) // Types is a registry for looking up or iterating over descriptor types. // The Find and Range methods are safe for concurrent use. type Types struct { typesByName typesByName extensionsByMessage extensionsByMessage numEnums int numMessages int numExtensions int } type ( typesByName map[protoreflect.FullName]interface{} extensionsByMessage map[protoreflect.FullName]extensionsByNumber extensionsByNumber map[protoreflect.FieldNumber]protoreflect.ExtensionType ) // RegisterMessage registers the provided message type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterMessage(mt protoreflect.MessageType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. md := mt.Descriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } if err := r.register("message", md, mt); err != nil { return err } r.numMessages++ return nil } // RegisterEnum registers the provided enum type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterEnum(et protoreflect.EnumType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. ed := et.Descriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } if err := r.register("enum", ed, et); err != nil { return err } r.numEnums++ return nil } // RegisterExtension registers the provided extension type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterExtension(xt protoreflect.ExtensionType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. // // A known case where this can happen: Fetching the TypeDescriptor for a // legacy ExtensionDesc can consult the global registry. xd := xt.TypeDescriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } field := xd.Number() message := xd.ContainingMessage().FullName() if prev := r.extensionsByMessage[message][field]; prev != nil { err := errors.New("extension number %d is already registered on message %v", field, message) err = amendErrorWithCaller(err, prev, xt) if !(r == GlobalTypes && ignoreConflict(xd, err)) { return err } } if err := r.register("extension", xd, xt); err != nil { return err } if r.extensionsByMessage == nil { r.extensionsByMessage = make(extensionsByMessage) } if r.extensionsByMessage[message] == nil { r.extensionsByMessage[message] = make(extensionsByNumber) } r.extensionsByMessage[message][field] = xt r.numExtensions++ return nil } func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interface{}) error { name := desc.FullName() prev := r.typesByName[name] if prev != nil { err := errors.New("%v %v is already registered", kind, name) err = amendErrorWithCaller(err, prev, typ) if !(r == GlobalTypes && ignoreConflict(desc, err)) { return err } } if r.typesByName == nil { r.typesByName = make(typesByName) } r.typesByName[name] = typ return nil } // FindEnumByName looks up an enum by its full name. // E.g., "google.protobuf.Field.Kind". // // This returns (nil, NotFound) if not found. func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[enum]; v != nil { if et, _ := v.(protoreflect.EnumType); et != nil { return et, nil } return nil, errors.New("found wrong type: got %v, want enum", typeName(v)) } return nil, NotFound } // FindMessageByName looks up a message by its full name, // e.g. "google.protobuf.Any". // // This returns (nil, NotFound) if not found. func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[message]; v != nil { if mt, _ := v.(protoreflect.MessageType); mt != nil { return mt, nil } return nil, errors.New("found wrong type: got %v, want message", typeName(v)) } return nil, NotFound } // FindMessageByURL looks up a message by a URL identifier. // See documentation on google.protobuf.Any.type_url for the URL format. // // This returns (nil, NotFound) if not found. func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) { // This function is similar to FindMessageByName but // truncates anything before and including '/' in the URL. if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } message := protoreflect.FullName(url) if i := strings.LastIndexByte(url, '/'); i >= 0 { message = message[i+len("/"):] } if v := r.typesByName[message]; v != nil { if mt, _ := v.(protoreflect.MessageType); mt != nil { return mt, nil } return nil, errors.New("found wrong type: got %v, want message", typeName(v)) } return nil, NotFound } // FindExtensionByName looks up a extension field by the field's full name. // Note that this is the full name of the field as determined by // where the extension is declared and is unrelated to the full name of the // message being extended. // // This returns (nil, NotFound) if not found. func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[field]; v != nil { if xt, _ := v.(protoreflect.ExtensionType); xt != nil { return xt, nil } // MessageSet extensions are special in that the name of the extension // is the name of the message type used to extend the MessageSet. // This naming scheme is used by text and JSON serialization. // // This feature is protected by the ProtoLegacy flag since MessageSets // are a proto1 feature that is long deprecated. if flags.ProtoLegacy { if _, ok := v.(protoreflect.MessageType); ok { field := field.Append(messageset.ExtensionName) if v := r.typesByName[field]; v != nil { if xt, _ := v.(protoreflect.ExtensionType); xt != nil { if messageset.IsMessageSetExtension(xt.TypeDescriptor()) { return xt, nil } } } } } return nil, errors.New("found wrong type: got %v, want extension", typeName(v)) } return nil, NotFound } // FindExtensionByNumber looks up a extension field by the field number // within some parent message, identified by full name. // // This returns (nil, NotFound) if not found. func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if xt, ok := r.extensionsByMessage[message][field]; ok { return xt, nil } return nil, NotFound } // NumEnums reports the number of registered enums. func (r *Types) NumEnums() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numEnums } // RangeEnums iterates over all registered enums while f returns true. // Iteration order is undefined. func (r *Types) RangeEnums(f func(protoreflect.EnumType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if et, ok := typ.(protoreflect.EnumType); ok { if !f(et) { return } } } } // NumMessages reports the number of registered messages. func (r *Types) NumMessages() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numMessages } // RangeMessages iterates over all registered messages while f returns true. // Iteration order is undefined. func (r *Types) RangeMessages(f func(protoreflect.MessageType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if mt, ok := typ.(protoreflect.MessageType); ok { if !f(mt) { return } } } } // NumExtensions reports the number of registered extensions. func (r *Types) NumExtensions() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numExtensions } // RangeExtensions iterates over all registered extensions while f returns true. // Iteration order is undefined. func (r *Types) RangeExtensions(f func(protoreflect.ExtensionType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if xt, ok := typ.(protoreflect.ExtensionType); ok { if !f(xt) { return } } } } // NumExtensionsByMessage reports the number of registered extensions for // a given message type. func (r *Types) NumExtensionsByMessage(message protoreflect.FullName) int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return len(r.extensionsByMessage[message]) } // RangeExtensionsByMessage iterates over all registered extensions filtered // by a given message type while f returns true. Iteration order is undefined. func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, xt := range r.extensionsByMessage[message] { if !f(xt) { return } } } func typeName(t interface{}) string { switch t.(type) { case protoreflect.EnumType: return "enum" case protoreflect.MessageType: return "message" case protoreflect.ExtensionType: return "extension" default: return fmt.Sprintf("%T", t) } } func amendErrorWithCaller(err error, prev, curr interface{}) error { prevPkg := goPackage(prev) currPkg := goPackage(curr) if prevPkg == "" || currPkg == "" || prevPkg == currPkg { return err } return errors.New("%s\n\tpreviously from: %q\n\tcurrently from: %q", err, prevPkg, currPkg) } func goPackage(v interface{}) string { switch d := v.(type) { case protoreflect.EnumType: v = d.Descriptor() case protoreflect.MessageType: v = d.Descriptor() case protoreflect.ExtensionType: v = d.TypeDescriptor() } if d, ok := v.(protoreflect.Descriptor); ok { v = d.ParentFile() } if d, ok := v.(interface{ GoPackagePath() string }); ok { return d.GoPackagePath() } return "" } ================================================ FILE: _tools/src/google.golang.org/protobuf/runtime/protoiface/legacy.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoiface type MessageV1 interface { Reset() String() string ProtoMessage() } type ExtensionRangeV1 struct { Start, End int32 // both inclusive } ================================================ FILE: _tools/src/google.golang.org/protobuf/runtime/protoiface/methods.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoiface contains types referenced or implemented by messages. // // WARNING: This package should only be imported by message implementations. // The functionality found in this package should be accessed through // higher-level abstractions provided by the proto package. package protoiface import ( "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" ) // Methods is a set of optional fast-path implementations of various operations. type Methods = struct { pragma.NoUnkeyedLiterals // Flags indicate support for optional features. Flags SupportFlags // Size returns the size in bytes of the wire-format encoding of a message. // Marshal must be provided if a custom Size is provided. Size func(SizeInput) SizeOutput // Marshal formats a message in the wire-format encoding to the provided buffer. // Size should be provided if a custom Marshal is provided. // It must not return an error for a partial message. Marshal func(MarshalInput) (MarshalOutput, error) // Unmarshal parses the wire-format encoding and merges the result into a message. // It must not reset the target message or return an error for a partial message. Unmarshal func(UnmarshalInput) (UnmarshalOutput, error) // Merge merges the contents of a source message into a destination message. Merge func(MergeInput) MergeOutput // CheckInitialized returns an error if any required fields in the message are not set. CheckInitialized func(CheckInitializedInput) (CheckInitializedOutput, error) } // SupportFlags indicate support for optional features. type SupportFlags = uint64 const ( // SupportMarshalDeterministic reports whether MarshalOptions.Deterministic is supported. SupportMarshalDeterministic SupportFlags = 1 << iota // SupportUnmarshalDiscardUnknown reports whether UnmarshalOptions.DiscardUnknown is supported. SupportUnmarshalDiscardUnknown ) // SizeInput is input to the Size method. type SizeInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Flags MarshalInputFlags } // SizeOutput is output from the Size method. type SizeOutput = struct { pragma.NoUnkeyedLiterals Size int } // MarshalInput is input to the Marshal method. type MarshalInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Buf []byte // output is appended to this buffer Flags MarshalInputFlags } // MarshalOutput is output from the Marshal method. type MarshalOutput = struct { pragma.NoUnkeyedLiterals Buf []byte // contains marshaled message } // MarshalInputFlags configure the marshaler. // Most flags correspond to fields in proto.MarshalOptions. type MarshalInputFlags = uint8 const ( MarshalDeterministic MarshalInputFlags = 1 << iota MarshalUseCachedSize ) // UnmarshalInput is input to the Unmarshal method. type UnmarshalInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Buf []byte // input buffer Flags UnmarshalInputFlags Resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } // UnmarshalOutput is output from the Unmarshal method. type UnmarshalOutput = struct { pragma.NoUnkeyedLiterals Flags UnmarshalOutputFlags } // UnmarshalInputFlags configure the unmarshaler. // Most flags correspond to fields in proto.UnmarshalOptions. type UnmarshalInputFlags = uint8 const ( UnmarshalDiscardUnknown UnmarshalInputFlags = 1 << iota ) // UnmarshalOutputFlags are output from the Unmarshal method. type UnmarshalOutputFlags = uint8 const ( // UnmarshalInitialized may be set on return if all required fields are known to be set. // If unset, then it does not necessarily indicate that the message is uninitialized, // only that its status could not be confirmed. UnmarshalInitialized UnmarshalOutputFlags = 1 << iota ) // MergeInput is input to the Merge method. type MergeInput = struct { pragma.NoUnkeyedLiterals Source protoreflect.Message Destination protoreflect.Message } // MergeOutput is output from the Merge method. type MergeOutput = struct { pragma.NoUnkeyedLiterals Flags MergeOutputFlags } // MergeOutputFlags are output from the Merge method. type MergeOutputFlags = uint8 const ( // MergeComplete reports whether the merge was performed. // If unset, the merger must have made no changes to the destination. MergeComplete MergeOutputFlags = 1 << iota ) // CheckInitializedInput is input to the CheckInitialized method. type CheckInitializedInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message } // CheckInitializedOutput is output from the CheckInitialized method. type CheckInitializedOutput = struct { pragma.NoUnkeyedLiterals } ================================================ FILE: _tools/src/google.golang.org/protobuf/runtime/protoimpl/impl.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoimpl contains the default implementation for messages // generated by protoc-gen-go. // // WARNING: This package should only ever be imported by generated messages. // The compatibility agreement covers nothing except for functionality needed // to keep existing generated messages operational. Breakages that occur due // to unauthorized usages of this package are not the author's responsibility. package protoimpl import ( "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/filetype" "google.golang.org/protobuf/internal/impl" ) // UnsafeEnabled specifies whether package unsafe can be used. const UnsafeEnabled = impl.UnsafeEnabled type ( // Types used by generated code in init functions. DescBuilder = filedesc.Builder TypeBuilder = filetype.Builder // Types used by generated code to implement EnumType, MessageType, and ExtensionType. EnumInfo = impl.EnumInfo MessageInfo = impl.MessageInfo ExtensionInfo = impl.ExtensionInfo // Types embedded in generated messages. MessageState = impl.MessageState SizeCache = impl.SizeCache WeakFields = impl.WeakFields UnknownFields = impl.UnknownFields ExtensionFields = impl.ExtensionFields ExtensionFieldV1 = impl.ExtensionField Pointer = impl.Pointer ) var X impl.Export ================================================ FILE: _tools/src/google.golang.org/protobuf/runtime/protoimpl/version.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoimpl import ( "google.golang.org/protobuf/internal/version" ) const ( // MaxVersion is the maximum supported version for generated .pb.go files. // It is always the current version of the module. MaxVersion = version.Minor // GenVersion is the runtime version required by generated .pb.go files. // This is incremented when generated code relies on new functionality // in the runtime. GenVersion = 20 // MinVersion is the minimum supported version for generated .pb.go files. // This is incremented when the runtime drops support for old code. MinVersion = 0 ) // EnforceVersion is used by code generated by protoc-gen-go // to statically enforce minimum and maximum versions of this package. // A compilation failure implies either that: // * the runtime package is too old and needs to be updated OR // * the generated code is too old and needs to be regenerated. // // The runtime package can be upgraded by running: // go get google.golang.org/protobuf // // The generated code can be regenerated by running: // protoc --go_out=${PROTOC_GEN_GO_ARGS} ${PROTO_FILES} // // Example usage by generated code: // const ( // // Verify that this generated code is sufficiently up-to-date. // _ = protoimpl.EnforceVersion(genVersion - protoimpl.MinVersion) // // Verify that runtime/protoimpl is sufficiently up-to-date. // _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - genVersion) // ) // // The genVersion is the current minor version used to generated the code. // This compile-time check relies on negative integer overflow of a uint // being a compilation failure (guaranteed by the Go specification). type EnforceVersion uint // This enforces the following invariant: // MinVersion ≤ GenVersion ≤ MaxVersion const ( _ = EnforceVersion(GenVersion - MinVersion) _ = EnforceVersion(MaxVersion - GenVersion) ) ================================================ FILE: _tools/src/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go ================================================ // 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. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // The messages in this file describe the definitions found in .proto files. // A valid .proto file can be translated directly to a FileDescriptorProto // without any other information (e.g. without reading its imports). // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/descriptor.proto package descriptorpb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) type FieldDescriptorProto_Type int32 const ( // 0 is reserved for errors. // Order is weird for historical reasons. FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1 FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3 FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5 FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6 FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7 FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8 FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9 // Tag-delimited aggregate. // Group type is deprecated and not supported in proto3. However, Proto3 // implementations should still be able to parse the group wire format and // treat group fields as unknown fields. FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10 FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 // Length-delimited aggregate. // New in version 2. FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12 FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13 FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14 FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15 FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16 FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17 // Uses ZigZag encoding. FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18 // Uses ZigZag encoding. ) // Enum value maps for FieldDescriptorProto_Type. var ( FieldDescriptorProto_Type_name = map[int32]string{ 1: "TYPE_DOUBLE", 2: "TYPE_FLOAT", 3: "TYPE_INT64", 4: "TYPE_UINT64", 5: "TYPE_INT32", 6: "TYPE_FIXED64", 7: "TYPE_FIXED32", 8: "TYPE_BOOL", 9: "TYPE_STRING", 10: "TYPE_GROUP", 11: "TYPE_MESSAGE", 12: "TYPE_BYTES", 13: "TYPE_UINT32", 14: "TYPE_ENUM", 15: "TYPE_SFIXED32", 16: "TYPE_SFIXED64", 17: "TYPE_SINT32", 18: "TYPE_SINT64", } FieldDescriptorProto_Type_value = map[string]int32{ "TYPE_DOUBLE": 1, "TYPE_FLOAT": 2, "TYPE_INT64": 3, "TYPE_UINT64": 4, "TYPE_INT32": 5, "TYPE_FIXED64": 6, "TYPE_FIXED32": 7, "TYPE_BOOL": 8, "TYPE_STRING": 9, "TYPE_GROUP": 10, "TYPE_MESSAGE": 11, "TYPE_BYTES": 12, "TYPE_UINT32": 13, "TYPE_ENUM": 14, "TYPE_SFIXED32": 15, "TYPE_SFIXED64": 16, "TYPE_SINT32": 17, "TYPE_SINT64": 18, } ) func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type { p := new(FieldDescriptorProto_Type) *p = x return p } func (x FieldDescriptorProto_Type) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[0].Descriptor() } func (FieldDescriptorProto_Type) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[0] } func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldDescriptorProto_Type) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldDescriptorProto_Type(num) return nil } // Deprecated: Use FieldDescriptorProto_Type.Descriptor instead. func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4, 0} } type FieldDescriptorProto_Label int32 const ( // 0 is reserved for errors FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1 FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2 FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3 ) // Enum value maps for FieldDescriptorProto_Label. var ( FieldDescriptorProto_Label_name = map[int32]string{ 1: "LABEL_OPTIONAL", 2: "LABEL_REQUIRED", 3: "LABEL_REPEATED", } FieldDescriptorProto_Label_value = map[string]int32{ "LABEL_OPTIONAL": 1, "LABEL_REQUIRED": 2, "LABEL_REPEATED": 3, } ) func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label { p := new(FieldDescriptorProto_Label) *p = x return p } func (x FieldDescriptorProto_Label) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor() } func (FieldDescriptorProto_Label) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[1] } func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldDescriptorProto_Label) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldDescriptorProto_Label(num) return nil } // Deprecated: Use FieldDescriptorProto_Label.Descriptor instead. func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4, 1} } // Generated classes can be optimized for speed or code size. type FileOptions_OptimizeMode int32 const ( FileOptions_SPEED FileOptions_OptimizeMode = 1 // Generate complete code for parsing, serialization, // etc. FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2 // Use ReflectionOps to implement these methods. FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3 // Generate code using MessageLite and the lite runtime. ) // Enum value maps for FileOptions_OptimizeMode. var ( FileOptions_OptimizeMode_name = map[int32]string{ 1: "SPEED", 2: "CODE_SIZE", 3: "LITE_RUNTIME", } FileOptions_OptimizeMode_value = map[string]int32{ "SPEED": 1, "CODE_SIZE": 2, "LITE_RUNTIME": 3, } ) func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode { p := new(FileOptions_OptimizeMode) *p = x return p } func (x FileOptions_OptimizeMode) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor() } func (FileOptions_OptimizeMode) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[2] } func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FileOptions_OptimizeMode) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FileOptions_OptimizeMode(num) return nil } // Deprecated: Use FileOptions_OptimizeMode.Descriptor instead. func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10, 0} } type FieldOptions_CType int32 const ( // Default mode. FieldOptions_STRING FieldOptions_CType = 0 FieldOptions_CORD FieldOptions_CType = 1 FieldOptions_STRING_PIECE FieldOptions_CType = 2 ) // Enum value maps for FieldOptions_CType. var ( FieldOptions_CType_name = map[int32]string{ 0: "STRING", 1: "CORD", 2: "STRING_PIECE", } FieldOptions_CType_value = map[string]int32{ "STRING": 0, "CORD": 1, "STRING_PIECE": 2, } ) func (x FieldOptions_CType) Enum() *FieldOptions_CType { p := new(FieldOptions_CType) *p = x return p } func (x FieldOptions_CType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor() } func (FieldOptions_CType) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[3] } func (x FieldOptions_CType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldOptions_CType) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldOptions_CType(num) return nil } // Deprecated: Use FieldOptions_CType.Descriptor instead. func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 0} } type FieldOptions_JSType int32 const ( // Use the default type. FieldOptions_JS_NORMAL FieldOptions_JSType = 0 // Use JavaScript strings. FieldOptions_JS_STRING FieldOptions_JSType = 1 // Use JavaScript numbers. FieldOptions_JS_NUMBER FieldOptions_JSType = 2 ) // Enum value maps for FieldOptions_JSType. var ( FieldOptions_JSType_name = map[int32]string{ 0: "JS_NORMAL", 1: "JS_STRING", 2: "JS_NUMBER", } FieldOptions_JSType_value = map[string]int32{ "JS_NORMAL": 0, "JS_STRING": 1, "JS_NUMBER": 2, } ) func (x FieldOptions_JSType) Enum() *FieldOptions_JSType { p := new(FieldOptions_JSType) *p = x return p } func (x FieldOptions_JSType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor() } func (FieldOptions_JSType) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[4] } func (x FieldOptions_JSType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldOptions_JSType) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldOptions_JSType(num) return nil } // Deprecated: Use FieldOptions_JSType.Descriptor instead. func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 1} } // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, // or neither? HTTP based RPC implementation may choose GET verb for safe // methods, and PUT verb for idempotent methods instead of the default POST. type MethodOptions_IdempotencyLevel int32 const ( MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0 MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1 // implies idempotent MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2 // idempotent, but may have side effects ) // Enum value maps for MethodOptions_IdempotencyLevel. var ( MethodOptions_IdempotencyLevel_name = map[int32]string{ 0: "IDEMPOTENCY_UNKNOWN", 1: "NO_SIDE_EFFECTS", 2: "IDEMPOTENT", } MethodOptions_IdempotencyLevel_value = map[string]int32{ "IDEMPOTENCY_UNKNOWN": 0, "NO_SIDE_EFFECTS": 1, "IDEMPOTENT": 2, } ) func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel { p := new(MethodOptions_IdempotencyLevel) *p = x return p } func (x MethodOptions_IdempotencyLevel) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor() } func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[5] } func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = MethodOptions_IdempotencyLevel(num) return nil } // Deprecated: Use MethodOptions_IdempotencyLevel.Descriptor instead. func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17, 0} } // The protocol compiler can output a FileDescriptorSet containing the .proto // files it parses. type FileDescriptorSet struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` } func (x *FileDescriptorSet) Reset() { *x = FileDescriptorSet{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileDescriptorSet) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileDescriptorSet) ProtoMessage() {} func (x *FileDescriptorSet) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 FileDescriptorSet.ProtoReflect.Descriptor instead. func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0} } func (x *FileDescriptorSet) GetFile() []*FileDescriptorProto { if x != nil { return x.File } return nil } // Describes a complete .proto file. type FileDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // file name, relative to root of source tree Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"` // e.g. "foo", "foo.bar", etc. // Names of files imported by this file. Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"` // Indexes of the public imported files in the dependency list above. PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"` // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"` // All top-level definitions in this file. MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"` Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` // This field contains optional information about the original source code. // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` // The syntax of the proto file. // The supported values are "proto2" and "proto3". Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` } func (x *FileDescriptorProto) Reset() { *x = FileDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileDescriptorProto) ProtoMessage() {} func (x *FileDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 FileDescriptorProto.ProtoReflect.Descriptor instead. func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1} } func (x *FileDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *FileDescriptorProto) GetPackage() string { if x != nil && x.Package != nil { return *x.Package } return "" } func (x *FileDescriptorProto) GetDependency() []string { if x != nil { return x.Dependency } return nil } func (x *FileDescriptorProto) GetPublicDependency() []int32 { if x != nil { return x.PublicDependency } return nil } func (x *FileDescriptorProto) GetWeakDependency() []int32 { if x != nil { return x.WeakDependency } return nil } func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto { if x != nil { return x.MessageType } return nil } func (x *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto { if x != nil { return x.EnumType } return nil } func (x *FileDescriptorProto) GetService() []*ServiceDescriptorProto { if x != nil { return x.Service } return nil } func (x *FileDescriptorProto) GetExtension() []*FieldDescriptorProto { if x != nil { return x.Extension } return nil } func (x *FileDescriptorProto) GetOptions() *FileOptions { if x != nil { return x.Options } return nil } func (x *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo { if x != nil { return x.SourceCodeInfo } return nil } func (x *FileDescriptorProto) GetSyntax() string { if x != nil && x.Syntax != nil { return *x.Syntax } return "" } // Describes a message type. type DescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"` NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"` OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"` Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"` ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` } func (x *DescriptorProto) Reset() { *x = DescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto) ProtoMessage() {} func (x *DescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 DescriptorProto.ProtoReflect.Descriptor instead. func (*DescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2} } func (x *DescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *DescriptorProto) GetField() []*FieldDescriptorProto { if x != nil { return x.Field } return nil } func (x *DescriptorProto) GetExtension() []*FieldDescriptorProto { if x != nil { return x.Extension } return nil } func (x *DescriptorProto) GetNestedType() []*DescriptorProto { if x != nil { return x.NestedType } return nil } func (x *DescriptorProto) GetEnumType() []*EnumDescriptorProto { if x != nil { return x.EnumType } return nil } func (x *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange { if x != nil { return x.ExtensionRange } return nil } func (x *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto { if x != nil { return x.OneofDecl } return nil } func (x *DescriptorProto) GetOptions() *MessageOptions { if x != nil { return x.Options } return nil } func (x *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange { if x != nil { return x.ReservedRange } return nil } func (x *DescriptorProto) GetReservedName() []string { if x != nil { return x.ReservedName } return nil } type ExtensionRangeOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } func (x *ExtensionRangeOptions) Reset() { *x = ExtensionRangeOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ExtensionRangeOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*ExtensionRangeOptions) ProtoMessage() {} func (x *ExtensionRangeOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 ExtensionRangeOptions.ProtoReflect.Descriptor instead. func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{3} } func (x *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } // Describes a field within a message. type FieldDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"` Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"` // If type_name is set, this need not be set. If both this and type_name // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"` // For message and enum types, this is the name of the type. If the name // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping // rules are used to find the type (i.e. first the nested types within this // message are searched, then within the parent, on up to the root // namespace). TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"` // For extensions, this is the name of the type being extended. It is // resolved in the same manner as type_name. Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"` // For numeric types, contains the original text representation of the value. // For booleans, "true" or "false". // For strings, contains the default text contents (not escaped in any way). // For bytes, contains the C escaped value. All bytes >= 128 are escaped. // TODO(kenton): Base-64 encode? DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` // If set, gives the index of a oneof in the containing type's oneof_decl // list. This field is a member of that oneof. OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"` // JSON name of this field. The value is set by protocol compiler. If the // user has set a "json_name" option on this field, that option's value // will be used. Otherwise, it's deduced from the field's name by converting // it to camelCase. JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` // If true, this is a proto3 "optional". When a proto3 field is optional, it // tracks presence regardless of field type. // // When proto3_optional is true, this field must be belong to a oneof to // signal to old proto3 clients that presence is tracked for this field. This // oneof is known as a "synthetic" oneof, and this field must be its sole // member (each proto3 optional field gets its own synthetic oneof). Synthetic // oneofs exist in the descriptor only, and do not generate any API. Synthetic // oneofs must be ordered after all "real" oneofs. // // For message fields, proto3_optional doesn't create any semantic change, // since non-repeated message fields always track presence. However it still // indicates the semantic detail of whether the user wrote "optional" or not. // This can be useful for round-tripping the .proto file. For consistency we // give message fields a synthetic oneof also, even though it is not required // to track presence. This is especially important because the parser can't // tell if a field is a message or an enum, so it must always create a // synthetic oneof. // // Proto2 optional fields do not set this flag, because they already indicate // optional with `LABEL_OPTIONAL`. Proto3Optional *bool `protobuf:"varint,17,opt,name=proto3_optional,json=proto3Optional" json:"proto3_optional,omitempty"` } func (x *FieldDescriptorProto) Reset() { *x = FieldDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FieldDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*FieldDescriptorProto) ProtoMessage() {} func (x *FieldDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[4] 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 FieldDescriptorProto.ProtoReflect.Descriptor instead. func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4} } func (x *FieldDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *FieldDescriptorProto) GetNumber() int32 { if x != nil && x.Number != nil { return *x.Number } return 0 } func (x *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label { if x != nil && x.Label != nil { return *x.Label } return FieldDescriptorProto_LABEL_OPTIONAL } func (x *FieldDescriptorProto) GetType() FieldDescriptorProto_Type { if x != nil && x.Type != nil { return *x.Type } return FieldDescriptorProto_TYPE_DOUBLE } func (x *FieldDescriptorProto) GetTypeName() string { if x != nil && x.TypeName != nil { return *x.TypeName } return "" } func (x *FieldDescriptorProto) GetExtendee() string { if x != nil && x.Extendee != nil { return *x.Extendee } return "" } func (x *FieldDescriptorProto) GetDefaultValue() string { if x != nil && x.DefaultValue != nil { return *x.DefaultValue } return "" } func (x *FieldDescriptorProto) GetOneofIndex() int32 { if x != nil && x.OneofIndex != nil { return *x.OneofIndex } return 0 } func (x *FieldDescriptorProto) GetJsonName() string { if x != nil && x.JsonName != nil { return *x.JsonName } return "" } func (x *FieldDescriptorProto) GetOptions() *FieldOptions { if x != nil { return x.Options } return nil } func (x *FieldDescriptorProto) GetProto3Optional() bool { if x != nil && x.Proto3Optional != nil { return *x.Proto3Optional } return false } // Describes a oneof. type OneofDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` } func (x *OneofDescriptorProto) Reset() { *x = OneofDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OneofDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*OneofDescriptorProto) ProtoMessage() {} func (x *OneofDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[5] 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 OneofDescriptorProto.ProtoReflect.Descriptor instead. func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{5} } func (x *OneofDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *OneofDescriptorProto) GetOptions() *OneofOptions { if x != nil { return x.Options } return nil } // Describes an enum type. type EnumDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` // Range of reserved numeric values. Reserved numeric values may not be used // by enum values in the same enum declaration. Reserved ranges may not // overlap. ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved enum value names, which may not be reused. A given name may only // be reserved once. ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` } func (x *EnumDescriptorProto) Reset() { *x = EnumDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumDescriptorProto) ProtoMessage() {} func (x *EnumDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[6] 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 EnumDescriptorProto.ProtoReflect.Descriptor instead. func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{6} } func (x *EnumDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto { if x != nil { return x.Value } return nil } func (x *EnumDescriptorProto) GetOptions() *EnumOptions { if x != nil { return x.Options } return nil } func (x *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange { if x != nil { return x.ReservedRange } return nil } func (x *EnumDescriptorProto) GetReservedName() []string { if x != nil { return x.ReservedName } return nil } // Describes a value within an enum. type EnumValueDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *EnumValueDescriptorProto) Reset() { *x = EnumValueDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumValueDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumValueDescriptorProto) ProtoMessage() {} func (x *EnumValueDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[7] 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 EnumValueDescriptorProto.ProtoReflect.Descriptor instead. func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{7} } func (x *EnumValueDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *EnumValueDescriptorProto) GetNumber() int32 { if x != nil && x.Number != nil { return *x.Number } return 0 } func (x *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { if x != nil { return x.Options } return nil } // Describes a service. type ServiceDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *ServiceDescriptorProto) Reset() { *x = ServiceDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ServiceDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*ServiceDescriptorProto) ProtoMessage() {} func (x *ServiceDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[8] 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 ServiceDescriptorProto.ProtoReflect.Descriptor instead. func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{8} } func (x *ServiceDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto { if x != nil { return x.Method } return nil } func (x *ServiceDescriptorProto) GetOptions() *ServiceOptions { if x != nil { return x.Options } return nil } // Describes a method of a service. type MethodDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // Input and output type names. These are resolved in the same way as // FieldDescriptorProto.type_name, but must refer to a message type. InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"` OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"` Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"` // Identifies if client streams multiple client messages ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` // Identifies if server streams multiple server messages ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` } // Default values for MethodDescriptorProto fields. const ( Default_MethodDescriptorProto_ClientStreaming = bool(false) Default_MethodDescriptorProto_ServerStreaming = bool(false) ) func (x *MethodDescriptorProto) Reset() { *x = MethodDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MethodDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*MethodDescriptorProto) ProtoMessage() {} func (x *MethodDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[9] 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 MethodDescriptorProto.ProtoReflect.Descriptor instead. func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{9} } func (x *MethodDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *MethodDescriptorProto) GetInputType() string { if x != nil && x.InputType != nil { return *x.InputType } return "" } func (x *MethodDescriptorProto) GetOutputType() string { if x != nil && x.OutputType != nil { return *x.OutputType } return "" } func (x *MethodDescriptorProto) GetOptions() *MethodOptions { if x != nil { return x.Options } return nil } func (x *MethodDescriptorProto) GetClientStreaming() bool { if x != nil && x.ClientStreaming != nil { return *x.ClientStreaming } return Default_MethodDescriptorProto_ClientStreaming } func (x *MethodDescriptorProto) GetServerStreaming() bool { if x != nil && x.ServerStreaming != nil { return *x.ServerStreaming } return Default_MethodDescriptorProto_ServerStreaming } type FileOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Sets the Java package where classes generated from this .proto will be // placed. By default, the proto package is used, but this is often // inappropriate because proto packages do not normally start with backwards // domain names. JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` // If set, all the classes from the .proto file are wrapped in a single // outer class with the given name. This applies to both Proto1 // (equivalent to the old "--one_java_file" option) and Proto2 (where // a .proto always translates to a single class, but you may want to // explicitly choose the class name). JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` // If set true, then the Java code generator will generate a separate .java // file for each top-level message, enum, and service defined in the .proto // file. Thus, these types will *not* be nested inside the outer class // named by java_outer_classname. However, the outer class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` // This option does nothing. // // Deprecated: Do not use. JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` // If set true, then the Java2 code generator will generate code that // throws an exception whenever an attempt is made to assign a non-UTF-8 // byte sequence to a string field. // Message reflection will do the same. // However, an extension field still accepts non-UTF-8 byte sequences. // This option has no effect on when used with the lite runtime. JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` // Sets the Go package where structs generated from this .proto will be // placed. If omitted, the Go package will be derived from the following: // - The basename of the package import path, if provided. // - Otherwise, the package statement in the .proto file, if present. // - Otherwise, the basename of the .proto file, without extension. GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"` // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). // Generic services were the only kind of service generation supported by // early versions of google.protobuf. // // Generic services are now considered deprecated in favor of using plugins // that generate code specific to your particular RPC system. Therefore, // these default to false. Old code which depends on generic services should // explicitly set them to true. CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"` // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations // for everything in the file, or it will be completely ignored; in the very // least, this is a formalization for deprecating files. Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=1" json:"cc_enable_arenas,omitempty"` // Sets the objective c class prefix which is prepended to all objective c // generated classes from this .proto. There is no default. ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"` // Namespace for generated classes; defaults to the package. CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"` // By default Swift generators will take the proto package and CamelCase it // replacing '.' with underscore and use that to prefix the types/symbols // defined. When this options is provided, they will use this value instead // to prefix the types/symbols defined. SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"` // Sets the php class prefix which is prepended to all php generated classes // from this .proto. Default is empty. PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"` // Use this option to change the namespace of php generated classes. Default // is empty. When this option is empty, the package name will be used for // determining the namespace. PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"` // Use this option to change the namespace of php generated metadata classes. // Default is empty. When this option is empty, the proto file name will be // used for determining the namespace. PhpMetadataNamespace *string `protobuf:"bytes,44,opt,name=php_metadata_namespace,json=phpMetadataNamespace" json:"php_metadata_namespace,omitempty"` // Use this option to change the package of ruby generated classes. Default // is empty. When this option is not set, the package name will be used for // determining the ruby package. RubyPackage *string `protobuf:"bytes,45,opt,name=ruby_package,json=rubyPackage" json:"ruby_package,omitempty"` // The parser stores options it doesn't recognize here. // See the documentation for the "Options" section above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for FileOptions fields. const ( Default_FileOptions_JavaMultipleFiles = bool(false) Default_FileOptions_JavaStringCheckUtf8 = bool(false) Default_FileOptions_OptimizeFor = FileOptions_SPEED Default_FileOptions_CcGenericServices = bool(false) Default_FileOptions_JavaGenericServices = bool(false) Default_FileOptions_PyGenericServices = bool(false) Default_FileOptions_PhpGenericServices = bool(false) Default_FileOptions_Deprecated = bool(false) Default_FileOptions_CcEnableArenas = bool(true) ) func (x *FileOptions) Reset() { *x = FileOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileOptions) ProtoMessage() {} func (x *FileOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[10] 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 FileOptions.ProtoReflect.Descriptor instead. func (*FileOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10} } func (x *FileOptions) GetJavaPackage() string { if x != nil && x.JavaPackage != nil { return *x.JavaPackage } return "" } func (x *FileOptions) GetJavaOuterClassname() string { if x != nil && x.JavaOuterClassname != nil { return *x.JavaOuterClassname } return "" } func (x *FileOptions) GetJavaMultipleFiles() bool { if x != nil && x.JavaMultipleFiles != nil { return *x.JavaMultipleFiles } return Default_FileOptions_JavaMultipleFiles } // Deprecated: Do not use. func (x *FileOptions) GetJavaGenerateEqualsAndHash() bool { if x != nil && x.JavaGenerateEqualsAndHash != nil { return *x.JavaGenerateEqualsAndHash } return false } func (x *FileOptions) GetJavaStringCheckUtf8() bool { if x != nil && x.JavaStringCheckUtf8 != nil { return *x.JavaStringCheckUtf8 } return Default_FileOptions_JavaStringCheckUtf8 } func (x *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode { if x != nil && x.OptimizeFor != nil { return *x.OptimizeFor } return Default_FileOptions_OptimizeFor } func (x *FileOptions) GetGoPackage() string { if x != nil && x.GoPackage != nil { return *x.GoPackage } return "" } func (x *FileOptions) GetCcGenericServices() bool { if x != nil && x.CcGenericServices != nil { return *x.CcGenericServices } return Default_FileOptions_CcGenericServices } func (x *FileOptions) GetJavaGenericServices() bool { if x != nil && x.JavaGenericServices != nil { return *x.JavaGenericServices } return Default_FileOptions_JavaGenericServices } func (x *FileOptions) GetPyGenericServices() bool { if x != nil && x.PyGenericServices != nil { return *x.PyGenericServices } return Default_FileOptions_PyGenericServices } func (x *FileOptions) GetPhpGenericServices() bool { if x != nil && x.PhpGenericServices != nil { return *x.PhpGenericServices } return Default_FileOptions_PhpGenericServices } func (x *FileOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_FileOptions_Deprecated } func (x *FileOptions) GetCcEnableArenas() bool { if x != nil && x.CcEnableArenas != nil { return *x.CcEnableArenas } return Default_FileOptions_CcEnableArenas } func (x *FileOptions) GetObjcClassPrefix() string { if x != nil && x.ObjcClassPrefix != nil { return *x.ObjcClassPrefix } return "" } func (x *FileOptions) GetCsharpNamespace() string { if x != nil && x.CsharpNamespace != nil { return *x.CsharpNamespace } return "" } func (x *FileOptions) GetSwiftPrefix() string { if x != nil && x.SwiftPrefix != nil { return *x.SwiftPrefix } return "" } func (x *FileOptions) GetPhpClassPrefix() string { if x != nil && x.PhpClassPrefix != nil { return *x.PhpClassPrefix } return "" } func (x *FileOptions) GetPhpNamespace() string { if x != nil && x.PhpNamespace != nil { return *x.PhpNamespace } return "" } func (x *FileOptions) GetPhpMetadataNamespace() string { if x != nil && x.PhpMetadataNamespace != nil { return *x.PhpMetadataNamespace } return "" } func (x *FileOptions) GetRubyPackage() string { if x != nil && x.RubyPackage != nil { return *x.RubyPackage } return "" } func (x *FileOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type MessageOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Set true to use the old proto1 MessageSet wire format for extensions. // This is provided for backwards-compatibility with the MessageSet wire // format. You should not use this for any other reason: It's less // efficient, has fewer features, and is more complicated. // // The message must be defined exactly as follows: // message Foo { // option message_set_wire_format = true; // extensions 4 to max; // } // Note that the message cannot have any defined fields; MessageSets only // have extensions. // // All extensions of your type must be singular messages; e.g. they cannot // be int32s, enums, or repeated messages. // // Because this is an option, the above two restrictions are not enforced by // the protocol compiler. MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"` // Disables the generation of the standard "descriptor()" accessor, which can // conflict with a field of the same name. This is meant to make migration // from proto1 easier; new code should avoid fields named "descriptor". NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"` // Is this message deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the message, or it will be completely ignored; in the very least, // this is a formalization for deprecating messages. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Whether the message is an automatically generated map entry type for the // maps field. // // For maps fields: // map map_field = 1; // The parsed descriptor looks like: // message MapFieldEntry { // option map_entry = true; // optional KeyType key = 1; // optional ValueType value = 2; // } // repeated MapFieldEntry map_field = 1; // // Implementations may choose not to generate the map_entry=true message, but // use a native map in the target language to hold the keys and values. // The reflection APIs in such implementations still need to work as // if the field is a repeated message field. // // NOTE: Do not set the option in .proto files. Always use the maps syntax // instead. The option should only be implicitly set by the proto compiler // parser. MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for MessageOptions fields. const ( Default_MessageOptions_MessageSetWireFormat = bool(false) Default_MessageOptions_NoStandardDescriptorAccessor = bool(false) Default_MessageOptions_Deprecated = bool(false) ) func (x *MessageOptions) Reset() { *x = MessageOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MessageOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*MessageOptions) ProtoMessage() {} func (x *MessageOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[11] 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 MessageOptions.ProtoReflect.Descriptor instead. func (*MessageOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{11} } func (x *MessageOptions) GetMessageSetWireFormat() bool { if x != nil && x.MessageSetWireFormat != nil { return *x.MessageSetWireFormat } return Default_MessageOptions_MessageSetWireFormat } func (x *MessageOptions) GetNoStandardDescriptorAccessor() bool { if x != nil && x.NoStandardDescriptorAccessor != nil { return *x.NoStandardDescriptorAccessor } return Default_MessageOptions_NoStandardDescriptorAccessor } func (x *MessageOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_MessageOptions_Deprecated } func (x *MessageOptions) GetMapEntry() bool { if x != nil && x.MapEntry != nil { return *x.MapEntry } return false } func (x *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type FieldOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The ctype option instructs the C++ code generator to use a different // representation of the field than it normally would. See the specific // options below. This option is not yet implemented in the open source // release -- sorry, we'll try to include it in a future version! Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"` // The packed option can be enabled for repeated primitive fields to enable // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as // a single length-delimited blob. In proto3, only explicit setting it to // false will avoid using packed encoding. Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"` // The jstype option determines the JavaScript type used for values of the // field. The option is permitted only for 64 bit integral and fixed types // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING // is represented as JavaScript string, which avoids loss of precision that // can happen when a large value is converted to a floating point JavaScript. // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to // use the JavaScript "number" type. The behavior of the default option // JS_NORMAL is implementation dependent. // // This option is an enum to permit additional types to be added, e.g. // goog.math.Integer. Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"` // Should this field be parsed lazily? Lazy applies only to message-type // fields. It means that when the outer message is initially parsed, the // inner message's contents will not be parsed but instead stored in encoded // form. The inner message will actually be parsed when it is first accessed. // // This is only a hint. Implementations are free to choose whether to use // eager or lazy parsing regardless of the value of this option. However, // setting this option true suggests that the protocol author believes that // using lazy parsing on this field is worth the additional bookkeeping // overhead typically needed to implement it. // // This option does not affect the public interface of any generated code; // all method signatures remain the same. Furthermore, thread-safety of the // interface is not affected by this option; const methods remain safe to // call from multiple threads concurrently, while non-const methods continue // to require exclusive access. // // // Note that implementations may choose not to check required fields within // a lazy sub-message. That is, calling IsInitialized() on the outer message // may return true even if the inner message has missing required fields. // This is necessary because otherwise the inner message would have to be // parsed in order to perform the check, defeating the purpose of lazy // parsing. An implementation which chooses not to check required fields // must be consistent about it. That is, for any particular sub-message, the // implementation must either *always* check its required fields, or *never* // check its required fields, regardless of whether or not the message has // been parsed. Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // For Google-internal migration only. Do not use. Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for FieldOptions fields. const ( Default_FieldOptions_Ctype = FieldOptions_STRING Default_FieldOptions_Jstype = FieldOptions_JS_NORMAL Default_FieldOptions_Lazy = bool(false) Default_FieldOptions_Deprecated = bool(false) Default_FieldOptions_Weak = bool(false) ) func (x *FieldOptions) Reset() { *x = FieldOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FieldOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*FieldOptions) ProtoMessage() {} func (x *FieldOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[12] 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 FieldOptions.ProtoReflect.Descriptor instead. func (*FieldOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12} } func (x *FieldOptions) GetCtype() FieldOptions_CType { if x != nil && x.Ctype != nil { return *x.Ctype } return Default_FieldOptions_Ctype } func (x *FieldOptions) GetPacked() bool { if x != nil && x.Packed != nil { return *x.Packed } return false } func (x *FieldOptions) GetJstype() FieldOptions_JSType { if x != nil && x.Jstype != nil { return *x.Jstype } return Default_FieldOptions_Jstype } func (x *FieldOptions) GetLazy() bool { if x != nil && x.Lazy != nil { return *x.Lazy } return Default_FieldOptions_Lazy } func (x *FieldOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_FieldOptions_Deprecated } func (x *FieldOptions) GetWeak() bool { if x != nil && x.Weak != nil { return *x.Weak } return Default_FieldOptions_Weak } func (x *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type OneofOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } func (x *OneofOptions) Reset() { *x = OneofOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OneofOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*OneofOptions) ProtoMessage() {} func (x *OneofOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[13] 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 OneofOptions.ProtoReflect.Descriptor instead. func (*OneofOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{13} } func (x *OneofOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type EnumOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Set this option to true to allow mapping different tag names to the same // value. AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"` // Is this enum deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum, or it will be completely ignored; in the very least, this // is a formalization for deprecating enums. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for EnumOptions fields. const ( Default_EnumOptions_Deprecated = bool(false) ) func (x *EnumOptions) Reset() { *x = EnumOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumOptions) ProtoMessage() {} func (x *EnumOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[14] 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 EnumOptions.ProtoReflect.Descriptor instead. func (*EnumOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{14} } func (x *EnumOptions) GetAllowAlias() bool { if x != nil && x.AllowAlias != nil { return *x.AllowAlias } return false } func (x *EnumOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_EnumOptions_Deprecated } func (x *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type EnumValueOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this enum value deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum value, or it will be completely ignored; in the very least, // this is a formalization for deprecating enum values. Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for EnumValueOptions fields. const ( Default_EnumValueOptions_Deprecated = bool(false) ) func (x *EnumValueOptions) Reset() { *x = EnumValueOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumValueOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumValueOptions) ProtoMessage() {} func (x *EnumValueOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[15] 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 EnumValueOptions.ProtoReflect.Descriptor instead. func (*EnumValueOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{15} } func (x *EnumValueOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_EnumValueOptions_Deprecated } func (x *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type ServiceOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this service deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the service, or it will be completely ignored; in the very least, // this is a formalization for deprecating services. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for ServiceOptions fields. const ( Default_ServiceOptions_Deprecated = bool(false) ) func (x *ServiceOptions) Reset() { *x = ServiceOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ServiceOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*ServiceOptions) ProtoMessage() {} func (x *ServiceOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[16] 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 ServiceOptions.ProtoReflect.Descriptor instead. func (*ServiceOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{16} } func (x *ServiceOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_ServiceOptions_Deprecated } func (x *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type MethodOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this method deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the method, or it will be completely ignored; in the very least, // this is a formalization for deprecating methods. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for MethodOptions fields. const ( Default_MethodOptions_Deprecated = bool(false) Default_MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN ) func (x *MethodOptions) Reset() { *x = MethodOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MethodOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*MethodOptions) ProtoMessage() {} func (x *MethodOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[17] 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 MethodOptions.ProtoReflect.Descriptor instead. func (*MethodOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17} } func (x *MethodOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_MethodOptions_Deprecated } func (x *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel { if x != nil && x.IdempotencyLevel != nil { return *x.IdempotencyLevel } return Default_MethodOptions_IdempotencyLevel } func (x *MethodOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } // A message representing a option the parser does not recognize. This only // appears in options protos created by the compiler::Parser class. // DescriptorPool resolves these when building Descriptor objects. Therefore, // options protos in descriptor objects (e.g. returned by Descriptor::options(), // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions // in them. type UninterpretedOption struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` } func (x *UninterpretedOption) Reset() { *x = UninterpretedOption{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UninterpretedOption) String() string { return protoimpl.X.MessageStringOf(x) } func (*UninterpretedOption) ProtoMessage() {} func (x *UninterpretedOption) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[18] 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 UninterpretedOption.ProtoReflect.Descriptor instead. func (*UninterpretedOption) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{18} } func (x *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { if x != nil { return x.Name } return nil } func (x *UninterpretedOption) GetIdentifierValue() string { if x != nil && x.IdentifierValue != nil { return *x.IdentifierValue } return "" } func (x *UninterpretedOption) GetPositiveIntValue() uint64 { if x != nil && x.PositiveIntValue != nil { return *x.PositiveIntValue } return 0 } func (x *UninterpretedOption) GetNegativeIntValue() int64 { if x != nil && x.NegativeIntValue != nil { return *x.NegativeIntValue } return 0 } func (x *UninterpretedOption) GetDoubleValue() float64 { if x != nil && x.DoubleValue != nil { return *x.DoubleValue } return 0 } func (x *UninterpretedOption) GetStringValue() []byte { if x != nil { return x.StringValue } return nil } func (x *UninterpretedOption) GetAggregateValue() string { if x != nil && x.AggregateValue != nil { return *x.AggregateValue } return "" } // Encapsulates information about the original source file from which a // FileDescriptorProto was generated. type SourceCodeInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // A Location identifies a piece of source code in a .proto file which // corresponds to a particular definition. This information is intended // to be useful to IDEs, code indexers, documentation generators, and similar // tools. // // For example, say we have a file like: // message Foo { // optional string foo = 1; // } // Let's look at just the field definition: // optional string foo = 1; // ^ ^^ ^^ ^ ^^^ // a bc de f ghi // We have the following locations: // span path represents // [a,i) [ 4, 0, 2, 0 ] The whole field definition. // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). // // Notes: // - A location may refer to a repeated field itself (i.e. not to any // particular index within it). This is used whenever a set of elements are // logically enclosed in a single code segment. For example, an entire // extend block (possibly containing multiple extension definitions) will // have an outer location whose path refers to the "extensions" repeated // field without an index. // - Multiple locations may have the same path. This happens when a single // logical declaration is spread out across multiple places. The most // obvious example is the "extend" block again -- there may be multiple // extend blocks in the same scope, each of which will have the same path. // - A location's span is not always a subset of its parent's span. For // example, the "extendee" of an extension declaration appears at the // beginning of the "extend" block and is shared by all extensions within // the block. // - Just because a location's span is a subset of some other location's span // does not mean that it is a descendant. For example, a "group" defines // both a type and a field in a single declaration. Thus, the locations // corresponding to the type and field and their components will overlap. // - Code which tries to interpret locations should probably be designed to // ignore those that it doesn't understand, as more types of locations could // be recorded in the future. Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` } func (x *SourceCodeInfo) Reset() { *x = SourceCodeInfo{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SourceCodeInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*SourceCodeInfo) ProtoMessage() {} func (x *SourceCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[19] 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 SourceCodeInfo.ProtoReflect.Descriptor instead. func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19} } func (x *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { if x != nil { return x.Location } return nil } // Describes the relationship between generated code and its original source // file. A GeneratedCodeInfo message is associated with only one generated // source file, but may contain references to different source .proto files. type GeneratedCodeInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // An Annotation connects some span of text in generated code to an element // of its generating .proto file. Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` } func (x *GeneratedCodeInfo) Reset() { *x = GeneratedCodeInfo{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GeneratedCodeInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*GeneratedCodeInfo) ProtoMessage() {} func (x *GeneratedCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[20] 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 GeneratedCodeInfo.ProtoReflect.Descriptor instead. func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20} } func (x *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation { if x != nil { return x.Annotation } return nil } type DescriptorProto_ExtensionRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Exclusive. Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *DescriptorProto_ExtensionRange) Reset() { *x = DescriptorProto_ExtensionRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto_ExtensionRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto_ExtensionRange) ProtoMessage() {} func (x *DescriptorProto_ExtensionRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[21] 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 DescriptorProto_ExtensionRange.ProtoReflect.Descriptor instead. func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2, 0} } func (x *DescriptorProto_ExtensionRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *DescriptorProto_ExtensionRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } func (x *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions { if x != nil { return x.Options } return nil } // Range of reserved tag numbers. Reserved tag numbers may not be used by // fields or extension ranges in the same message. Reserved ranges may // not overlap. type DescriptorProto_ReservedRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Exclusive. } func (x *DescriptorProto_ReservedRange) Reset() { *x = DescriptorProto_ReservedRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto_ReservedRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto_ReservedRange) ProtoMessage() {} func (x *DescriptorProto_ReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[22] 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 DescriptorProto_ReservedRange.ProtoReflect.Descriptor instead. func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2, 1} } func (x *DescriptorProto_ReservedRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *DescriptorProto_ReservedRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } // Range of reserved numeric values. Reserved values may not be used by // entries in the same enum. Reserved ranges may not overlap. // // Note that this is distinct from DescriptorProto.ReservedRange in that it // is inclusive such that it can appropriately represent the entire int32 // domain. type EnumDescriptorProto_EnumReservedRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Inclusive. } func (x *EnumDescriptorProto_EnumReservedRange) Reset() { *x = EnumDescriptorProto_EnumReservedRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumDescriptorProto_EnumReservedRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {} func (x *EnumDescriptorProto_EnumReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[23] 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 EnumDescriptorProto_EnumReservedRange.ProtoReflect.Descriptor instead. func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{6, 0} } func (x *EnumDescriptorProto_EnumReservedRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } // The name of the uninterpreted option. Each string represents a segment in // a dot-separated name. is_extension is true iff a segment represents an // extension (denoted with parentheses in options specs in .proto files). // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents // "foo.(bar.baz).qux". type UninterpretedOption_NamePart struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` } func (x *UninterpretedOption_NamePart) Reset() { *x = UninterpretedOption_NamePart{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UninterpretedOption_NamePart) String() string { return protoimpl.X.MessageStringOf(x) } func (*UninterpretedOption_NamePart) ProtoMessage() {} func (x *UninterpretedOption_NamePart) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[24] 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 UninterpretedOption_NamePart.ProtoReflect.Descriptor instead. func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{18, 0} } func (x *UninterpretedOption_NamePart) GetNamePart() string { if x != nil && x.NamePart != nil { return *x.NamePart } return "" } func (x *UninterpretedOption_NamePart) GetIsExtension() bool { if x != nil && x.IsExtension != nil { return *x.IsExtension } return false } type SourceCodeInfo_Location struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Identifies which part of the FileDescriptorProto was defined at this // location. // // Each element is a field number or an index. They form a path from // the root FileDescriptorProto to the place where the definition. For // example, this path: // [ 4, 3, 2, 7, 1 ] // refers to: // file.message_type(3) // 4, 3 // .field(7) // 2, 7 // .name() // 1 // This is because FileDescriptorProto.message_type has field number 4: // repeated DescriptorProto message_type = 4; // and DescriptorProto.field has field number 2: // repeated FieldDescriptorProto field = 2; // and FieldDescriptorProto.name has field number 1: // optional string name = 1; // // Thus, the above path gives the location of a field name. If we removed // the last element: // [ 4, 3, 2, 7 ] // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. // These are packed into a single field for efficiency. Note that line // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"` // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be // attached to the declaration. // // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // // leading_detached_comments will keep paragraphs of comments that appear // before (but not connected to) the current element. Each paragraph, // separated by empty lines, will be one comment element in the repeated // field. // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. // Newlines are included in the output. // // Examples: // // optional int32 foo = 1; // Comment attached to foo. // // Comment attached to bar. // optional int32 bar = 2; // // optional string baz = 3; // // Comment attached to baz. // // Another line attached to baz. // // // Comment attached to qux. // // // // Another line attached to qux. // optional double qux = 4; // // // Detached comment for corge. This is not leading or trailing comments // // to qux or corge because there are blank lines separating it from // // both. // // // Detached comment for corge paragraph 2. // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks // * will be removed. */ // /* Block comment attached to // * grault. */ // optional int32 grault = 6; // // // ignored detached comments. LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` } func (x *SourceCodeInfo_Location) Reset() { *x = SourceCodeInfo_Location{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SourceCodeInfo_Location) String() string { return protoimpl.X.MessageStringOf(x) } func (*SourceCodeInfo_Location) ProtoMessage() {} func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[25] 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 SourceCodeInfo_Location.ProtoReflect.Descriptor instead. func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0} } func (x *SourceCodeInfo_Location) GetPath() []int32 { if x != nil { return x.Path } return nil } func (x *SourceCodeInfo_Location) GetSpan() []int32 { if x != nil { return x.Span } return nil } func (x *SourceCodeInfo_Location) GetLeadingComments() string { if x != nil && x.LeadingComments != nil { return *x.LeadingComments } return "" } func (x *SourceCodeInfo_Location) GetTrailingComments() string { if x != nil && x.TrailingComments != nil { return *x.TrailingComments } return "" } func (x *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { if x != nil { return x.LeadingDetachedComments } return nil } type GeneratedCodeInfo_Annotation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Identifies the element in the original source .proto file. This field // is formatted the same as SourceCodeInfo.Location.path. Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` // Identifies the filesystem path to the original source .proto. SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"` // Identifies the starting offset in bytes in the generated code // that relates to the identified object. Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"` // Identifies the ending offset in bytes in the generated code that // relates to the identified offset. The end offset should be one past // the last relevant byte (so the length of the text = end - begin). End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` } func (x *GeneratedCodeInfo_Annotation) Reset() { *x = GeneratedCodeInfo_Annotation{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GeneratedCodeInfo_Annotation) String() string { return protoimpl.X.MessageStringOf(x) } func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[26] 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 GeneratedCodeInfo_Annotation.ProtoReflect.Descriptor instead. func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0} } func (x *GeneratedCodeInfo_Annotation) GetPath() []int32 { if x != nil { return x.Path } return nil } func (x *GeneratedCodeInfo_Annotation) GetSourceFile() string { if x != nil && x.SourceFile != nil { return *x.SourceFile } return "" } func (x *GeneratedCodeInfo_Annotation) GetBegin() int32 { if x != nil && x.Begin != nil { return *x.Begin } return 0 } func (x *GeneratedCodeInfo_Annotation) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } var File_google_protobuf_descriptor_proto protoreflect.FileDescriptor var file_google_protobuf_descriptor_proto_rawDesc = []byte{ 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc1, 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x22, 0x91, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70, 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x10, 0x63, 0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x7e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 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, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, } var ( file_google_protobuf_descriptor_proto_rawDescOnce sync.Once file_google_protobuf_descriptor_proto_rawDescData = file_google_protobuf_descriptor_proto_rawDesc ) func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte { file_google_protobuf_descriptor_proto_rawDescOnce.Do(func() { file_google_protobuf_descriptor_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_descriptor_proto_rawDescData) }) return file_google_protobuf_descriptor_proto_rawDescData } var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 6) var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ (FieldDescriptorProto_Type)(0), // 0: google.protobuf.FieldDescriptorProto.Type (FieldDescriptorProto_Label)(0), // 1: google.protobuf.FieldDescriptorProto.Label (FileOptions_OptimizeMode)(0), // 2: google.protobuf.FileOptions.OptimizeMode (FieldOptions_CType)(0), // 3: google.protobuf.FieldOptions.CType (FieldOptions_JSType)(0), // 4: google.protobuf.FieldOptions.JSType (MethodOptions_IdempotencyLevel)(0), // 5: google.protobuf.MethodOptions.IdempotencyLevel (*FileDescriptorSet)(nil), // 6: google.protobuf.FileDescriptorSet (*FileDescriptorProto)(nil), // 7: google.protobuf.FileDescriptorProto (*DescriptorProto)(nil), // 8: google.protobuf.DescriptorProto (*ExtensionRangeOptions)(nil), // 9: google.protobuf.ExtensionRangeOptions (*FieldDescriptorProto)(nil), // 10: google.protobuf.FieldDescriptorProto (*OneofDescriptorProto)(nil), // 11: google.protobuf.OneofDescriptorProto (*EnumDescriptorProto)(nil), // 12: google.protobuf.EnumDescriptorProto (*EnumValueDescriptorProto)(nil), // 13: google.protobuf.EnumValueDescriptorProto (*ServiceDescriptorProto)(nil), // 14: google.protobuf.ServiceDescriptorProto (*MethodDescriptorProto)(nil), // 15: google.protobuf.MethodDescriptorProto (*FileOptions)(nil), // 16: google.protobuf.FileOptions (*MessageOptions)(nil), // 17: google.protobuf.MessageOptions (*FieldOptions)(nil), // 18: google.protobuf.FieldOptions (*OneofOptions)(nil), // 19: google.protobuf.OneofOptions (*EnumOptions)(nil), // 20: google.protobuf.EnumOptions (*EnumValueOptions)(nil), // 21: google.protobuf.EnumValueOptions (*ServiceOptions)(nil), // 22: google.protobuf.ServiceOptions (*MethodOptions)(nil), // 23: google.protobuf.MethodOptions (*UninterpretedOption)(nil), // 24: google.protobuf.UninterpretedOption (*SourceCodeInfo)(nil), // 25: google.protobuf.SourceCodeInfo (*GeneratedCodeInfo)(nil), // 26: google.protobuf.GeneratedCodeInfo (*DescriptorProto_ExtensionRange)(nil), // 27: google.protobuf.DescriptorProto.ExtensionRange (*DescriptorProto_ReservedRange)(nil), // 28: google.protobuf.DescriptorProto.ReservedRange (*EnumDescriptorProto_EnumReservedRange)(nil), // 29: google.protobuf.EnumDescriptorProto.EnumReservedRange (*UninterpretedOption_NamePart)(nil), // 30: google.protobuf.UninterpretedOption.NamePart (*SourceCodeInfo_Location)(nil), // 31: google.protobuf.SourceCodeInfo.Location (*GeneratedCodeInfo_Annotation)(nil), // 32: google.protobuf.GeneratedCodeInfo.Annotation } var file_google_protobuf_descriptor_proto_depIdxs = []int32{ 7, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto 8, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto 12, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto 14, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto 10, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto 16, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions 25, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo 10, // 7: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto 10, // 8: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto 8, // 9: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto 12, // 10: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto 27, // 11: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange 11, // 12: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto 17, // 13: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions 28, // 14: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange 24, // 15: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 1, // 16: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label 0, // 17: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type 18, // 18: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions 19, // 19: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions 13, // 20: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto 20, // 21: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions 29, // 22: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange 21, // 23: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions 15, // 24: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto 22, // 25: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions 23, // 26: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions 2, // 27: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode 24, // 28: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 29: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 3, // 30: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType 4, // 31: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType 24, // 32: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 33: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 34: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 35: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 36: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 5, // 37: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel 24, // 38: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 30, // 39: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart 31, // 40: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location 32, // 41: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation 9, // 42: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions 43, // [43:43] is the sub-list for method output_type 43, // [43:43] is the sub-list for method input_type 43, // [43:43] is the sub-list for extension type_name 43, // [43:43] is the sub-list for extension extendee 0, // [0:43] is the sub-list for field type_name } func init() { file_google_protobuf_descriptor_proto_init() } func file_google_protobuf_descriptor_proto_init() { if File_google_protobuf_descriptor_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_protobuf_descriptor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileDescriptorSet); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExtensionRangeOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FieldDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OneofDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumValueDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MethodDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MessageOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FieldOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OneofOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumValueOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MethodOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UninterpretedOption); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SourceCodeInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeneratedCodeInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto_ExtensionRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto_ReservedRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumDescriptorProto_EnumReservedRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UninterpretedOption_NamePart); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SourceCodeInfo_Location); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeneratedCodeInfo_Annotation); 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_descriptor_proto_rawDesc, NumEnums: 6, NumMessages: 27, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_protobuf_descriptor_proto_goTypes, DependencyIndexes: file_google_protobuf_descriptor_proto_depIdxs, EnumInfos: file_google_protobuf_descriptor_proto_enumTypes, MessageInfos: file_google_protobuf_descriptor_proto_msgTypes, }.Build() File_google_protobuf_descriptor_proto = out.File file_google_protobuf_descriptor_proto_rawDesc = nil file_google_protobuf_descriptor_proto_goTypes = nil file_google_protobuf_descriptor_proto_depIdxs = nil } ================================================ FILE: _tools/src/google.golang.org/protobuf/types/pluginpb/plugin.pb.go ================================================ // 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. // Author: kenton@google.com (Kenton Varda) // // WARNING: The plugin interface is currently EXPERIMENTAL and is subject to // change. // // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is // just a program that reads a CodeGeneratorRequest from stdin and writes a // CodeGeneratorResponse to stdout. // // Plugins written using C++ can use google/protobuf/compiler/plugin.h instead // of dealing with the raw protocol defined here. // // A plugin executable needs only to be placed somewhere in the path. The // plugin should be named "protoc-gen-$NAME", and will then be used when the // flag "--${NAME}_out" is passed to protoc. // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/compiler/plugin.proto package pluginpb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" descriptorpb "google.golang.org/protobuf/types/descriptorpb" reflect "reflect" sync "sync" ) // Sync with code_generator.h. type CodeGeneratorResponse_Feature int32 const ( CodeGeneratorResponse_FEATURE_NONE CodeGeneratorResponse_Feature = 0 CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL CodeGeneratorResponse_Feature = 1 ) // Enum value maps for CodeGeneratorResponse_Feature. var ( CodeGeneratorResponse_Feature_name = map[int32]string{ 0: "FEATURE_NONE", 1: "FEATURE_PROTO3_OPTIONAL", } CodeGeneratorResponse_Feature_value = map[string]int32{ "FEATURE_NONE": 0, "FEATURE_PROTO3_OPTIONAL": 1, } ) func (x CodeGeneratorResponse_Feature) Enum() *CodeGeneratorResponse_Feature { p := new(CodeGeneratorResponse_Feature) *p = x return p } func (x CodeGeneratorResponse_Feature) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (CodeGeneratorResponse_Feature) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_compiler_plugin_proto_enumTypes[0].Descriptor() } func (CodeGeneratorResponse_Feature) Type() protoreflect.EnumType { return &file_google_protobuf_compiler_plugin_proto_enumTypes[0] } func (x CodeGeneratorResponse_Feature) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *CodeGeneratorResponse_Feature) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = CodeGeneratorResponse_Feature(num) return nil } // Deprecated: Use CodeGeneratorResponse_Feature.Descriptor instead. func (CodeGeneratorResponse_Feature) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0} } // The version number of protocol compiler. type Version struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields 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"` } func (x *Version) Reset() { *x = Version{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Version) String() string { return protoimpl.X.MessageStringOf(x) } func (*Version) ProtoMessage() {} func (x *Version) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0] if 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 Version.ProtoReflect.Descriptor instead. func (*Version) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{0} } func (x *Version) GetMajor() int32 { if x != nil && x.Major != nil { return *x.Major } return 0 } func (x *Version) GetMinor() int32 { if x != nil && x.Minor != nil { return *x.Minor } return 0 } func (x *Version) GetPatch() int32 { if x != nil && x.Patch != nil { return *x.Patch } return 0 } func (x *Version) GetSuffix() string { if x != nil && x.Suffix != nil { return *x.Suffix } return "" } // An encoded CodeGeneratorRequest is written to the plugin's stdin. type CodeGeneratorRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // 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 []*descriptorpb.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"` } func (x *CodeGeneratorRequest) Reset() { *x = CodeGeneratorRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorRequest) ProtoMessage() {} func (x *CodeGeneratorRequest) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1] if 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 CodeGeneratorRequest.ProtoReflect.Descriptor instead. func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{1} } func (x *CodeGeneratorRequest) GetFileToGenerate() []string { if x != nil { return x.FileToGenerate } return nil } func (x *CodeGeneratorRequest) GetParameter() string { if x != nil && x.Parameter != nil { return *x.Parameter } return "" } func (x *CodeGeneratorRequest) GetProtoFile() []*descriptorpb.FileDescriptorProto { if x != nil { return x.ProtoFile } return nil } func (x *CodeGeneratorRequest) GetCompilerVersion() *Version { if x != nil { return x.CompilerVersion } return nil } // The plugin writes an encoded CodeGeneratorResponse to stdout. type CodeGeneratorResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Error message. If non-empty, code generation failed. The plugin process // should exit with status code zero even if it reports an error in this way. // // This should be used to indicate errors in .proto files which prevent the // code generator from generating correct code. Errors which indicate a // problem in protoc itself -- such as the input CodeGeneratorRequest being // unparseable -- should be reported by writing a message to stderr and // exiting with a non-zero status code. Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` // A bitmask of supported features that the code generator supports. // This is a bitwise "or" of values from the Feature enum. SupportedFeatures *uint64 `protobuf:"varint,2,opt,name=supported_features,json=supportedFeatures" json:"supported_features,omitempty"` File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` } func (x *CodeGeneratorResponse) Reset() { *x = CodeGeneratorResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorResponse) ProtoMessage() {} func (x *CodeGeneratorResponse) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2] if 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 CodeGeneratorResponse.ProtoReflect.Descriptor instead. func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2} } func (x *CodeGeneratorResponse) GetError() string { if x != nil && x.Error != nil { return *x.Error } return "" } func (x *CodeGeneratorResponse) GetSupportedFeatures() uint64 { if x != nil && x.SupportedFeatures != nil { return *x.SupportedFeatures } return 0 } func (x *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File { if x != nil { return x.File } return nil } // Represents a single generated file. type CodeGeneratorResponse_File struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The file name, relative to the output directory. The name must not // contain "." or ".." components and must be relative, not be absolute (so, // the file cannot lie outside the output directory). "/" must be used as // the path separator, not "\". // // If the name is omitted, the content will be appended to the previous // file. This allows the generator to break large files into small chunks, // and allows the generated text to be streamed back to protoc so that large // files need not reside completely in memory at one time. Note that as of // this writing protoc does not optimize for this -- it will read the entire // CodeGeneratorResponse before writing files to disk. Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // If non-empty, indicates that the named file should already exist, and the // content here is to be inserted into that file at a defined insertion // point. This feature allows a code generator to extend the output // produced by another code generator. The original generator may provide // insertion points by placing special annotations in the file that look // like: // @@protoc_insertion_point(NAME) // The annotation can have arbitrary text before and after it on the line, // which allows it to be placed in a comment. NAME should be replaced with // an identifier naming the point -- this is what other generators will use // as the insertion_point. Code inserted at this point will be placed // immediately above the line containing the insertion point (thus multiple // insertions to the same point will come out in the order they were added). // The double-@ is intended to make it unlikely that the generated code // could contain things that look like insertion points by accident. // // For example, the C++ code generator places the following line in the // .pb.h files that it generates: // // @@protoc_insertion_point(namespace_scope) // This line appears within the scope of the file's package namespace, but // outside of any particular class. Another plugin can then specify the // insertion_point "namespace_scope" to generate additional classes or // other declarations that should be placed in this scope. // // Note that if the line containing the insertion point begins with // whitespace, the same whitespace will be added to every line of the // inserted text. This is useful for languages like Python, where // indentation matters. In these languages, the insertion point comment // should be indented the same amount as any inserted code will need to be // in order to work correctly in that context. // // The code generator that generates the initial file and the one which // inserts into it must both run as part of a single invocation of protoc. // Code generators are executed in the order in which they appear on the // command line. // // If |insertion_point| is present, |name| must also be present. InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"` // The file contents. Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` // Information describing the file content being inserted. If an insertion // point is used, this information will be appropriately offset and inserted // into the code generation metadata for the generated files. GeneratedCodeInfo *descriptorpb.GeneratedCodeInfo `protobuf:"bytes,16,opt,name=generated_code_info,json=generatedCodeInfo" json:"generated_code_info,omitempty"` } func (x *CodeGeneratorResponse_File) Reset() { *x = CodeGeneratorResponse_File{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorResponse_File) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorResponse_File) ProtoMessage() {} func (x *CodeGeneratorResponse_File) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3] if 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 CodeGeneratorResponse_File.ProtoReflect.Descriptor instead. func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0} } func (x *CodeGeneratorResponse_File) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *CodeGeneratorResponse_File) GetInsertionPoint() string { if x != nil && x.InsertionPoint != nil { return *x.InsertionPoint } return "" } func (x *CodeGeneratorResponse_File) GetContent() string { if x != nil && x.Content != nil { return *x.Content } return "" } func (x *CodeGeneratorResponse_File) GetGeneratedCodeInfo() *descriptorpb.GeneratedCodeInfo { if x != nil { return x.GeneratedCodeInfo } return nil } var File_google_protobuf_compiler_plugin_proto protoreflect.FileDescriptor var file_google_protobuf_compiler_plugin_proto_rawDesc = []byte{ 0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x63, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x03, 0x0a, 0x15, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0xb1, 0x01, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x38, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x42, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x5a, 0x29, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x70, 0x62, } var ( file_google_protobuf_compiler_plugin_proto_rawDescOnce sync.Once file_google_protobuf_compiler_plugin_proto_rawDescData = file_google_protobuf_compiler_plugin_proto_rawDesc ) func file_google_protobuf_compiler_plugin_proto_rawDescGZIP() []byte { file_google_protobuf_compiler_plugin_proto_rawDescOnce.Do(func() { file_google_protobuf_compiler_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_compiler_plugin_proto_rawDescData) }) return file_google_protobuf_compiler_plugin_proto_rawDescData } var file_google_protobuf_compiler_plugin_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_protobuf_compiler_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_google_protobuf_compiler_plugin_proto_goTypes = []interface{}{ (CodeGeneratorResponse_Feature)(0), // 0: google.protobuf.compiler.CodeGeneratorResponse.Feature (*Version)(nil), // 1: google.protobuf.compiler.Version (*CodeGeneratorRequest)(nil), // 2: google.protobuf.compiler.CodeGeneratorRequest (*CodeGeneratorResponse)(nil), // 3: google.protobuf.compiler.CodeGeneratorResponse (*CodeGeneratorResponse_File)(nil), // 4: google.protobuf.compiler.CodeGeneratorResponse.File (*descriptorpb.FileDescriptorProto)(nil), // 5: google.protobuf.FileDescriptorProto (*descriptorpb.GeneratedCodeInfo)(nil), // 6: google.protobuf.GeneratedCodeInfo } var file_google_protobuf_compiler_plugin_proto_depIdxs = []int32{ 5, // 0: google.protobuf.compiler.CodeGeneratorRequest.proto_file:type_name -> google.protobuf.FileDescriptorProto 1, // 1: google.protobuf.compiler.CodeGeneratorRequest.compiler_version:type_name -> google.protobuf.compiler.Version 4, // 2: google.protobuf.compiler.CodeGeneratorResponse.file:type_name -> google.protobuf.compiler.CodeGeneratorResponse.File 6, // 3: google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info:type_name -> google.protobuf.GeneratedCodeInfo 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_google_protobuf_compiler_plugin_proto_init() } func file_google_protobuf_compiler_plugin_proto_init() { if File_google_protobuf_compiler_plugin_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_protobuf_compiler_plugin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Version); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorResponse_File); 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_compiler_plugin_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_protobuf_compiler_plugin_proto_goTypes, DependencyIndexes: file_google_protobuf_compiler_plugin_proto_depIdxs, EnumInfos: file_google_protobuf_compiler_plugin_proto_enumTypes, MessageInfos: file_google_protobuf_compiler_plugin_proto_msgTypes, }.Build() File_google_protobuf_compiler_plugin_proto = out.File file_google_protobuf_compiler_plugin_proto_rawDesc = nil file_google_protobuf_compiler_plugin_proto_goTypes = nil file_google_protobuf_compiler_plugin_proto_depIdxs = nil } ================================================ FILE: check_protoc_version.sh ================================================ #!/usr/bin/env bash # Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"). You may not # use this file except in compliance with the License. A copy of the License is # located at # # http://www.apache.org/licenses/LICENSE-2.0 # # or in the "license" file accompanying this file. This file 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. which protoc PROTOC_EXISTS=$? if [ $PROTOC_EXISTS -eq 0 ]; then PROTOC_VERSION=`protoc --version` if [[ $PROTOC_VERSION == "libprotoc 3."* ]]; then echo "protoc version: $PROTOC_VERSION" exit 0 fi echo "required protoc v3, but found: $PROTOC_VERSION" exit 1 fi echo "Please install protoc v3. See https://grpc.io/docs/protoc-installation/, for example in MacOS: brew install protobuf" exit 1 ================================================ FILE: client_options.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "net/http" "reflect" ) // ClientOption is a functional option for extending a Twirp client. type ClientOption func(*ClientOptions) // WithClientHooks defines the hooks for a Twirp client. func WithClientHooks(hooks *ClientHooks) ClientOption { return func(opts *ClientOptions) { opts.Hooks = hooks } } // WithClientInterceptors defines the interceptors for a Twirp client. func WithClientInterceptors(interceptors ...Interceptor) ClientOption { return func(opts *ClientOptions) { opts.Interceptors = append(opts.Interceptors, interceptors...) } } // WithClientPathPrefix specifies a different prefix to use for routing. // If not specified, the "/twirp" prefix is used by default. // The service must be configured to serve on the same prefix. // An empty value "" can be specified to use no prefix. // URL format: "[]/./" // More info on Twirp docs: https://twitchtv.github.io/twirp/docs/routing.html func WithClientPathPrefix(prefix string) ClientOption { return func(opts *ClientOptions) { opts.setOpt("pathPrefix", prefix) opts.pathPrefix = &prefix // for code generated before v8.1.0 } } // WithClientLiteralURLs configures the Twirp client to use the exact values // as defined in the proto file for Service and Method names, // fixing the issue https://github.com/twitchtv/twirp/issues/244, which is manifested // when working with Twirp services implemented other languages (e.g. Python) and the proto file definitions // are not properly following the [Protobuf Style Guide](https://developers.google.com/protocol-buffers/docs/style#services). // By default (false), Go clients modify the routes by CamelCasing the values. For example, // with Service: `haberdasher`, Method: `make_hat`, the URLs generated by Go clients are `Haberdasher/MakeHat`, // but with this option enabled (true) the client will properly use `haberdasher/make_hat` instead. func WithClientLiteralURLs(b bool) ClientOption { return func(opts *ClientOptions) { opts.setOpt("literalURLs", b) opts.LiteralURLs = b // for code generated before v8.1.0 } } // ClientHooks is a container for callbacks that can instrument a // Twirp-generated client. These callbacks all accept a context and some return // a context. They can use this to add to the context, appending values or // deadlines to it. // // The RequestPrepared hook is special because it can return errors. If it // returns non-nil error, handling for that request will be stopped at that // point. The Error hook will then be triggered. // // The RequestPrepared hook will always be called first and will be called for // each outgoing request from the Twirp client. The last hook to be called // will either be Error or ResponseReceived, so be sure to handle both cases in // your hooks. type ClientHooks struct { // RequestPrepared is called as soon as a request has been created and before // it has been sent to the Twirp server. RequestPrepared func(context.Context, *http.Request) (context.Context, error) // ResponseReceived is called after a request has finished sending. Since this // is terminal, the context is not returned. ResponseReceived will not be // called in the case of an error being returned from the request. ResponseReceived func(context.Context) // Error hook is called whenever an error occurs during the sending of a // request. The Error is passed as an argument to the hook. Error func(context.Context, Error) } // ChainClientHooks creates a new *ClientHooks which chains the callbacks in // each of the constituent hooks passed in. Each hook function will be // called in the order of the ClientHooks values passed in. // // For the erroring hook, RequestPrepared, any returned // errors prevent processing by later hooks. func ChainClientHooks(hooks ...*ClientHooks) *ClientHooks { if len(hooks) == 0 { return nil } if len(hooks) == 1 { return hooks[0] } return &ClientHooks{ RequestPrepared: func(ctx context.Context, req *http.Request) (context.Context, error) { for _, h := range hooks { if h != nil && h.RequestPrepared != nil { var err error ctx, err = h.RequestPrepared(ctx, req) if err != nil { return ctx, err } } } return ctx, nil }, ResponseReceived: func(ctx context.Context) { for _, h := range hooks { if h != nil && h.ResponseReceived != nil { h.ResponseReceived(ctx) } } }, Error: func(ctx context.Context, twerr Error) { for _, h := range hooks { if h != nil && h.Error != nil { h.Error(ctx, twerr) } } }, } } // ClientOptions encapsulate the configurable parameters on a Twirp client. // This type is meant to be used only by generated code. type ClientOptions struct { // Untyped options map. The methods setOpt and ReadOpt are used to set // and read options. The options are untyped so when a new option is added, // newly generated code can still work with older versions of the runtime. m map[string]interface{} Hooks *ClientHooks Interceptors []Interceptor // Properties below are only used by code that was // generated by older versions of Twirp (before v8.1.0). // New options with standard types added in the future // don't need new properties, they should use ReadOpt. LiteralURLs bool pathPrefix *string } // ReadOpt extracts an option to a pointer value, // returns true if the option exists and was extracted. // This method is meant to be used by generated code, // keeping the type dependency outside of the runtime. // // Usage example: // // opts.setOpt("fooOpt", 123) // var foo int // ok := opts.ReadOpt("fooOpt", &int) // func (opts *ClientOptions) ReadOpt(key string, out interface{}) bool { val, ok := opts.m[key] if !ok { return false } rout := reflect.ValueOf(out) if rout.Kind() != reflect.Ptr { panic("ReadOpt(key, out); out must be a pointer but it was not") } rout.Elem().Set(reflect.ValueOf(val)) return true } // setOpt adds an option key/value. It is used by ServerOption helpers. // The value can be extracted with ReadOpt by passing a pointer to the same type. func (opts *ClientOptions) setOpt(key string, val interface{}) { if opts.m == nil { opts.m = make(map[string]interface{}) } opts.m[key] = val } // PathPrefix() is used only by clients generated before v8.1.0 func (opts *ClientOptions) PathPrefix() string { if opts.pathPrefix == nil { return "/twirp" // default prefix } return *opts.pathPrefix } ================================================ FILE: client_options_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "net/http" "reflect" "testing" ) func TestClientOptionsReadOpt(t *testing.T) { opts := &ClientOptions{} ok := false var fooNum int ok = opts.ReadOpt("fooNum", &fooNum) if ok { t.Errorf("option 'fooNum' does not exist, opts.ReadOpt should have returned false") } opts.setOpt("fooNum", 455) ok = opts.ReadOpt("fooNum", &fooNum) if !ok || fooNum != 455 { t.Errorf("option 'fooNum' expected to be 455") } var literalURLs bool ok = opts.ReadOpt("literalURLs", &literalURLs) if ok { t.Errorf("option 'literalURLs' does not exist, opts.ReadOpt should have returned false") } WithClientLiteralURLs(true)(opts) ok = opts.ReadOpt("literalURLs", &literalURLs) if !ok || !literalURLs { t.Errorf("option 'literalURLs' expected to be true, ok: %v, val: %v", ok, literalURLs) } WithClientLiteralURLs(false)(opts) ok = opts.ReadOpt("literalURLs", &literalURLs) if !ok || literalURLs { t.Errorf("option 'literalURLs' expected to be false, ok: %v, val: %v", ok, literalURLs) } } func TestChainClientHooks(t *testing.T) { var ( hook1 = new(ClientHooks) hook2 = new(ClientHooks) hook3 = new(ClientHooks) responseReceivedCalled []string errorCalled []string ) const key = "key" hook1.RequestPrepared = func(ctx context.Context, req *http.Request) (context.Context, error) { return context.WithValue(ctx, key, []string{"hook1"}), nil } hook2.RequestPrepared = func(ctx context.Context, req *http.Request) (context.Context, error) { v := ctx.Value(key).([]string) return context.WithValue(ctx, key, append(v, "hook2")), nil } hook3.RequestPrepared = func(ctx context.Context, req *http.Request) (context.Context, error) { v := ctx.Value(key).([]string) return context.WithValue(ctx, key, append(v, "hook3")), nil } hook1.ResponseReceived = func(ctx context.Context) { responseReceivedCalled = append(responseReceivedCalled, "hook1") } hook2.Error = func(ctx context.Context, twerr Error) { errorCalled = append(errorCalled, "hook2") } chain := ChainClientHooks(hook1, hook2, hook3) ctx := context.Background() // When all three chained hooks have a handler, all should be called in order. want := []string{"hook1", "hook2", "hook3"} haveCtx, err := chain.RequestPrepared(ctx, new(http.Request)) if err != nil { t.Fatalf("RequestPrepared chain has unexpected err %v", err) } have := haveCtx.Value(key) if !reflect.DeepEqual(have, want) { t.Errorf("RequestPrepared chain has unexpected ctx, have=%v, want=%v", have, want) } // When only the first chained hook has a handler, it should be called, and // there should be no panic. want = []string{"hook1"} chain.ResponseReceived(ctx) if have := responseReceivedCalled; !reflect.DeepEqual(have, want) { t.Errorf("unexpected hooks called, have: %v, want: %v", have, want) } // When only the second chained hook has a handler, it should be called, and // there should be no panic. want = []string{"hook2"} chain.Error(ctx, InternalError("whoops")) if have := errorCalled; !reflect.DeepEqual(have, want) { t.Errorf("unexpected hooks called, have: %v, want: %v", have, want) } // When none of the chained hooks has a handler there should be no panic. errorCalled = nil hook2.Error = nil chain.Error(ctx, InternalError("whoops")) if have, want := len(errorCalled), 0; have != want { t.Errorf("unexpected number of calls, have: %d, want: %d", have, want) } } func TestWithClientPathPrefix(t *testing.T) { opts := &ClientOptions{} // Default value if have, want := opts.PathPrefix(), "/twirp"; have != want { t.Errorf("unexpected default PathPrefix() on ClientOptions, have: %q, want: %q", have, want) } // Set a different prefix WithClientPathPrefix("/newprfx/foobar")(opts) if have, want := opts.PathPrefix(), "/newprfx/foobar"; have != want { t.Errorf("unexpected value after WithClientPathPrefix, have: %q, want: %q", have, want) } // Use empty value for no-prefix WithClientPathPrefix("")(opts) if have, want := opts.PathPrefix(), ""; have != want { t.Errorf("unexpected value after WithClientPathPrefix, have: %q, want: %q", have, want) } } func TestWithClientLiteralURLs(t *testing.T) { opts := &ClientOptions{} WithClientLiteralURLs(true)(opts) if have, want := opts.LiteralURLs, true; have != want { t.Errorf("unexpected value after WithClientLiteralURLs, have: %t, want: %t", have, want) return } WithClientLiteralURLs(false)(opts) if have, want := opts.LiteralURLs, false; have != want { t.Errorf("unexpected value after WithClientLiteralURLs, have: %t, want: %t", have, want) return } } ================================================ FILE: clientcompat/README.md ================================================ # clientcompat # clientcompat is a tool to test the compatibility of Twirp client implementations. ## Usage ## `clientcompat -client=` The client should be generated for the compattest.proto file found in this directory. The client binary must accept, over stdin, a protobuf-encoded ClientCompatMessage (defined in clientcompat.proto). This message contains a `service_address`, which is the address of a reference-implementation CompatService to talk to, a `method`, which specifies which RPC of the CompatService should be called, and an embedded, proto-encoded `request` which the client should send. If the server sends an error, then the client should parse the error and write the error code string ("internal", "unauthenticated", etc) to stderr. If the server doesn't send an error, the client should encode the response message it received as protobuf and write it to stdout. ## Example ## The [gocompat](./gocompat) subdirectory contains an example implementation which can be run with clientcompat to prove that the Go client implementation works. ================================================ FILE: clientcompat/clientcompat.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "context" "github.com/twitchtv/twirp/clientcompat/internal/clientcompat" ) type clientCompat struct { method func(context.Context, *clientcompat.Req) (*clientcompat.Resp, error) noop func(context.Context, *clientcompat.Empty) (*clientcompat.Empty, error) } func (c *clientCompat) Method(ctx context.Context, req *clientcompat.Req) (*clientcompat.Resp, error) { return c.method(ctx, req) } func (c *clientCompat) NoopMethod(ctx context.Context, e *clientcompat.Empty) (*clientcompat.Empty, error) { return c.noop(ctx, e) } ================================================ FILE: clientcompat/clientcompat.proto ================================================ syntax = "proto3"; package twirp.clientcompat; option go_package = "/internal/clientcompat"; service CompatService { rpc Method(Req) returns (Resp); rpc NoopMethod(Empty) returns (Empty); } message Empty {} message Req { string v = 1; } message Resp { int32 v = 1; } message ClientCompatMessage { string service_address = 1; enum CompatServiceMethod { NOOP = 0; METHOD = 1; } CompatServiceMethod method = 2; bytes request = 3; } ================================================ FILE: clientcompat/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main //go:generate protoc --twirp_out=. --go_out=. clientcompat.proto ================================================ FILE: clientcompat/gocompat/gocompat.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "context" "io" "log" "net/http" "os" "google.golang.org/protobuf/proto" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/clientcompat/internal/clientcompat" ) func main() { var in clientcompat.ClientCompatMessage inBytes, err := io.ReadAll(os.Stdin) if err != nil { log.Fatalf("read stdin err: %v", err) } err = proto.Unmarshal(inBytes, &in) if err != nil { log.Fatalf("unmarshal err: %v", err) } client := clientcompat.NewCompatServiceProtobufClient(in.ServiceAddress, http.DefaultClient) switch in.Method { case clientcompat.ClientCompatMessage_NOOP: if err := doNoop(client, in.Request); err != nil { log.Fatalf("doNoop err: %v", err) } case clientcompat.ClientCompatMessage_METHOD: if err := doMethod(client, in.Request); err != nil { log.Fatalf("doMethod err: %v", err) } default: log.Fatalf("unexpected method: %v", in.Method) } } func doNoop(client clientcompat.CompatService, req []byte) error { var e clientcompat.Empty err := proto.Unmarshal(req, &e) if err != nil { return err } resp, err := client.NoopMethod(context.Background(), &e) if err != nil { errCode := err.(twirp.Error).Code() os.Stderr.Write([]byte(errCode)) } else { respBytes, err := proto.Marshal(resp) if err != nil { return err } os.Stdout.Write(respBytes) } return nil } func doMethod(client clientcompat.CompatService, req []byte) error { var r clientcompat.Req err := proto.Unmarshal(req, &r) if err != nil { return err } resp, err := client.Method(context.Background(), &r) if err != nil { errCode := err.(twirp.Error).Code() os.Stderr.Write([]byte(errCode)) } else { respBytes, err := proto.Marshal(resp) if err != nil { return err } os.Stdout.Write(respBytes) } return nil } ================================================ FILE: clientcompat/internal/clientcompat/clientcompat.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: clientcompat.proto package clientcompat import ( 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 ClientCompatMessage_CompatServiceMethod int32 const ( ClientCompatMessage_NOOP ClientCompatMessage_CompatServiceMethod = 0 ClientCompatMessage_METHOD ClientCompatMessage_CompatServiceMethod = 1 ) // Enum value maps for ClientCompatMessage_CompatServiceMethod. var ( ClientCompatMessage_CompatServiceMethod_name = map[int32]string{ 0: "NOOP", 1: "METHOD", } ClientCompatMessage_CompatServiceMethod_value = map[string]int32{ "NOOP": 0, "METHOD": 1, } ) func (x ClientCompatMessage_CompatServiceMethod) Enum() *ClientCompatMessage_CompatServiceMethod { p := new(ClientCompatMessage_CompatServiceMethod) *p = x return p } func (x ClientCompatMessage_CompatServiceMethod) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (ClientCompatMessage_CompatServiceMethod) Descriptor() protoreflect.EnumDescriptor { return file_clientcompat_proto_enumTypes[0].Descriptor() } func (ClientCompatMessage_CompatServiceMethod) Type() protoreflect.EnumType { return &file_clientcompat_proto_enumTypes[0] } func (x ClientCompatMessage_CompatServiceMethod) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use ClientCompatMessage_CompatServiceMethod.Descriptor instead. func (ClientCompatMessage_CompatServiceMethod) EnumDescriptor() ([]byte, []int) { return file_clientcompat_proto_rawDescGZIP(), []int{3, 0} } type Empty struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Empty) Reset() { *x = Empty{} if protoimpl.UnsafeEnabled { mi := &file_clientcompat_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_clientcompat_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_clientcompat_proto_rawDescGZIP(), []int{0} } type Req struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields V string `protobuf:"bytes,1,opt,name=v,proto3" json:"v,omitempty"` } func (x *Req) Reset() { *x = Req{} if protoimpl.UnsafeEnabled { mi := &file_clientcompat_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Req) String() string { return protoimpl.X.MessageStringOf(x) } func (*Req) ProtoMessage() {} func (x *Req) ProtoReflect() protoreflect.Message { mi := &file_clientcompat_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 Req.ProtoReflect.Descriptor instead. func (*Req) Descriptor() ([]byte, []int) { return file_clientcompat_proto_rawDescGZIP(), []int{1} } func (x *Req) GetV() string { if x != nil { return x.V } return "" } type Resp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields V int32 `protobuf:"varint,1,opt,name=v,proto3" json:"v,omitempty"` } func (x *Resp) Reset() { *x = Resp{} if protoimpl.UnsafeEnabled { mi := &file_clientcompat_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Resp) String() string { return protoimpl.X.MessageStringOf(x) } func (*Resp) ProtoMessage() {} func (x *Resp) ProtoReflect() protoreflect.Message { mi := &file_clientcompat_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 Resp.ProtoReflect.Descriptor instead. func (*Resp) Descriptor() ([]byte, []int) { return file_clientcompat_proto_rawDescGZIP(), []int{2} } func (x *Resp) GetV() int32 { if x != nil { return x.V } return 0 } type ClientCompatMessage struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields ServiceAddress string `protobuf:"bytes,1,opt,name=service_address,json=serviceAddress,proto3" json:"service_address,omitempty"` Method ClientCompatMessage_CompatServiceMethod `protobuf:"varint,2,opt,name=method,proto3,enum=twirp.clientcompat.ClientCompatMessage_CompatServiceMethod" json:"method,omitempty"` Request []byte `protobuf:"bytes,3,opt,name=request,proto3" json:"request,omitempty"` } func (x *ClientCompatMessage) Reset() { *x = ClientCompatMessage{} if protoimpl.UnsafeEnabled { mi := &file_clientcompat_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ClientCompatMessage) String() string { return protoimpl.X.MessageStringOf(x) } func (*ClientCompatMessage) ProtoMessage() {} func (x *ClientCompatMessage) ProtoReflect() protoreflect.Message { mi := &file_clientcompat_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 ClientCompatMessage.ProtoReflect.Descriptor instead. func (*ClientCompatMessage) Descriptor() ([]byte, []int) { return file_clientcompat_proto_rawDescGZIP(), []int{3} } func (x *ClientCompatMessage) GetServiceAddress() string { if x != nil { return x.ServiceAddress } return "" } func (x *ClientCompatMessage) GetMethod() ClientCompatMessage_CompatServiceMethod { if x != nil { return x.Method } return ClientCompatMessage_NOOP } func (x *ClientCompatMessage) GetRequest() []byte { if x != nil { return x.Request } return nil } var File_clientcompat_proto protoreflect.FileDescriptor var file_clientcompat_proto_rawDesc = []byte{ 0x0a, 0x12, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x13, 0x0a, 0x03, 0x52, 0x65, 0x71, 0x12, 0x0c, 0x0a, 0x01, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x01, 0x76, 0x22, 0x14, 0x0a, 0x04, 0x52, 0x65, 0x73, 0x70, 0x12, 0x0c, 0x0a, 0x01, 0x76, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x01, 0x76, 0x22, 0xda, 0x01, 0x0a, 0x13, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x53, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x3b, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x2b, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4f, 0x50, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4d, 0x45, 0x54, 0x48, 0x4f, 0x44, 0x10, 0x01, 0x32, 0x90, 0x01, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x17, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0a, 0x4e, 0x6f, 0x6f, 0x70, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x19, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x18, 0x5a, 0x16, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_clientcompat_proto_rawDescOnce sync.Once file_clientcompat_proto_rawDescData = file_clientcompat_proto_rawDesc ) func file_clientcompat_proto_rawDescGZIP() []byte { file_clientcompat_proto_rawDescOnce.Do(func() { file_clientcompat_proto_rawDescData = protoimpl.X.CompressGZIP(file_clientcompat_proto_rawDescData) }) return file_clientcompat_proto_rawDescData } var file_clientcompat_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_clientcompat_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_clientcompat_proto_goTypes = []interface{}{ (ClientCompatMessage_CompatServiceMethod)(0), // 0: twirp.clientcompat.ClientCompatMessage.CompatServiceMethod (*Empty)(nil), // 1: twirp.clientcompat.Empty (*Req)(nil), // 2: twirp.clientcompat.Req (*Resp)(nil), // 3: twirp.clientcompat.Resp (*ClientCompatMessage)(nil), // 4: twirp.clientcompat.ClientCompatMessage } var file_clientcompat_proto_depIdxs = []int32{ 0, // 0: twirp.clientcompat.ClientCompatMessage.method:type_name -> twirp.clientcompat.ClientCompatMessage.CompatServiceMethod 2, // 1: twirp.clientcompat.CompatService.Method:input_type -> twirp.clientcompat.Req 1, // 2: twirp.clientcompat.CompatService.NoopMethod:input_type -> twirp.clientcompat.Empty 3, // 3: twirp.clientcompat.CompatService.Method:output_type -> twirp.clientcompat.Resp 1, // 4: twirp.clientcompat.CompatService.NoopMethod:output_type -> twirp.clientcompat.Empty 3, // [3:5] is the sub-list for method output_type 1, // [1:3] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_clientcompat_proto_init() } func file_clientcompat_proto_init() { if File_clientcompat_proto != nil { return } if !protoimpl.UnsafeEnabled { file_clientcompat_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 } } file_clientcompat_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Req); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_clientcompat_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Resp); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_clientcompat_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ClientCompatMessage); 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_clientcompat_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 1, }, GoTypes: file_clientcompat_proto_goTypes, DependencyIndexes: file_clientcompat_proto_depIdxs, EnumInfos: file_clientcompat_proto_enumTypes, MessageInfos: file_clientcompat_proto_msgTypes, }.Build() File_clientcompat_proto = out.File file_clientcompat_proto_rawDesc = nil file_clientcompat_proto_goTypes = nil file_clientcompat_proto_depIdxs = nil } ================================================ FILE: clientcompat/internal/clientcompat/clientcompat.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: clientcompat.proto package clientcompat import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ======================= // CompatService Interface // ======================= type CompatService interface { Method(context.Context, *Req) (*Resp, error) NoopMethod(context.Context, *Empty) (*Empty, error) } // ============================= // CompatService Protobuf Client // ============================= type compatServiceProtobufClient struct { client HTTPClient urls [2]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewCompatServiceProtobufClient creates a Protobuf client that implements the CompatService interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewCompatServiceProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) CompatService { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.clientcompat", "CompatService") urls := [2]string{ serviceURL + "Method", serviceURL + "NoopMethod", } return &compatServiceProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *compatServiceProtobufClient) Method(ctx context.Context, in *Req) (*Resp, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.clientcompat") ctx = ctxsetters.WithServiceName(ctx, "CompatService") ctx = ctxsetters.WithMethodName(ctx, "Method") caller := c.callMethod if c.interceptor != nil { caller = func(ctx context.Context, req *Req) (*Resp, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Req) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Req) when calling interceptor") } return c.callMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Resp) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Resp) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *compatServiceProtobufClient) callMethod(ctx context.Context, in *Req) (*Resp, error) { out := new(Resp) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } func (c *compatServiceProtobufClient) NoopMethod(ctx context.Context, in *Empty) (*Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.clientcompat") ctx = ctxsetters.WithServiceName(ctx, "CompatService") ctx = ctxsetters.WithMethodName(ctx, "NoopMethod") caller := c.callNoopMethod if c.interceptor != nil { caller = func(ctx context.Context, req *Empty) (*Empty, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Empty) when calling interceptor") } return c.callNoopMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Empty) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *compatServiceProtobufClient) callNoopMethod(ctx context.Context, in *Empty) (*Empty, error) { out := new(Empty) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ========================= // CompatService JSON Client // ========================= type compatServiceJSONClient struct { client HTTPClient urls [2]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewCompatServiceJSONClient creates a JSON client that implements the CompatService interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewCompatServiceJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) CompatService { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.clientcompat", "CompatService") urls := [2]string{ serviceURL + "Method", serviceURL + "NoopMethod", } return &compatServiceJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *compatServiceJSONClient) Method(ctx context.Context, in *Req) (*Resp, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.clientcompat") ctx = ctxsetters.WithServiceName(ctx, "CompatService") ctx = ctxsetters.WithMethodName(ctx, "Method") caller := c.callMethod if c.interceptor != nil { caller = func(ctx context.Context, req *Req) (*Resp, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Req) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Req) when calling interceptor") } return c.callMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Resp) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Resp) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *compatServiceJSONClient) callMethod(ctx context.Context, in *Req) (*Resp, error) { out := new(Resp) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } func (c *compatServiceJSONClient) NoopMethod(ctx context.Context, in *Empty) (*Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.clientcompat") ctx = ctxsetters.WithServiceName(ctx, "CompatService") ctx = ctxsetters.WithMethodName(ctx, "NoopMethod") caller := c.callNoopMethod if c.interceptor != nil { caller = func(ctx context.Context, req *Empty) (*Empty, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Empty) when calling interceptor") } return c.callNoopMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Empty) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *compatServiceJSONClient) callNoopMethod(ctx context.Context, in *Empty) (*Empty, error) { out := new(Empty) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ============================ // CompatService Server Handler // ============================ type compatServiceServer struct { CompatService interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewCompatServiceServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewCompatServiceServer(svc CompatService, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &compatServiceServer{ CompatService: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *compatServiceServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *compatServiceServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // CompatServicePathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const CompatServicePathPrefix = "/twirp/twirp.clientcompat.CompatService/" func (s *compatServiceServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.clientcompat") ctx = ctxsetters.WithServiceName(ctx, "CompatService") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.clientcompat.CompatService" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Method": s.serveMethod(ctx, resp, req) return case "NoopMethod": s.serveNoopMethod(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *compatServiceServer) serveMethod(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveMethodJSON(ctx, resp, req) case "application/protobuf": s.serveMethodProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *compatServiceServer) serveMethodJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Method") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Req) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.CompatService.Method if s.interceptor != nil { handler = func(ctx context.Context, req *Req) (*Resp, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Req) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Req) when calling interceptor") } return s.CompatService.Method(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Resp) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Resp) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Resp func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Resp and nil error while calling Method. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *compatServiceServer) serveMethodProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Method") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Req) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.CompatService.Method if s.interceptor != nil { handler = func(ctx context.Context, req *Req) (*Resp, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Req) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Req) when calling interceptor") } return s.CompatService.Method(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Resp) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Resp) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Resp func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Resp and nil error while calling Method. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *compatServiceServer) serveNoopMethod(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveNoopMethodJSON(ctx, resp, req) case "application/protobuf": s.serveNoopMethodProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *compatServiceServer) serveNoopMethodJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "NoopMethod") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Empty) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.CompatService.NoopMethod if s.interceptor != nil { handler = func(ctx context.Context, req *Empty) (*Empty, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Empty) when calling interceptor") } return s.CompatService.NoopMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Empty) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Empty and nil error while calling NoopMethod. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *compatServiceServer) serveNoopMethodProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "NoopMethod") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Empty) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.CompatService.NoopMethod if s.interceptor != nil { handler = func(ctx context.Context, req *Empty) (*Empty, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Empty) when calling interceptor") } return s.CompatService.NoopMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Empty) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Empty and nil error while calling NoopMethod. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *compatServiceServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *compatServiceServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *compatServiceServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.clientcompat", "CompatService") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 285 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0xc1, 0x4a, 0xc3, 0x40, 0x10, 0x86, 0x5d, 0xdb, 0xa6, 0x3a, 0xd4, 0x5a, 0x36, 0xa2, 0x6b, 0x4f, 0x21, 0x17, 0x03, 0x42, 0x0a, 0xf5, 0xd8, 0x93, 0xad, 0x05, 0x2f, 0x69, 0x64, 0xeb, 0xc9, 0x8b, 0xc4, 0x64, 0xd0, 0x40, 0x93, 0xdd, 0xec, 0xae, 0x11, 0xdf, 0xc2, 0xe7, 0xf3, 0x69, 0xc4, 0x24, 0x62, 0xc5, 0xf4, 0x38, 0xff, 0x37, 0xf3, 0xed, 0xb0, 0x03, 0x34, 0xde, 0xa4, 0x98, 0x9b, 0x58, 0x64, 0x32, 0x32, 0xbe, 0x54, 0xc2, 0x08, 0x4a, 0xcd, 0x5b, 0xaa, 0xa4, 0xbf, 0x4d, 0xdc, 0x3e, 0xf4, 0x96, 0x99, 0x34, 0xef, 0xae, 0x0d, 0x1d, 0x8e, 0x05, 0x1d, 0x00, 0x29, 0x19, 0x71, 0x88, 0x77, 0xc8, 0x49, 0xe9, 0x9e, 0x40, 0x97, 0xa3, 0x96, 0xbf, 0x69, 0xef, 0x3b, 0xfd, 0x24, 0x60, 0x2f, 0x2a, 0xc9, 0xa2, 0x92, 0x04, 0xa8, 0x75, 0xf4, 0x8c, 0xf4, 0x02, 0x8e, 0x35, 0xaa, 0x32, 0x8d, 0xf1, 0x31, 0x4a, 0x12, 0x85, 0x5a, 0x37, 0xa6, 0x61, 0x13, 0x5f, 0xd7, 0x29, 0x5d, 0x83, 0x95, 0xa1, 0x79, 0x11, 0x09, 0xdb, 0x77, 0x88, 0x37, 0x9c, 0xce, 0xfc, 0xff, 0x9b, 0xf9, 0x2d, 0x2f, 0xf8, 0x75, 0xb5, 0xae, 0x6d, 0x41, 0xa5, 0xe0, 0x8d, 0x8a, 0x32, 0xe8, 0x2b, 0x2c, 0x5e, 0x51, 0x1b, 0xd6, 0x71, 0x88, 0x37, 0xe0, 0x3f, 0xa5, 0x7b, 0x09, 0x76, 0xcb, 0x20, 0x3d, 0x80, 0xee, 0x2a, 0x0c, 0xef, 0x46, 0x7b, 0x14, 0xc0, 0x0a, 0x96, 0xf7, 0xb7, 0xe1, 0xcd, 0x88, 0x4c, 0x3f, 0x08, 0x1c, 0xfd, 0xe9, 0xa6, 0x33, 0xb0, 0x9a, 0x89, 0xb3, 0xb6, 0x3d, 0x39, 0x16, 0x63, 0xd6, 0x0e, 0xb4, 0xa4, 0x73, 0x80, 0x95, 0x10, 0xb2, 0x11, 0x9c, 0xb7, 0xf5, 0x55, 0xff, 0x3f, 0xde, 0x8d, 0xe6, 0xec, 0xe1, 0x74, 0x92, 0xe6, 0x06, 0x55, 0x1e, 0x6d, 0x26, 0xdb, 0xfc, 0xc9, 0xaa, 0x0e, 0x7b, 0xf5, 0x15, 0x00, 0x00, 0xff, 0xff, 0x89, 0x54, 0x2a, 0x1e, 0xee, 0x01, 0x00, 0x00, } ================================================ FILE: clientcompat/main.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "context" "flag" "fmt" "google.golang.org/protobuf/proto" "log" "net/http" "net/http/httptest" "os" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/clientcompat/internal/clientcompat" ) var ( failures = 0 successes = 0 ) func main() { clientBin := flag.String("client", "", "client binary") flag.Parse() if *clientBin == "" { log.Fatal("-client must be specified") } cc, s := newServer() defer s.Close() testNoop(cc, s, *clientBin) testMethod(cc, s, *clientBin) testInvalidErrorHandling(*clientBin) if failures > 0 { fmt.Printf("FAILED with %d failures, %d successes\n", failures, successes) os.Exit(1) } fmt.Printf("PASSED with %d failures, %d successes\n", failures, successes) } func newServer() (*clientCompat, *httptest.Server) { cc := &clientCompat{} s := clientcompat.NewCompatServiceServer(cc, nil) return cc, httptest.NewServer(s) } func startTest(name string) { fmt.Printf("Testing %v... ", name) } func fail(msg string, args ...interface{}) { failures++ fmt.Printf("FAIL: "+msg+"\n", args...) } func pass() { successes++ fmt.Printf("PASS\n") } func testNoop(cc *clientCompat, s *httptest.Server, clientBin string) { type noop func(context.Context, *clientcompat.Empty) (*clientcompat.Empty, error) testcase := func(name string, f noop, wantErrCode string) { startTest(name) cc.noop = f _, haveErrCode, err := runClientNoop(s.URL, clientBin) if err != nil { fail("error: %v", err) return } switch { case wantErrCode == "" && haveErrCode != "": fail("client reported twirp error %q when server did not error", haveErrCode) case wantErrCode != "" && haveErrCode == "": fail("client did not report err code when server errored, expected %q", wantErrCode) case wantErrCode != haveErrCode: fail("client reported wrong error code %q, want %q", haveErrCode, wantErrCode) default: pass() } } testcase( "noop without error", func(context.Context, *clientcompat.Empty) (*clientcompat.Empty, error) { return &clientcompat.Empty{}, nil }, "", ) for _, code := range []twirp.ErrorCode{ twirp.Canceled, twirp.Unknown, twirp.InvalidArgument, twirp.DeadlineExceeded, twirp.NotFound, twirp.BadRoute, twirp.AlreadyExists, twirp.PermissionDenied, twirp.Unauthenticated, twirp.ResourceExhausted, twirp.FailedPrecondition, twirp.Aborted, twirp.OutOfRange, twirp.Unimplemented, twirp.Internal, twirp.Unavailable, twirp.DataLoss, } { testcase( fmt.Sprintf("%q error parsing", code), func(context.Context, *clientcompat.Empty) (*clientcompat.Empty, error) { return nil, twirp.NewError(code, "failed") }, string(code), ) } } func testMethod(cc *clientCompat, s *httptest.Server, clientBin string) { type method func(context.Context, *clientcompat.Req) (*clientcompat.Resp, error) testcase := func(name string, req *clientcompat.Req, f method, wantResp *clientcompat.Resp, wantErrCode string) { startTest(name) called := false cc.method = func(ctx context.Context, req *clientcompat.Req) (*clientcompat.Resp, error) { called = true return f(ctx, req) } resp, haveErrCode, err := runClientMethod(s.URL, clientBin, req) if err != nil { fail("error: %v", err) return } if !called { fail("RPC Method was not called on server") return } switch { case wantErrCode == "" && haveErrCode != "": fail("client reported twirp error %q when server did not error", haveErrCode) return case wantErrCode != "" && haveErrCode == "": fail("client did not report err code when server errored, expected %q", wantErrCode) return case wantErrCode != haveErrCode: fail("client reported wrong error code %q, want %q", haveErrCode, wantErrCode) return } if !proto.Equal(resp, wantResp) { fail("client has wrong response, have %+v want %+v", resp, wantResp) return } pass() } testcase( "empty value", &clientcompat.Req{}, func(context.Context, *clientcompat.Req) (*clientcompat.Resp, error) { return &clientcompat.Resp{}, nil }, &clientcompat.Resp{}, "", ) testcase( "request value formatting", &clientcompat.Req{ V: "value", }, func(_ context.Context, req *clientcompat.Req) (*clientcompat.Resp, error) { if req.V != "value" { return nil, twirp.InvalidArgumentError("V", "should be 'value'") } return &clientcompat.Resp{V: 1}, nil }, &clientcompat.Resp{V: 1}, "", ) } func testInvalidErrorHandling(clientBin string) { startTest("handling invalid error formatting from server") s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(400) _, err := w.Write([]byte("garbage")) if err != nil { panic(err) } })) defer s.Close() _, errCode, err := runClientNoop(s.URL, clientBin) if err != nil { fail("err: %v", err) } else if errCode != "internal" { fail("wrong error code: %v", errCode) } pass() } ================================================ FILE: clientcompat/run.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "bytes" "log" "os/exec" "github.com/pkg/errors" "github.com/twitchtv/twirp/clientcompat/internal/clientcompat" "google.golang.org/protobuf/proto" ) func runClient(clientBin string, msg *clientcompat.ClientCompatMessage) (resp []byte, errCode string, err error) { cmd := exec.Command(clientBin) msgBytes, err := proto.Marshal(msg) if err != nil { return nil, "", errors.Wrap(err, "unable to marshal ClientCompatMessage message") } cmd.Stdin = bytes.NewReader(msgBytes) stdout, stderr := bytes.NewBuffer(nil), bytes.NewBuffer(nil) cmd.Stdout = stdout cmd.Stderr = stderr err = cmd.Run() if err != nil { err = errors.Wrap(err, "error running client binary") log.Printf("client stdout: %s", stdout.String()) log.Printf("client stderr: %s", stderr.String()) return nil, "", err } if stdout.Len() > 0 && stderr.Len() > 0 { return nil, "", errors.Errorf("client bin should write to either stdout or stderr, but never both in one invocation") } if stderr.Len() > 0 { return nil, stderr.String(), err } return stdout.Bytes(), "", nil } func runClientNoop(serverURL string, clientBin string) (resp *clientcompat.Empty, twirpErrCode string, err error) { req := &clientcompat.Empty{} reqBytes, err := proto.Marshal(req) if err != nil { return nil, "", errors.Wrap(err, "unable to marshal Empty message") } msg := &clientcompat.ClientCompatMessage{ ServiceAddress: serverURL, Method: clientcompat.ClientCompatMessage_NOOP, Request: reqBytes, } respBytes, code, err := runClient(clientBin, msg) if err != nil { return nil, "", err } if respBytes != nil { resp = new(clientcompat.Empty) err = proto.Unmarshal(respBytes, resp) if err != nil { return nil, "", errors.Wrap(err, "unable to unmarshal stdout from client bin as an Empty response") } } return resp, code, nil } func runClientMethod(serverURL string, clientBin string, req *clientcompat.Req) (resp *clientcompat.Resp, twirpErrCode string, err error) { reqBytes, err := proto.Marshal(req) if err != nil { return nil, "", errors.Wrap(err, "unable to marshal Req") } msg := &clientcompat.ClientCompatMessage{ ServiceAddress: serverURL, Method: clientcompat.ClientCompatMessage_METHOD, Request: reqBytes, } respBytes, code, err := runClient(clientBin, msg) if err != nil { return nil, "", err } if respBytes != nil { resp = new(clientcompat.Resp) err = proto.Unmarshal(respBytes, resp) if err != nil { return nil, "", errors.Wrap(err, "unable to unmarshal stdout from client bin as a Resp") } } return resp, code, nil } ================================================ FILE: context.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "errors" "net/http" "github.com/twitchtv/twirp/internal/contextkeys" ) // MethodName extracts the name of the method being handled in the given // context. If it is not known, it returns ("", false). func MethodName(ctx context.Context) (string, bool) { name, ok := ctx.Value(contextkeys.MethodNameKey).(string) return name, ok } // ServiceName extracts the name of the service handling the given context. If // it is not known, it returns ("", false). func ServiceName(ctx context.Context) (string, bool) { name, ok := ctx.Value(contextkeys.ServiceNameKey).(string) return name, ok } // PackageName extracts the fully-qualified protobuf package name of the service // handling the given context. If it is not known, it returns ("", false). If // the service comes from a proto file that does not declare a package name, it // returns ("", true). // // Note that the protobuf package name can be very different than the go package // name; the two are unrelated. func PackageName(ctx context.Context) (string, bool) { name, ok := ctx.Value(contextkeys.PackageNameKey).(string) return name, ok } // StatusCode retrieves the status code of the response (as string like "200"). // If it is known returns (status, true). // If it is not known, it returns ("", false). func StatusCode(ctx context.Context) (string, bool) { code, ok := ctx.Value(contextkeys.StatusCodeKey).(string) return code, ok } // WithHTTPRequestHeaders stores an http.Header in a context.Context. When // using a Twirp-generated client, you can pass the returned context // into any of the request methods, and the stored header will be // included in outbound HTTP requests. // // This can be used to set custom HTTP headers like authorization tokens or // client IDs. But note that HTTP headers are a Twirp implementation detail, // only visible by middleware, not by the server implementation. // // WithHTTPRequestHeaders returns an error if the provided http.Header // would overwrite a header that is needed by Twirp, like "Content-Type". func WithHTTPRequestHeaders(ctx context.Context, h http.Header) (context.Context, error) { if _, ok := h["Accept"]; ok { return nil, errors.New("provided header cannot set Accept") } if _, ok := h["Content-Type"]; ok { return nil, errors.New("provided header cannot set Content-Type") } if _, ok := h["Twirp-Version"]; ok { return nil, errors.New("provided header cannot set Twirp-Version") } copied := make(http.Header, len(h)) for k, vv := range h { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return context.WithValue(ctx, contextkeys.RequestHeaderKey, copied), nil } func HTTPRequestHeaders(ctx context.Context) (http.Header, bool) { h, ok := ctx.Value(contextkeys.RequestHeaderKey).(http.Header) return h, ok } // SetHTTPResponseHeader sets an HTTP header key-value pair using a context // provided by a twirp-generated server, or a child of that context. // The server will include the header in its response for that request context. // // This can be used to respond with custom HTTP headers like "Cache-Control". // But note that HTTP headers are a Twirp implementation detail, // only visible by middleware, not by the clients or their responses. // // The header will be ignored (noop) if the context is invalid (i.e. using a new // context.Background() instead of passing the context from the handler). // // If called multiple times with the same key, it replaces any existing values // associated with that key. // // SetHTTPResponseHeader returns an error if the provided header key // would overwrite a header that is needed by Twirp, like "Content-Type". func SetHTTPResponseHeader(ctx context.Context, key, value string) error { if key == "Content-Type" { return errors.New("header key can not be Content-Type") } responseWriter, ok := ctx.Value(contextkeys.ResponseWriterKey).(http.ResponseWriter) if ok { responseWriter.Header().Set(key, value) } // invalid context is ignored, not an error, this is to allow easy unit testing with mock servers return nil } // AddHTTPResponseHeader behaves like SetHTTPResponseHeader, // but it appends the key-value pair to the header (instead of replacing it). // // AddHTTPResponseHeader returns an error if the key is "Content-Type". func AddHTTPResponseHeader(ctx context.Context, key, value string) error { if key == "Content-Type" { return errors.New("header key can not be Content-Type") } responseWriter, ok := ctx.Value(contextkeys.ResponseWriterKey).(http.ResponseWriter) if ok { responseWriter.Header().Add(key, value) } // invalid context is ignored, not an error, this is to allow easy unit testing with mock servers return nil } ================================================ FILE: ctxsetters/ctxsetters.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 ctxsetters is an implementation detail for twirp generated code, used // by the generated servers to set values in contexts for later access with the // twirp package's accessors. // // Do not use ctxsetters outside of twirp's generated code. package ctxsetters import ( "context" "net/http" "strconv" "github.com/twitchtv/twirp/internal/contextkeys" ) func WithMethodName(ctx context.Context, name string) context.Context { return context.WithValue(ctx, contextkeys.MethodNameKey, name) } func WithServiceName(ctx context.Context, name string) context.Context { return context.WithValue(ctx, contextkeys.ServiceNameKey, name) } func WithPackageName(ctx context.Context, name string) context.Context { return context.WithValue(ctx, contextkeys.PackageNameKey, name) } func WithStatusCode(ctx context.Context, code int) context.Context { return context.WithValue(ctx, contextkeys.StatusCodeKey, strconv.Itoa(code)) } func WithResponseWriter(ctx context.Context, w http.ResponseWriter) context.Context { return context.WithValue(ctx, contextkeys.ResponseWriterKey, w) } ================================================ FILE: docs/best_practices.md ================================================ --- id: "best_practices" title: "Best Practices" sidebar_label: "Best Practices" --- Twirp simplifies service design when compared with a REST endpoint: method definitions, message types and parsing is handled by the framework (i.e. you don’t have to worry about JSON fields or types). However, there are still some things to consider when making a new service in Twirp, mainly to keep consistency. ## Folder/Package Structure The recommended folder/package structure for your twirp `` is: ``` /cmd / main.go /rpc / service.proto // and auto-generated files /internal /server server.go // and usually one other file per method ``` For example, for the Haberdasher service it would be: ``` /cmd /haberdasherserver main.go /rpc /haberdasher service.proto service.pb.go service.twirp.go /internal /haberdasherserver server_test.go server.go make_hat_test.go make_hat.go ``` Notes: * Keep the `.proto` and generated files in their own package. * Do not implement the server or other files in the same package. This allows other services to do a "clean import" of the autogenerated client. * Do not name the package something generic like `api`, `client` or `service`; name it after your service. Remember that the package is going to be imported by other projects that will likely import other clients from other services as well. ## `.proto` File The `.proto` file is the source of truth for your service design. * The first step to design your service is to write a `.proto` file. Use that to discuss design with your coworkers before starting the implementation. * Use proto3 (first line should be `syntax="proto3"`). Do not use proto2. * Use `option go_package = "";` for the Go package name. * Add comments on message fields; they translate to the generated Go interfaces. * Don’t worry about fields like `user_id` being auto-converted into `UserId` in Go. I know, the right case should be `UserID`, but it's not your fault how the protoc-gen-go compiler decides to translate it. Avoid doing hacks like naming it `user_i_d` so it looks "good" in Go (`UserID`). In the future, we may use a better Go code generator, or generate clients for other languages like Python or JavaScript. * rpc methods should clearly be named with (i.e.: ListBooks, GetBook, CreateBook, UpdateBook, RenameBook, DeleteBook). See more in "Naming Conventions" below. The header of the `.proto` file should look like this (change and with your values): ```go syntax = "proto3" package ..; option go_package = ""; ``` ## Specifying protoc version and using `Makefile` for code generation Code generation depends on `protoc` and its plugins `protoc-gen-go` and `protoc-gen-twirp`. Having different versions may cause problems. Make sure to specify the required `protoc` version in your README or CONTRIBUTING file. Using a Makefile is a good way to simplify code generation: ```Makefile gen: # Auto-generate code protoc --proto_path=. --twirp_out=. --go_out=. rpc//service.proto upgrade: # Upgrade dependencies if using modules go get -u ``` ## Naming Conventions Like in any other API or interface, it is very important to have names that are simple, intuitive and consistent. Respect the [Protocol Buffers Style Guide](https://developers.google.com/protocol-buffers/docs/style): * Use `CamelCase` for `Service`, `Message` and `Type` names. * Use `underscore_separated_names` for field names. * Use `CAPITALS_WITH_UNDERSCORES` for enum value names. For naming conventions, the [Google Cloud Platform design guides](https://cloud.google.com/apis/design/naming_convention) are a good reference: * Use the same name for the same concept, even across APIs. * Avoid name overloading. Use different names for different concepts. * Include units on field names for durations and quantities (e.g. `delay_seconds` is better than just `delay`). For times, we have a few Twitch-specific conventions that have worked for us: * Timestamp names should end with `_at` whenever possible (i.e. `created_at`, `updated_at`). * Timestamps should be [RFC3339](https://tools.ietf.org/html/rfc3339) strings (in Go it's very easy to generate these with `t.Format(time.RFC3339)` and parse them with `time.Parse(time.RFC3339Nano, t)`). * Timestamps can also be a `google.protobuf.Timestamp`, in which case their names should end with `_time` for clarity. ## Default Values and Required Fields In proto3 all fields have zero-value defaults (string is `""`, int32 is `0`), so all fields are optional. If you want to make a required field (i.e. "name is required"), it needs to be handled by the service implementation. But to make this clear in the `.proto` file: * Add a "required" comment on the field. For example `string name = 1; // required` implies that the server implementation will return an `twirp.RequiredArgumentError("name")` if the name is empty. If you need a different default (e.g. limit default 20 for paginated collections), it needs to be handled by the service implementation. But to make this clear in the `.proto` file: * Add a "(default X)" comment on the field. For example `int32 limit = 1; // (default 20)` implies that the server implementation will convert the zero-value 0 to 20 (0 == 20). * For enums, the first item is the default. Your service implementation cannot tell the difference between empty and missing fields (this is by design). If you really need to tell them apart, you need to use an extra bool field, or use `google/protobuf.wrappers.proto` messages (which can be nil in go). ## Twirp Errors Protocol Buffers do not specify errors. You can always add an extra field on the returned message for the error, but Twirp has an excellent system that you should use instead: * Familiarize yourself with the possible [Twirp error codes](errors.md) and use the ones that make sense for each situation (i.e. `InvalidArgument`, `NotFound`, `Internal`). The codes are very straightforward and are almost the same as in gRPC. * Always return a `twirp.Error`. Twirp allows you to return a regular `error`, that will get wrapped with `twirp.InternalErrorWith(err)`, but it is better if you explicitly wrap it yourself. Being explicit makes the server and the client to always return the same twirp errors, which is more predictable and easier for unit tests. * Include possible errors on the `.proto` file (add comments to RPC methods). * But there's no need to document all the obvious `Internal` errors, which can always happen for diverse reasons (e.g. backend service is down, or there was a problem on the client). * Make sure to document (with comments) possible validation errors on the specific message fields. For example `int32 amount = 1; // must be positive` implies that the server implementation will return a `twirp.InvalidArgumentError("amount", "must be positive")` error if the condition is not met. * Required fields are also validation errors. For example, if a given string field cannot be empty, you should add a "required" comment in the proto file, which implies that a `twirp.RequiredArgumentError(field)` will be returned if the field is empty (or missing, which is the same thing in proto3). If you are using proto2 (I hope not), the "required" comment is still preferred over the required field type. ================================================ FILE: docs/command_line.md ================================================ --- id: "command_line" title: "Generator Flags for the Protoc Compiler" sidebar_label: "Generator Flags" --- ### Protoc Compiler Invocation Make sure to [Install Twirp and Protobuf](install.md) generators first. The `protoc` compiler uses the flag `--twirp_out` to generate `twirp.go` files, and `--go_out` to generate `.pb.go` files. See [Protobuf Docs](https://developers.google.com/protocol-buffers/docs/reference/go-generated) for details on how to use the protoc compiler with `--go-out`, the Twirp flag `--twirp_out` supports the same parameters. For example, invoke the protoc compiler with default parameters to generate code for `rpc/haberdasher/service.proto`: ```sh protoc --go_out=. --twirp_out=. rpc/haberdasher/service.proto ``` ### Modifying imports The protoc compiler invocation can include optional flags to set the import path to be used in generated code: `--go_opt` and `--twirp_opt`. When working with multiple proto files that use import statements, `protoc-gen-twirp` uses the `option go_package` field in the `.proto` files to determine the import paths for imported message types. For example: ```protobuf option go_package = "github.com/twitchtv/thisisanexample"; ``` The `import_prefix` parameter can be passed to `--twirp_out` in order to prefix the generated import path with something. ```sh $ PROTO_SRC_PATH=./ $ IMPORT_PREFIX="github.com/example/rpc/haberdasher" $ protoc \ --proto_path=$PROTO_SRC_PATH \ --twirp_out=import_prefix=$IMPORT_PREFIX:$PROTO_SRC_PATH \ --go_out=import_prefix=$IMPORT_PREFIX:$PROTO_SRC_PATH \ $PROTO_SRC_PATH/rpc/haberdasher/service.proto ``` Alternatively, an import mapping parameter can be passed multiple times to `--twirp_out` in order to substitute the import path for a given proto file with something else. By passing the parameter multiple times you can build up a map of proto file to import path inside the generator. This parameter should be used when one of your proto files imports a proto file from another package and you're not generating your code at the `$GOPATH/src` root. For example, you could tell `protoc-gen-twirp` that `rpcutil/empty.proto` can be found at `github.com/example/rpcutil` by using `Mrpcutil/empty.proto=github.com/example/rpcutil`: ```sh $ PROTO_SRC_PATH=./ $ IMPORT_MAPPING="rpcutil/empty.proto=github.com/example/rpcutil" $ protoc \ --proto_path=$PROTO_SRC_PATH \ --twirp_out=M$IMPORT_MAPPING:$PROTO_SRC_PATH \ --go_out=M$IMPORT_MAPPING:$PROTO_SRC_PATH \ $PROTO_SRC_PATH/rpc/haberdasher/service.proto ``` ================================================ FILE: docs/curl.md ================================================ --- id: "curl" title: "cURL" sidebar_label: "cURL" --- You can access a Twirp service with cURL, using either JSON or Protobuf. ## Example With the following HelloWorld service defined in this proto file: ```proto syntax = "proto3"; package example.helloworld; service HelloWorld { rpc Hello(HelloReq) returns (HelloResp); } message HelloReq { string subject = 1; } message HelloResp { string text = 1; } ``` Assuming a service generated from this definition is running in `http://localhost:8080` with the default "/twirp" prefix, you can call it with cURL by following the routing rules (see [Routing](routing.md)) ### JSON Use the header `Content-Type: application/json` to signal that the request and response are JSON: ```sh curl --request "POST" \ --header "Content-Type: application/json" \ --data '{"subject": "World"}' \ http://localhost:8080/twirp/example.helloworld.HelloWorld/Hello ``` The service should respond with something like this: ```json {"text": "Hello World"} ``` NOTE: Twirp uses [proto3-json mapping](https://developers.google.com/protocol-buffers/docs/proto3#json), which means that empty fields are excluded. If you specify an empty request `--data '{}'` it will be interpreted as zero-values. Zero-values are also excluded on responses. In this example, if the service responded with an empty "text" field, the response you will see is empty `{}`. ### Protobuf Use the header `Content-Type: application/protobuf` to signal that the request and response are Protobuf. Use the `protoc` tool to encode and decode the Protobuf messages into readable key-values: ```sh echo 'subject:"World"' \ | protoc --encode example.helloworld.HelloReq ./rpc/helloworld/service.proto \ | curl -s --request POST \ --header "Content-Type: application/protobuf" \ --data-binary @- \ http://localhost:8080/twirp/example.helloworld.HelloWorld/Hello \ | protoc --decode example.helloworld.HelloResp ./rpc/haberdasher/service.proto ``` The service should respond with something like this: ``` text:"Hello World" ``` ### Errors Twirp error responses are always JSON, even if the request is done in Protobuf. A Twirp error response looks like this: ```json {"code": "internal", "msg": "Something went wrong"} ``` ================================================ FILE: docs/errors.md ================================================ --- id: "errors" title: "Errors" sidebar_label: "Errors" --- A Twirp error has the following properties: * **code**: Identifies the type of error. * **msg**: Free-form message with detailed information about the error. This is for humans, to help with debugging. Programs should not try to parse the error message. * **meta**: (optional) key-value pairs with arbitrary string metadata. Useful to define subtypes under the same code, or add extra fields for the callers. On the network, an error is represented as a JSON response with those properties. In Go, any value that implements the [twirp.Error](https://pkg.go.dev/github.com/twitchtv/twirp#Error) interface is considered a Twirp error. Other languages have different ways to represent the errors, but they always have the same properties and valid set of codes. ## Error Codes Twirp error codes with equivalent [HTTP status](https://pkg.go.dev/github.com/twitchtv/twirp#ServerHTTPStatusFromErrorCode): * `internal` (500) * `not_found` (404) * `invalid_argument` (400) * `unauthenticated` (401) * `permission_denied` (403) * `already_exists` (409) * ... more on the [Errors Spec](spec_v7.md#error-codes) ## Overview A Twirp service may implement an endpoint that returns an error. For example: ```go func (s *Server) OpenDoor(ctx context.Context, req *pb.OpenDoorRequest) (*pb.OpenDoorResp, error) { return nil, twirp.PermissionDenied.Error("this door is closed") } ``` The service HTTP response becomes be the error serialized as JSON: ```json // HTTP status: 403 { "code": "permission_denied", "msg": "this door is closed" } ``` Calling the endpoint from an auto-generated client will result on the same error, that can be inspected through the properties on the [twirp.Error](https://pkg.go.dev/github.com/twitchtv/twirp#Error) interface: ```go resp, err := client.OpenDoor(ctx, req) if twerr, ok := err.(twirp.Error); ok { twerr.Code() // => twirp.PermissionDenied twerr.Msg() //=> "this door is closed" } ``` ## Server Side: Returning Error Responses The `twirp` package provides a variety of error constructors. Check the [errors.go file for details](https://github.com/twitchtv/twirp/blob/main/errors.go). Some examples: ```go // (twirp.Code).Error(msg) to build a new error from the code twirp.Internal.Error("oops") twirp.NotFound.Error("user not found") twirp.InvalidArgument.Error("user_id must be alphanumeric") // (twirp.Code).Errorf(msg, ...args) to wrap other errors twirp.Internal.Errorf("Failed to perform operation: w%", err) // Generic constructor twirp.NewError(twirp.InvalidArgument, "user_id must be alphanumeric") // Any value that implements the twirp.Error interface myOwnTwirpErrImpl{code: twirp.NotFound} ``` Example of a Twirp endpoint that returns errors: ```go func (s *Server) FindUser(ctx context.Context, req *pb.FindUserRequest) (*pb.FindUserResp, error) { // Validation errors if req.UserId == "" { return nil, twirp.InvalidArgument.Error("user_id is required") } if !isAlphanumeric(req.UserId) { return nil, twirp.InvalidArgument.Error("user_id must be alphanumeric") } if !isAuthorized(ctx, req.UserId) { return nil, twirp.PermissionDenied.Error("not allowed to access user profiles") } // Perform some operation user, err := s.DB.FindByID(ctx, req.UserID) if errors.Is(err, DB_NOT_FOUND) { return nil, twirp.NotFound.Error("user not found") } if err != nil { return nil, twirp.Internal.Errorf("DB error: %w", err) } // Success return &pb.FindUserResp{ Login: user.Login, }, nil } ``` If the endpoint returns a vanilla (non-twirp) error, it will be automatically wrapped using [twirp.InternalErrorWith(err)](https://pkg.go.dev/github.com/twitchtv/twirp#InternalErrorWith). The following examples are equivalent (the client receives the same internal error). ```go func (s *Server) FindUser(ctx context.Context, req *pb.FindUserRequest) (*pb.FindUserResp, error) { return nil, errors.New("vanilla") } ``` Is equivalent to wrap the error with the helper: ```go func (s *Server) FindUser(ctx context.Context, req *pb.FindUserRequest) (*pb.FindUserResp, error) { return nil, twirp.InternalErrorWith(errors.New("vanilla")) } ``` Which is also equivalent to building the error from scratch this way: ```go func (s *Server) FindUser(ctx context.Context, req *pb.FindUserRequest) (*pb.FindUserResp, error) { err := errors.New("vanilla") return twirp.Internal.Errorf("%w", err). WithMeta("cause", fmt.Sprintf("%T", err)) } ``` #### Middleware, outside Twirp endpoints Twirp services can be [muxed with other HTTP services](mux.md). For consistent responses and error codes _outside_ Twirp servers, such as HTTP middleware, you can call [twirp.WriteError](https://pkg.go.dev/github.com/twitchtv/twirp#WriteError). ```go twirp.WriteError(responseWriter, twirp.Unauthenticated.Error("invalid token")) ``` ## Client Side: Handling Error Responses Twirp clients return errors that can always be cast to the `twirp.Error` interface. Unpack the error type to access the `Code()`, `Msg()` and `Meta(key)` properties. For example: ```go resp, err := client.FindUser(ctx, req) if err != nil { if twerr, ok := err.(twirp.Error); ok { if twerr.Code() == twirp.NotFound { fmt.Println("not found") } } fmt.Printf("internal: %s", err) } ``` You can also use [errors.Is](https://pkg.go.dev/errors#Is) and [errors.As](https://pkg.go.dev/errors#As) to check and unwrap Twirp errors: ```go resp, err := client.MakeHat(ctx, req) var twerr twirp.Error if errors.As(err, &twerr) { if twerr.Code() == twirp.NotFound { fmt.Println("not found") } } else if err != nil { fmt.Printf("internal: %s", err) } ``` Transport-level errors (e.g. connection issues) are returned as internal errors. If desired, the original client-side network error can be unwrapped: ```go resp, err := client.MakeHat(ctx, req) var twerr twirp.Error if errors.As(err, &twerr) { if twerr.Code() == twirp.Internal { if transportErr := errors.Unwrap(twerr); transportErr != nil { // transportErr could be something like an HTTP connection error } } } ``` ### HTTP Errors from Intermediary Proxies Twirp Clients may receive HTTP responses with non-200 status from different sources like proxies or load balancers. For example, a "503 Service Temporarily Unavailable" body, which cannot be deserialized into a Twirp error. In those cases, generated Go clients will try to best-guess the equivalent Twirp error depending on the HTTP status of the invalid response: | HTTP status code | Twirp Error Code | ------------------------ | ------------------ | 3xx (redirects) | Internal | 400 Bad Request | Internal | 401 Unauthorized | Unauthenticated | 403 Forbidden | PermissionDenied | 404 Not Found | BadRoute | 429 Too Many Requests | ResourceExhausted | 502 Bad Gateway | Unavailable | 503 Service Unavailable | Unavailable | 504 Gateway Timeout | Unavailable | ... other | Unknown Additional metadata is added to make it easy to identify intermediary errors: * `"http_error_from_intermediary": "true"` * `"status_code": string` (original status code on the HTTP response, e.g. `"500"`). * `"body": string` (original non-Twirp error response as string). * `"location": url-string` (only on 3xx responses, matching the `Location` header). ## Metadata In addition to `code` and `msg`, Twirp errors can optionally include arbitrary string metadata in the `meta` field. Use the chainable method [WithMeta(key, val)](https://pkg.go.dev/github.com/twitchtv/twirp#Error.WithMeta) to add extra metadata to a Twirp error. For example: ```go if unavailable { return nil, twirp.Unavailable.Error("taking a nap ..."). WithMeta("retryable", "true"). WithMeta("retry_after", "15s") } ``` Twirp serializes the response as JSON with the additional `meta` field: ```json // HTTP status: 503 { "code": "unavailable", "msg": "taking a nap ...", "meta": { "retryable": "true", "retry_after": "15s" } } ``` Metadata is available on the client through the [Meta(key)](https://pkg.go.dev/github.com/twitchtv/twirp#Error.Meta) accessor: ```go if twerr.Code() == twirp.Unavailable { if twerr.Meta("retryable") == "true" { fmt.Printf("retry after %s", twerr.Meta("retry_after")) } } ``` Error metadata can only have string values. This is to simplify error parsing by client implementations in multiple platforms. If your service requires errors with complex shapes, consider adding client wrappers on top of the auto-generated clients, or include specific business-logic errors on the Protobuf messages (as part of success responses). ================================================ FILE: docs/example.md ================================================ --- id: "example" title: "Usage Example: Haberdasher" sidebar_label: "Usage Example" --- Let's make the canonical Twirp service: a `Haberdasher`. The `Haberdasher` service makes hats. It has only one RPC method, `MakeHat`, which makes a new hat of a particular size. Make sure to [Install Protobuf and Twirp](install.md) before starting. By the end of this, we'll run a Haberdasher service with a strongly typed client. There are 5 steps here: 1. [Write a Protobuf service definition](#write-a-protobuf-service-definition) 2. [Generate code](#generate-code) 3. [Implement the server](#implement-the-server) 4. [Mount and run the server](#mount-and-run-the-server) 5. [Use the client](#use-the-client) ## Write a Protobuf Service Definition Start with the proto definition file, placed in `rpc/haberdasher/service.proto`: ```protobuf syntax = "proto3"; package twirp.example.haberdasher; option go_package = "github.com/example/rpc/haberdasher"; // Haberdasher service makes hats for clients. service Haberdasher { // MakeHat produces a hat of mysterious, randomly-selected color! rpc MakeHat(Size) returns (Hat); } // Size of a Hat, in inches. message Size { int32 inches = 1; // must be > 0 } // A Hat is a piece of headwear made by a Haberdasher. message Hat { int32 inches = 1; string color = 2; // anything but "invisible" string name = 3; // i.e. "bowler" } ``` It's a good idea to add comments on your Protobuf file. These files can work as the primary documentation of your API. The comments also show up in the generated Go types. ## Generate code To generate code run the `protoc` compiler pointed at your service's `.proto` files: ```sh $ protoc --go_out=. --twirp_out=. \ --go_opt=paths=source_relative \ --twirp_opt=paths=source_relative \ rpc/haberdasher/service.proto ``` See [Generator Command Line Arguments](command_line.md) for details about running the generator. The code should be generated in the same directory as the `.proto` files. ```text /rpc /haberdasher service.proto service.pb.go # generated by protoc-gen-go service.twirp.go # generated by protoc-gen-twirp ``` If you open the generated `.twirp.go` file, you should see a Go interface like this: ```go // A Haberdasher makes hats for clients. type Haberdasher interface { // MakeHat produces a hat of mysterious, randomly-selected color! MakeHat(context.Context, *Size) (*Hat, error) } ``` along with code to instantiate clients and servers. ## Implement the Server Now, our job is to write code that fulfills the `Haberdasher` interface. This will be the "backend" logic to handle the requests. The implementation could go in `internal/haberdasherserver/server.go`: ```go package haberdasherserver import ( "context" "math/rand" "github.com/twitchtv/twirp" pb "github.com/example/rpc/haberdasher" ) // Server implements the Haberdasher service type Server struct {} func (s *Server) MakeHat(ctx context.Context, size *pb.Size) (hat *pb.Hat, err error) { if size.Inches <= 0 { return nil, twirp.InvalidArgumentError("inches", "I can't make a hat that small!") } return &pb.Hat{ Inches: size.Inches, Color: []string{"white", "black", "brown", "red", "blue"}[rand.Intn(5)], Name: []string{"bowler", "baseball cap", "top hat", "derby"}[rand.Intn(4)], }, nil } ``` ## Mount and run the server To serve our Haberdasher over HTTP, use the generated server constructor `New{{Service}}Server`. For Haberdasher, it is: ```go func NewHaberdasherServer(svc Haberdasher, opts ...interface{}) TwirpServer ``` This constructor wraps your interface implementation as an `TwirpServer`, which is a `http.Handler` with a few extra bells and whistles. The `http.Handler` can be mounted like any other HTTP handler. For example, using the standard library `http.ListenAndServe` method. In `cmd/server/main.go`: ```go package main import ( "net/http" "github.com/example/internal/haberdasherserver" "github.com/example/rpc/haberdasher" ) func main() { server := &haberdasherserver.Server{} // implements Haberdasher interface twirpHandler := haberdasher.NewHaberdasherServer(server) http.ListenAndServe(":8080", twirpHandler) } ``` If you `go run ./cmd/server/main.go`, you'll be running your server at `localhost:8080`. All that's left is to create a client! ## Use the Client Client stubs are automatically generated, hooray! For each service, there are 2 client constructors: * `New{{Service}}ProtobufClient` for Protobuf requests. * `New{{Service}}JSONClient` for JSON requests. You should use the ProtobufClient. See [Protobuf vs JSON](protobuf_and_json.md) for comparison. Clients in other languages can also be generated by using the respective `protoc` plugins defined by their languages, for example [--twirp_ruby_out](https://github.com/twitchtv/twirp-ruby/wiki/Code-Generation#code-generation). To use the `Haberdasher` service from another Go project, import the auto-generated client. For example, in `cmd/client/main.go`: ```go package main import ( "context" "net/http" "os" "fmt" "github.com/example/rpc/haberdasher" ) func main() { client := haberdasher.NewHaberdasherProtobufClient("http://localhost:8080", &http.Client{}) hat, err := client.MakeHat(context.Background(), &haberdasher.Size{Inches: 12}) if err != nil { fmt.Printf("oh no: %v", err) os.Exit(1) } fmt.Printf("I have a nice new hat: %+v", hat) } ``` If you have the server running in another terminal, try running this client with `go run ./cmd/client/main.go`. Enjoy the new hat! ================================================ FILE: docs/headers.md ================================================ --- id: "headers" title: "Using custom HTTP Headers" sidebar_label: "Custom HTTP Headers" --- Sometimes, you need to send custom HTTP headers. For Twirp, HTTP headers are a transport implementation detail. You should not have to worry about them, but maybe your HTTP middleware requires them. If so, there's nothing the Twirp spec that _forbids_ extra headers, so go ahead. The rest of this doc is a guide on how to do this. ## Client side ### Send HTTP Headers with client requests Use `twirp.WithHTTPRequestHeaders` to attach the `http.Header` to a particular `context.Context`, then use that context in the client request: ```go // Given a client ... client := haberdasher.NewHaberdasherProtobufClient(addr, &http.Client{}) // Given some headers ... header := make(http.Header) header.Set("Twitch-Authorization", "uDRlDxQYbFVXarBvmTncBoWKcZKqrZTY") header.Set("Twitch-Client-ID", "FrankerZ") // Attach the headers to a context ctx := context.Background() ctx, err := twirp.WithHTTPRequestHeaders(ctx, header) if err != nil { log.Printf("twirp error setting headers: %s", err) return } // And use the context in the request. Headers will be included in the request! resp, err := client.MakeHat(ctx, &haberdasher.Size{Inches: 7}) ``` ### Read HTTP Headers from responses Twirp client responses are structs that depend only on the Protobuf response. HTTP headers can not be used by the Twirp client in any way. However, remember that the Twirp client is instantiated with an `http.Client`, which can be configured with any `http.RoundTripper` transport. You could make a RoundTripper that reads some response headers and does something with them. ## Server side ### Send HTTP Headers on server responses In your server implementation code, set response headers one by one with the helper `twirp.SetHTTPResponseHeader`, using the same context provided by the handler. For example: ```go func (h *myServer) MyRPC(ctx context.Context, req *pb.Req) (*pb.Resp, error) { // Add Cache-Control custom header to HTTP response err := twirp.SetHTTPResponseHeader(ctx, "Cache-Control", "public, max-age=60") if err != nil { return nil, twirp.InternalErrorWith(err) } return &pb.Resp{}, nil } ``` `twirp.AddHTTPResponseHeader` can be used to append values to a header. ### Read HTTP Headers from requests Twirp server methods are abstracted away from HTTP, therefore they don't have direct access to HTTP Headers. However, they receive the `http.Request`'s `context.Context` as parameter that can be modified by HTTP middleware before being used by the Twirp method. In more detail, you could do the following: * Write some middleware (a `func(http.Handler) http.Handler`) that reads the header's value and stores it in the request context. * Wrap your Twirp server with the middleware you wrote. * Inside your service, pull the header value out through the context. For example, lets say you want to read the 'User-Agent' HTTP header inside a twirp server method. You might write this middleware: ```go func WithUserAgent(base http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { ctx := r.Context() ua := r.Header.Get("User-Agent") ctx = context.WithValue(ctx, "user-agent", ua) r = r.WithContext(ctx) base.ServeHTTP(w, r) }) } ``` Then, you could wrap your generated Twirp server with this middleware: ```go h := haberdasher.NewHaberdasherServer(...) wrapped := WithUserAgent(h) http.ListenAndServe(":8080", wrapped) ``` Now, in your application code, you would have access to the header through the context, so you can do whatever you like with it: ```go func (h *haberdasherImpl) MakeHat(ctx context.Context, req *pb.MakeHatRequest) (*pb.Hat, error) { ua := ctx.Value("user-agent").(string) log.Printf("user agent: %v", ua) } ``` ================================================ FILE: docs/hooks.md ================================================ --- id: "hooks" title: "Hooks and Interceptors" sidebar_label: "Hooks and Interceptors" --- Twirp main responsibility is [routing and serialization](routing.md), but extra functionality can be plugged in through Hooks and Interceptors. This is useful to do things like log requests, record response times, report metrics, authenticate requests, and so on. There are multiple ways to inject functionality: * [Server Hooks](https://pkg.go.dev/github.com/twitchtv/twirp#ServerHooks): Can be used on the generated server constructor. They provide callbacks for before and after the request is handled. The Error hook is called only if an error was returned by the handler. Every hook receives the request `context.Context` and can return a modified `context.Context` if desired. * [Client Hooks](https://pkg.go.dev/github.com/twitchtv/twirp#ClientHooks): Can be used on the generated client constructor. They provide callbacks for before and after the request is sent over the network. The Error hook is called only if an error was returned through the network. * [Interceptors](https://pkg.go.dev/github.com/twitchtv/twirp#Interceptor): Can be used to wrap servers and clients. Interceptors are a form of middleware for Twirp requests. Interceptors can mutate the request and responses, which can enable some powerful integrations, but in most cases, it is better to use Hooks for observability at key points during a request. Mutating the request adds complexity to the request lifecycle. ### Examples Server Hooks: ```go // NewLoggingServerHooks logs request and errors to stdout in the service func NewLoggingServerHooks() *twirp.ServerHooks { return &twirp.ServerHooks{ RequestRouted: func(ctx context.Context) (context.Context, error) { method, _ := twirp.MethodName(ctx) log.Println("Method: " + method) return ctx, nil }, Error: func(ctx context.Context, twerr twirp.Error) context.Context { log.Println("Error: " + string(twerr.Code())) return ctx }, ResponseSent: func(ctx context.Context) { log.Println("Response Sent (error or success)") }, } } ``` Client Hooks: ```go // NewLoggingClientHooks logs request and errors to stdout in the client func NewLoggingClientHooks() *twirp.ClientHooks { return &twirp.ClientHooks{ RequestPrepared: func(ctx context.Context, r *http.Request) (context.Context, error) { fmt.Printf("Req: %s %s\n", r.Host, r.URL.Path) return ctx, nil }, Error: func(ctx context.Context, twerr twirp.Error) { log.Println("Error: " + string(twerr.Code())) return ctx }, ResponseReceived: func(ctx context.Context) { log.Println("Success") }, } } ``` Interceptor: ```go // NewInterceptorMakeSmallHats builds an interceptor that modifies // calls to MakeHat ignoring the request, and instead always making small hats. func NewInterceptorMakeSmallHats() twirp.Interceptor { return func(next twirp.Method) twirp.Method { return func(ctx context.Context, req interface{}) (interface{}, error) { if twirp.MethodName(ctx) == "MakeHat" { return next(ctx, &haberdasher.Size{Inches: 1}) } return next(ctx, req) } } } ``` Instantiate an example [Haberdasher](example.md) server with hooks and interceptors: ```go server := NewHaberdasherServer(svcImpl, twirp.WithServerInterceptors(NewInterceptorMakeSmallHats()), twirp.WithServerHooks(NewLoggingServerHooks())) ``` Instantiate an example [Haberdasher](example.md) client with hooks and interceptors: ```go client := NewHaberdasherProtobufClient(url, &http.Client{}, twirp.WithClientInterceptors(NewInterceptorMakeSmallHats()), twirp.WithClientHooks(NewLoggingClientHooks())) ``` ================================================ FILE: docs/install.md ================================================ --- id: install title: Installing Twirp sidebar_label: Installation --- ## Runtime Library The runtime library package `github.com/twitchtv/twirp` contains common types like `twirp.Error`. If you are only importing Twirp clients from other services, you only need to import the twirp package and the protobuf APIv2 dependency (`google.golang.org/protobuf`). If the Twirp client was generated with older versions of Twirp (v5, v7), then you need to import the older protobuf APIv1 dependency (`github.com/golang/protobuf`). ## Code Generator You need to install `go` and the `protoc` compiler in your system. Then, install the protoc plugins `protoc-gen-twirp` and `protoc-gen-go` to generate Go code. ### Prerequisites * [Go](https://golang.org/): Twirp works well with any one of the three latest major [releases of Go](https://golang.org/doc/devel/release.html). For installation instructions, see Go’s [Getting Started](https://golang.org/doc/install) guide. * [Protocol buffer](https://developers.google.com/protocol-buffers) compiler, `protoc` [version 3](https://developers.google.com/protocol-buffers/docs/proto3). For installation instructions, see [Protocol Buffer Compiler Installation](https://grpc.io/docs/protoc-installation/) (For example in MacOS: `brew install protobuf`). ### Define tools.go for versioning in go.mod You should track the Twirp and Protobuf versions like any other go-based tool (e.g. `stringer`). The currently recommended approach is to track the tool's version in your module's `go.mod` file (See ["Go Modules by Example" walkthrough](https://github.com/go-modules-by-example/index/blob/master/010_tools/README.md)). For example, a `tools.go` file may look like this: ```go // +build tools package tools import ( _ "google.golang.org/protobuf/cmd/protoc-gen-go" _ "github.com/twitchtv/twirp/protoc-gen-twirp" ) ``` ### Install Twirp and Protobuf Generators Set `GOBIN` (see [go help environment](https://golang.org/cmd/go/#hdr-Environment_variables)) to define where the tool dependencies will be installed. For example, if you have a `/bin` folder in your project: ```sh export GOBIN=$PWD/bin ``` The installed packages need to be accessible by the `protoc` compiler. You might need to add GOBIN to your PATH: ```sh export PATH=$GOBIN:$PATH ``` Install generators: ```sh go install github.com/twitchtv/twirp/protoc-gen-twirp@latest go install google.golang.org/protobuf/cmd/protoc-gen-go@latest ``` ### Old Twirp versions (v5, v7) depend on Protobuf APIv1 Older versions of Twirp require Protobuf APIv1 instead of APIv2 (See [Version Compatibility](version_matrix.md)), that has a different module name: ```sh go get github.com/twitchtv/twirp/protoc-gen-twirp@v7.2.0 go get github.com/golang/protobuf/protoc-gen-go@1.5.2 ``` ### Generate code Try the `protoc` compiler with the flags `--twirp_out` and `--go_out` to see if it is able to generate the `twirp.go` and `.pb.go` files. See [protobuf docs](https://developers.google.com/protocol-buffers/docs/reference/go-generated) for details on how to use the protoc compiler with `--go-out`, the Twirp flag `--twirp_out` supports the same parameters (see [Generator Flags](command_line.md) for more options). An example call with default parameters to generate code for `rpc/haberdasher/service.proto`: ```sh protoc --go_out=. --twirp_out=. rpc/haberdasher/service.proto ``` ================================================ FILE: docs/intro.md ================================================ --- id: intro title: Meet Twirp! sidebar_label: Overview --- Twirp is a simple RPC framework built on [protobuf](https://developers.google.com/protocol-buffers/). You define a service in a `.proto` specification file, then Twirp will _generate_ servers and clients for that service. It's your job to fill in the "business logic" that powers the server, and then generated clients can consume your service straight away. This doc is an overview of how you use Twirp - how you interact with it, what you write, and what it generates. Using the Go implementation as example: https://github.com/twitchtv/twirp ## Making a Twirp Service in Go To make a Twirp service: 1. Define your service in a **Proto** file. 2. Use the `protoc` command to generate go code from the **Proto** file, it will generate an **interface**, a **client** and some **server utils** (to easily start an http listener). 3. Implement the generated **interface** to implement the service. For example, a HelloWorld **Proto** file: ```protobuf syntax = "proto3"; package example.com.my.package.helloworld; option go_package = "example.com/my/package/helloworld"; service HelloWorld { rpc Hello(HelloReq) returns (HelloResp); } message HelloReq { string subject = 1; } message HelloResp { string text = 1; } ``` Running the `protoc` compiler with the `--go_out` and `--twirp_out` options will generate `.pb.go` and `.twirp.go` files. The Twirp file contains this **interface**: ```go type HelloWorld interface { Hello(context.Context, *HelloReq) (*HelloResp, error) } ``` You provide the **implementation**: ```go package main import ( "context" "net/http" pb "github.com/twitchtv/twirp-example/rpc/helloworld" ) type HelloWorldServer struct{} func (s *HelloWorldServer) Hello(ctx context.Context, req *pb.HelloReq) (*pb.HelloResp, error) { return &pb.HelloResp{Text: "Hello " + req.Subject}, nil } // Run the implementation in a local server func main() { twirpHandler := pb.NewHelloWorldServer(&HelloWorldServer{}) // You can use any mux you like - NewHelloWorldServer gives you an http.Handler. mux := http.NewServeMux() // The generated code includes a method, PathPrefix(), which // can be used to mount your service on a mux. mux.Handle(twirpHandler.PathPrefix(), twirpHandler) http.ListenAndServe(":8080", mux) } ``` And voila! Now you can use the auto-generated **Client** to make remote calls to your new service: ```go package main import ( "context" "fmt" "net/http" pb "github.com/twitchtv/twirp-example/rpc/helloworld" ) func main() { client := pb.NewHelloWorldProtobufClient("http://localhost:8080", &http.Client{}) resp, err := client.Hello(context.Background(), &pb.HelloReq{Subject: "World"}) if err == nil { fmt.Println(resp.Text) // prints "Hello World" } } ``` ## Why this is good Twirp [routing and serialization](routing.md) reduces the risk of introducing bugs. Both JSON and Protobuf are supported. The [Protobuf protocol](https://developers.google.com/protocol-buffers/docs/proto3) is designed to allow backwards compatible changes (unlike JSON, it is trivial to rename fields). Protobuf is super fast and the proto file definition also works well as documentation for your service. ## What's next? * [Install Twirp](install.md): instructions to install or upgrade Twirp tools for code auto-generation (protoc, protoc-gen-go and protoc-gen-twirp). * [Usage Example](example.md): step by step guide to build an awesome Haberdasher service. * [How Twirp routes requests](routing.md): learn more about how Twirp works under the covers. ================================================ FILE: docs/migrate_to_twirp.md ================================================ --- id: migrate_to_twirp title: Migrate APIs to Twirp sidebar_label: Migrate APIs to Twirp --- ## Migrate REST/JSON APIs to Twirp Migrating existing REST/JSON APIs to Twirp is a case-by-case scenario. Unfortunately, it involves creating a new service, generating a new client, and migrating callers to use the new endpoints in the new client. Twirp APIs are restricted to requests in the form `POST []/[.]/` (see [Routing and Serialization](routing.md)). That limitation is what allows building simple and consistent API schemas. In the other hand, REST/JSON APIs usually don't have strongly defined schemas and tend to have edge cases that need special attention when being translated into Twirp endpoints. The process is a case-by-case scenario, but we can highlight a few common steps: 1. Identify all the API endpoints in your old service, including request parameters, valid responses and possible errors. Also, identify all the API callers (upstream services) and let them know about the migration, they will soon need to update their client to use the new Twirp client when available. 2. Write a Protobuf schema. Respect [Protobuf naming and best practices](https://developers.google.com/protocol-buffers/docs/style) when possible, but don't try and significantly change the API design of your application during the migration; it will be a lot easier to migrate callers to the new API if the new endpoints are closely related to the old endpoints. Try to use parameter types that are similar to the old parameters. Use comments on the schema to clarify edge cases. 3. If the API is too big, it may be better to only migrate a few endpoints first. Protobuf schemas are good at evolving over time, you can always complete the migration for a few endpoints and add more endpoints later. 4. Generate code and implement your new API methods. You may be able to re-use some of the older code from the previous endpoints. One way to do this is to implement the new service in a subfolder inside the same project, and then mount the new Twirp handler in a sub-route (see [Muxing Twirp with other services](mux.md)). 5. Make sure to track stats about API endpoint usage, so you can see the traffic being migrated to the new endpoints. Use [hooks, interceptors](hooks.md) and/or HTTP [middleware](mux.md) as needed. 6. When the new Twirp service is ready, the API callers (upstream services) need to import the new Twirp client and update their calls to use the new Twirp API. This is why making the new API similar to the old one is useful. Some services may be able to just replace the old client with the new one and start sending traffic to the new endpoints, relying on their staging/canary environment for testing. Other services may want to implement a rollout slider to migrate traffic slowly (10%, 50%, etc.). The slider can be implemented in different ways. Here's a very naive implementation in Go to allow 10% traffic on the new client: `if r.Intn(100) < 10 { callNewClient() } else { callOldClient() }`. In more complex cases, it is also possible to make client that implements the same Twirp service interface, but with options to split the traffic between the new API and the old API. 7. When all traffic is migrated, don't forget to clean up the old code. If the old API is impossible to remove completely, it may be useful to re-implement old endpoints as shim calls to the new Twirp endpoints. ================================================ FILE: docs/mux.md ================================================ --- id: "mux" title: "Muxing Twirp with other HTTP services" sidebar_label: "Muxing Twirp services" --- If you want run your server next to other `http.Handler`s, you'll need to use a mux. The generated code includes a path prefix that you can use for routing Twirp requests correctly. It's an exported string const, always as `PathPrefix`, and it is the prefix for all Twirp requests. For example, you could use it with [`http.ServeMux`](https://golang.org/pkg/net/http/#ServeMux) like this: ```go serverImpl := &haberdasherserver.Server{} twirpHandler := haberdasher.NewHaberdasherServer(serverImpl) mux := http.NewServeMux() mux.Handle(twirpHandler.PathPrefix(), twirpHandler) mux.Handle("/some/other/path", someOtherHandler) http.ListenAndServe(":8080", mux) ``` You can also serve your Handler on many third-party muxes which accept `http.Handler`s. For example, on a `goji.Mux`: ```go serverImpl := &haberdasherserver.Server{} // implements Haberdasher interface twirpHandler := haberdasher.NewHaberdasherServer(serverImpl) mux := goji.NewMux() mux.Handle(pat.Post(twirpHandler.PathPrefix()+"*"), twirpHandler) // mux.Handle other things like health checks ... http.ListenAndServe("localhost:8000", mux) ``` ### Using a different path prefix By default, Twirp routes have a "/twirp" path prefix. See [Routing](routing.md) for more info. While the URL format can not be customized, the prefix can be changed to allow mounting the service in different routes. Use the option `twirp.WithServerPathPrefix`: ```go serverImpl := &haberdasherserver.Server{} twirpHandler := haberdasher.NewHaberdasherServer(serverImpl, twirp.WithServerPathPrefix("/my/custom/prefix")) mux := http.NewServeMux() mux.Handle(twirpHandler.PathPrefix(), twirpHandler) http.ListenAndServe(":8080", mux) ``` The clients must be initialized with the same prefix to send requests to the right routes. Use the option `twirp.WithClientPathPrefix`: ```go client := haberdasher.NewHaberdasherProtoClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/my/custom/prefix")) resp, err := c.MakeHat(ctx, &Size{Inches: 1}) ``` ================================================ FILE: docs/protobuf_and_json.md ================================================ --- id: "proto_and_json" title: "Twirp's Serialization Schemes" sidebar_label: "Protobuf and JSON" --- Twirp can handle both Protobuf and JSON encoding for requests and responses. This is transparent to your service implementation. Twirp parses the HTTP request (returning an Internal error if the `Content-Type` or the body are invalid) and converts it into the request struct defined in the interface. Your implementation returns a response struct, which Twirp serializes back to a Protobuf or JSON response (depending on the request `Content-Type`). See [the spec](spec_v7.md) for more details on routing and serialization. Twirp can generates two types of clients for your service: * `New{{Service}}ProtobufClient`: makes Protobuf requests to your service. * `New{{Service}}JSONClient`: makes JSON requests to your service. ### Which one should I use, ProtobufClient or JSONClient? You should use the **ProtobufClient**. Protobuf uses fewer bytes to encode than JSON (it is more compact), and it serializes faster. In addition, Protobuf is designed to gracefully handle schema updates. Did you notice the numbers added after each field? They allow you to change a field and it still works if the client and the server have a different versions (that doesn't work with JSON clients). ### If Protobuf is better, why does Twirp support JSON? You will probably never need to use a Twirp **JSONClient** in Go, but having your servers automatically handle JSON requests is still very convenient. It makes it easier to debug (see [cURL requests](curl.md)), allows to easily write clients in other languages like Python, or make REST mappings to Twirp services. The JSON client is generated to provide a reference for implementations in other languages, and because in some rare circumstances, binary encoding of request bodies is unacceptable, and you just need to use JSON. ================================================ FILE: docs/routing.md ================================================ --- id: "routing" title: "Routing and Serialization" sidebar_label: "Routing and Serialization" --- Routing and Serialization is handled by Twirp. All you really need to know is that "it just works". However you may find this interesting and useful for debugging and advanced configuration. ### HTTP Routes Twirp works over HTTP 1.1; all RPC methods map to routes that follow the format: ```plaintext POST []/[.]/ ``` Where: - The `` is "/twirp" by default, but it is optional and can be configured with other paths like "/my/custom/prefix" (see `twirp.WithServerPathPrefix`). - The ``, `` and `` names are the same values used in the `.proto` file where the service was defined. For example, to make a hat with the [Haberdasher service](example.md): ```plaintext POST /twirp/twirp.example.haberdasher.Haberdasher/MakeHat ``` More details on the [protocol specification](spec_v7.md). #### Naming Style For maximum compatibility, please follow the [Protocol Buffers Style Guide](https://developers.google.com/protocol-buffers/docs/style#services). In particular, the `` and `` names should be CamelCased (with an initial capital). This will ensure cross-language compatibility and prevent name collisions (e.g. `myMethod` and `my_method` would both map to `MyMethod`, causing a compile time error in some languages like Go). ### Content-Type Header (json or protobuf) The `Content-Type` header is required and must be either `application/json` or `application/protobuf`. JSON is easier for debugging (particularly when making requests with cURL), but Protobuf is better in almost every other way. Please use Protobuf in real code. See [Protobuf and JSON](protobuf_and_json.md) for more details. ### JSON serialization The JSON format generally matches the [official spec](https://developers.google.com/protocol-buffers/docs/proto3#json)'s rules for JSON serialization. In a nutshell: _all_ fields must be set, _no_ extra fields may be set, and `null` means "I want to leave this field blank". One exception to this is that names match the proto names, this is considered more predictable to those writing custom JSON clients. ### Error responses Errors returned by Twirp servers use non-200 HTTP status codes and always have JSON-encoded bodies (even if the request was Protobuf-encoded). The body JSON has three fields `{code, msg, meta}`. For example: ``` POST /twirp/twirp.example.haberdasher.Haberdasher/INVALIDROUTE 404 Not Found { "code": "bad_route", "msg": "no handler for path /twirp/twirp.example.haberdasher.Haberdasher/INVALIDROUTE", "meta": {"twirp_invalid_route": "POST /twirp/twirp.example.haberdasher.Haberdasher/INVALIDROUTE"} } ``` ================================================ FILE: docs/spec_v5.md ================================================ --- id: "spec_v5" title: "Twirp Wire Protocol (v5)" sidebar_label: "Version 5 (Previous)" --- This document defines the initial Twirp wire protocol over HTTP. The version 5 of the protocol was the initial version released to the public. If you are working on a new implementation of Twirp, please use the latest version of the spec. ## Overview The Twirp wire protocol is a simple RPC protocol based on HTTP and Protocol Buffers (proto). The protocol uses HTTP URLs to specify the RPC endpoints, and sends/receives proto messages as HTTP request/response bodies. To use Twirp, developers first define their APIs using proto files, then use Twirp tools to generate the client and the server libraries. The generated libraries implement the Twirp wire protocol, using the standard HTTP library provided by the programming language runtime or the operating system. Once the client and the server are implemented, the client can communicate with the server by making RPC calls. The Twirp wire protocol supports both binary and JSON encodings of proto messages, and works with any HTTP client and any HTTP version. ### URLs In [ABNF syntax](https://tools.ietf.org/html/rfc5234), Twirp's URLs have the following format: ```abnf URL ::= Base-URL "/twirp/" [ Package "." ] Service "/" Method ``` The Twirp wire protocol uses HTTP URLs to specify the RPC endpoints on the server for sending the requests. Such direct mapping makes the request routing simple and efficient. The Twirp URLs have the following components. * **Base-URL** is the virtual location of a Twirp API server, which is typically published via API documentation or service discovery. Currently, it should only contain URL `scheme` and `authority`. For example, "https://example.com". * **Package** is the proto `package` name for an API, which is often considered as an API version. For example, `example.calendar.v1`. This component is omitted if the API definition doesn't have a package name. * **Service** is the proto `service` name for an API. For example, `CalendarService`. * **Method** is the proto `rpc` name for an API method. For example, `CreateEvent`. ### Requests Twirp always uses HTTP POST method to send requests, because it closely matches the semantics of RPC methods. The **Request-Headers** are normal HTTP headers. The Twirp wire protocol uses the following headers. * **Content-Type** header indicates the proto message encoding, which should be one of "application/protobuf", "application/json". The server uses this value to decide how to parse the request body, and encode the response body. The **Request-Body** is the encoded request message, contained in the HTTP request body. The encoding is specified by the `Content-Type` header. ### Responses The **Response-Headers** are just normal HTTP response headers. The Twirp wire protocol uses the following headers. * **Content-Type** The value should be either "application/protobuf" or "application/json" to indicate the encoding of the response message. It must match the "Content-Type" header in the request. The **Request-Body** is the encoded response message contained in the HTTP response body. The encoding is specified by the `Content-Type` header. ### Example The following example shows a simple Echo API definition and its corresponding wire payloads. The example assumes the server base URL is "https://example.com". ```proto syntax = "proto3"; package example.echoer; service Echo { rpc Hello(HelloRequest) returns (HelloResponse); } message HelloRequest { string message; } message HelloResponse { string message; } ``` **Proto Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/protobuf Content-Length: 15 ``` **JSON Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` **Proto Response** ``` HTTP/1.1 200 OK Content-Type: application/protobuf Content-Length: 15 ``` **JSON Response** ``` HTTP/1.1 200 OK Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` ## Errors Twirp error responses are always JSON-encoded, regardless of the request's Content-Type, with a corresponding `Content-Type: application/json` header. This ensures that the errors are human-readable in any setting. Twirp errors are a JSON object with the keys: * **code**: One of the Twirp error codes as a string. * **msg**: A human-readable message describing the error as a string. * **meta**: (optional) An object with string values holding arbitrary additional metadata describing the error. Example: ```json { "code": "internal", "msg": "Something went wrong" } ``` Example with metadata: ```json { "code": "permission_denied", "msg": "Thou shall not pass", "meta": { "target": "Balrog", "power": "999" } } ``` ### Error Codes Twirp errors always include an error code. This code is represented as a string and must be one of a fixed set of codes, listed in the table below. Each code has an associated HTTP Status Code. When a server responds with the given error code, it must set the corresponding HTTP Status Code for the response. | Twirp Error Code | HTTP Status | Description | ------------------- | ----------- | ----------- | canceled | 408 | The operation was cancelled. | unknown | 500 | An unknown error occurred. For example, this can be used when handling errors raised by APIs that do not return any error information. | invalid_argument | 400 | The client specified an invalid argument. This indicates arguments that are invalid regardless of the state of the system (i.e. a malformed file name, required argument, number out of range, etc.). | malformed | 400 | The client sent a message which could not be decoded. This may mean that the message was encoded improperly or that the client and server have incompatible message definitions. | deadline_exceeded | 408 | Operation expired before completion. For operations that change the state of the system, this error may be returned even if the operation has completed successfully (timeout). | not_found | 404 | Some requested entity was not found. | bad_route | 404 | The requested URL path wasn't routable to a Twirp service and method. This is returned by generated server code and should not be returned by application code (use "not_found" or "unimplemented" instead). | already_exists | 409 | An attempt to create an entity failed because one already exists. | permission_denied | 403 | The caller does not have permission to execute the specified operation. It must not be used if the caller cannot be identified (use "unauthenticated" instead). | unauthenticated | 401 | The request does not have valid authentication credentials for the operation. | resource_exhausted | 403 | Some resource has been exhausted, perhaps a per-user quota, or perhaps the entire file system is out of space. | failed_precondition | 412 | The operation was rejected because the system is not in a state required for the operation's execution. For example, doing an rmdir operation on a directory that is non-empty, or on a non-directory object, or when having conflicting read-modify-write on the same resource. | aborted | 409 | The operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction aborts, etc. | out_of_range | 400 | The operation was attempted past the valid range. For example, seeking or reading past end of a paginated collection. Unlike "invalid_argument", this error indicates a problem that may be fixed if the system state changes (i.e. adding more items to the collection). 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. | unimplemented | 501 | The operation is not implemented or not supported/enabled in this service. | internal | 500 | When some invariants expected by the underlying system have been broken. In other words, something bad happened in the library or backend service. Twirp specific issues like wire and serialization problems are also reported as "internal" errors. | unavailable | 503 | The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff. | dataloss | 500 | The operation resulted in unrecoverable data loss or corruption. ================================================ FILE: docs/spec_v6.md ================================================ --- id: "spec_v6" title: "Twirp Wire Protocol (v6)" sidebar_label: "Version 6 (Archived)" --- This is a historical document for the Twirp wire protocol "v6", that was never released. At the time of writing, all existing production systems were using the "v5" protocol. New systems will implement "v7" and above. ## Why was v6 never released? The proposal for the v6 protocol has been standing without progress for too long. The streaming proposal was not simple enough to be officially released. The wire protocol is the glue connecting all the systems in production, once formalized it needs to be implemented by all different implementations across multiple languages. Because of this, it is very difficult to plan a path forward without having a negative impact on the Twirp ecosystem. ### Feature: Streaming API Issue: https://github.com/twitchtv/twirp/issues/70 Handling streams out of the box. Not implemented because streams require assumptions about how the connection state is managed, they are complex and not required by the majority of Twirp users. Websockets or gRPC may be good alternatives. There may still be reasons to implement streams in the future. If that happens, it will be managed separately from this v6 protocol draft. ### Feature: HTTP Routes update Issue: https://github.com/twitchtv/twirp/issues/55 Twirp routes have a `/twirp` prefix that is inconvenient in some cases. The different proposals to allow different routes were not entirely backwards compatible, and they were waiting for the Streaming API branch to be finalized. Too much time has passed since those routing proposals, and the backwards compatibility requirements have become more important. The "v7" protocol introduces an optional prefix for routing (where `/twirp` is the default prefix): https://github.com/twitchtv/twirp/pull/264 ================================================ FILE: docs/spec_v7.md ================================================ --- id: "spec_v7" title: "Twirp Wire Protocol (v7)" sidebar_label: "Version 7 (Current)" --- This document defines the Twirp wire protocol over HTTP. The current protocol version is v7. ## Overview The Twirp wire protocol is a simple RPC protocol based on HTTP and Protocol Buffers (proto). The protocol uses HTTP URLs to specify the RPC endpoints, and sends/receives proto messages as HTTP request/response bodies. To use Twirp, developers first define their APIs using proto files, then use Twirp tools to generate the client and the server libraries. The generated libraries implement the Twirp wire protocol, using the standard HTTP library provided by the programming language runtime or the operating system. Once the client and the server are implemented, the client can communicate with the server by making RPC calls. The Twirp wire protocol supports both binary and JSON encodings of proto messages, and works with any HTTP client and any HTTP version. ### URLs In [ABNF syntax](https://tools.ietf.org/html/rfc5234), Twirp's URLs have the following format: ```abnf URL ::= Base-URL [ Prefix ] "/" [ Package "." ] Service "/" Method ``` The Twirp wire protocol uses HTTP URLs to specify the RPC endpoints on the server for sending the requests. Such direct mapping makes the request routing simple and efficient. The Twirp URLs have the following components. * **Base-URL** is the virtual location of a Twirp API server, which is typically published via API documentation or service discovery. Currently, it should only contain URL `scheme` and `authority`. For example, "https://example.com". * **Prefix** is usually "/twirp", but it could be empty "", or an arbitrary path like "/my/custom/prefix". * **Package** is the proto `package` name for an API, which is often considered as an API version. For example, `example.calendar.v1`. This component is omitted if the API definition doesn't have a package name. * **Service** is the proto `service` name for an API. For example, `CalendarService`. * **Method** is the proto `rpc` name for an API method. For example, `CreateEvent`. ### Requests Twirp always uses HTTP POST method to send requests, because it closely matches the semantics of RPC methods. The **Request-Headers** are normal HTTP headers. The Twirp wire protocol uses the following headers. * **Content-Type** header indicates the proto message encoding, which should be one of "application/protobuf", "application/json". The server uses this value to decide how to parse the request body, and encode the response body. The **Request-Body** is the encoded request message, contained in the HTTP request body. The encoding is specified by the `Content-Type` header. ### Responses The **Response-Headers** are just normal HTTP response headers. The Twirp wire protocol uses the following headers. * **Content-Type** The value should be either "application/protobuf" or "application/json" to indicate the encoding of the response message. It must match the "Content-Type" header in the request. The **Request-Body** is the encoded response message contained in the HTTP response body. The encoding is specified by the `Content-Type` header. ### Example The following example shows a simple Echo API definition and its corresponding wire payloads. The example assumes the server base URL is "https://example.com". ```proto syntax = "proto3"; package example.echoer; service Echo { rpc Hello(HelloRequest) returns (HelloResponse); } message HelloRequest { string message; } message HelloResponse { string message; } ``` **Proto Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/protobuf Content-Length: 15 ``` **JSON Request** ``` POST /twirp/example.echoer.Echo/Hello HTTP/1.1 Host: example.com Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` **Proto Response** ``` HTTP/1.1 200 OK Content-Type: application/protobuf Content-Length: 15 ``` **JSON Response** ``` HTTP/1.1 200 OK Content-Type: application/json Content-Length: 27 {"message":"Hello, World!"} ``` ## Errors Twirp error responses are always JSON-encoded, regardless of the request's Content-Type, with a corresponding `Content-Type: application/json` header. This ensures that the errors are human-readable in any setting. Twirp errors are a JSON object with the keys: * **code**: One of the Twirp error codes as a string. * **msg**: A human-readable message describing the error as a string. * **meta**: (optional) An object with string values holding arbitrary additional metadata describing the error. Example: ```json { "code": "internal", "msg": "Something went wrong" } ``` Example with metadata: ```json { "code": "permission_denied", "msg": "Thou shall not pass", "meta": { "target": "Balrog", "power": "999" } } ``` ### Error Codes Twirp errors always include an error code. This code is represented as a string and must be one of a fixed set of codes, listed in the table below. Each code has an associated HTTP Status Code. When a server responds with the given error code, it must set the corresponding HTTP Status Code for the response. | Twirp Error Code | HTTP Status | Description | ------------------- | ----------- | ----------- | canceled | 408 | The operation was cancelled. | unknown | 500 | An unknown error occurred. For example, this can be used when handling errors raised by APIs that do not return any error information. | invalid_argument | 400 | The client specified an invalid argument. This indicates arguments that are invalid regardless of the state of the system (i.e. a malformed file name, required argument, number out of range, etc.). | malformed | 400 | The client sent a message which could not be decoded. This may mean that the message was encoded improperly or that the client and server have incompatible message definitions. | deadline_exceeded | 408 | Operation expired before completion. For operations that change the state of the system, this error may be returned even if the operation has completed successfully (timeout). | not_found | 404 | Some requested entity was not found. | bad_route | 404 | The requested URL path wasn't routable to a Twirp service and method. This is returned by generated server code and should not be returned by application code (use "not_found" or "unimplemented" instead). | already_exists | 409 | An attempt to create an entity failed because one already exists. | permission_denied | 403 | The caller does not have permission to execute the specified operation. It must not be used if the caller cannot be identified (use "unauthenticated" instead). | unauthenticated | 401 | The request does not have valid authentication credentials for the operation. | resource_exhausted | 429 | Some resource has been exhausted or rate-limited, perhaps a per-user quota, or perhaps the entire file system is out of space. | failed_precondition | 412 | The operation was rejected because the system is not in a state required for the operation's execution. For example, doing an rmdir operation on a directory that is non-empty, or on a non-directory object, or when having conflicting read-modify-write on the same resource. | aborted | 409 | The operation was aborted, typically due to a concurrency issue like sequencer check failures, transaction aborts, etc. | out_of_range | 400 | The operation was attempted past the valid range. For example, seeking or reading past end of a paginated collection. Unlike "invalid_argument", this error indicates a problem that may be fixed if the system state changes (i.e. adding more items to the collection). 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. | unimplemented | 501 | The operation is not implemented or not supported/enabled in this service. | internal | 500 | When some invariants expected by the underlying system have been broken. In other words, something bad happened in the library or backend service. Twirp specific issues like wire and serialization problems are also reported as "internal" errors. | unavailable | 503 | The service is currently unavailable. This is most likely a transient condition and may be corrected by retrying with a backoff. | dataloss | 500 | The operation resulted in unrecoverable data loss or corruption. ## Differences with v5 Note v6 was a draft and never released. Twirp implementations supporting the protocol spec v5 should update directly to support v7. * Twirp URLs in v5 could only have the "/twirp" prefix. In v7 they can have any arbitrary prefix or no prefix. See Go PR for reference: https://github.com/twitchtv/twirp/pull/264 * Error responses with code `resource_exhausted` in v5 had the HTTP status `403`. In v7 they have status `429`. See Go PR for reference: https://github.com/twitchtv/twirp/pull/270 ================================================ FILE: docs/version_matrix.md ================================================ --- id: version_matrix title: Version Compatibility sidebar_label: Version Compatibility --- ## Compatibility Matrix Generally speaking, code generated with newer versions of the generator require newer versions of the runtime, but runtime library is backwards compatible and works with older clients. This allows importing multiple clients generated at different versions into the same service, as long as the service is running the latest runtime. Read the matrix from left to right: Code generated with the Twirp Generator version on the left, is compatible with the runtime, protobuf runtime, protobuf generated code, and spec versions on the right. | Twirp Generator | Twirp Runtime | Protobuf | Twirp Spec | Key feature | | ---------------- |---------------| ---------| ---------- | ------------| | **v8.1** | v8.1+ | APIv2 | V7 | [Error matching with errors.As](https://github.com/twitchtv/twirp/releases/tag/v8.1.0) | **v8.0** | v7.1+ | APIv2 | V7 | [Protobuf APIv2](https://github.com/twitchtv/twirp/releases/tag/v8.0.0) | **v7.1** | v7.1+ | APIv1 | V7 | [Interceptors](https://github.com/twitchtv/twirp/releases/tag/v7.1.0) | **v7.0** | v7.0+ | APIv1 | V7 | [V7 Spec and ServerOptions](https://github.com/twitchtv/twirp/releases/tag/v7.0.0) | **v5.11** | v5.10+ | APIv1 | V7, V5 | [Unwrap errors](https://github.com/twitchtv/twirp/releases/tag/v5.11.0) | **v5.10** | v5.10+ | APIv1 | V7, V5 | [ClientHooks](https://github.com/twitchtv/twirp/releases/tag/v5.10.0) | **v5.8** | v5.8+ | APIv1 | V7, V5 | [Marlformed Error](https://github.com/twitchtv/twirp/releases/tag/v5.8.0) | **v5** | v5+ | APIv1 | V7, V5 | [First Public Release](https://github.com/twitchtv/twirp/releases/tag/v5.0.0) This table includes only versions that have potential breaking changes. Please read the [Release Notes](https://github.com/twitchtv/twirp/releases) to ensure upgrading without issues. ### Go Twirp and Protobuf compatibility Both Twirp and Protobuf contain a runtime library and a code generator plugin. The generated code can have incompatibility issues with different versions of the library. Twirp (https://github.com/twitchtv/twirp): * Twirp Generator: `github.com/twitchtv/twirp/protoc-gen-twirp`. Generates Go code with the `.twirp.go` file extension, with Twirp clients and servers. * Twirp Runtime: `github.com/twitchtv/twirp`. Is the Go library with shared types like `twirp.Error` and `twirp.ServerOptions`) Protobuf APIv2 (https://github.com/protocolbuffers/protobuf-go, https://blog.golang.org/protobuf-apiv2) * Proto Generator: `google.golang.org/protobuf/cmd/protoc-gen-go`. Generates Go code with the `.pb.go` file extension, with Protobuf message types. * Proto Runtime: `google.golang.org/protobuf/proto`. Is the Proto library used to serialize Protobuf and JSON messages over the network. The new version (APIv2) is used by new versions of Twirp (v8+). The older version (APIv1) has a different import path (`github.com/golang/protobuf/proto`) and is used by older versions of Twirp (v5 and v7). Protobuf APIv1 (DEPRECATED) (https://github.com/golang/protobuf): * Proto Generator: `github.com/golang/protobuf/protoc-gen-go`. * Proto Runtime: `github.com/golang/protobuf/proto`. NOTE: Different versions of Protobuf APIv1 can breaking changes, make sure to check their release notes when upgrading. ### Protocol Spec Compatibility The [Twirp Spec Protocol](https://twitchtv.github.io/twirp/docs/spec_v7.html) is the main point of compatibility for Twirp clients and services, across different versions and implementations in different languages. The Spec was first released as v5, and later updated to V7. Twirp (for Go) versions of the runtime library and generator labeled with `v5.x.x` are all compliant with the V5 spec and also with the V7 spec (V7 is backwards compatible). Any old service implementing V5 also works with the V7 spec. See [V7 release notes](https://github.com/twitchtv/twirp/releases/tag/v7.0.0) for compatibility details and upgrade instructions. Golang versions of the runtime library and generator labeled with `v7.x.x` and above (`v8+`), are compliant with the V7 spec. ================================================ FILE: errors.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp provides core types used in generated Twirp servers and client. // // Twirp services handle errors using the `twirp.Error` interface. // // For example, a server method may return an InvalidArgumentError: // // if req.Order != "DESC" && req.Order != "ASC" { // return nil, twirp.InvalidArgumentError("Order", "must be DESC or ASC") // } // // And the same twirp.Error is returned by the client, for example: // // resp, err := twirpClient.RPCMethod(ctx, req) // if err != nil { // if twerr, ok := err.(twirp.Error); ok { // switch twerr.Code() { // case twirp.InvalidArgument: // log.Error("invalid argument "+twirp.Meta("argument")) // default: // log.Error(twerr.Error()) // } // } // } // // Clients may also return Internal errors if something failed on the system: // the server, the network, or the client itself (i.e. failure parsing // response). // package twirp import ( "encoding/json" "errors" "fmt" "net/http" "strconv" ) // Error represents an error in a Twirp service call. type Error interface { // Code is of the valid error codes. Code() ErrorCode // Msg returns a human-readable, unstructured messages describing the error. Msg() string // WithMeta returns a copy of the Error with the given key-value pair attached // as metadata. If the key is already set, it is overwritten. WithMeta(key string, val string) Error // Meta returns the stored value for the given key. If the key has no set // value, Meta returns an empty string. There is no way to distinguish between // an unset value and an explicit empty string. Meta(key string) string // MetaMap returns the complete key-value metadata map stored on the error. MetaMap() map[string]string // Error returns a string of the form "twirp error : " Error() string } // code.Error(msg) builds a new Twirp error with code and msg. Example: // twirp.NotFound.Error("Resource not found") // twirp.Internal.Error("Oops") func (code ErrorCode) Error(msg string) Error { return NewError(code, msg) } // code.Errorf(msg, args...) builds a new Twirp error with code and formatted msg. // The format may include "%w" to wrap other errors. Examples: // twirp.Internal.Error("Oops: %w", originalErr) // twirp.NotFound.Error("Resource not found with id: %q", resourceID) func (code ErrorCode) Errorf(msgFmt string, a ...interface{}) Error { return NewErrorf(code, msgFmt, a...) } // WrapError allows Twirp errors to wrap other errors. // The wrapped error can be extracted later with (github.com/pkg/errors).Unwrap // or errors.Is from the standard errors package on Go 1.13+. func WrapError(twerr Error, err error) Error { return &wrappedErr{ wrapper: twerr, cause: err, } } // NewError builds a twirp.Error. The code must be one of the valid predefined constants. // To add metadata, use .WithMeta(key, value) method after building the error. func NewError(code ErrorCode, msg string) Error { if !IsValidErrorCode(code) { return &twerr{code: Internal, msg: "invalid error type " + string(code)} } return &twerr{code: code, msg: msg} } // NewErrorf builds a twirp.Error with a formatted msg. // The format may include "%w" to wrap other errors. Examples: // twirp.NewErrorf(twirp.Internal, "Oops: %w", originalErr) // twirp.NewErrorf(twirp.NotFound, "resource with id: %q", resourceID) func NewErrorf(code ErrorCode, msgFmt string, a ...interface{}) Error { err := fmt.Errorf(msgFmt, a...) // format error message, may include "%w" with an original error twerr := NewError(code, err.Error()) // use the error as msg return WrapError(twerr, err) // wrap so the original error can be identified with errors.Is } // NotFoundError is a convenience constructor for NotFound errors. func NotFoundError(msg string) Error { return NewError(NotFound, msg) } // InvalidArgumentError is a convenience constructor for InvalidArgument errors. // The argument name is included on the "argument" metadata for convenience. func InvalidArgumentError(argument string, validationMsg string) Error { err := NewError(InvalidArgument, argument+" "+validationMsg) err = err.WithMeta("argument", argument) return err } // RequiredArgumentError builds an InvalidArgument error. // Useful when a request argument is expected to have a non-zero value. func RequiredArgumentError(argument string) Error { return InvalidArgumentError(argument, "is required") } // InternalError is a convenience constructor for Internal errors. func InternalError(msg string) Error { return NewError(Internal, msg) } // InternalErrorf uses the formatted message as the internal error msg. // The format may include "%w" to wrap other errors. Examples: // twirp.InternalErrorf("database error: %w", err) // twirp.InternalErrorf("failed to load resource %q: %w", resourceID, originalErr) func InternalErrorf(msgFmt string, a ...interface{}) Error { return NewErrorf(Internal, msgFmt, a...) } // InternalErrorWith makes an internal error, wrapping the original error and using it // for the error message, and with metadata "cause" with the original error type. // This function is used by Twirp services to wrap non-Twirp errors as internal errors. // The wrapped error can be extracted later with (github.com/pkg/errors).Unwrap // or errors.Is from the standard errors package on Go 1.13+. func InternalErrorWith(err error) Error { twerr := NewError(Internal, err.Error()) twerr = twerr.WithMeta("cause", fmt.Sprintf("%T", err)) // to easily tell apart wrapped internal errors from explicit ones return WrapError(twerr, err) } // ErrorCode represents a Twirp error type. type ErrorCode string // Valid Twirp error types. Most error types are equivalent to gRPC status codes // and follow the same semantics. const ( // Canceled indicates the operation was cancelled (typically by the caller). Canceled ErrorCode = "canceled" // Unknown error. For example when handling errors raised by APIs that do not // return enough error information. Unknown ErrorCode = "unknown" // InvalidArgument indicates client specified an invalid argument. It // indicates arguments that are problematic regardless of the state of the // system (i.e. a malformed file name, required argument, number out of range, // etc.). InvalidArgument ErrorCode = "invalid_argument" // Malformed indicates an error occurred while decoding the client's request. // This may mean that the message was encoded improperly, or that there is a // disagreement in message format between the client and server. Malformed ErrorCode = "malformed" // DeadlineExceeded means operation expired before completion. For operations // that change the state of the system, this error may be returned even if the // operation has completed successfully (timeout). DeadlineExceeded ErrorCode = "deadline_exceeded" // NotFound means some requested entity was not found. NotFound ErrorCode = "not_found" // BadRoute means that the requested URL path wasn't routable to a Twirp // service and method. This is returned by the generated server, and usually // shouldn't be returned by applications. Instead, applications should use // NotFound or Unimplemented. BadRoute ErrorCode = "bad_route" // AlreadyExists means an attempt to create an entity failed because one // already exists. AlreadyExists ErrorCode = "already_exists" // PermissionDenied indicates the caller does not have permission to execute // the specified operation. It must not be used if the caller cannot be // identified (Unauthenticated). PermissionDenied ErrorCode = "permission_denied" // Unauthenticated indicates the request does not have valid authentication // credentials for the operation. Unauthenticated ErrorCode = "unauthenticated" // ResourceExhausted indicates some resource has been exhausted or rate-limited, // perhaps a per-user quota, or perhaps the entire file system is out of space. ResourceExhausted ErrorCode = "resource_exhausted" // FailedPrecondition indicates operation was rejected because the system is // not in a state required for the operation's execution. For example, doing // an rmdir operation on a directory that is non-empty, or on a non-directory // object, or when having conflicting read-modify-write on the same resource. FailedPrecondition ErrorCode = "failed_precondition" // Aborted indicates the operation was aborted, typically due to a concurrency // issue like sequencer check failures, transaction aborts, etc. Aborted ErrorCode = "aborted" // OutOfRange means operation was attempted past the valid range. For example, // seeking or reading past end of a paginated collection. // // Unlike InvalidArgument, this error indicates a problem that may be fixed if // the system state changes (i.e. adding more items to the collection). // // There is a fair bit of overlap between FailedPrecondition and OutOfRange. // We recommend using OutOfRange (the more specific error) when it applies so // that callers who are iterating through a space can easily look for an // OutOfRange error to detect when they are done. OutOfRange ErrorCode = "out_of_range" // Unimplemented indicates operation is not implemented or not // supported/enabled in this service. Unimplemented ErrorCode = "unimplemented" // Internal errors. When some invariants expected by the underlying system // have been broken. In other words, something bad happened in the library or // backend service. Do not confuse with HTTP Internal Server Error; an // Internal error could also happen on the client code, i.e. when parsing a // server response. Internal ErrorCode = "internal" // Unavailable indicates the service is currently unavailable. This is a most // likely a transient condition and may be corrected by retrying with a // backoff. Unavailable ErrorCode = "unavailable" // DataLoss indicates unrecoverable data loss or corruption. DataLoss ErrorCode = "data_loss" // NoError is the zero-value, is considered an empty error and should not be // used. NoError ErrorCode = "" ) // ServerHTTPStatusFromErrorCode maps a Twirp error type into a similar HTTP // response status. It is used by the Twirp server handler to set the HTTP // response status code. Returns 0 if the ErrorCode is invalid. func ServerHTTPStatusFromErrorCode(code ErrorCode) int { switch code { case Canceled: return 408 // RequestTimeout case Unknown: return 500 // Internal Server Error case InvalidArgument: return 400 // BadRequest case Malformed: return 400 // BadRequest case DeadlineExceeded: return 408 // RequestTimeout case NotFound: return 404 // Not Found case BadRoute: return 404 // Not Found case AlreadyExists: return 409 // Conflict case PermissionDenied: return 403 // Forbidden case Unauthenticated: return 401 // Unauthorized case ResourceExhausted: return 429 // Too Many Requests case FailedPrecondition: return 412 // Precondition Failed case Aborted: return 409 // Conflict case OutOfRange: return 400 // Bad Request case Unimplemented: return 501 // Not Implemented case Internal: return 500 // Internal Server Error case Unavailable: return 503 // Service Unavailable case DataLoss: return 500 // Internal Server Error case NoError: return 200 // OK default: return 0 // Invalid! } } // IsValidErrorCode returns true if is one of the valid predefined constants. func IsValidErrorCode(code ErrorCode) bool { return ServerHTTPStatusFromErrorCode(code) != 0 } // twirp.Error implementation type twerr struct { code ErrorCode msg string meta map[string]string } func (e *twerr) Code() ErrorCode { return e.code } func (e *twerr) Msg() string { return e.msg } func (e *twerr) Meta(key string) string { if e.meta != nil { return e.meta[key] // also returns "" if key is not in meta map } return "" } func (e *twerr) WithMeta(key string, value string) Error { newErr := &twerr{ code: e.code, msg: e.msg, meta: make(map[string]string, len(e.meta)), } for k, v := range e.meta { newErr.meta[k] = v } newErr.meta[key] = value return newErr } func (e *twerr) MetaMap() map[string]string { return e.meta } func (e *twerr) Error() string { return fmt.Sprintf("twirp error %s: %s", e.code, e.msg) } // wrappedErr is the error returned by twirp.InternalErrorWith(err), which is used by clients. // Implements Unwrap() to allow go 1.13+ errors.Is/As checks, // and Cause() to allow (github.com/pkg/errors).Unwrap. type wrappedErr struct { wrapper Error cause error } func (e *wrappedErr) Code() ErrorCode { return e.wrapper.Code() } func (e *wrappedErr) Msg() string { return e.wrapper.Msg() } func (e *wrappedErr) Meta(key string) string { return e.wrapper.Meta(key) } func (e *wrappedErr) MetaMap() map[string]string { return e.wrapper.MetaMap() } func (e *wrappedErr) Error() string { return e.wrapper.Error() } func (e *wrappedErr) WithMeta(key string, val string) Error { return &wrappedErr{ wrapper: e.wrapper.WithMeta(key, val), cause: e.cause, } } func (e *wrappedErr) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedErr) Cause() error { return e.cause } // for github.com/pkg/errors // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware). // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) error { var twerr Error if !errors.As(err, &twerr) { twerr = InternalErrorWith(err) } statusCode := ServerHTTPStatusFromErrorCode(twerr.Code()) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { return writeErr } return nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } ================================================ FILE: errors_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp_test import ( "encoding/json" "errors" "fmt" "net/http/httptest" "sync" "testing" pkgerrors "github.com/pkg/errors" "github.com/twitchtv/twirp" ) func TestErrorConstructors(t *testing.T) { var twerr twirp.Error err := errors.New("The OG error") // code.Error twerr = twirp.NotFound.Error("oops") assertTwirpError(t, twerr, twirp.NotFound, "oops") // code.Errorf twerr = twirp.Aborted.Errorf("oops %d %s", 11, "times") assertTwirpError(t, twerr, twirp.Aborted, "oops 11 times") twerr = twirp.Internal.Errorf("oops: %w", err) assertTwirpError(t, twerr, twirp.Internal, "oops: The OG error") if !errors.Is(twerr, err) { t.Errorf("expected wrap the original error") } // twirp.NewError twerr = twirp.NewError(twirp.NotFound, "oops") assertTwirpError(t, twerr, twirp.NotFound, "oops") // twirp.NewErrorf twerr = twirp.NewErrorf(twirp.Aborted, "oops %d %s", 11, "times") assertTwirpError(t, twerr, twirp.Aborted, "oops 11 times") twerr = twirp.NewErrorf(twirp.Internal, "oops: %w", err) assertTwirpError(t, twerr, twirp.Internal, "oops: The OG error") if !errors.Is(twerr, err) { t.Errorf("expected wrap the original error") } // Convenience constructors twerr = twirp.NotFoundError("oops") assertTwirpError(t, twerr, twirp.NotFound, "oops") twerr = twirp.InvalidArgumentError("my_arg", "is invalid") assertTwirpError(t, twerr, twirp.InvalidArgument, "my_arg is invalid") assertTwirpErrorMeta(t, twerr, "argument", "my_arg") twerr = twirp.RequiredArgumentError("my_arg") assertTwirpError(t, twerr, twirp.InvalidArgument, "my_arg is required") assertTwirpErrorMeta(t, twerr, "argument", "my_arg") twerr = twirp.InternalError("oops") assertTwirpError(t, twerr, twirp.Internal, "oops") twerr = twirp.InternalErrorf("oops: %w", err) assertTwirpError(t, twerr, twirp.Internal, "oops: The OG error") if !errors.Is(twerr, err) { t.Errorf("expected wrap the original error") } twerr = twirp.InternalErrorWith(err) assertTwirpError(t, twerr, twirp.Internal, "The OG error") if !errors.Is(twerr, err) { t.Errorf("expected wrap the original error") } assertTwirpErrorMeta(t, twerr, "cause", "*errors.errorString") } func TestWithMetaRaces(t *testing.T) { err := twirp.NewError(twirp.Internal, "msg") err = err.WithMeta("k1", "v1") var wg sync.WaitGroup for i := 0; i < 1000; i++ { wg.Add(1) go func(i int) { _ = err.WithMeta(fmt.Sprintf("k-%d", i), "v") wg.Done() }(i) } wg.Wait() if len(err.MetaMap()) != 1 { t.Errorf("err was mutated") } } func TestPkgErrorCause(t *testing.T) { rootCause := pkgerrors.New("this is only a test") twerr := twirp.InternalErrorWith(rootCause) cause := pkgerrors.Cause(twerr) if cause != rootCause { t.Errorf("got wrong cause for err. have=%q, want=%q", cause, rootCause) } } func TestWrapError(t *testing.T) { rootCause := errors.New("cause") twerr := twirp.NewError(twirp.NotFound, "it ain't there") err := twirp.WrapError(twerr, rootCause) cause := pkgerrors.Cause(err) if cause != rootCause { t.Errorf("got wrong cause. got=%q, want=%q", cause, rootCause) } wantMsg := "twirp error not_found: it ain't there" if gotMsg := err.Error(); gotMsg != wantMsg { t.Errorf("got wrong error text. got=%q, want=%q", gotMsg, wantMsg) } } type myError string func (e myError) Error() string { return string(e) } func TestInternalErrorWith_Unwrap(t *testing.T) { myErr := myError("myError") wrErr := fmt.Errorf("wrapped: %w", myErr) // double wrap twerr := twirp.InternalErrorWith(wrErr) if !errors.Is(twerr, myErr) { t.Errorf("expected errors.Is to match the error wrapped by twirp.InternalErrorWith") } var errTarget myError if !errors.As(twerr, &errTarget) { t.Errorf("expected errors.As to match the error wrapped by twirp.InternalErrorWith") } if errTarget.Error() != myErr.Error() { t.Errorf("invalid value for errTarget.Error(). have=%q, want=%q", errTarget.Error(), myErr.Error()) } } type errorResponseWriter struct { *httptest.ResponseRecorder } func (errorResponseWriter) Write([]byte) (int, error) { return 0, errors.New("this is only a test") } type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } func TestWriteError(t *testing.T) { resp := httptest.NewRecorder() twerr := twirp.NewError(twirp.Internal, "test middleware error") err := twirp.WriteError(resp, twerr) if err != nil { t.Errorf("got an error from WriteError when not expecting one: %s", err) return } twerrCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) if resp.Code != twerrCode { t.Errorf("got wrong status. have=%d, want=%d", resp.Code, twerrCode) return } var gotTwerrJSON twerrJSON err = json.NewDecoder(resp.Body).Decode(&gotTwerrJSON) if err != nil { t.Errorf("got an error decoding response body: %s", err) return } if twirp.ErrorCode(gotTwerrJSON.Code) != twerr.Code() { t.Errorf("got wrong error code. have=%s, want=%s", gotTwerrJSON.Code, twerr.Code()) return } if gotTwerrJSON.Msg != twerr.Msg() { t.Errorf("got wrong error message. have=%s, want=%s", gotTwerrJSON.Msg, twerr.Msg()) return } errResp := &errorResponseWriter{ResponseRecorder: resp} // Writing again should error out as headers are being rewritten err = twirp.WriteError(errResp, twerr) if err == nil { t.Errorf("did not get error on write. have=nil, want=some error") } } func TestWriteError_WithNonTwirpError(t *testing.T) { resp := httptest.NewRecorder() nonTwerr := errors.New("not a twirp error") err := twirp.WriteError(resp, nonTwerr) if err != nil { t.Errorf("got an error from WriteError when not expecting one: %s", err) return } if resp.Code != 500 { t.Errorf("got wrong status. have=%d, want=%d", resp.Code, 500) return } var gotTwerrJSON twerrJSON err = json.NewDecoder(resp.Body).Decode(&gotTwerrJSON) if err != nil { t.Errorf("got an error decoding response body: %s", err) return } if twirp.ErrorCode(gotTwerrJSON.Code) != twirp.Internal { t.Errorf("got wrong error code. have=%s, want=%s", gotTwerrJSON.Code, twirp.Internal) return } if gotTwerrJSON.Msg != ""+nonTwerr.Error() { t.Errorf("got wrong error message. have=%s, want=%s", gotTwerrJSON.Msg, nonTwerr.Error()) return } } // Test helpers func assertTwirpError(t *testing.T, twerr twirp.Error, code twirp.ErrorCode, msg string) { t.Helper() if twerr.Code() != code { t.Errorf("wrong code. have=%q, want=%q", twerr.Code(), code) } if twerr.Msg() != msg { t.Errorf("wrong msg. have=%q, want=%q", twerr.Msg(), msg) } } func assertTwirpErrorMeta(t *testing.T, twerr twirp.Error, key string, value string) { t.Helper() if twerr.Meta(key) != value { t.Errorf("wrong meta. have=%q, want=%q", twerr.Meta(key), value) } } ================================================ FILE: example/cmd/client/main.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "context" "fmt" "log" "net/http" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/example" ) func main() { client := example.NewHaberdasherJSONClient("http://localhost:8080", &http.Client{}) var ( hat *example.Hat err error ) for i := 0; i < 5; i++ { hat, err = client.MakeHat(context.Background(), &example.Size{Inches: 12}) if err != nil { if twerr, ok := err.(twirp.Error); ok { if twerr.Meta("retryable") != "" { // Log the error and go again. log.Printf("got error %q, retrying", twerr) continue } } // This was some fatal error! log.Fatal(err) } } fmt.Printf("%+v", hat) } ================================================ FILE: example/cmd/server/README.md ================================================ # twirp example server # This binary is an example twirp server. It's meant mostly to be read and to be used in conjunction with the neighboring client binary. When a request is made, the server will log the statsd messages it would have sent, so you'll see stuff like this: -> % ./server incr twirp.total.requests: 1 @ 1.000000 incr twirp.MakeHat.requests: 1 @ 1.000000 incr twirp.total.responses: 1 @ 1.000000 incr twirp.MakeHat.responses: 1 @ 1.000000 incr twirp.status_codes.total.200: 1 @ 1.000000 incr twirp.status_codes.MakeHat.200: 1 @ 1.000000 time twirp.all_methods.response: 370.695µs @ 1.000000 time twirp.MakeHat.response: 370.695µs @ 1.000000 time twirp.status_codes.all_methods.200: 370.695µs @ 1.000000 time twirp.status_codes.MakeHat.200: 370.695µs @ 1.000000 ================================================ FILE: example/cmd/server/main.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "context" "log" "math/rand" "net/http" "os" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/example" "github.com/twitchtv/twirp/hooks/statsd" ) type randomHaberdasher struct{} func (h *randomHaberdasher) MakeHat(ctx context.Context, size *example.Size) (*example.Hat, error) { if size.Inches <= 0 { return nil, twirp.InvalidArgumentError("Inches", "I can't make a hat that small!") } colors := []string{"white", "black", "brown", "red", "blue"} names := []string{"bowler", "baseball cap", "top hat", "derby"} return &example.Hat{ Size: size.Inches, Color: colors[rand.Intn(len(colors))], Name: names[rand.Intn(len(names))], }, nil } func main() { hook := statsd.NewStatsdServerHooks(LoggingStatter{os.Stderr}) server := example.NewHaberdasherServer(&randomHaberdasher{}, hook) log.Fatal(http.ListenAndServe(":8080", server)) } ================================================ FILE: example/cmd/server/statter.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "fmt" "io" "time" ) type LoggingStatter struct { io.Writer } func (ls LoggingStatter) Inc(metric string, val int64, rate float32) error { _, err := fmt.Fprintf(ls, "incr %s: %d @ %f\n", metric, val, rate) return err } func (ls LoggingStatter) TimingDuration(metric string, val time.Duration, rate float32) error { _, err := fmt.Fprintf(ls, "time %s: %s @ %f\n", metric, val, rate) return err } ================================================ FILE: example/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 example //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. service.proto ================================================ FILE: example/service.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: service.proto package example import ( 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) ) // A Hat is a piece of headwear made by a Haberdasher. type Hat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The size of a hat should always be in inches. Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"` // The color of a hat will never be 'invisible', but other than // that, anything is fair game. Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"` // The name of a hat is it's type. Like, 'bowler', or something. Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` } func (x *Hat) Reset() { *x = Hat{} if protoimpl.UnsafeEnabled { mi := &file_service_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Hat) String() string { return protoimpl.X.MessageStringOf(x) } func (*Hat) ProtoMessage() {} func (x *Hat) ProtoReflect() protoreflect.Message { mi := &file_service_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 Hat.ProtoReflect.Descriptor instead. func (*Hat) Descriptor() ([]byte, []int) { return file_service_proto_rawDescGZIP(), []int{0} } func (x *Hat) GetSize() int32 { if x != nil { return x.Size } return 0 } func (x *Hat) GetColor() string { if x != nil { return x.Color } return "" } func (x *Hat) GetName() string { if x != nil { return x.Name } return "" } // Size is passed when requesting a new hat to be made. It's always // measured in inches. type Size struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Inches int32 `protobuf:"varint,1,opt,name=inches,proto3" json:"inches,omitempty"` } func (x *Size) Reset() { *x = Size{} if protoimpl.UnsafeEnabled { mi := &file_service_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Size) String() string { return protoimpl.X.MessageStringOf(x) } func (*Size) ProtoMessage() {} func (x *Size) ProtoReflect() protoreflect.Message { mi := &file_service_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 Size.ProtoReflect.Descriptor instead. func (*Size) Descriptor() ([]byte, []int) { return file_service_proto_rawDescGZIP(), []int{1} } func (x *Size) GetInches() int32 { if x != nil { return x.Inches } return 0 } var File_service_proto protoreflect.FileDescriptor var file_service_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x14, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x22, 0x43, 0x0a, 0x03, 0x48, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x32, 0x4f, 0x0a, 0x0b, 0x48, 0x61, 0x62, 0x65, 0x72, 0x64, 0x61, 0x73, 0x68, 0x65, 0x72, 0x12, 0x40, 0x0a, 0x07, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x12, 0x1a, 0x2e, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x19, 0x2e, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x48, 0x61, 0x74, 0x42, 0x0a, 0x5a, 0x08, 0x2f, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_service_proto_rawDescOnce sync.Once file_service_proto_rawDescData = file_service_proto_rawDesc ) func file_service_proto_rawDescGZIP() []byte { file_service_proto_rawDescOnce.Do(func() { file_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_proto_rawDescData) }) return file_service_proto_rawDescData } var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_service_proto_goTypes = []interface{}{ (*Hat)(nil), // 0: twitch.twirp.example.Hat (*Size)(nil), // 1: twitch.twirp.example.Size } var file_service_proto_depIdxs = []int32{ 1, // 0: twitch.twirp.example.Haberdasher.MakeHat:input_type -> twitch.twirp.example.Size 0, // 1: twitch.twirp.example.Haberdasher.MakeHat:output_type -> twitch.twirp.example.Hat 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_service_proto_init() } func file_service_proto_init() { if File_service_proto != nil { return } if !protoimpl.UnsafeEnabled { file_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Hat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Size); 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_service_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, GoTypes: file_service_proto_goTypes, DependencyIndexes: file_service_proto_depIdxs, MessageInfos: file_service_proto_msgTypes, }.Build() File_service_proto = out.File file_service_proto_rawDesc = nil file_service_proto_goTypes = nil file_service_proto_depIdxs = nil } ================================================ FILE: example/service.proto ================================================ syntax = "proto3"; package twitch.twirp.example; option go_package = "/example"; // A Hat is a piece of headwear made by a Haberdasher. message Hat { // The size of a hat should always be in inches. int32 size = 1; // The color of a hat will never be 'invisible', but other than // that, anything is fair game. string color = 2; // The name of a hat is it's type. Like, 'bowler', or something. string name = 3; } // Size is passed when requesting a new hat to be made. It's always // measured in inches. message Size { int32 inches = 1; } // A Haberdasher makes hats for clients. service Haberdasher { // MakeHat produces a hat of mysterious, randomly-selected color! rpc MakeHat(Size) returns (Hat); } ================================================ FILE: example/service.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: service.proto package example import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ===================== // Haberdasher Interface // ===================== // A Haberdasher makes hats for clients. type Haberdasher interface { // MakeHat produces a hat of mysterious, randomly-selected color! MakeHat(context.Context, *Size) (*Hat, error) } // =========================== // Haberdasher Protobuf Client // =========================== type haberdasherProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherProtobufClient creates a Protobuf client that implements the Haberdasher interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewHaberdasherProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Haberdasher { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twitch.twirp.example", "Haberdasher") urls := [1]string{ serviceURL + "MakeHat", } return &haberdasherProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { ctx = ctxsetters.WithPackageName(ctx, "twitch.twirp.example") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithMethodName(ctx, "MakeHat") caller := c.callMakeHat if c.interceptor != nil { caller = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return c.callMakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherProtobufClient) callMakeHat(ctx context.Context, in *Size) (*Hat, error) { out := new(Hat) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ======================= // Haberdasher JSON Client // ======================= type haberdasherJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherJSONClient creates a JSON client that implements the Haberdasher interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewHaberdasherJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Haberdasher { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twitch.twirp.example", "Haberdasher") urls := [1]string{ serviceURL + "MakeHat", } return &haberdasherJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherJSONClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { ctx = ctxsetters.WithPackageName(ctx, "twitch.twirp.example") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithMethodName(ctx, "MakeHat") caller := c.callMakeHat if c.interceptor != nil { caller = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return c.callMakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherJSONClient) callMakeHat(ctx context.Context, in *Size) (*Hat, error) { out := new(Hat) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ========================== // Haberdasher Server Handler // ========================== type haberdasherServer struct { Haberdasher interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewHaberdasherServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewHaberdasherServer(svc Haberdasher, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &haberdasherServer{ Haberdasher: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *haberdasherServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *haberdasherServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // HaberdasherPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const HaberdasherPathPrefix = "/twirp/twitch.twirp.example.Haberdasher/" func (s *haberdasherServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twitch.twirp.example") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twitch.twirp.example.Haberdasher" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "MakeHat": s.serveMakeHat(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *haberdasherServer) serveMakeHat(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveMakeHatJSON(ctx, resp, req) case "application/protobuf": s.serveMakeHatProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *haberdasherServer) serveMakeHatJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHat") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Size) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Haberdasher.MakeHat if s.interceptor != nil { handler = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return s.Haberdasher.MakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Hat func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Hat and nil error while calling MakeHat. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherServer) serveMakeHatProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHat") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Size) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Haberdasher.MakeHat if s.interceptor != nil { handler = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return s.Haberdasher.MakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Hat func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Hat and nil error while calling MakeHat. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *haberdasherServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *haberdasherServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twitch.twirp.example", "Haberdasher") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 186 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x12, 0x29, 0x29, 0xcf, 0x2c, 0x49, 0xce, 0xd0, 0x2b, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0x4b, 0xad, 0x48, 0xcc, 0x2d, 0xc8, 0x49, 0x55, 0x72, 0xe6, 0x62, 0xf6, 0x48, 0x2c, 0x11, 0x12, 0xe2, 0x62, 0x29, 0xce, 0xac, 0x4a, 0x95, 0x60, 0x54, 0x60, 0xd4, 0x60, 0x0d, 0x02, 0xb3, 0x85, 0x44, 0xb8, 0x58, 0x93, 0xf3, 0x73, 0xf2, 0x8b, 0x24, 0x98, 0x14, 0x18, 0x35, 0x38, 0x83, 0x20, 0x1c, 0x90, 0xca, 0xbc, 0xc4, 0xdc, 0x54, 0x09, 0x66, 0xb0, 0x20, 0x98, 0xad, 0x24, 0xc7, 0xc5, 0x12, 0x0c, 0xd2, 0x21, 0xc6, 0xc5, 0x96, 0x99, 0x97, 0x9c, 0x91, 0x5a, 0x0c, 0x35, 0x07, 0xca, 0x33, 0xf2, 0xe7, 0xe2, 0xf6, 0x48, 0x4c, 0x4a, 0x2d, 0x4a, 0x49, 0x2c, 0xce, 0x48, 0x2d, 0x12, 0x72, 0xe0, 0x62, 0xf7, 0x4d, 0xcc, 0x4e, 0x05, 0xd9, 0x2b, 0xa5, 0x87, 0xcd, 0x55, 0x7a, 0x20, 0xd3, 0xa4, 0x24, 0xb1, 0xcb, 0x79, 0x24, 0x96, 0x38, 0x71, 0x45, 0x71, 0xe8, 0x43, 0xf9, 0x49, 0x6c, 0x60, 0xef, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x02, 0x7a, 0x15, 0x14, 0xef, 0x00, 0x00, 0x00, } ================================================ FILE: hooks/statsd/statsd.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 statsd import ( "context" "strings" "time" "github.com/twitchtv/twirp" ) var reqStartTimestampKey = new(int) func markReqStart(ctx context.Context) context.Context { return context.WithValue(ctx, reqStartTimestampKey, time.Now()) } func getReqStart(ctx context.Context) (time.Time, bool) { t, ok := ctx.Value(reqStartTimestampKey).(time.Time) return t, ok } type Statter interface { Inc(metric string, val int64, rate float32) error TimingDuration(metric string, val time.Duration, rate float32) error } // NewStatsdServerHooks provides a twirp.ServerHooks struct which // sends data to statsd. func NewStatsdServerHooks(stats Statter) *twirp.ServerHooks { hooks := &twirp.ServerHooks{} // RequestReceived: inc twirp.total.req_recv hooks.RequestReceived = func(ctx context.Context) (context.Context, error) { ctx = markReqStart(ctx) stats.Inc("twirp.total.requests", 1, 1.0) return ctx, nil } // RequestRouted: inc twirp..req_recv hooks.RequestRouted = func(ctx context.Context) (context.Context, error) { method, ok := twirp.MethodName(ctx) if !ok { return ctx, nil } stats.Inc("twirp."+sanitize(method)+".requests", 1, 1.0) return ctx, nil } // ResponseSent: // - inc twirp.total.responses // - inc twirp..responses // - inc twirp.status_codes.total. // - inc twirp.status_codes.. // - time twirp.all_methods.response // - time twirp..response // - time twirp.status_codes.all_methods. // - time twirp.status_codes.. hooks.ResponseSent = func(ctx context.Context) { // Three pieces of data to get, none are guaranteed to be present: // - time that the request started // - method that was called // - status code of response var ( start time.Time method string status string haveStart bool haveMethod bool haveStatus bool ) start, haveStart = getReqStart(ctx) method, haveMethod = twirp.MethodName(ctx) status, haveStatus = twirp.StatusCode(ctx) method = sanitize(method) status = sanitize(status) stats.Inc("twirp.total.responses", 1, 1.0) if haveMethod { stats.Inc("twirp."+method+".responses", 1, 1.0) } if haveStatus { stats.Inc("twirp.status_codes.total."+status, 1, 1.0) } if haveMethod && haveStatus { stats.Inc("twirp.status_codes."+method+"."+status, 1, 1.0) } if haveStart { dur := time.Now().Sub(start) stats.TimingDuration("twirp.all_methods.response", dur, 1.0) if haveMethod { stats.TimingDuration("twirp."+method+".response", dur, 1.0) } if haveStatus { stats.TimingDuration("twirp.status_codes.all_methods."+status, dur, 1.0) } if haveMethod && haveStatus { stats.TimingDuration("twirp.status_codes."+method+"."+status, dur, 1.0) } } } return hooks } func sanitize(s string) string { return strings.Map(sanitizeRune, s) } func sanitizeRune(r rune) rune { switch { case 'a' <= r && r <= 'z': return r case '0' <= r && r <= '9': return r case 'A' <= r && r <= 'Z': return r default: return '_' } } ================================================ FILE: hooks/statsd/statsd_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 statsd import ( "context" "net/http/httptest" "testing" "time" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/internal/twirptest" ) func TestSanitize(t *testing.T) { type test struct { in string want string } cases := []test{ {"", ""}, {"SomeString", "SomeString"}, {"with whitespace", "with_whitespace"}, {"with.punctuation", "with_punctuation"}, {"with世界unicode", "with__unicode"}, {"with123numbers", "with123numbers"}, } for _, c := range cases { have := sanitize(c.in) if have != c.want { t.Errorf("in=%q have=%q want=%q", c.in, have, c.want) } } } func TestTimingHooks(t *testing.T) { statter := &fakeStatter{} hooks := NewStatsdServerHooks(statter) server, client := serverAndClient(hooks) defer server.Close() _, err := client.MakeHat(context.Background(), &twirptest.Size{}) if err != nil { t.Fatalf("twirptest Client err=%q", err) } expectedIncrements := []string{ "twirp.total.requests", "twirp.MakeHat.requests", "twirp.total.responses", "twirp.MakeHat.responses", "twirp.status_codes.total.200", "twirp.status_codes.MakeHat.200", } for _, inc := range expectedIncrements { if !statter.receivedInc(inc) { t.Errorf("statter did not receive increment %q", inc) } } expectedTimers := []string{ "twirp.all_methods.response", "twirp.MakeHat.response", "twirp.status_codes.all_methods.200", "twirp.status_codes.MakeHat.200", } for _, tim := range expectedTimers { if !statter.receivedTiming(tim) { t.Errorf("statter did not receive timing %q", tim) } } } func serverAndClient(hooks *twirp.ServerHooks) (*httptest.Server, twirptest.Haberdasher) { return twirptest.ServerAndClient(twirptest.NoopHatmaker(), hooks) } type increment struct { metric string val int64 rate float32 } type timing struct { metric string val time.Duration rate float32 } type fakeStatter struct { incs []increment times []timing } func (s *fakeStatter) Inc(metric string, val int64, rate float32) error { s.incs = append(s.incs, increment{metric, val, rate}) return nil } func (s *fakeStatter) TimingDuration(metric string, val time.Duration, rate float32) error { s.times = append(s.times, timing{metric, val, rate}) return nil } func (s *fakeStatter) receivedInc(metric string) bool { for _, i := range s.incs { if i.metric == metric { return true } } return false } func (s *fakeStatter) receivedTiming(metric string) bool { for _, t := range s.times { if t.metric == metric { return true } } return false } ================================================ FILE: interceptors.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" ) // Interceptor is a form of middleware for Twirp requests, that can be installed on both // clients and servers. To intercept RPC calls in the client, use the option // `twirp.WithClientInterceptors` on the client constructor. To intercept RPC calls in the server, // use the option `twirp.WithServerInterceptors` on the server constructor. // // Just like http middleware, interceptors can mutate requests and responses. // This can enable some powerful integrations, but it should be used with much care // because it may result in code that is very hard to debug. // // Example of an interceptor that logs every request and response: // // func LogInterceptor(l *log.Logger) twirp.Interceptor { // return func(next twirp.Method) twirp.Method { // return func(ctx context.Context, req interface{}) (interface{}, error) { // l.Printf("Service: %s, Method: %s, Request: %v", // twirp.ServiceName(ctx), twirp.MethodName(ctx), req) // resp, err := next(ctx, req) // l.Printf("Response: %v, Error: %v", resp) // return resp, err // } // } // } // type Interceptor func(Method) Method // Method is a generic representation of a Twirp-generated RPC method. // It is used to define Interceptors. type Method func(ctx context.Context, request interface{}) (interface{}, error) // ChainInterceptors chains multiple Interceptors into a single Interceptor. // The first interceptor wraps the second one, and so on. // Returns nil if interceptors is empty. Nil interceptors are ignored. func ChainInterceptors(interceptors ...Interceptor) Interceptor { filtered := make([]Interceptor, 0, len(interceptors)) for _, interceptor := range interceptors { if interceptor != nil { filtered = append(filtered, interceptor) } } switch n := len(filtered); n { case 0: return nil case 1: return filtered[0] default: first := filtered[0] return func(next Method) Method { for i := len(filtered) - 1; i > 0; i-- { next = filtered[i](next) } return first(next) } } } ================================================ FILE: interceptors_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "testing" ) func TestChainInterceptors(t *testing.T) { if chain := ChainInterceptors(); chain != nil { t.Errorf("ChainInterceptors(0) expected to be nil, but was %v", chain) } if chain := ChainInterceptors(nil); chain != nil { t.Errorf("ChainInterceptors(0) expected to be nil, but was %v", chain) } if chain := ChainInterceptors(nil, nil); chain != nil { t.Errorf("ChainInterceptors(0) expected to be nil, but was %v", chain) } interceptor1 := func(next Method) Method { return func(ctx context.Context, request interface{}) (interface{}, error) { response, err := next(ctx, request.(string)+"a") return response.(string) + "1", err } } interceptor2 := func(next Method) Method { return func(ctx context.Context, request interface{}) (interface{}, error) { response, err := next(ctx, request.(string)+"b") return response.(string) + "2", err } } interceptor3 := func(next Method) Method { return func(ctx context.Context, request interface{}) (interface{}, error) { response, err := next(ctx, request.(string)+"c") return response.(string) + "3", err } } method := func(ctx context.Context, request interface{}) (interface{}, error) { return request.(string) + "x", nil } for _, testCase := range []struct { interceptors []Interceptor want string }{ { interceptors: []Interceptor{interceptor1}, want: "ax1", }, { interceptors: []Interceptor{interceptor1, interceptor2}, want: "abx21", }, { interceptors: []Interceptor{interceptor1, interceptor2, interceptor3}, want: "abcx321", }, { interceptors: []Interceptor{interceptor1, interceptor2, nil, interceptor3}, want: "abcx321", }, { interceptors: []Interceptor{interceptor1, interceptor1, interceptor1}, want: "aaax111", }, } { response, err := ChainInterceptors(testCase.interceptors...)(method)(context.Background(), "") if err != nil { t.Fatalf("ChainInterceptors(%d) method has unexpected err %v", len(testCase.interceptors), err) } if response != testCase.want { t.Errorf("ChainInterceptors(%d) has unexpected value, have=%v, want=%v", len(testCase.interceptors), response, testCase.want) } } } ================================================ FILE: internal/contextkeys/keys.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 contextkeys stores the keys to the context accessor // functions, letting generated code safely set values in contexts // without exposing the setters to the outside world. package contextkeys type contextKey int const ( MethodNameKey contextKey = 1 + iota ServiceNameKey PackageNameKey StatusCodeKey RequestHeaderKey ResponseWriterKey ) ================================================ FILE: internal/descriptors/descriptors.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 descriptors provides tools for manipulating and inspecting protobuf // descriptors. package descriptors import ( "bytes" "compress/gzip" "io" "google.golang.org/protobuf/proto" protobuf "google.golang.org/protobuf/types/descriptorpb" "github.com/pkg/errors" ) // UnpackFile reads gz as a gzipped, protobuf-encoded FileDescriptorProto. This // is the format used to store descriptors in protoc-gen-go and // protoc-gen-twirp. func UnpackFile(gz []byte) (*protobuf.FileDescriptorProto, error) { r, err := gzip.NewReader(bytes.NewReader(gz)) if err != nil { return nil, errors.Wrap(err, "failed to open gzip reader") } defer r.Close() b, err := io.ReadAll(r) if err != nil { return nil, errors.Wrap(err, "failed to uncompress descriptor") } fd := new(protobuf.FileDescriptorProto) if err := proto.Unmarshal(b, fd); err != nil { return nil, errors.Wrap(err, "malformed FileDescriptorProto") } return fd, nil } // A DescribableMessage provides a gzipped, protobuf-encoded // FileDescriptorProto, and a series of ints which index into the File to // provide the address of a DescriptorProto describing a message. // // This interface should be fulfilled by any message structs generated by // protoc-gen-go. type DescribableMessage interface { Descriptor() ([]byte, []int) } // MessageDescriptor returns the DescriptorProto describing a message value, and // the FileDescriptorProto in which the message is defined. func MessageDescriptor(msg DescribableMessage) (*protobuf.FileDescriptorProto, *protobuf.DescriptorProto, error) { gz, path := msg.Descriptor() fd, err := UnpackFile(gz) if err != nil { return nil, nil, errors.Wrap(err, "unable to unpack gzipped descriptor") } d, err := MessageInFile(fd, path) if err != nil { return nil, nil, errors.Wrap(err, "unable to find message") } return fd, d, nil } // MessageInFile finds a message in fd using the given path as an address. func MessageInFile(fd *protobuf.FileDescriptorProto, path []int) (*protobuf.DescriptorProto, error) { if path[0] > len(fd.MessageType) { return nil, errors.Errorf("message index %d out of bounds on file", path[0]) } d := fd.MessageType[path[0]] for _, i := range path[1:] { if i < 0 || i > len(d.NestedType) { return nil, errors.Errorf("nested message index %d out of bounds on type %q", i, d.GetName()) } d = d.NestedType[i] } return d, nil } // A DescribableEnum provides a gzipped, protobuf-encoded FileDescriptorProto, // and a series of ints which index into the File to provide the address of an // EnumDescriptorProto describing an enum. // // This interface should be fulfilled by any enums generated by protoc-gen-go. type DescribableEnum interface { EnumDescriptor() ([]byte, []int) } // EnumDescriptor returns the EnumDescriptorProto describing an enum value, and // the FileDescriptorProto in which the enum is defined. func EnumDescriptor(enum DescribableEnum) (*protobuf.FileDescriptorProto, *protobuf.EnumDescriptorProto, error) { gz, path := enum.EnumDescriptor() fd, err := UnpackFile(gz) if err != nil { return nil, nil, errors.Wrap(err, "unable to unpack gzipped descriptor") } ed, err := EnumInFile(fd, path) if err != nil { return nil, nil, errors.Wrap(err, "unable to find enum") } return fd, ed, nil } // EnumInFile uses the given path to find an enum in the given file. func EnumInFile(fd *protobuf.FileDescriptorProto, path []int) (*protobuf.EnumDescriptorProto, error) { if len(path) == 1 { // This is an enum declared at the top level of a file. if path[0] < 0 || path[0] > len(fd.EnumType) { return nil, errors.Errorf("enum index %d out of bounds on file", path[0]) } return fd.EnumType[path[0]], nil } // This is an enum declared inside a message. We need to find the message, and // then the enum within it. // // The last element of the path will be the index of the enum inside a message // descriptor's EnumType slice. Everything before that indexes us through // messages. msgPath := path[0 : len(path)-1] md, err := MessageInFile(fd, msgPath) if err != nil { return nil, errors.Wrap(err, "unable to find enum inside message") } enumIdx := path[len(path)-1] if enumIdx < 0 || enumIdx > len(md.EnumType) { return nil, errors.Errorf("enum index %d out of bounds on message type %q", enumIdx, md.GetName()) } return md.EnumType[enumIdx], nil } // A DescribableService provides a gzipped, protobuf-encoded // FileDescriptorProto, and an int which indexes into the File to provide the // address of a ServiceDescriptorProto describing a service. // // This interface should be fulfilled by any servers generated by // protoc-gen-twirp. type DescribableService interface { ServiceDescriptor() ([]byte, int) } // ServiceDescriptor returns the ServiceDescriptorProto describing a service // value, and the FileDescriptorProto in which the service is defined. func ServiceDescriptor(svc DescribableService) (*protobuf.FileDescriptorProto, *protobuf.ServiceDescriptorProto, error) { gz, idx := svc.ServiceDescriptor() fd, err := UnpackFile(gz) if err != nil { return nil, nil, errors.Wrap(err, "unable to unpack gzipped descriptor") } sd, err := ServiceInFile(fd, idx) if err != nil { return nil, nil, errors.Wrap(err, "unable to find service") } return fd, sd, nil } // ServiceInFile uses the given index to find the service within the given // FileDescriptorProto. func ServiceInFile(fd *protobuf.FileDescriptorProto, index int) (*protobuf.ServiceDescriptorProto, error) { if index > len(fd.Service) { return nil, errors.Errorf("service index %d out of bounds on file", index) } return fd.Service[index], nil } ================================================ FILE: internal/gen/logging.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 gen import ( "log" "os" "strings" ) func Fail(msgs ...string) { s := strings.Join(msgs, " ") log.Print("error:", s) os.Exit(1) } func Error(err error, msgs ...string) { s := strings.Join(msgs, " ") + ":" + err.Error() log.Print("error:", s) os.Exit(1) } ================================================ FILE: internal/gen/main.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 gen import ( "io" "os" "google.golang.org/protobuf/proto" descriptor "google.golang.org/protobuf/types/descriptorpb" plugin "google.golang.org/protobuf/types/pluginpb" ) type Generator interface { Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse } func Main(g Generator) { req := readGenRequest(os.Stdin) resp := g.Generate(req) writeResponse(os.Stdout, resp) } func FilesToGenerate(req *plugin.CodeGeneratorRequest) []*descriptor.FileDescriptorProto { genFiles := make([]*descriptor.FileDescriptorProto, 0) Outer: for _, name := range req.FileToGenerate { for _, f := range req.ProtoFile { if f.GetName() == name { genFiles = append(genFiles, f) continue Outer } } Fail("could not find file named", name) } return genFiles } func readGenRequest(r io.Reader) *plugin.CodeGeneratorRequest { data, err := io.ReadAll(r) if err != nil { Error(err, "reading input") } req := new(plugin.CodeGeneratorRequest) if err = proto.Unmarshal(data, req); err != nil { Error(err, "parsing input proto") } if len(req.FileToGenerate) == 0 { Fail("no files to generate") } return req } func writeResponse(w io.Writer, resp *plugin.CodeGeneratorResponse) { data, err := proto.Marshal(resp) if err != nil { Error(err, "marshaling response") } _, err = w.Write(data) if err != nil { Error(err, "writing response") } } ================================================ FILE: internal/gen/stringutils/stringutils.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file is distributed on // an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either // express or implied. See the License for the specific language governing // permissions and limitations under the License. package stringutils import ( "bytes" "fmt" "strings" "unicode" ) // Is c an ASCII lower-case letter? func isASCIILower(c byte) bool { return 'a' <= c && c <= 'z' } // Is c an ASCII digit? func isASCIIDigit(c byte) bool { return '0' <= c && c <= '9' } // CamelCase converts a string from snake_case to CamelCased. // // If there is an interior underscore followed by a lower case letter, drop the // underscore and convert the letter to upper case. There is a remote // possibility of this rewrite causing a name collision, but it's so remote // we're prepared to pretend it's nonexistent - since the C++ generator // lowercases names, it's extremely unlikely to have two fields with different // capitalizations. In short, _my_field_name_2 becomes XMyFieldName_2. func CamelCase(s string) string { if s == "" { return "" } t := make([]byte, 0, 32) i := 0 if s[0] == '_' { // Need a capital letter; drop the '_'. t = append(t, 'X') i++ } // Invariant: if the next letter is lower case, it must be converted // to upper case. // // That is, we process a word at a time, where words are marked by _ or upper // case letter. Digits are treated as words. for ; i < len(s); i++ { c := s[i] if c == '_' && i+1 < len(s) && isASCIILower(s[i+1]) { continue // Skip the underscore in s. } if isASCIIDigit(c) { t = append(t, c) continue } // Assume we have a letter now - if not, it's a bogus identifier. The next // word is a sequence of characters that must start upper case. if isASCIILower(c) { c ^= ' ' // Make it a capital letter. } t = append(t, c) // Guaranteed not lower case. // Accept lower case sequence that follows. for i+1 < len(s) && isASCIILower(s[i+1]) { i++ t = append(t, s[i]) } } return string(t) } // CamelCaseSlice is like CamelCase, but the argument is a slice of strings to // be joined with "_" and then camelcased. func CamelCaseSlice(elem []string) string { return CamelCase(strings.Join(elem, "_")) } // DotJoin joins a slice of strings with '.' func DotJoin(elem []string) string { return strings.Join(elem, ".") } // AlphaDigitize replaces non-letter, non-digit, non-underscore characters with // underscore. func AlphaDigitize(r rune) rune { if unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_' { return r } return '_' } // CleanIdentifier makes sure s is a valid 'identifier' string: it contains only // letters, numbers, and underscore. func CleanIdentifier(s string) string { return strings.Map(AlphaDigitize, s) } // BaseName the last path element of a slash-delimited name, with the last // dotted suffix removed. func BaseName(name string) string { // First, find the last element if i := strings.LastIndex(name, "/"); i >= 0 { name = name[i+1:] } // Now drop the suffix if i := strings.LastIndex(name, "."); i >= 0 { name = name[0:i] } return name } // SnakeCase converts a string from CamelCase to snake_case. func SnakeCase(s string) string { var buf bytes.Buffer for i, r := range s { if unicode.IsUpper(r) && i > 0 { fmt.Fprintf(&buf, "_") } r = unicode.ToLower(r) fmt.Fprintf(&buf, "%c", r) } return buf.String() } ================================================ FILE: internal/gen/typemap/testdata/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 testdata //go:generate protoc --descriptor_set_out=fileset.pb --include_imports --include_source_info ./service.proto ================================================ FILE: internal/gen/typemap/testdata/importer.proto ================================================ syntax = "proto3"; package twirp.internal.gen.typemap.testdata.importer; import "root_pkg.proto"; message ImporterMsg { root_pkg.RootMsg a = 1; message ImporterInner {} } ================================================ FILE: internal/gen/typemap/testdata/public_importer.proto ================================================ syntax = "proto3"; package twirp.internal.gen.typemap.testdata.public_importer; import public "root_pkg.proto"; import public "importer.proto"; message PublicImporterMsgA { importer.ImporterMsg a = 1; } message PublicImporterMsgB { root_pkg.RootMsg a = 1; } ================================================ FILE: internal/gen/typemap/testdata/public_reimporter.proto ================================================ syntax = "proto3"; package twirp.internal.gen.typemap.testdata.public_reimporter; import public "public_importer.proto"; message PublicReimporterMsg { public_importer.PublicImporterMsgA a = 1; public_importer.PublicImporterMsgB b = 2; root_pkg.RootMsg c = 3; importer.ImporterMsg d = 4; } ================================================ FILE: internal/gen/typemap/testdata/root_pkg.proto ================================================ syntax = "proto3"; package twirp.internal.gen.typemap.testdata.root_pkg; // RootMsg leading message RootMsg {} ================================================ FILE: internal/gen/typemap/testdata/service.proto ================================================ syntax = "proto3"; package twirp.internal.gen.typemap.testdata.public_reimporter; import public "public_reimporter.proto"; message ServiceMsg { public_importer.PublicImporterMsgA a = 1; public_importer.PublicImporterMsgB b = 2; root_pkg.RootMsg c = 3; importer.ImporterMsg d = 4; } message Parent { message NestedOuter{ message NestedInner{} } } service EmptyService {} service ServiceWithOneMethod{ // Method1 leading rpc Method1(root_pkg.RootMsg) returns (importer.ImporterMsg); // Method1 trailing } // ServiceWithManyMethods leading service ServiceWithManyMethods{ // Method1 leading rpc Method1(root_pkg.RootMsg) returns (importer.ImporterMsg); // Method2 leading rpc Method2(Parent) returns (Parent.NestedOuter); // Method2 trailing rpc Method3(importer.ImporterMsg.ImporterInner) returns (Parent.NestedOuter.NestedInner); } ================================================ FILE: internal/gen/typemap/typemap.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 typemap import ( "github.com/pkg/errors" descriptor "google.golang.org/protobuf/types/descriptorpb" ) type Registry struct { allFiles []*descriptor.FileDescriptorProto filesByName map[string]*descriptor.FileDescriptorProto // Mapping of fully-qualified names to their definitions messagesByProtoName map[string]*MessageDefinition } func New(files []*descriptor.FileDescriptorProto) *Registry { r := &Registry{ allFiles: files, filesByName: make(map[string]*descriptor.FileDescriptorProto), messagesByProtoName: make(map[string]*MessageDefinition), } // First, index the file descriptors by name. We need this so // messageDefsForFile can correctly scan imports. for _, f := range files { r.filesByName[f.GetName()] = f } // Next, index all the message definitions by their fully-qualified proto // names. for _, f := range files { defs := messageDefsForFile(f, r.filesByName) for name, def := range defs { r.messagesByProtoName[name] = def } } return r } func (r *Registry) FileComments(file *descriptor.FileDescriptorProto) (DefinitionComments, error) { return commentsAtPath([]int32{packagePath}, file), nil } func (r *Registry) ServiceComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto) (DefinitionComments, error) { for i, s := range file.Service { if s == svc { path := []int32{servicePath, int32(i)} return commentsAtPath(path, file), nil } } return DefinitionComments{}, errors.Errorf("service not found in file") } func (r *Registry) MethodComments(file *descriptor.FileDescriptorProto, svc *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) (DefinitionComments, error) { for i, s := range file.Service { if s == svc { path := []int32{servicePath, int32(i)} for j, m := range s.Method { if m == method { path = append(path, serviceMethodPath, int32(j)) return commentsAtPath(path, file), nil } } } } return DefinitionComments{}, errors.Errorf("service not found in file") } func (r *Registry) MethodInputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition { return r.messagesByProtoName[method.GetInputType()] } func (r *Registry) MethodOutputDefinition(method *descriptor.MethodDescriptorProto) *MessageDefinition { return r.messagesByProtoName[method.GetOutputType()] } func (r *Registry) MessageDefinition(name string) *MessageDefinition { return r.messagesByProtoName[name] } type MessageDefinition struct { // Descriptor is is the DescriptorProto defining the message. Descriptor *descriptor.DescriptorProto // File is the File that the message was defined in. Or, if it has been // publicly imported, what File was that import performed in? File *descriptor.FileDescriptorProto // Parent is the parent message, if this was defined as a nested message. If // this was defined at the top level, parent is nil. Parent *MessageDefinition // Comments describes the comments surrounding a message's definition. If it // was publicly imported, then these comments are from the actual source file, // not the file that the import was performed in. Comments DefinitionComments // path is the 'SourceCodeInfo' path. See the documentation for // google.golang.org/protobuf/types/descriptorpb.SourceCodeInfo for an // explanation of its format. path []int32 } // ProtoName returns the dot-delimited, fully-qualified protobuf name of the // message. func (m *MessageDefinition) ProtoName() string { prefix := "." if pkg := m.File.GetPackage(); pkg != "" { prefix += pkg + "." } if lineage := m.Lineage(); len(lineage) > 0 { for _, parent := range lineage { prefix += parent.Descriptor.GetName() + "." } } return prefix + m.Descriptor.GetName() } // Lineage returns m's parental chain all the way back up to a top-level message // definition. The first element of the returned slice is the highest-level // parent. func (m *MessageDefinition) Lineage() []*MessageDefinition { var parents []*MessageDefinition for p := m.Parent; p != nil; p = p.Parent { parents = append([]*MessageDefinition{p}, parents...) } return parents } // descendants returns all the submessages defined within m, and all the // descendants of those, recursively. func (m *MessageDefinition) descendants() []*MessageDefinition { descendants := make([]*MessageDefinition, 0) for i, child := range m.Descriptor.NestedType { path := append(m.path, []int32{messageMessagePath, int32(i)}...) childDef := &MessageDefinition{ Descriptor: child, File: m.File, Parent: m, Comments: commentsAtPath(path, m.File), path: path, } descendants = append(descendants, childDef) descendants = append(descendants, childDef.descendants()...) } return descendants } // messageDefsForFile gathers a mapping of fully-qualified protobuf names to // their definitions. It scans a singles file at a time. It requires a mapping // of .proto file names to their definitions in order to correctly handle // 'import public' declarations; this mapping should include all files // transitively imported by f. func messageDefsForFile(f *descriptor.FileDescriptorProto, filesByName map[string]*descriptor.FileDescriptorProto) map[string]*MessageDefinition { byProtoName := make(map[string]*MessageDefinition) // First, gather all the messages defined at the top level. for i, d := range f.MessageType { path := []int32{messagePath, int32(i)} def := &MessageDefinition{ Descriptor: d, File: f, Parent: nil, Comments: commentsAtPath(path, f), path: path, } byProtoName[def.ProtoName()] = def // Next, all nested message definitions. for _, child := range def.descendants() { byProtoName[child.ProtoName()] = child } } // Finally, all messages imported publicly. for _, depIdx := range f.PublicDependency { depFileName := f.Dependency[depIdx] depFile := filesByName[depFileName] depDefs := messageDefsForFile(depFile, filesByName) for _, def := range depDefs { imported := &MessageDefinition{ Descriptor: def.Descriptor, File: f, Parent: def.Parent, Comments: commentsAtPath(def.path, depFile), path: def.path, } byProtoName[imported.ProtoName()] = imported } } return byProtoName } // DefinitionComments contains the comments surrounding a definition in a // protobuf file. // // These follow the rules described by protobuf: // // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // // leading_detached_comments will keep paragraphs of comments that appear // before (but not connected to) the current element. Each paragraph, // separated by empty lines, will be one comment element in the repeated // field. // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. // Newlines are included in the output. // // Examples: // // optional int32 foo = 1; // Comment attached to foo. // // Comment attached to bar. // optional int32 bar = 2; // // optional string baz = 3; // // Comment attached to baz. // // Another line attached to baz. // // // Comment attached to qux. // // // // Another line attached to qux. // optional double qux = 4; // // // Detached comment for corge. This is not leading or trailing comments // // to qux or corge because there are blank lines separating it from // // both. // // // Detached comment for corge paragraph 2. // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks // * will be removed. */ // /* Block comment attached to // * grault. */ // optional int32 grault = 6; // // // ignored detached comments. type DefinitionComments struct { Leading string Trailing string LeadingDetached []string } func commentsAtPath(path []int32, sourceFile *descriptor.FileDescriptorProto) DefinitionComments { if sourceFile.SourceCodeInfo == nil { // The compiler didn't provide us with comments. return DefinitionComments{} } for _, loc := range sourceFile.SourceCodeInfo.Location { if pathEqual(path, loc.Path) { return DefinitionComments{ Leading: loc.GetLeadingComments(), LeadingDetached: loc.GetLeadingDetachedComments(), Trailing: loc.GetTrailingComments(), } } } return DefinitionComments{} } func pathEqual(path1, path2 []int32) bool { if len(path1) != len(path2) { return false } for i, v := range path1 { if path2[i] != v { return false } } return true } const ( // tag numbers in FileDescriptorProto packagePath = 2 // package messagePath = 4 // message_type enumPath = 5 // enum_type servicePath = 6 // service // tag numbers in DescriptorProto messageFieldPath = 2 // field messageMessagePath = 3 // nested_type messageEnumPath = 4 // enum_type messageOneofPath = 8 // oneof_decl // tag numbers in ServiceDescriptorProto serviceNamePath = 1 // name serviceMethodPath = 2 // method serviceOptionsPath = 3 // options // tag numbers in MethodDescriptorProto methodNamePath = 1 // name methodInputPath = 2 // input_type methodOutputPath = 3 // output_type ) ================================================ FILE: internal/gen/typemap/typemap_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 typemap import ( "os" "path/filepath" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "google.golang.org/protobuf/proto" descriptor "google.golang.org/protobuf/types/descriptorpb" ) func loadTestPb(t *testing.T) []*descriptor.FileDescriptorProto { f, err := os.ReadFile(filepath.Join("testdata", "fileset.pb")) require.NoError(t, err, "unable to read testdata protobuf file") set := new(descriptor.FileDescriptorSet) err = proto.Unmarshal(f, set) require.NoError(t, err, "unable to unmarshal testdata protobuf file") return set.File } func protoFile(files []*descriptor.FileDescriptorProto, name string) *descriptor.FileDescriptorProto { for _, f := range files { if filepath.Base(f.GetName()) == name { return f } } return nil } func service(f *descriptor.FileDescriptorProto, name string) *descriptor.ServiceDescriptorProto { for _, s := range f.Service { if s.GetName() == name { return s } } return nil } func method(s *descriptor.ServiceDescriptorProto, name string) *descriptor.MethodDescriptorProto { for _, m := range s.Method { if m.GetName() == name { return m } } return nil } func TestNewRegistry(t *testing.T) { files := loadTestPb(t) file := protoFile(files, "service.proto") service := service(file, "ServiceWithManyMethods") reg := New(files) comments, err := reg.ServiceComments(file, service) require.NoError(t, err, "unable to load service comments") assert.Equal(t, " ServiceWithManyMethods leading\n", comments.Leading) method1 := method(service, "Method1") require.NotNil(t, method1) method1Input := reg.MethodInputDefinition(method1) require.NotNil(t, method1Input) assert.Equal(t, "RootMsg", method1Input.Descriptor.GetName()) } ================================================ FILE: internal/gen/version.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 gen const Version = "v8.1.3" ================================================ FILE: internal/gen/wrappers.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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. // // // This file contains some code from https://github.com/protocolbuffers/protobuf-go: // Copyright 2010 The Go Authors. All rights reserved. // https://github.com/protocolbuffers/protobuf-go // // 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 gen import ( "fmt" "log" "path" "strconv" "strings" descriptor "google.golang.org/protobuf/types/descriptorpb" plugin "google.golang.org/protobuf/types/pluginpb" "github.com/twitchtv/twirp/internal/gen/stringutils" ) // Each type we import as a protocol buffer (other than FileDescriptorProto) needs // a pointer to the FileDescriptorProto that represents it. These types achieve that // wrapping by placing each Proto inside a struct with the pointer to its File. The // structs have the same names as their contents, with "Proto" removed. // FileDescriptor is used to store the things that it points to. // WrapTypes walks the incoming data, wrapping DescriptorProtos, EnumDescriptorProtos // and FileDescriptorProtos into file-referenced objects within the Generator. // It also creates the list of files to generate and so should be called before GenerateAllFiles. func WrapTypes(req *plugin.CodeGeneratorRequest) (genFiles, allFiles []*FileDescriptor, allFilesByName map[string]*FileDescriptor) { allFiles = make([]*FileDescriptor, 0, len(req.ProtoFile)) allFilesByName = make(map[string]*FileDescriptor, len(allFiles)) for _, f := range req.ProtoFile { // We must wrap the descriptors before we wrap the enums descs := wrapDescriptors(f) buildNestedDescriptors(descs) enums := wrapEnumDescriptors(f, descs) buildNestedEnums(descs, enums) exts := wrapExtensions(f) svcs := wrapServices(f) fd := &FileDescriptor{ FileDescriptorProto: f, Services: svcs, Descriptors: descs, Enums: enums, Extensions: exts, proto3: fileIsProto3(f), } extractComments(fd) allFiles = append(allFiles, fd) allFilesByName[f.GetName()] = fd } for _, fd := range allFiles { fd.Imported = wrapImported(fd.FileDescriptorProto, allFilesByName) } genFiles = make([]*FileDescriptor, 0, len(req.FileToGenerate)) for _, fileName := range req.FileToGenerate { fd := allFilesByName[fileName] if fd == nil { Fail("could not find file named", fileName) } fd.Index = len(genFiles) genFiles = append(genFiles, fd) } return genFiles, allFiles, allFilesByName } // The file and package name method are common to messages and enums. type common struct { file *descriptor.FileDescriptorProto // File this object comes from. } func (c *common) File() *descriptor.FileDescriptorProto { return c.file } func fileIsProto3(file *descriptor.FileDescriptorProto) bool { return file.GetSyntax() == "proto3" } func (c *common) proto3() bool { return fileIsProto3(c.file) } // Descriptor represents a protocol buffer message. type Descriptor struct { common *descriptor.DescriptorProto Parent *Descriptor // The containing message, if any. nested []*Descriptor // Inner messages, if any. enums []*EnumDescriptor // Inner enums, if any. ext []*ExtensionDescriptor // Extensions, if any. typename []string // Cached typename vector. index int // The index into the container, whether the file or another message. path string // The SourceCodeInfo path as comma-separated integers. group bool } func newDescriptor(desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *Descriptor { d := &Descriptor{ common: common{file}, DescriptorProto: desc, Parent: parent, index: index, } if parent == nil { d.path = fmt.Sprintf("%d,%d", messagePath, index) } else { d.path = fmt.Sprintf("%s,%d,%d", parent.path, messageMessagePath, index) } // The only way to distinguish a group from a message is whether // the containing message has a TYPE_GROUP field that matches. if parent != nil { parts := d.TypeName() if file.Package != nil { parts = append([]string{*file.Package}, parts...) } exp := "." + strings.Join(parts, ".") for _, field := range parent.Field { if field.GetType() == descriptor.FieldDescriptorProto_TYPE_GROUP && field.GetTypeName() == exp { d.group = true break } } } for _, field := range desc.Extension { d.ext = append(d.ext, &ExtensionDescriptor{common{file}, field, d}) } return d } // Return a slice of all the Descriptors defined within this file func wrapDescriptors(file *descriptor.FileDescriptorProto) []*Descriptor { sl := make([]*Descriptor, 0, len(file.MessageType)+10) for i, desc := range file.MessageType { sl = wrapThisDescriptor(sl, desc, nil, file, i) } return sl } // Wrap this Descriptor, recursively func wrapThisDescriptor(sl []*Descriptor, desc *descriptor.DescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) []*Descriptor { sl = append(sl, newDescriptor(desc, parent, file, index)) me := sl[len(sl)-1] for i, nested := range desc.NestedType { sl = wrapThisDescriptor(sl, nested, me, file, i) } return sl } func buildNestedDescriptors(descs []*Descriptor) { for _, desc := range descs { if len(desc.NestedType) != 0 { for _, nest := range descs { if nest.Parent == desc { desc.nested = append(desc.nested, nest) } } if len(desc.nested) != len(desc.NestedType) { Fail("internal error: nesting failure for", desc.GetName()) } } } } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (d *Descriptor) TypeName() []string { if d.typename != nil { return d.typename } n := 0 for parent := d; parent != nil; parent = parent.Parent { n++ } s := make([]string, n, n) for parent := d; parent != nil; parent = parent.Parent { n-- s[n] = parent.GetName() } d.typename = s return s } // EnumDescriptor describes an enum. If it's at top level, its parent will be nil. // Otherwise it will be the descriptor of the message in which it is defined. type EnumDescriptor struct { common *descriptor.EnumDescriptorProto parent *Descriptor // The containing message, if any. typename []string // Cached typename vector. index int // The index into the container, whether the file or a message. path string // The SourceCodeInfo path as comma-separated integers. } // Construct a new EnumDescriptor func newEnumDescriptor(desc *descriptor.EnumDescriptorProto, parent *Descriptor, file *descriptor.FileDescriptorProto, index int) *EnumDescriptor { ed := &EnumDescriptor{ common: common{file}, EnumDescriptorProto: desc, parent: parent, index: index, } if parent == nil { ed.path = fmt.Sprintf("%d,%d", enumPath, index) } else { ed.path = fmt.Sprintf("%s,%d,%d", parent.path, messageEnumPath, index) } return ed } // Return a slice of all the EnumDescriptors defined within this file func wrapEnumDescriptors(file *descriptor.FileDescriptorProto, descs []*Descriptor) []*EnumDescriptor { sl := make([]*EnumDescriptor, 0, len(file.EnumType)+10) // Top-level enums. for i, enum := range file.EnumType { sl = append(sl, newEnumDescriptor(enum, nil, file, i)) } // Enums within messages. Enums within embedded messages appear in the outer-most message. for _, nested := range descs { for i, enum := range nested.EnumType { sl = append(sl, newEnumDescriptor(enum, nested, file, i)) } } return sl } func buildNestedEnums(descs []*Descriptor, enums []*EnumDescriptor) { for _, desc := range descs { if len(desc.EnumType) != 0 { for _, enum := range enums { if enum.parent == desc { desc.enums = append(desc.enums, enum) } } if len(desc.enums) != len(desc.EnumType) { Fail("internal error: enum nesting failure for", desc.GetName()) } } } } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (e *EnumDescriptor) TypeName() (s []string) { if e.typename != nil { return e.typename } name := e.GetName() if e.parent == nil { s = make([]string, 1) } else { pname := e.parent.TypeName() s = make([]string, len(pname)+1) copy(s, pname) } s[len(s)-1] = name e.typename = s return s } // Everything but the last element of the full type name, CamelCased. // The values of type Foo.Bar are call Foo_value1... not Foo_Bar_value1... . func (e *EnumDescriptor) prefix() string { if e.parent == nil { // If the enum is not part of a message, the prefix is just the type name. return stringutils.CamelCase(*e.Name) + "_" } typeName := e.TypeName() return stringutils.CamelCaseSlice(typeName[0:len(typeName)-1]) + "_" } // The integer value of the named constant in this enumerated type. func (e *EnumDescriptor) integerValueAsString(name string) string { for _, c := range e.Value { if c.GetName() == name { return fmt.Sprint(c.GetNumber()) } } log.Fatal("cannot find value for enum constant") return "" } // ExtensionDescriptor describes an extension. If it's at top level, its parent will be nil. // Otherwise it will be the descriptor of the message in which it is defined. type ExtensionDescriptor struct { common *descriptor.FieldDescriptorProto parent *Descriptor // The containing message, if any. } // Return a slice of all the top-level ExtensionDescriptors defined within this file. func wrapExtensions(file *descriptor.FileDescriptorProto) []*ExtensionDescriptor { var sl []*ExtensionDescriptor for _, field := range file.Extension { sl = append(sl, &ExtensionDescriptor{common{file}, field, nil}) } return sl } // TypeName returns the elements of the dotted type name. // The package name is not part of this name. func (e *ExtensionDescriptor) TypeName() (s []string) { name := e.GetName() if e.parent == nil { // top-level extension s = make([]string, 1) } else { pname := e.parent.TypeName() s = make([]string, len(pname)+1) copy(s, pname) } s[len(s)-1] = name return s } // DescName returns the variable name used for the generated descriptor. func (e *ExtensionDescriptor) DescName() string { // The full type name. typeName := e.TypeName() // Each scope of the extension is individually CamelCased, and all are joined with "_" with an "E_" prefix. for i, s := range typeName { typeName[i] = stringutils.CamelCase(s) } return "E_" + strings.Join(typeName, "_") } // ImportedDescriptor describes a type that has been publicly imported from another file. type ImportedDescriptor struct { common Object Object } // Return a slice of all the types that are publicly imported into this file. func wrapImported(file *descriptor.FileDescriptorProto, fileMap map[string]*FileDescriptor) (sl []*ImportedDescriptor) { for _, index := range file.PublicDependency { df := fileMap[file.Dependency[index]] for _, d := range df.Descriptors { if d.GetOptions().GetMapEntry() { continue } sl = append(sl, &ImportedDescriptor{common{file}, d}) } for _, e := range df.Enums { sl = append(sl, &ImportedDescriptor{common{file}, e}) } for _, ext := range df.Extensions { sl = append(sl, &ImportedDescriptor{common{file}, ext}) } } return } func (id *ImportedDescriptor) TypeName() []string { return id.Object.TypeName() } // ServiceDescriptor represents a protocol buffer service. type ServiceDescriptor struct { common *descriptor.ServiceDescriptorProto Methods []*MethodDescriptor Index int // index of the ServiceDescriptorProto in its parent FileDescriptorProto Path string // The SourceCodeInfo path as comma-separated integers. } func (sd *ServiceDescriptor) TypeName() []string { return []string{sd.GetName()} } func wrapServices(file *descriptor.FileDescriptorProto) (sl []*ServiceDescriptor) { for i, svc := range file.Service { sd := &ServiceDescriptor{ common: common{file}, ServiceDescriptorProto: svc, Index: i, Path: fmt.Sprintf("%d,%d", servicePath, i), } for j, method := range svc.Method { md := &MethodDescriptor{ common: common{file}, MethodDescriptorProto: method, service: sd, Path: fmt.Sprintf("%d,%d,%d,%d", servicePath, i, serviceMethodPath, j), } sd.Methods = append(sd.Methods, md) } sl = append(sl, sd) } return sl } // MethodDescriptor represents an RPC method on a protocol buffer // service. type MethodDescriptor struct { common *descriptor.MethodDescriptorProto service *ServiceDescriptor Path string // The SourceCodeInfo path as comma-separated integers. } func (md *MethodDescriptor) TypeName() []string { return []string{md.service.GetName(), md.GetName()} } // FileDescriptor describes an protocol buffer descriptor file (.proto). // It includes slices of all the messages and enums defined within it. // Those slices are constructed by WrapTypes. type FileDescriptor struct { *descriptor.FileDescriptorProto Descriptors []*Descriptor // All the messages defined in this file. Enums []*EnumDescriptor // All the enums defined in this file. Extensions []*ExtensionDescriptor // All the top-level extensions defined in this file. Imported []*ImportedDescriptor // All types defined in files publicly imported by this file. Services []*ServiceDescriptor // All the services defined in this file. // Comments, stored as a map of path (comma-separated integers) to the comment. Comments map[string]*descriptor.SourceCodeInfo_Location Index int // The index of this file in the list of files to generate code for proto3 bool // whether to generate proto3 code for this file } // VarName is the variable name used in generated code to refer to the // compressed bytes of this descriptor. It is not exported, so it is only valid // inside the generated package. // // protoc-gen-go writes its own version of this file, but so does // protoc-gen-gogo - with a different name! Twirp aims to be compatible with // both; the simplest way forward is to write the file descriptor again as // another variable that we control. func (d *FileDescriptor) VarName() string { return fmt.Sprintf("twirpFileDescriptor%d", d.Index) } func (d *FileDescriptor) PackageComments() string { if loc, ok := d.Comments[strconv.Itoa(packagePath)]; ok { text := strings.TrimSuffix(loc.GetLeadingComments(), "\n") return text } return "" } func (d *FileDescriptor) BaseFileName() string { name := *d.Name if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { name = name[:len(name)-len(ext)] } return name } func extractComments(file *FileDescriptor) { file.Comments = make(map[string]*descriptor.SourceCodeInfo_Location) for _, loc := range file.GetSourceCodeInfo().GetLocation() { if loc.LeadingComments == nil { continue } var p []string for _, n := range loc.Path { p = append(p, strconv.Itoa(int(n))) } file.Comments[strings.Join(p, ",")] = loc } } type messageSymbol struct { sym string hasExtensions, isMessageSet bool hasOneof bool getters []getterSymbol } type getterSymbol struct { name string typ string typeName string // canonical name in proto world; empty for proto.Message and similar genType bool // whether typ contains a generated type (message/group/enum) } // Object is an interface abstracting the abilities shared by enums, messages, extensions and imported objects. type Object interface { TypeName() []string File() *descriptor.FileDescriptorProto } // The SourceCodeInfo message describes the location of elements of a parsed // .proto file by way of a "path", which is a sequence of integers that // describe the route from a FileDescriptorProto to the relevant submessage. // The path alternates between a field number of a repeated field, and an index // into that repeated field. The constants below define the field numbers that // are used. // // See descriptor.proto for more information about this. const ( // tag numbers in FileDescriptorProto packagePath = 2 // package messagePath = 4 // message_type enumPath = 5 // enum_type servicePath = 6 // service // tag numbers in DescriptorProto messageFieldPath = 2 // field messageMessagePath = 3 // nested_type messageEnumPath = 4 // enum_type messageOneofPath = 8 // oneof_decl // tag numbers in ServiceDescriptorProto serviceNamePath = 1 // name serviceMethodPath = 2 // method serviceOptionsPath = 3 // options // tag numbers in MethodDescriptorProto methodNamePath = 1 // name methodInputPath = 2 // input_type methodOutputPath = 3 // output_type ) ================================================ FILE: internal/twirptest/client_1_13_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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. // +build go1.13 package twirptest import ( "context" "errors" "fmt" "net/http" "testing" "github.com/twitchtv/twirp" ) func TestClientContextCanceled(t *testing.T) { // Context that is already canceled. ctx, cancel := context.WithCancel(context.Background()) cancel() // Make request, should immediately fail because the context is canceled. protoCli := NewHaberdasherProtobufClient("", &http.Client{}) _, err := protoCli.MakeHat(ctx, &Size{}) // The failure is a twirp internal error twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error, have=%T", err) } if twerr.Code() != twirp.Internal { t.Fatalf("expected twirp.Error Code to be internal, have=%q", twerr.Code()) } // But the context.Canceled error can be identified easily with errors.Is if !errors.Is(err, context.Canceled) { t.Fatalf("expected errors.Is(err, context.Canceled) to match, but it didn't") } } func TestClientErrorsCanBeUnwrapped(t *testing.T) { rootErr := fmt.Errorf("some root cause") httpClient := &http.Client{ Transport: &failingTransport{rootErr}, } client := NewHaberdasherJSONClient("", httpClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Errorf("JSON MakeHat err is unexpectedly nil") } if !errors.Is(err, rootErr) { t.Fatalf("expected errors.Is(err, rootErr) to match, but it didn't") } } ================================================ FILE: internal/twirptest/client_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirptest import ( "context" "fmt" "net/http" "net/http/httptest" "net/url" "strconv" "strings" "testing" "github.com/pkg/errors" "github.com/twitchtv/twirp" ) // reqInspector is a tool to check inspect HTTP Requests as they pass // through an http.Client. It implements the http.RoundTripper // interface by calling its callback, and then using the default // RoundTripper. type reqInspector struct { callback func(*http.Request) } func (i *reqInspector) RoundTrip(r *http.Request) (*http.Response, error) { i.callback(r) return http.DefaultTransport.RoundTrip(r) } func TestClientSuccessAndErrorResponses(t *testing.T) { // Service that succeeds only if requested size is 1, otherwise errors h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() // Clients protoCli := NewHaberdasherProtobufClient(s.URL, &http.Client{}) jsonCli := NewHaberdasherJSONClient(s.URL, &http.Client{}) ctx := context.Background() var resp *Hat var err error // Test proto success resp, err = protoCli.MakeHat(ctx, &Size{Inches: 1}) if err != nil { t.Fatalf("Proto client method returned unexpected error: %s", err) } if resp == nil { t.Fatalf("Proto client method expected to return non-nil response, but it is nil") } // Test proto failure resp, err = protoCli.MakeHat(ctx, &Size{Inches: 666}) if err == nil { t.Fatalf("Proto client method expected to fail, but error is nil") } if resp != nil { t.Fatalf("Proto client method expected to return nil response on error, but returned non-nil") } // Test json success resp, err = jsonCli.MakeHat(ctx, &Size{Inches: 1}) if err != nil { t.Fatalf("JSON client method returned unexpected error: %s", err) } if resp == nil { t.Fatalf("JSON client method expected to return non-nil response, but it is nil") } // Test json failure resp, err = jsonCli.MakeHat(ctx, &Size{Inches: 666}) if err == nil { t.Fatalf("JSON client method expected to fail, but error is nil") } if resp != nil { t.Fatalf("JSON client method expected to return nil response on error, but returned non-nil") } } func TestClientSetsRequestContext(t *testing.T) { // Start up a server just so we can make a working client later. h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() // Make an *http.Client that validates that the key-value is present // in the context. httpClient := &http.Client{ Transport: &reqInspector{ callback: func(req *http.Request) { ctx := req.Context() pkgName, exists := twirp.PackageName(ctx) if !exists { t.Error("packageName not found in context") return } if pkgName != "twirp.internal.twirptest" { t.Errorf("packageName has wrong value, have=%s, want=%s", pkgName, "twirp.internal.twirptest") } serviceName, exists := twirp.ServiceName(ctx) if !exists { t.Error("serviceName not found in context") return } if serviceName != "Haberdasher" { t.Errorf("serviceName has wrong value, have=%s, want=%s", pkgName, "Haberdasher") } methodName, exists := twirp.MethodName(ctx) if !exists { t.Error("methodName not found in context") return } if methodName != "MakeHat" { t.Errorf("methodName has wrong value, have=%s, want=%s", pkgName, "Haberdasher") } }, }, } // Test the JSON client and the Protobuf client. client := NewHaberdasherJSONClient(s.URL, httpClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } client = NewHaberdasherProtobufClient(s.URL, httpClient) _, err = client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } } func TestClientSetsAcceptHeader(t *testing.T) { // Start up a server just so we can make a working client later. h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() // Make an *http.Client that validates that the correct accept header is present // in the request. httpClient := &http.Client{ Transport: &reqInspector{ callback: func(req *http.Request) { if req.Header.Get("Accept") != "application/json" { t.Error("Accept header not found in req") return } }, }, } // Test the JSON client client := NewHaberdasherJSONClient(s.URL, httpClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } // Make an *http.Client that validates that the correct accept header is present // in the request. httpClient = &http.Client{ Transport: &reqInspector{ callback: func(req *http.Request) { if req.Header.Get("Accept") != "application/protobuf" { t.Error("Accept header not found in req") return } }, }, } // test the Protobuf client. client = NewHaberdasherProtobufClient(s.URL, httpClient) _, err = client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } } // If a server returns a 3xx response, give a clear error message func TestClientRedirectError(t *testing.T) { testcase := func(code int, clientMaker func(string, HTTPClient, ...twirp.ClientOption) Haberdasher) func(*testing.T) { return func(t *testing.T) { // Make a server that redirects all requests redirecter := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "http://bogus/notreal", code) }) s := httptest.NewServer(redirecter) defer s.Close() client := clientMaker(s.URL, http.DefaultClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatal("MakeHat err=nil, expected an error because redirects aren't allowed") } if twerr, ok := err.(twirp.Error); !ok { t.Fatalf("expected twirp.Error typed err, have=%T", err) } else { // error message should mention the code if !strings.Contains(twerr.Error(), strconv.Itoa(code)) { t.Errorf("expected error message to mention the status code, but its missing: %q", twerr) } // error message should mention the redirect location if !strings.Contains(twerr.Error(), "http://bogus/notreal") { t.Errorf("expected error message to mention the redirect location, but its missing: %q", twerr) } // error meta should include http_error_from_intermediary if twerr.Meta("http_error_from_intermediary") != "true" { t.Errorf("expected error.Meta('http_error_from_intermediary') to be %q, but found %q", "true", twerr.Meta("http_error_from_intermediary")) } // error meta should include status if twerr.Meta("status_code") != strconv.Itoa(code) { t.Errorf("expected error.Meta('status_code') to be %q, but found %q", code, twerr.Meta("status_code")) } // error meta should include location if twerr.Meta("location") != "http://bogus/notreal" { t.Errorf("expected error.Meta('location') to be the redirect from intermediary, but found %q", twerr.Meta("location")) } } } } // It's important to test all redirect codes because Go actually handles them differently. 302 and // 303 get automatically redirected, even POSTs. The others do not (although this may change in // go1.8). We want all of them to have the same output. t.Run("json client", func(t *testing.T) { for code := 300; code <= 308; code++ { t.Run(strconv.Itoa(code), testcase(code, NewHaberdasherJSONClient)) } }) t.Run("protobuf client", func(t *testing.T) { for code := 300; code <= 308; code++ { t.Run(strconv.Itoa(code), testcase(code, NewHaberdasherProtobufClient)) } }) } func TestClientWithHooks(t *testing.T) { tests := []struct { desc string in *Size requestPreparedError error wantRequestPreparedCalled bool wantResponseReceivedCalled bool wantErrorCalled bool }{ { desc: "calls ResponseReceived and RequestPrepared hooks but not Error for successful calls", in: &Size{Inches: 1}, wantRequestPreparedCalled: true, wantResponseReceivedCalled: true, wantErrorCalled: false, }, { desc: "calls RequestPrepared and Error hooks for errored calls", in: &Size{Inches: 666}, wantRequestPreparedCalled: true, wantResponseReceivedCalled: false, wantErrorCalled: true, }, { desc: "calls RequestPrepared and Error hooks for error in hook", in: &Size{Inches: 1}, wantRequestPreparedCalled: true, requestPreparedError: errors.New("test"), wantResponseReceivedCalled: false, wantErrorCalled: true, }, } for _, tt := range tests { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() t.Run(tt.desc, func(t *testing.T) { requestPreparedCalled := false responseReceivedCalled := false errorCalled := false hooks := &twirp.ClientHooks{ RequestPrepared: func(ctx context.Context, req *http.Request) (context.Context, error) { requestPreparedCalled = true return ctx, tt.requestPreparedError }, ResponseReceived: func(ctx context.Context) { responseReceivedCalled = true }, Error: func(ctx context.Context, err twirp.Error) { errorCalled = true }, } // Clients protoCli := NewHaberdasherProtobufClient(s.URL, &http.Client{}, twirp.WithClientHooks(hooks)) ctx := context.Background() _, err := protoCli.MakeHat(ctx, tt.in) if tt.wantErrorCalled && err == nil { t.Error("unexpected nil error") } if !tt.wantErrorCalled && err != nil { t.Errorf("unexpected error: %v", err) } if tt.wantRequestPreparedCalled != requestPreparedCalled { t.Errorf("unexpected value for requestPreparedCalled: got %t, want %t", requestPreparedCalled, tt.wantRequestPreparedCalled) } if tt.wantResponseReceivedCalled != responseReceivedCalled { t.Errorf("unexpected value for responseReceivedCalled: got %t, want %t", responseReceivedCalled, tt.wantResponseReceivedCalled) } if tt.wantErrorCalled != errorCalled { t.Errorf("unexpected value for errorCalled: got %t, want %t", errorCalled, tt.wantErrorCalled) } requestPreparedCalled = false responseReceivedCalled = false errorCalled = false jsonCli := NewHaberdasherJSONClient(s.URL, &http.Client{}, twirp.WithClientHooks(hooks)) _, err = jsonCli.MakeHat(ctx, tt.in) if tt.wantErrorCalled && err == nil { t.Error("unexpected nil error") } if !tt.wantErrorCalled && err != nil { t.Errorf("unexpected error: %v", err) } if tt.wantRequestPreparedCalled != requestPreparedCalled { t.Errorf("unexpected value for requestPreparedCalled: got %t, want %t", requestPreparedCalled, tt.wantRequestPreparedCalled) } if tt.wantResponseReceivedCalled != responseReceivedCalled { t.Errorf("unexpected value for responseReceivedCalled: got %t, want %t", responseReceivedCalled, tt.wantResponseReceivedCalled) } if tt.wantErrorCalled != errorCalled { t.Errorf("unexpected value for errorCalled: got %t, want %t", errorCalled, tt.wantErrorCalled) } }) } } func TestClientContextToHook(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) type Key uint const testKey Key = 0 requestCalled := false responseCalled := false hooks := &twirp.ClientHooks{ RequestPrepared: func(ctx context.Context, req *http.Request) (context.Context, error) { requestCalled = true return context.WithValue(ctx, testKey, "test-value"), nil }, ResponseReceived: func(ctx context.Context) { responseCalled = true ctxVal := ctx.Value(testKey) if "test-value" != ctxVal { t.Errorf("context value set in RequestPrepared is not received in ResponseReceived: got %v, want test-value", ctxVal) } }, Error: func(ctx context.Context, err twirp.Error) {}, } protoCli := NewHaberdasherProtobufClient(s.URL, &http.Client{}, twirp.WithClientHooks(hooks)) ctx := context.Background() _, err := protoCli.MakeHat(ctx, &Size{Inches: 1}) if err != nil { t.Error("unexpected error %w from MakeHat call", err) } if !requestCalled { t.Error("missing RequestPrepared hook call") } if !responseCalled { t.Error("missing ResponseReceived hook call") } } func TestClientInterceptor(t *testing.T) { interceptor := func(next twirp.Method) twirp.Method { return func(ctx context.Context, request interface{}) (interface{}, error) { methodName, _ := twirp.MethodName(ctx) if methodName != "MakeHat" { return nil, fmt.Errorf("unexpected methodName: %q", methodName) } serviceName, _ := twirp.ServiceName(ctx) if serviceName != "Haberdasher" { return nil, fmt.Errorf("unexpected serviceName: %q", serviceName) } packageName, _ := twirp.PackageName(ctx) if packageName != "twirp.internal.twirptest" { return nil, fmt.Errorf("unexpected packageName: %q", packageName) } size, ok := request.(*Size) if !ok { return nil, fmt.Errorf("could not cast %T to a *Size", request) } size.Inches = size.Inches + 1 response, err := next(ctx, request) hat, ok := response.(*Hat) if ok && hat != nil { hat.Color = hat.Color + "x" return hat, err } return nil, err } } h := PickyHatmaker(3) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() client := NewHaberdasherProtobufClient( s.URL, http.DefaultClient, twirp.WithClientInterceptors( interceptor, interceptor, ), ) hat, clientErr := client.MakeHat(context.Background(), &Size{Inches: 1}) if clientErr != nil { t.Fatalf("client err=%q", clientErr) } if hat.Size != 3 { t.Errorf("hat size expected=3 actual=%v", hat.Size) } if hat.Color != "bluexx" { t.Errorf("hat color expected=bluexx actual=%v", hat.Color) } _, clientErr = client.MakeHat(context.Background(), &Size{Inches: 3}) twerr, ok := clientErr.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", clientErr) } if twerr.Code() != twirp.InvalidArgument { t.Errorf("expected error type to be InvalidArgument, buf found %q", twerr.Code()) } } func TestClientIntermediaryErrors(t *testing.T) { testcase := func(body string, code int, expectedErrorCode twirp.ErrorCode, clientMaker func(string, HTTPClient, ...twirp.ClientOption) Haberdasher) func(*testing.T) { return func(t *testing.T) { // Make a server that returns invalid twirp error responses, // simulating a network intermediary. s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(code) _, err := w.Write([]byte(body)) if err != nil { t.Fatalf("Unexpected error: %s", err.Error()) } })) defer s.Close() client := clientMaker(s.URL, http.DefaultClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatal("Expected error, but found nil") } if twerr, ok := err.(twirp.Error); !ok { t.Fatalf("expected twirp.Error typed err, have=%T", err) } else { // error message should mention the code if !strings.Contains(twerr.Msg(), fmt.Sprintf("Error from intermediary with HTTP status code %d", code)) { t.Errorf("unexpected error message: %q", twerr.Msg()) } // error meta should include http_error_from_intermediary if twerr.Meta("http_error_from_intermediary") != "true" { t.Errorf("expected error.Meta('http_error_from_intermediary') to be %q, but found %q", "true", twerr.Meta("http_error_from_intermediary")) } // error meta should include status if twerr.Meta("status_code") != strconv.Itoa(code) { t.Errorf("expected error.Meta('status_code') to be %q, but found %q", code, twerr.Meta("status_code")) } // error meta should include body if twerr.Meta("body") != body { t.Errorf("expected error.Meta('body') to be the response from intermediary, but found %q", twerr.Meta("body")) } // error code should be properly mapped from HTTP Code if twerr.Code() != expectedErrorCode { t.Errorf("expected to map HTTP status %q to twirp.ErrorCode %q, but found %q", code, expectedErrorCode, twerr.Code()) } } } } // HTTP Status Code -> desired Twirp Error Code statusCodes := map[int]twirp.ErrorCode{ // Map meaningful HTTP codes to semantic equivalent twirp.ErrorCodes 400: twirp.Internal, 401: twirp.Unauthenticated, 403: twirp.PermissionDenied, 404: twirp.BadRoute, 429: twirp.ResourceExhausted, 502: twirp.Unavailable, 503: twirp.Unavailable, 504: twirp.Unavailable, // all other codes are unknown 505: twirp.Unknown, 410: twirp.Unknown, 408: twirp.Unknown, } // label -> http response body bodies := map[string]string{ "text": "error from intermediary", "emptyjson": "{}", "invalidjson": `{"message":"Signature expired: 19700101T000000Z is now earlier than 20190612T110154Z (20190612T110654Z - 5 min.)"}`, } clients := map[string]func(string, HTTPClient, ...twirp.ClientOption) Haberdasher{ "json_client": NewHaberdasherJSONClient, "proto_client": NewHaberdasherProtobufClient, } for name, client := range clients { t.Run(name, func(t *testing.T) { for name, body := range bodies { t.Run(name, func(t *testing.T) { for httpcode, twirpcode := range statusCodes { t.Run(fmt.Sprintf("%d_to_%s", httpcode, twirpcode), testcase(body, httpcode, twirpcode, client)) } }) } }) } } func TestJSONClientAllowUnknownFields(t *testing.T) { // Make a server that always returns JSON with extra fields s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { json := `{"size":1, "color":"black", "extra1":"foo", "EXTRAMORE":"bar"}` w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "application/json") _, err := w.Write([]byte(json)) if err != nil { t.Fatalf("Unexpected error: %s", err.Error()) } })) defer s.Close() client := NewHaberdasherJSONClient(s.URL, http.DefaultClient) resp, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("Unexpected error: %s", err.Error()) } // resp should have the values from the response json if resp.Size != 1 { t.Errorf("expected resp.Size to be %d, found %d", 1, resp.Size) } if resp.Color != "black" { t.Errorf("expected resp.Color to be %q, found %q", "black", resp.Color) } if resp.Name != "" { // not included in the response, should default to zero-value t.Errorf("expected resp.Name to be empty (zero-value), found %q", resp.Name) } } func TestClientErrorsCanBeCaused(t *testing.T) { rootErr := fmt.Errorf("some root cause") httpClient := &http.Client{ Transport: &failingTransport{rootErr}, } client := NewHaberdasherJSONClient("", httpClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Errorf("JSON MakeHat err is unexpectedly nil") } cause := errCause(err) if cause != rootErr { t.Errorf("JSON MakeHat err cause is %q, want %q", cause, rootErr) } client = NewHaberdasherProtobufClient("", httpClient) _, err = client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Errorf("Protobuf MakeHat err is unexpectedly nil") } cause = errCause(err) if cause != rootErr { t.Errorf("Protobuf MakeHat err cause is %q, want %q", cause, rootErr) } } func TestCustomHTTPClientInterface(t *testing.T) { // Start up a server just so we can make a working client later. h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() // Create a custom wrapper to wrap our default client httpClient := &wrappedHTTPClient{ client: http.DefaultClient, wasCalled: false, } // Test the JSON client and the Protobuf client with a custom http.Client interface client := NewHaberdasherJSONClient(s.URL, httpClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } // Check if the Do function within the http.Client wrapper gets actually called if !httpClient.wasCalled { t.Errorf("HTTPClient.Do function was not called within the JSONClient") } // Reset bool for second test httpClient.wasCalled = false client = NewHaberdasherProtobufClient(s.URL, httpClient) _, err = client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("MakeHat err=%s", err) } // Check if the Do function within the http.Client wrapper gets actually called if !httpClient.wasCalled { t.Errorf("HTTPClient.Do function was not called within the ProtobufClient") } } // failingTransport is a http.RoundTripper which always returns an error. type failingTransport struct { err error // the error to return } func (t failingTransport) RoundTrip(*http.Request) (*http.Response, error) { return nil, t.err } func errCause(err error) error { cause := errors.Cause(err) if uerr, ok := cause.(*url.Error); ok { // in go1.8+, http.Client errors are wrapped in *url.Error cause = uerr.Err } return cause } // wrappedHTTPClient implements HTTPClient, but can be inspected during tests. type wrappedHTTPClient struct { client *http.Client wasCalled bool } func (c *wrappedHTTPClient) Do(req *http.Request) (resp *http.Response, err error) { c.wasCalled = true return c.client.Do(req) } ================================================ FILE: internal/twirptest/empty_service/compile_test.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 empty_service import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/empty_service/empty_service.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: empty_service.proto package empty_service import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" ) 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) ) var File_empty_service_proto protoreflect.FileDescriptor var file_empty_service_proto_rawDesc = []byte{ 0x0a, 0x13, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x25, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x32, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x10, 0x5a, 0x0e, 0x2f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_empty_service_proto_goTypes = []interface{}{} var file_empty_service_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_empty_service_proto_init() } func file_empty_service_proto_init() { if File_empty_service_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_empty_service_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_empty_service_proto_goTypes, DependencyIndexes: file_empty_service_proto_depIdxs, }.Build() File_empty_service_proto = out.File file_empty_service_proto_rawDesc = nil file_empty_service_proto_goTypes = nil file_empty_service_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/empty_service/empty_service.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.emptyservice; // Test to make sure that a service with no methods doesn't break. option go_package = "/empty_service"; service Empty{} ================================================ FILE: internal/twirptest/empty_service/empty_service.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: empty_service.proto package empty_service import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // =============== // Empty Interface // =============== type Empty interface { } // ===================== // Empty Protobuf Client // ===================== type emptyProtobufClient struct { client HTTPClient urls [0]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewEmptyProtobufClient creates a Protobuf client that implements the Empty interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewEmptyProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Empty { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } urls := [0]string{} return &emptyProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } // ================= // Empty JSON Client // ================= type emptyJSONClient struct { client HTTPClient urls [0]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewEmptyJSONClient creates a JSON client that implements the Empty interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewEmptyJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Empty { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } urls := [0]string{} return &emptyJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } // ==================== // Empty Server Handler // ==================== type emptyServer struct { Empty interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewEmptyServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewEmptyServer(svc Empty, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &emptyServer{ Empty: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *emptyServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *emptyServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // EmptyPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const EmptyPathPrefix = "/twirp/twirp.internal.twirptest.emptyservice.Empty/" func (s *emptyServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.emptyservice") ctx = ctxsetters.WithServiceName(ctx, "Empty") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.emptyservice.Empty" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *emptyServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *emptyServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *emptyServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.emptyservice", "Empty") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 92 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x4e, 0xcd, 0x2d, 0x28, 0xa9, 0x8c, 0x2f, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2d, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0xc0, 0xaa, 0xa1, 0x8a, 0x8d, 0xd8, 0xb9, 0x58, 0x5d, 0x41, 0x7c, 0x27, 0x81, 0x28, 0x3e, 0x7d, 0x14, 0x73, 0x92, 0xd8, 0xc0, 0x06, 0x19, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x08, 0xd8, 0xe5, 0xa8, 0x5f, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/empty_service/gen.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 empty_service //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. empty_service.proto ================================================ FILE: internal/twirptest/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirptest //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. service.proto ================================================ FILE: internal/twirptest/google_protobuf_imports/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 google_protobuf_imports import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/google_protobuf_imports/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 google_protobuf_imports //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. service.proto ================================================ FILE: internal/twirptest/google_protobuf_imports/service.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: service.proto package google_protobuf_imports import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" emptypb "google.golang.org/protobuf/types/known/emptypb" wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" ) 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) ) var File_service_proto protoreflect.FileDescriptor var file_service_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x22, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 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, 0x1a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x43, 0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x3c, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x1a, 0x5a, 0x18, 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_service_proto_goTypes = []interface{}{ (*wrapperspb.StringValue)(nil), // 0: google.protobuf.StringValue (*emptypb.Empty)(nil), // 1: google.protobuf.Empty } var file_service_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.use_empty.Svc.Send:input_type -> google.protobuf.StringValue 1, // 1: twirp.internal.twirptest.use_empty.Svc.Send:output_type -> google.protobuf.Empty 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_service_proto_init() } func file_service_proto_init() { if File_service_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_service_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_service_proto_goTypes, DependencyIndexes: file_service_proto_depIdxs, }.Build() File_service_proto = out.File file_service_proto_rawDesc = nil file_service_proto_goTypes = nil file_service_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/google_protobuf_imports/service.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.use_empty; option go_package = "/google_protobuf_imports"; import "google/protobuf/empty.proto"; import "google/protobuf/wrappers.proto"; service Svc { rpc Send(google.protobuf.StringValue) returns(google.protobuf.Empty); } ================================================ FILE: internal/twirptest/google_protobuf_imports/service.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: service.proto package google_protobuf_imports import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import google_protobuf "google.golang.org/protobuf/types/known/emptypb" import google_protobuf1 "google.golang.org/protobuf/types/known/wrapperspb" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============= // Svc Interface // ============= type Svc interface { Send(context.Context, *google_protobuf1.StringValue) (*google_protobuf.Empty, error) } // =================== // Svc Protobuf Client // =================== type svcProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvcProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.use_empty", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcProtobufClient) Send(ctx context.Context, in *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.use_empty") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*google_protobuf1.StringValue) if !ok { return nil, twirp.InternalError("failed type assertion req.(*google_protobuf1.StringValue) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*google_protobuf.Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf.Empty) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcProtobufClient) callSend(ctx context.Context, in *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { out := new(google_protobuf.Empty) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =============== // Svc JSON Client // =============== type svcJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvcJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.use_empty", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcJSONClient) Send(ctx context.Context, in *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.use_empty") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*google_protobuf1.StringValue) if !ok { return nil, twirp.InternalError("failed type assertion req.(*google_protobuf1.StringValue) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*google_protobuf.Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf.Empty) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcJSONClient) callSend(ctx context.Context, in *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { out := new(google_protobuf.Empty) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================== // Svc Server Handler // ================== type svcServer struct { Svc interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvcServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvcServer(svc Svc, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svcServer{ Svc: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svcServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svcServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // SvcPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const SvcPathPrefix = "/twirp/twirp.internal.twirptest.use_empty.Svc/" func (s *svcServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.use_empty") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.use_empty.Svc" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svcServer) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svcServer) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(google_protobuf1.StringValue) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*google_protobuf1.StringValue) if !ok { return nil, twirp.InternalError("failed type assertion req.(*google_protobuf1.StringValue) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*google_protobuf.Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf.Empty) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *google_protobuf.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf.Empty and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(google_protobuf1.StringValue) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *google_protobuf1.StringValue) (*google_protobuf.Empty, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*google_protobuf1.StringValue) if !ok { return nil, twirp.InternalError("failed type assertion req.(*google_protobuf1.StringValue) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*google_protobuf.Empty) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf.Empty) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *google_protobuf.Empty func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf.Empty and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svcServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svcServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.use_empty", "Svc") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 169 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2a, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x4a, 0x8b, 0x53, 0xe3, 0x53, 0x73, 0x0b, 0x4a, 0x2a, 0xa5, 0xa4, 0xd3, 0xf3, 0xf3, 0xd3, 0x73, 0x52, 0xf5, 0xc1, 0x3a, 0x92, 0x4a, 0xd3, 0xf4, 0xc1, 0xc2, 0x10, 0x03, 0xa4, 0xe4, 0xd0, 0x25, 0xcb, 0x8b, 0x12, 0x0b, 0x0a, 0x52, 0x8b, 0x8a, 0x21, 0xf2, 0x46, 0xce, 0x5c, 0xcc, 0xc1, 0x65, 0xc9, 0x42, 0x36, 0x5c, 0x2c, 0xc1, 0xa9, 0x79, 0x29, 0x42, 0x32, 0x7a, 0x10, 0xf5, 0x7a, 0x30, 0xf5, 0x7a, 0xc1, 0x25, 0x45, 0x99, 0x79, 0xe9, 0x61, 0x89, 0x39, 0xa5, 0xa9, 0x52, 0x62, 0x18, 0xb2, 0xae, 0x20, 0xab, 0x9c, 0xa4, 0xa2, 0x24, 0xf4, 0x21, 0x32, 0xf1, 0x30, 0x99, 0xf8, 0xcc, 0xdc, 0x82, 0xfc, 0xa2, 0x92, 0xe2, 0x24, 0x36, 0xb0, 0x88, 0x31, 0x20, 0x00, 0x00, 0xff, 0xff, 0x09, 0x85, 0xee, 0x47, 0xd9, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/hatmakers.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirptest import ( "context" "net/http" "net/http/httptest" "time" "github.com/twitchtv/twirp" ) type hatmaker func(ctx context.Context, s *Size) (*Hat, error) func (h hatmaker) MakeHat(ctx context.Context, s *Size) (*Hat, error) { return h(ctx, s) } // HaberdasherFunc is a convenience to convert a function into a Haberdasher service. func HaberdasherFunc(f func(ctx context.Context, s *Size) (*Hat, error)) Haberdasher { return hatmaker(f) } // Always makes a blank hat. func NoopHatmaker() Haberdasher { return hatmaker(func(context.Context, *Size) (*Hat, error) { return &Hat{}, nil }) } // Makes a hat, as long as its the size they like func PickyHatmaker(want int32) Haberdasher { return hatmaker(func(ctx context.Context, s *Size) (*Hat, error) { if s.Inches != want { return nil, twirp.InvalidArgumentError("Inches", "I can't make a hat that size!") } return &Hat{Size: s.Inches, Color: "blue", Name: "top hat"}, nil }) } // Makes a hat, but sure takes their time func SlowHatmaker(dur time.Duration) Haberdasher { return hatmaker(func(ctx context.Context, s *Size) (*Hat, error) { time.Sleep(dur) return &Hat{Size: s.Inches, Color: "blue", Name: "top hat"}, nil }) } // Always errors. func ErroringHatmaker(err error) Haberdasher { return hatmaker(func(ctx context.Context, s *Size) (*Hat, error) { return nil, err }) } // Panics. func PanickyHatmaker(p interface{}) Haberdasher { return hatmaker(func(ctx context.Context, s *Size) (*Hat, error) { panic(p) }) } // Returns nil, nil func NilHatmaker() Haberdasher { return hatmaker(func(context.Context, *Size) (*Hat, error) { return nil, nil }) } func ServerAndClient(h Haberdasher, hooks *twirp.ServerHooks) (*httptest.Server, Haberdasher) { s := httptest.NewServer(NewHaberdasherServer(h, hooks)) c := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) return s, c } func TwirpServerAndClient(hooks *twirp.ServerHooks) (*httptest.Server, Haberdasher) { return ServerAndClient(NoopHatmaker(), hooks) } ================================================ FILE: internal/twirptest/importable/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importable import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/importable/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importable //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. importable.proto ================================================ FILE: internal/twirptest/importable/importable.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: importable.proto // Test to make sure that importing other packages doesnt break package importable import ( 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 Msg struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg) Reset() { *x = Msg{} if protoimpl.UnsafeEnabled { mi := &file_importable_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg) ProtoMessage() {} func (x *Msg) ProtoReflect() protoreflect.Message { mi := &file_importable_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 Msg.ProtoReflect.Descriptor instead. func (*Msg) Descriptor() ([]byte, []int) { return file_importable_proto_rawDescGZIP(), []int{0} } var File_importable_proto protoreflect.FileDescriptor var file_importable_proto_rawDesc = []byte{ 0x0a, 0x10, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x23, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x61, 0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x5a, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x28, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x28, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_importable_proto_rawDescOnce sync.Once file_importable_proto_rawDescData = file_importable_proto_rawDesc ) func file_importable_proto_rawDescGZIP() []byte { file_importable_proto_rawDescOnce.Do(func() { file_importable_proto_rawDescData = protoimpl.X.CompressGZIP(file_importable_proto_rawDescData) }) return file_importable_proto_rawDescData } var file_importable_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_importable_proto_goTypes = []interface{}{ (*Msg)(nil), // 0: twirp.internal.twirptest.importable.Msg } var file_importable_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.importable.Svc.Send:input_type -> twirp.internal.twirptest.importable.Msg 0, // 1: twirp.internal.twirptest.importable.Svc.Send:output_type -> twirp.internal.twirptest.importable.Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_importable_proto_init() } func file_importable_proto_init() { if File_importable_proto != nil { return } if !protoimpl.UnsafeEnabled { file_importable_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg); 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_importable_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_importable_proto_goTypes, DependencyIndexes: file_importable_proto_depIdxs, MessageInfos: file_importable_proto_msgTypes, }.Build() File_importable_proto = out.File file_importable_proto_rawDesc = nil file_importable_proto_goTypes = nil file_importable_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importable/importable.proto ================================================ syntax = "proto3"; // Test to make sure that importing other packages doesnt break package twirp.internal.twirptest.importable; option go_package = "github.com/twitchtv/twirp/internal/twirptest/importable"; message Msg {} service Svc { rpc Send(Msg) returns(Msg); } ================================================ FILE: internal/twirptest/importable/importable.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: importable.proto // Test to make sure that importing other packages doesnt break package importable import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============= // Svc Interface // ============= type Svc interface { Send(context.Context, *Msg) (*Msg, error) } // =================== // Svc Protobuf Client // =================== type svcProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvcProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importable", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importable") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcProtobufClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =============== // Svc JSON Client // =============== type svcJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvcJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importable", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importable") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcJSONClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================== // Svc Server Handler // ================== type svcServer struct { Svc interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvcServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvcServer(svc Svc, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svcServer{ Svc: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svcServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svcServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // SvcPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const SvcPathPrefix = "/twirp/twirp.internal.twirptest.importable.Svc/" func (s *svcServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importable") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.importable.Svc" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svcServer) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svcServer) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svcServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svcServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.importable", "Svc") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 143 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc8, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a, 0x49, 0x4c, 0xca, 0x49, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2e, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x10, 0x4a, 0x95, 0x58, 0xb9, 0x98, 0x7d, 0x8b, 0xd3, 0x8d, 0x12, 0xb9, 0x98, 0x83, 0xcb, 0x92, 0x85, 0xa2, 0xb8, 0x58, 0x82, 0x53, 0xf3, 0x52, 0x84, 0x34, 0xf4, 0x88, 0xd0, 0xab, 0xe7, 0x5b, 0x9c, 0x2e, 0x45, 0xb4, 0x4a, 0x27, 0xcb, 0x28, 0xf3, 0xf4, 0xcc, 0x92, 0x8c, 0xd2, 0x24, 0xbd, 0xe4, 0xfc, 0x5c, 0xfd, 0x92, 0xf2, 0xcc, 0x92, 0xe4, 0x8c, 0x92, 0x32, 0x7d, 0xb0, 0x7a, 0x7d, 0x98, 0x76, 0x7d, 0xb8, 0x76, 0x7d, 0x84, 0xf6, 0x24, 0x36, 0xb0, 0x87, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xf3, 0xa1, 0x41, 0x82, 0xe4, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/importer/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importer import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/importer/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importer //go:generate protoc -I=. -I=../importable --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. importer.proto ================================================ FILE: internal/twirptest/importer/importer.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: importer.proto // Test to make sure that importing other packages doesnt break package importer import ( importable "github.com/twitchtv/twirp/internal/twirptest/importable" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" ) 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) ) var File_importer_proto protoreflect.FileDescriptor var file_importer_proto_rawDesc = []byte{ 0x0a, 0x0e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x1a, 0x10, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x62, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x32, 0x12, 0x5a, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x28, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x28, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x37, 0x5a, 0x35, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_importer_proto_goTypes = []interface{}{ (*importable.Msg)(nil), // 0: twirp.internal.twirptest.importable.Msg } var file_importer_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.importer.Svc2.Send:input_type -> twirp.internal.twirptest.importable.Msg 0, // 1: twirp.internal.twirptest.importer.Svc2.Send:output_type -> twirp.internal.twirptest.importable.Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_importer_proto_init() } func file_importer_proto_init() { if File_importer_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_importer_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_importer_proto_goTypes, DependencyIndexes: file_importer_proto_depIdxs, }.Build() File_importer_proto = out.File file_importer_proto_rawDesc = nil file_importer_proto_goTypes = nil file_importer_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importer/importer.proto ================================================ syntax = "proto3"; // Test to make sure that importing other packages doesnt break package twirp.internal.twirptest.importer; option go_package = "github.com/twitchtv/twirp/internal/twirptest/importer"; import "importable.proto"; service Svc2 { rpc Send(importable.Msg) returns(importable.Msg); } ================================================ FILE: internal/twirptest/importer/importer.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: importer.proto // Test to make sure that importing other packages doesnt break package importer import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import twirp_internal_twirptest_importable "github.com/twitchtv/twirp/internal/twirptest/importable" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Svc2 Interface // ============== type Svc2 interface { Send(context.Context, *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) } // ==================== // Svc2 Protobuf Client // ==================== type svc2ProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvc2ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importer", "Svc2") urls := [1]string{ serviceURL + "Send", } return &svc2ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2ProtobufClient) Send(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2ProtobufClient) callSend(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { out := new(twirp_internal_twirptest_importable.Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Svc2 JSON Client // ================ type svc2JSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvc2JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importer", "Svc2") urls := [1]string{ serviceURL + "Send", } return &svc2JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2JSONClient) Send(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2JSONClient) callSend(ctx context.Context, in *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { out := new(twirp_internal_twirptest_importable.Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Svc2 Server Handler // =================== type svc2Server struct { Svc2 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvc2Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvc2Server(svc Svc2, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svc2Server{ Svc2: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svc2Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svc2Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // Svc2PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const Svc2PathPrefix = "/twirp/twirp.internal.twirptest.importer.Svc2/" func (s *svc2Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.importer.Svc2" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svc2Server) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc2Server) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(twirp_internal_twirptest_importable.Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc2.Send if s.interceptor != nil { handler = func(ctx context.Context, req *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return s.Svc2.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *twirp_internal_twirptest_importable.Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *twirp_internal_twirptest_importable.Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(twirp_internal_twirptest_importable.Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc2.Send if s.interceptor != nil { handler = func(ctx context.Context, req *twirp_internal_twirptest_importable.Msg) (*twirp_internal_twirptest_importable.Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return s.Svc2.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importable.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importable.Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *twirp_internal_twirptest_importable.Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *twirp_internal_twirptest_importable.Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svc2Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svc2Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.importer", "Svc2") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 146 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcb, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a, 0x49, 0x2d, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2c, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x60, 0x0a, 0xa5, 0x04, 0x20, 0xac, 0xc4, 0xa4, 0x9c, 0x54, 0x88, 0x26, 0xa3, 0x24, 0x2e, 0x96, 0xe0, 0xb2, 0x64, 0x23, 0xa1, 0x28, 0x2e, 0x96, 0xe0, 0xd4, 0xbc, 0x14, 0x21, 0x0d, 0x3d, 0x02, 0xa6, 0x80, 0xf5, 0xfa, 0x16, 0xa7, 0x4b, 0x11, 0xad, 0xd2, 0xc9, 0x3c, 0xca, 0x34, 0x3d, 0xb3, 0x24, 0xa3, 0x34, 0x49, 0x2f, 0x39, 0x3f, 0x57, 0xbf, 0xa4, 0x3c, 0xb3, 0x24, 0x39, 0xa3, 0xa4, 0x4c, 0x1f, 0xac, 0x5e, 0x1f, 0xa6, 0x5d, 0x1f, 0xae, 0x5d, 0x1f, 0xe6, 0xdc, 0x24, 0x36, 0xb0, 0x1b, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x14, 0x68, 0x43, 0x4d, 0xea, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/importer_local/compile_test.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importer_local import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/importer_local/gen.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importer_local //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. importer_local_msgdef.proto //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. importer_local.proto ================================================ FILE: internal/twirptest/importer_local/importer_local.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: importer_local.proto package importer_local import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" ) 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) ) var File_importer_local_proto protoreflect.FileDescriptor var file_importer_local_proto_rawDesc = []byte{ 0x0a, 0x14, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x27, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x1a, 0x1b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x64, 0x65, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x69, 0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x62, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x2c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x2c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_importer_local_proto_goTypes = []interface{}{ (*Msg)(nil), // 0: twirp.internal.twirptest.importer_local.Msg } var file_importer_local_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.importer_local.Svc.Send:input_type -> twirp.internal.twirptest.importer_local.Msg 0, // 1: twirp.internal.twirptest.importer_local.Svc.Send:output_type -> twirp.internal.twirptest.importer_local.Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_importer_local_proto_init() } func file_importer_local_proto_init() { if File_importer_local_proto != nil { return } file_importer_local_msgdef_proto_init() type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_importer_local_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_importer_local_proto_goTypes, DependencyIndexes: file_importer_local_proto_depIdxs, }.Build() File_importer_local_proto = out.File file_importer_local_proto_rawDesc = nil file_importer_local_proto_goTypes = nil file_importer_local_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importer_local/importer_local.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.importer_local; option go_package = "github.com/twitchtv/twirp/internal/twirptest/importer_local"; import "importer_local_msgdef.proto"; service Svc { rpc Send(Msg) returns (Msg); } ================================================ FILE: internal/twirptest/importer_local/importer_local.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: importer_local.proto package importer_local import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============= // Svc Interface // ============= type Svc interface { Send(context.Context, *Msg) (*Msg, error) } // =================== // Svc Protobuf Client // =================== type svcProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvcProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importer_local", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer_local") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcProtobufClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =============== // Svc JSON Client // =============== type svcJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvcJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importer_local", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer_local") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcJSONClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================== // Svc Server Handler // ================== type svcServer struct { Svc interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvcServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvcServer(svc Svc, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svcServer{ Svc: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svcServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svcServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // SvcPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const SvcPathPrefix = "/twirp/twirp.internal.twirptest.importer_local.Svc/" func (s *svcServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importer_local") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.importer_local.Svc" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svcServer) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svcServer) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svcServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svcServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.importer_local", "Svc") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 154 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xc9, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a, 0x49, 0x2d, 0x8a, 0xcf, 0xc9, 0x4f, 0x4e, 0xcc, 0xd1, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2f, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x50, 0x95, 0x4b, 0x49, 0xa3, 0xf2, 0xe3, 0x73, 0x8b, 0xd3, 0x53, 0x52, 0xd3, 0x20, 0xa6, 0x18, 0x65, 0x72, 0x31, 0x07, 0x97, 0x25, 0x0b, 0x25, 0x71, 0xb1, 0x04, 0xa7, 0xe6, 0xa5, 0x08, 0xe9, 0xe8, 0x11, 0x69, 0xaa, 0x9e, 0x6f, 0x71, 0xba, 0x14, 0x49, 0xaa, 0x9d, 0x6c, 0xa3, 0xac, 0xd3, 0x33, 0x4b, 0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0x4b, 0xca, 0x33, 0x4b, 0x92, 0x33, 0x4a, 0xca, 0xf4, 0xc1, 0x7a, 0xf4, 0x61, 0x46, 0xe8, 0xc3, 0x8d, 0xd0, 0x47, 0x35, 0x22, 0x89, 0x0d, 0xec, 0x60, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x9a, 0xfb, 0xc0, 0xc5, 0x0e, 0x01, 0x00, 0x00, } ================================================ FILE: internal/twirptest/importer_local/importer_local_msgdef.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: importer_local_msgdef.proto package importer_local import ( 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 Msg struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg) Reset() { *x = Msg{} if protoimpl.UnsafeEnabled { mi := &file_importer_local_msgdef_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg) ProtoMessage() {} func (x *Msg) ProtoReflect() protoreflect.Message { mi := &file_importer_local_msgdef_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 Msg.ProtoReflect.Descriptor instead. func (*Msg) Descriptor() ([]byte, []int) { return file_importer_local_msgdef_proto_rawDescGZIP(), []int{0} } var File_importer_local_msgdef_proto protoreflect.FileDescriptor var file_importer_local_msgdef_proto_rawDesc = []byte{ 0x0a, 0x1b, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x6d, 0x73, 0x67, 0x64, 0x65, 0x66, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x27, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x42, 0x3d, 0x5a, 0x3b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_importer_local_msgdef_proto_rawDescOnce sync.Once file_importer_local_msgdef_proto_rawDescData = file_importer_local_msgdef_proto_rawDesc ) func file_importer_local_msgdef_proto_rawDescGZIP() []byte { file_importer_local_msgdef_proto_rawDescOnce.Do(func() { file_importer_local_msgdef_proto_rawDescData = protoimpl.X.CompressGZIP(file_importer_local_msgdef_proto_rawDescData) }) return file_importer_local_msgdef_proto_rawDescData } var file_importer_local_msgdef_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_importer_local_msgdef_proto_goTypes = []interface{}{ (*Msg)(nil), // 0: twirp.internal.twirptest.importer_local.Msg } var file_importer_local_msgdef_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_importer_local_msgdef_proto_init() } func file_importer_local_msgdef_proto_init() { if File_importer_local_msgdef_proto != nil { return } if !protoimpl.UnsafeEnabled { file_importer_local_msgdef_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg); 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_importer_local_msgdef_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_importer_local_msgdef_proto_goTypes, DependencyIndexes: file_importer_local_msgdef_proto_depIdxs, MessageInfos: file_importer_local_msgdef_proto_msgTypes, }.Build() File_importer_local_msgdef_proto = out.File file_importer_local_msgdef_proto_rawDesc = nil file_importer_local_msgdef_proto_goTypes = nil file_importer_local_msgdef_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importer_local/importer_local_msgdef.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.importer_local; option go_package = "github.com/twitchtv/twirp/internal/twirptest/importer_local"; message Msg {} ================================================ FILE: internal/twirptest/importmapping/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importmapping import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/importmapping/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 importmapping //go:generate ./gen.sh ================================================ FILE: internal/twirptest/importmapping/gen.sh ================================================ #!/usr/bin/env bash set -euo pipefail protoc --go_out=. --twirp_out=. \ --go_opt=paths=source_relative \ --go_opt=My/y.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/y \ --twirp_opt=paths=source_relative \ --twirp_opt=My/y.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/y \ y/y.proto protoc --go_out=. --twirp_out=. \ --go_opt=paths=source_relative \ --go_opt=My/y.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/y \ --go_opt=Mx/x.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/x \ --twirp_opt=paths=source_relative \ --twirp_opt=My/y.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/y \ --twirp_opt=Mx/x.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/x \ x/x.proto ================================================ FILE: internal/twirptest/importmapping/protoc_gen-x.sh ================================================ #!/usr/bin/env bash set -euo pipefail # Pull into variable since both protoc-gen-go and protoc-gen-twirp need the map. Y_IMPORT_MAPPING="y/y.proto=github.com/twitchtv/twirp/internal/twirptest/importmapping/y" PROTOC_GEN_GO_PARAMS="M${Y_IMPORT_MAPPING}" \ PROTOC_GEN_TWIRP_PARAMS="go_import_mapping@${Y_IMPORT_MAPPING}" \ ../../protoc_gen.sh x/x.proto ================================================ FILE: internal/twirptest/importmapping/x/x.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: x/x.proto package x import ( y "github.com/twitchtv/twirp/internal/twirptest/importmapping/y" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" ) 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) ) var File_x_x_proto protoreflect.FileDescriptor var file_x_x_proto_rawDesc = []byte{ 0x0a, 0x09, 0x78, 0x2f, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x28, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x78, 0x1a, 0x09, 0x79, 0x2f, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x6e, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x31, 0x12, 0x66, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x2e, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x79, 0x2e, 0x4d, 0x73, 0x67, 0x59, 0x1a, 0x2e, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x79, 0x2e, 0x4d, 0x73, 0x67, 0x59, 0x42, 0x1f, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x69, 0x6c, 0x6c, 0x2f, 0x62, 0x65, 0x2f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x2f, 0x78, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_x_x_proto_goTypes = []interface{}{ (*y.MsgY)(nil), // 0: twirp.internal.twirptest.importmapping.y.MsgY } var file_x_x_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.importmapping.x.Svc1.Send:input_type -> twirp.internal.twirptest.importmapping.y.MsgY 0, // 1: twirp.internal.twirptest.importmapping.x.Svc1.Send:output_type -> twirp.internal.twirptest.importmapping.y.MsgY 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_x_x_proto_init() } func file_x_x_proto_init() { if File_x_x_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_x_x_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_x_x_proto_goTypes, DependencyIndexes: file_x_x_proto_depIdxs, }.Build() File_x_x_proto = out.File file_x_x_proto_rawDesc = nil file_x_x_proto_goTypes = nil file_x_x_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importmapping/x/x.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.importmapping.x; option go_package = "example.com/will/be/ignored/x"; import "y/y.proto"; service Svc1 { rpc Send(y.MsgY) returns (y.MsgY); } ================================================ FILE: internal/twirptest/importmapping/x/x.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: x/x.proto package x import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import twirp_internal_twirptest_importmapping_y "github.com/twitchtv/twirp/internal/twirptest/importmapping/y" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Svc1 Interface // ============== type Svc1 interface { Send(context.Context, *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) } // ==================== // Svc1 Protobuf Client // ==================== type svc1ProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc1ProtobufClient creates a Protobuf client that implements the Svc1 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvc1ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importmapping.x", "Svc1") urls := [1]string{ serviceURL + "Send", } return &svc1ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc1ProtobufClient) Send(ctx context.Context, in *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importmapping.x") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc1ProtobufClient) callSend(ctx context.Context, in *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { out := new(twirp_internal_twirptest_importmapping_y.MsgY) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Svc1 JSON Client // ================ type svc1JSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc1JSONClient creates a JSON client that implements the Svc1 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvc1JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.importmapping.x", "Svc1") urls := [1]string{ serviceURL + "Send", } return &svc1JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc1JSONClient) Send(ctx context.Context, in *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importmapping.x") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc1JSONClient) callSend(ctx context.Context, in *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { out := new(twirp_internal_twirptest_importmapping_y.MsgY) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Svc1 Server Handler // =================== type svc1Server struct { Svc1 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvc1Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvc1Server(svc Svc1, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svc1Server{ Svc1: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svc1Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svc1Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // Svc1PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const Svc1PathPrefix = "/twirp/twirp.internal.twirptest.importmapping.x.Svc1/" func (s *svc1Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.importmapping.x") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.importmapping.x.Svc1" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svc1Server) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc1Server) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(twirp_internal_twirptest_importmapping_y.MsgY) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc1.Send if s.interceptor != nil { handler = func(ctx context.Context, req *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return s.Svc1.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *twirp_internal_twirptest_importmapping_y.MsgY func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *twirp_internal_twirptest_importmapping_y.MsgY and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc1Server) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(twirp_internal_twirptest_importmapping_y.MsgY) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc1.Send if s.interceptor != nil { handler = func(ctx context.Context, req *twirp_internal_twirptest_importmapping_y.MsgY) (*twirp_internal_twirptest_importmapping_y.MsgY, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion req.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return s.Svc1.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*twirp_internal_twirptest_importmapping_y.MsgY) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*twirp_internal_twirptest_importmapping_y.MsgY) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *twirp_internal_twirptest_importmapping_y.MsgY func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *twirp_internal_twirptest_importmapping_y.MsgY and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc1Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svc1Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svc1Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.importmapping.x", "Svc1") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 150 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x8e, 0xb1, 0xaa, 0xc2, 0x40, 0x10, 0x45, 0x9b, 0xf0, 0x20, 0x29, 0x53, 0x06, 0x1e, 0xb6, 0x56, 0x33, 0xa8, 0x7f, 0x60, 0x6f, 0x95, 0x4a, 0xbb, 0x4d, 0x32, 0x2e, 0x03, 0xbb, 0xb3, 0xc3, 0x66, 0x30, 0xbb, 0x7f, 0x2f, 0xc4, 0x1f, 0xd0, 0xf2, 0xc2, 0x3d, 0x87, 0xd3, 0xb5, 0x05, 0x0b, 0x68, 0x4e, 0x96, 0xfa, 0xa3, 0x6d, 0x9c, 0x15, 0x58, 0x8c, 0xb2, 0xb8, 0x00, 0xfb, 0x34, 0x5a, 0x0d, 0x38, 0x6a, 0xca, 0x16, 0x9d, 0x2a, 0x8b, 0x87, 0x32, 0xb4, 0x15, 0xeb, 0x07, 0x3a, 0x4b, 0xd7, 0x8c, 0xaf, 0xf9, 0xd4, 0x3f, 0xbb, 0x66, 0x24, 0x59, 0x7a, 0x80, 0x2f, 0x2d, 0x15, 0x6e, 0xab, 0xbf, 0x0f, 0x3f, 0xfe, 0xaf, 0x87, 0xc7, 0x3f, 0x15, 0x17, 0x35, 0x10, 0xcc, 0x29, 0xe2, 0xc6, 0x21, 0xe0, 0x44, 0xc8, 0x5e, 0x52, 0xa6, 0x05, 0xcb, 0xf4, 0xb7, 0x77, 0x5d, 0xde, 0x01, 0x00, 0x00, 0xff, 0xff, 0x77, 0x79, 0x60, 0xd7, 0xd9, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/importmapping/y/y.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: y/y.proto package y import ( 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 MsgY struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *MsgY) Reset() { *x = MsgY{} if protoimpl.UnsafeEnabled { mi := &file_y_y_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MsgY) String() string { return protoimpl.X.MessageStringOf(x) } func (*MsgY) ProtoMessage() {} func (x *MsgY) ProtoReflect() protoreflect.Message { mi := &file_y_y_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 MsgY.ProtoReflect.Descriptor instead. func (*MsgY) Descriptor() ([]byte, []int) { return file_y_y_proto_rawDescGZIP(), []int{0} } var File_y_y_proto protoreflect.FileDescriptor var file_y_y_proto_rawDesc = []byte{ 0x0a, 0x09, 0x79, 0x2f, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x28, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x6d, 0x61, 0x70, 0x70, 0x69, 0x6e, 0x67, 0x2e, 0x79, 0x22, 0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x59, 0x42, 0x1f, 0x5a, 0x1d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x77, 0x69, 0x6c, 0x6c, 0x2f, 0x62, 0x65, 0x2f, 0x69, 0x67, 0x6e, 0x6f, 0x72, 0x65, 0x64, 0x2f, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_y_y_proto_rawDescOnce sync.Once file_y_y_proto_rawDescData = file_y_y_proto_rawDesc ) func file_y_y_proto_rawDescGZIP() []byte { file_y_y_proto_rawDescOnce.Do(func() { file_y_y_proto_rawDescData = protoimpl.X.CompressGZIP(file_y_y_proto_rawDescData) }) return file_y_y_proto_rawDescData } var file_y_y_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_y_y_proto_goTypes = []interface{}{ (*MsgY)(nil), // 0: twirp.internal.twirptest.importmapping.y.MsgY } var file_y_y_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_y_y_proto_init() } func file_y_y_proto_init() { if File_y_y_proto != nil { return } if !protoimpl.UnsafeEnabled { file_y_y_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MsgY); 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_y_y_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 0, }, GoTypes: file_y_y_proto_goTypes, DependencyIndexes: file_y_y_proto_depIdxs, MessageInfos: file_y_y_proto_msgTypes, }.Build() File_y_y_proto = out.File file_y_y_proto_rawDesc = nil file_y_y_proto_goTypes = nil file_y_y_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/importmapping/y/y.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest.importmapping.y; option go_package = "example.com/will/be/ignored/y"; message MsgY {} ================================================ FILE: internal/twirptest/json_serialization/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 json_serialization //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. json_serialization.proto ================================================ FILE: internal/twirptest/json_serialization/json_serialization.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: json_serialization.proto package json_serialization import ( 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 Msg_FooBar int32 const ( Msg_FOO Msg_FooBar = 0 Msg_BAR Msg_FooBar = 1 ) // Enum value maps for Msg_FooBar. var ( Msg_FooBar_name = map[int32]string{ 0: "FOO", 1: "BAR", } Msg_FooBar_value = map[string]int32{ "FOO": 0, "BAR": 1, } ) func (x Msg_FooBar) Enum() *Msg_FooBar { p := new(Msg_FooBar) *p = x return p } func (x Msg_FooBar) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (Msg_FooBar) Descriptor() protoreflect.EnumDescriptor { return file_json_serialization_proto_enumTypes[0].Descriptor() } func (Msg_FooBar) Type() protoreflect.EnumType { return &file_json_serialization_proto_enumTypes[0] } func (x Msg_FooBar) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Use Msg_FooBar.Descriptor instead. func (Msg_FooBar) EnumDescriptor() ([]byte, []int) { return file_json_serialization_proto_rawDescGZIP(), []int{0, 0} } type Msg struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` PageNumber int32 `protobuf:"varint,2,opt,name=page_number,json=pageNumber,proto3" json:"page_number,omitempty"` Hell float64 `protobuf:"fixed64,3,opt,name=hell,proto3" json:"hell,omitempty"` Foobar Msg_FooBar `protobuf:"varint,4,opt,name=foobar,proto3,enum=Msg_FooBar" json:"foobar,omitempty"` Snippets []string `protobuf:"bytes,5,rep,name=snippets,proto3" json:"snippets,omitempty"` AllEmpty bool `protobuf:"varint,6,opt,name=all_empty,json=allEmpty,proto3" json:"all_empty,omitempty"` } func (x *Msg) Reset() { *x = Msg{} if protoimpl.UnsafeEnabled { mi := &file_json_serialization_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg) ProtoMessage() {} func (x *Msg) ProtoReflect() protoreflect.Message { mi := &file_json_serialization_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 Msg.ProtoReflect.Descriptor instead. func (*Msg) Descriptor() ([]byte, []int) { return file_json_serialization_proto_rawDescGZIP(), []int{0} } func (x *Msg) GetQuery() string { if x != nil { return x.Query } return "" } func (x *Msg) GetPageNumber() int32 { if x != nil { return x.PageNumber } return 0 } func (x *Msg) GetHell() float64 { if x != nil { return x.Hell } return 0 } func (x *Msg) GetFoobar() Msg_FooBar { if x != nil { return x.Foobar } return Msg_FOO } func (x *Msg) GetSnippets() []string { if x != nil { return x.Snippets } return nil } func (x *Msg) GetAllEmpty() bool { if x != nil { return x.AllEmpty } return false } type Result struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Result) Reset() { *x = Result{} if protoimpl.UnsafeEnabled { mi := &file_json_serialization_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Result) String() string { return protoimpl.X.MessageStringOf(x) } func (*Result) ProtoMessage() {} func (x *Result) ProtoReflect() protoreflect.Message { mi := &file_json_serialization_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 Result.ProtoReflect.Descriptor instead. func (*Result) Descriptor() ([]byte, []int) { return file_json_serialization_proto_rawDescGZIP(), []int{1} } var File_json_serialization_proto protoreflect.FileDescriptor var file_json_serialization_proto_rawDesc = []byte{ 0x0a, 0x18, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xca, 0x01, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x65, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x65, 0x6c, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x04, 0x68, 0x65, 0x6c, 0x6c, 0x12, 0x23, 0x0a, 0x06, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0b, 0x2e, 0x4d, 0x73, 0x67, 0x2e, 0x46, 0x6f, 0x6f, 0x42, 0x61, 0x72, 0x52, 0x06, 0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x6e, 0x69, 0x70, 0x70, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x73, 0x6e, 0x69, 0x70, 0x70, 0x65, 0x74, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x61, 0x6c, 0x6c, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x1a, 0x0a, 0x06, 0x46, 0x6f, 0x6f, 0x42, 0x61, 0x72, 0x12, 0x07, 0x0a, 0x03, 0x46, 0x4f, 0x4f, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x42, 0x41, 0x52, 0x10, 0x01, 0x22, 0x08, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x32, 0x2d, 0x0a, 0x11, 0x4a, 0x53, 0x4f, 0x4e, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x08, 0x45, 0x63, 0x68, 0x6f, 0x4a, 0x53, 0x4f, 0x4e, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x22, 0x00, 0x42, 0x15, 0x5a, 0x13, 0x2f, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x73, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_json_serialization_proto_rawDescOnce sync.Once file_json_serialization_proto_rawDescData = file_json_serialization_proto_rawDesc ) func file_json_serialization_proto_rawDescGZIP() []byte { file_json_serialization_proto_rawDescOnce.Do(func() { file_json_serialization_proto_rawDescData = protoimpl.X.CompressGZIP(file_json_serialization_proto_rawDescData) }) return file_json_serialization_proto_rawDescData } var file_json_serialization_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_json_serialization_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_json_serialization_proto_goTypes = []interface{}{ (Msg_FooBar)(0), // 0: Msg.FooBar (*Msg)(nil), // 1: Msg (*Result)(nil), // 2: Result } var file_json_serialization_proto_depIdxs = []int32{ 0, // 0: Msg.foobar:type_name -> Msg.FooBar 1, // 1: JSONSerialization.EchoJSON:input_type -> Msg 1, // 2: JSONSerialization.EchoJSON:output_type -> Msg 2, // [2:3] is the sub-list for method output_type 1, // [1:2] is the sub-list for method input_type 1, // [1:1] is the sub-list for extension type_name 1, // [1:1] is the sub-list for extension extendee 0, // [0:1] is the sub-list for field type_name } func init() { file_json_serialization_proto_init() } func file_json_serialization_proto_init() { if File_json_serialization_proto != nil { return } if !protoimpl.UnsafeEnabled { file_json_serialization_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_json_serialization_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Result); 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_json_serialization_proto_rawDesc, NumEnums: 1, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, GoTypes: file_json_serialization_proto_goTypes, DependencyIndexes: file_json_serialization_proto_depIdxs, EnumInfos: file_json_serialization_proto_enumTypes, MessageInfos: file_json_serialization_proto_msgTypes, }.Build() File_json_serialization_proto = out.File file_json_serialization_proto_rawDesc = nil file_json_serialization_proto_goTypes = nil file_json_serialization_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/json_serialization/json_serialization.proto ================================================ syntax = "proto3"; // Test JSON serialization for all types of fields option go_package = "/json_serialization"; service JSONSerialization{ rpc EchoJSON(Msg) returns (Msg) {} } message Msg { string query = 1; int32 page_number = 2; double hell = 3; enum FooBar { FOO = 0; BAR = 1; } FooBar foobar = 4; repeated string snippets = 5; bool all_empty = 6; } message Result { } ================================================ FILE: internal/twirptest/json_serialization/json_serialization.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: json_serialization.proto package json_serialization import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // =========================== // JSONSerialization Interface // =========================== type JSONSerialization interface { EchoJSON(context.Context, *Msg) (*Msg, error) } // ================================= // JSONSerialization Protobuf Client // ================================= type jSONSerializationProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewJSONSerializationProtobufClient creates a Protobuf client that implements the JSONSerialization interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewJSONSerializationProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) JSONSerialization { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "JSONSerialization") urls := [1]string{ serviceURL + "EchoJSON", } return &jSONSerializationProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *jSONSerializationProtobufClient) EchoJSON(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "JSONSerialization") ctx = ctxsetters.WithMethodName(ctx, "EchoJSON") caller := c.callEchoJSON if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callEchoJSON(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *jSONSerializationProtobufClient) callEchoJSON(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ============================= // JSONSerialization JSON Client // ============================= type jSONSerializationJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewJSONSerializationJSONClient creates a JSON client that implements the JSONSerialization interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewJSONSerializationJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) JSONSerialization { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "JSONSerialization") urls := [1]string{ serviceURL + "EchoJSON", } return &jSONSerializationJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *jSONSerializationJSONClient) EchoJSON(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "JSONSerialization") ctx = ctxsetters.WithMethodName(ctx, "EchoJSON") caller := c.callEchoJSON if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callEchoJSON(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *jSONSerializationJSONClient) callEchoJSON(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================================ // JSONSerialization Server Handler // ================================ type jSONSerializationServer struct { JSONSerialization interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewJSONSerializationServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewJSONSerializationServer(svc JSONSerialization, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &jSONSerializationServer{ JSONSerialization: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *jSONSerializationServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *jSONSerializationServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // JSONSerializationPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const JSONSerializationPathPrefix = "/twirp/JSONSerialization/" func (s *jSONSerializationServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "JSONSerialization") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "JSONSerialization" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "EchoJSON": s.serveEchoJSON(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *jSONSerializationServer) serveEchoJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveEchoJSONJSON(ctx, resp, req) case "application/protobuf": s.serveEchoJSONProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *jSONSerializationServer) serveEchoJSONJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "EchoJSON") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.JSONSerialization.EchoJSON if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.JSONSerialization.EchoJSON(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling EchoJSON. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *jSONSerializationServer) serveEchoJSONProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "EchoJSON") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.JSONSerialization.EchoJSON if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.JSONSerialization.EchoJSON(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling EchoJSON. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *jSONSerializationServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *jSONSerializationServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *jSONSerializationServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "", "JSONSerialization") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 267 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x64, 0x90, 0xcf, 0x4a, 0xf3, 0x40, 0x14, 0xc5, 0x3b, 0x5f, 0xfe, 0x7c, 0xc9, 0x2d, 0x48, 0xbd, 0x2a, 0x0c, 0x71, 0xe1, 0x10, 0x37, 0xb3, 0x31, 0x42, 0x7d, 0x02, 0x03, 0xed, 0x42, 0x68, 0x03, 0xd3, 0x9d, 0x9b, 0x30, 0x91, 0x31, 0x8d, 0x4c, 0x33, 0x71, 0x26, 0x59, 0xd4, 0x47, 0xf4, 0xa9, 0x24, 0xa9, 0x88, 0xe0, 0xe6, 0x72, 0x7e, 0xe7, 0xc0, 0xe5, 0xde, 0x03, 0xf4, 0xcd, 0x99, 0xb6, 0x74, 0xca, 0x36, 0x52, 0x37, 0x1f, 0xb2, 0x6f, 0x4c, 0x9b, 0x75, 0xd6, 0xf4, 0x26, 0xfd, 0x24, 0xe0, 0x6d, 0x5c, 0x8d, 0x97, 0x10, 0xbc, 0x0f, 0xca, 0x1e, 0x29, 0x61, 0x84, 0xc7, 0xe2, 0x04, 0x78, 0x03, 0xf3, 0x4e, 0xd6, 0xaa, 0x6c, 0x87, 0x43, 0xa5, 0x2c, 0xfd, 0xc7, 0x08, 0x0f, 0x04, 0x8c, 0xd6, 0x76, 0x72, 0x10, 0xc1, 0xdf, 0x2b, 0xad, 0xa9, 0xc7, 0x08, 0x27, 0x62, 0xd2, 0x78, 0x0b, 0xe1, 0xab, 0x31, 0x95, 0xb4, 0xd4, 0x67, 0x84, 0x9f, 0x2d, 0xe7, 0xd9, 0xc6, 0xd5, 0xd9, 0xda, 0x98, 0x5c, 0x5a, 0xf1, 0x1d, 0x61, 0x02, 0x91, 0x6b, 0x9b, 0xae, 0x53, 0xbd, 0xa3, 0x01, 0xf3, 0x78, 0x2c, 0x7e, 0x18, 0xaf, 0x21, 0x96, 0x5a, 0x97, 0xea, 0xd0, 0xf5, 0x47, 0x1a, 0x32, 0xc2, 0x23, 0x11, 0x49, 0xad, 0x57, 0x23, 0xa7, 0x09, 0x84, 0xa7, 0x55, 0xf8, 0x1f, 0xbc, 0x75, 0x51, 0x2c, 0x66, 0xa3, 0xc8, 0x1f, 0xc5, 0x82, 0xa4, 0x11, 0x84, 0x42, 0xb9, 0x41, 0xf7, 0xcb, 0x3b, 0x38, 0x7f, 0xda, 0x15, 0xdb, 0xdd, 0xef, 0x8f, 0x91, 0x42, 0xb4, 0x7a, 0xd9, 0x9b, 0x31, 0x40, 0x7f, 0x3c, 0x2a, 0x99, 0x66, 0x3a, 0xcb, 0xaf, 0x9e, 0x2f, 0xee, 0xff, 0x56, 0x54, 0x85, 0x53, 0x47, 0x0f, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0xc5, 0x38, 0x86, 0xbf, 0x3f, 0x01, 0x00, 0x00, } ================================================ FILE: internal/twirptest/json_serialization/json_serialization_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 json_serialization import ( bytes "bytes" "context" json "encoding/json" io "io" "net/http" "net/http/httptest" "testing" "github.com/twitchtv/twirp" ) type JSONSerializationService struct{} func (h *JSONSerializationService) EchoJSON(ctx context.Context, req *Msg) (*Msg, error) { if req.AllEmpty { return &Msg{}, nil } return &Msg{ Query: req.Query, PageNumber: req.PageNumber, Hell: req.Hell, Foobar: req.Foobar, Snippets: req.Snippets, }, nil } func TestJSONSerializationServiceWithDefaults(t *testing.T) { s := httptest.NewServer(NewJSONSerializationServer(&JSONSerializationService{})) defer s.Close() // Manual JSON request to get empty response // Response should include empty fields by default reqBody := bytes.NewBuffer([]byte( `{"allEmpty": true}`, )) req, _ := http.NewRequest("POST", s.URL+"/twirp/JSONSerialization/EchoJSON", reqBody) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("manual EchoJSON err=%q", err) } if resp.StatusCode != 200 { t.Fatalf("manual EchoJSON invalid status, have=%d, want=200", resp.StatusCode) } objmap := readJSONAsMap(t, resp.Body) for _, field := range []string{"query", "page_number", "hell", "foobar", "snippets", "all_empty"} { if _, ok := objmap[field]; !ok { t.Fatalf("expected JSON response to include field %q", field) } } // JSON Client client := NewJSONSerializationJSONClient(s.URL, http.DefaultClient) // Check empty fields msg, err := client.EchoJSON(context.Background(), &Msg{ AllEmpty: true, }) if err != nil { t.Fatalf("client.EchoJSON err=%q", err) } if have, want := msg.Query, ""; have != want { t.Fatalf("invalid msg.Query, have=%v, want=%v", have, want) } if have, want := msg.PageNumber, int32(0); have != want { t.Fatalf("invalid msg.PageNumber, have=%v, want=%v", have, want) } if have, want := msg.Hell, float64(0); have != want { t.Fatalf("invalid msg.Hell, have=%v, want=%v", have, want) } if have, want := msg.Foobar, Msg_FOO; have != want { t.Fatalf("invalid msg.Foobar, have=%v, want=%v", have, want) } if have, want := len(msg.Snippets), 0; have != want { t.Fatalf("invalid len(msg.Snippets), have=%v, want=%v", have, want) } // Check sending some values and reading the echo msg2, err := client.EchoJSON(context.Background(), &Msg{ Query: "my query", PageNumber: 33, Hell: 666.666, Foobar: Msg_BAR, Snippets: []string{"s1", "s2"}, }) if err != nil { t.Fatalf("client.DoJSON err=%q", err) } if have, want := msg2.Query, "my query"; have != want { t.Fatalf("invalid msg.Query, have=%v, want=%v", have, want) } if have, want := msg2.PageNumber, int32(33); have != want { t.Fatalf("invalid msg.PageNumber, have=%v, want=%v", have, want) } if have, want := msg2.Hell, 666.666; have != want { t.Fatalf("invalid msg.Hell, have=%v, want=%v", have, want) } if have, want := msg2.Foobar, Msg_BAR; have != want { t.Fatalf("invalid msg.Foobar, have=%v, want=%v", have, want) } if have, want := len(msg2.Snippets), 2; have != want { t.Fatalf("invalid len(msg.Snippets), have=%v, want=%v", have, want) } if have, want := msg2.Snippets[0], "s1"; have != want { t.Fatalf("invalid msg2.Snippets[0], have=%v, want=%v", have, want) } } func TestJSONSerializationServiceSkipDefaults(t *testing.T) { s := httptest.NewServer( NewJSONSerializationServer( &JSONSerializationService{}, twirp.WithServerJSONSkipDefaults(true), ), ) defer s.Close() // Manual JSON request to get empty response. // Response should skip empty fields, in this case be completely empty reqBody := bytes.NewBuffer([]byte( `{"allEmpty": true}`, )) req, _ := http.NewRequest("POST", s.URL+"/twirp/JSONSerialization/EchoJSON", reqBody) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("manual EchoJSON err=%q", err) } if resp.StatusCode != 200 { t.Fatalf("manual EchoJSON invalid status, have=%d, want=200", resp.StatusCode) } buf := new(bytes.Buffer) _, _ = buf.ReadFrom(resp.Body) if buf.String() != "{}" { t.Fatalf("manual EchoJSON response with JSONSkipDefaults expected to be '{}'. But it is=%q", buf.String()) } // JSON Client client := NewJSONSerializationJSONClient(s.URL, http.DefaultClient) // Check empty fields msg, err := client.EchoJSON(context.Background(), &Msg{ AllEmpty: true, }) if err != nil { t.Fatalf("client.DoJSON err=%q", err) } if have, want := msg.Query, ""; have != want { t.Fatalf("invalid msg.Query, have=%v, want=%v", have, want) } if have, want := msg.PageNumber, int32(0); have != want { t.Fatalf("invalid msg.PageNumber, have=%v, want=%v", have, want) } if have, want := msg.Hell, float64(0); have != want { t.Fatalf("invalid msg.Hell, have=%v, want=%v", have, want) } if have, want := msg.Foobar, Msg_FOO; have != want { t.Fatalf("invalid msg.Foobar, have=%v, want=%v", have, want) } if have, want := len(msg.Snippets), 0; have != want { t.Fatalf("invalid len(msg.Snippets), have=%v, want=%v", have, want) } // Check sending some values and reading the echo msg2, err := client.EchoJSON(context.Background(), &Msg{ Query: "my query", PageNumber: 33, Hell: 666.666, Foobar: Msg_BAR, Snippets: []string{"s1", "s2"}, }) if err != nil { t.Fatalf("client.DoJSON err=%q", err) } if have, want := msg2.Query, "my query"; have != want { t.Fatalf("invalid msg.Query, have=%v, want=%v", have, want) } if have, want := msg2.PageNumber, int32(33); have != want { t.Fatalf("invalid msg.PageNumber, have=%v, want=%v", have, want) } if have, want := msg2.Hell, 666.666; have != want { t.Fatalf("invalid msg.Hell, have=%v, want=%v", have, want) } if have, want := msg2.Foobar, Msg_BAR; have != want { t.Fatalf("invalid msg.Foobar, have=%v, want=%v", have, want) } if have, want := len(msg2.Snippets), 2; have != want { t.Fatalf("invalid len(msg.Snippets), have=%v, want=%v", have, want) } if have, want := msg2.Snippets[0], "s1"; have != want { t.Fatalf("invalid msg2.Snippets[0], have=%v, want=%v", have, want) } } func TestJSONSerializationCamelCase(t *testing.T) { s := httptest.NewServer( NewJSONSerializationServer( &JSONSerializationService{}, twirp.WithServerJSONCamelCaseNames(true), ), ) defer s.Close() reqBody := bytes.NewBuffer([]byte(`{"pageNumber": 123}`)) req, _ := http.NewRequest("POST", s.URL+"/twirp/JSONSerialization/EchoJSON", reqBody) req.Header.Set("Content-Type", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatalf("manual EchoJSON err=%q", err) } if resp.StatusCode != 200 { t.Fatalf("manual EchoJSON invalid status, have=%d, want=200", resp.StatusCode) } objmap := readJSONAsMap(t, resp.Body) // response includes camelCase names for _, field := range []string{"query", "pageNumber", "hell", "foobar", "snippets", "allEmpty"} { if _, ok := objmap[field]; !ok { t.Fatalf("expected JSON response to include camelCase field %q", field) } } // response does not include original snake_case names for _, field := range []string{"page_number", "all_empty"} { if _, ok := objmap[field]; ok { t.Fatalf("expected JSON response to NOT include snake_case field %q", field) } } } // // Test helpers // func readJSONAsMap(t *testing.T, body io.Reader) map[string]json.RawMessage { buf := new(bytes.Buffer) _, _ = buf.ReadFrom(body) var objmap map[string]json.RawMessage err := json.Unmarshal(buf.Bytes(), &objmap) if err != nil { t.Fatalf("json.Unmarshal err=%q", err) } return objmap } ================================================ FILE: internal/twirptest/multiple/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 multiple //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. multiple1.proto multiple2.proto ================================================ FILE: internal/twirptest/multiple/multiple1.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: multiple1.proto // Multiple proto files in one package package multiple import ( 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 Msg1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg1) Reset() { *x = Msg1{} if protoimpl.UnsafeEnabled { mi := &file_multiple1_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg1) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg1) ProtoMessage() {} func (x *Msg1) ProtoReflect() protoreflect.Message { mi := &file_multiple1_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 Msg1.ProtoReflect.Descriptor instead. func (*Msg1) Descriptor() ([]byte, []int) { return file_multiple1_proto_rawDescGZIP(), []int{0} } var File_multiple1_proto protoreflect.FileDescriptor var file_multiple1_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x22, 0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x31, 0x32, 0x60, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x31, 0x12, 0x58, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x1a, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x42, 0x0b, 0x5a, 0x09, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_multiple1_proto_rawDescOnce sync.Once file_multiple1_proto_rawDescData = file_multiple1_proto_rawDesc ) func file_multiple1_proto_rawDescGZIP() []byte { file_multiple1_proto_rawDescOnce.Do(func() { file_multiple1_proto_rawDescData = protoimpl.X.CompressGZIP(file_multiple1_proto_rawDescData) }) return file_multiple1_proto_rawDescData } var file_multiple1_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_multiple1_proto_goTypes = []interface{}{ (*Msg1)(nil), // 0: twirp.internal.twirptest.multiple.Msg1 } var file_multiple1_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.multiple.Svc1.Send:input_type -> twirp.internal.twirptest.multiple.Msg1 0, // 1: twirp.internal.twirptest.multiple.Svc1.Send:output_type -> twirp.internal.twirptest.multiple.Msg1 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_multiple1_proto_init() } func file_multiple1_proto_init() { if File_multiple1_proto != nil { return } if !protoimpl.UnsafeEnabled { file_multiple1_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg1); 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_multiple1_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_multiple1_proto_goTypes, DependencyIndexes: file_multiple1_proto_depIdxs, MessageInfos: file_multiple1_proto_msgTypes, }.Build() File_multiple1_proto = out.File file_multiple1_proto_rawDesc = nil file_multiple1_proto_goTypes = nil file_multiple1_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/multiple/multiple1.proto ================================================ syntax = "proto3"; // Multiple proto files in one package package twirp.internal.twirptest.multiple; option go_package = "/multiple"; message Msg1 {} service Svc1 { rpc Send(Msg1) returns (Msg1); } ================================================ FILE: internal/twirptest/multiple/multiple1.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: multiple1.proto // Multiple proto files in one package package multiple import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Svc1 Interface // ============== type Svc1 interface { Send(context.Context, *Msg1) (*Msg1, error) } // ==================== // Svc1 Protobuf Client // ==================== type svc1ProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc1ProtobufClient creates a Protobuf client that implements the Svc1 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvc1ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.multiple", "Svc1") urls := [1]string{ serviceURL + "Send", } return &svc1ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc1ProtobufClient) Send(ctx context.Context, in *Msg1) (*Msg1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc1ProtobufClient) callSend(ctx context.Context, in *Msg1) (*Msg1, error) { out := new(Msg1) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Svc1 JSON Client // ================ type svc1JSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc1JSONClient creates a JSON client that implements the Svc1 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvc1JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.multiple", "Svc1") urls := [1]string{ serviceURL + "Send", } return &svc1JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc1JSONClient) Send(ctx context.Context, in *Msg1) (*Msg1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc1JSONClient) callSend(ctx context.Context, in *Msg1) (*Msg1, error) { out := new(Msg1) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Svc1 Server Handler // =================== type svc1Server struct { Svc1 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvc1Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvc1Server(svc Svc1, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svc1Server{ Svc1: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svc1Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svc1Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // Svc1PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const Svc1PathPrefix = "/twirp/twirp.internal.twirptest.multiple.Svc1/" func (s *svc1Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc1") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.multiple.Svc1" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svc1Server) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc1Server) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg1) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc1.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return s.Svc1.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg1 and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc1Server) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg1) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc1.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return s.Svc1.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg1 and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc1Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svc1Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svc1Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.multiple", "Svc1") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 115 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcf, 0x2d, 0xcd, 0x29, 0xc9, 0x2c, 0xc8, 0x49, 0x35, 0xd4, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2c, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x60, 0x2a, 0x95, 0xd8, 0xb8, 0x58, 0x7c, 0x8b, 0xd3, 0x0d, 0x8d, 0x12, 0xb8, 0x58, 0x82, 0xcb, 0x92, 0x0d, 0x85, 0x22, 0xb8, 0x58, 0x82, 0x53, 0xf3, 0x52, 0x84, 0xd4, 0xf5, 0x08, 0xea, 0xd5, 0x03, 0x69, 0x94, 0x22, 0x56, 0xa1, 0x13, 0x77, 0x14, 0xa7, 0x3e, 0x4c, 0x24, 0x89, 0x0d, 0xec, 0x40, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0x1c, 0xeb, 0xea, 0x24, 0xb3, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/multiple/multiple2.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: multiple2.proto // Multiple proto files in one package package multiple import ( 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 Msg2 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg2) Reset() { *x = Msg2{} if protoimpl.UnsafeEnabled { mi := &file_multiple2_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg2) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg2) ProtoMessage() {} func (x *Msg2) ProtoReflect() protoreflect.Message { mi := &file_multiple2_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 Msg2.ProtoReflect.Descriptor instead. func (*Msg2) Descriptor() ([]byte, []int) { return file_multiple2_proto_rawDescGZIP(), []int{0} } var File_multiple2_proto protoreflect.FileDescriptor var file_multiple2_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x32, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x21, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x1a, 0x0f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x31, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x06, 0x0a, 0x04, 0x4d, 0x73, 0x67, 0x32, 0x32, 0xcc, 0x01, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x32, 0x12, 0x58, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x32, 0x1a, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x32, 0x12, 0x6a, 0x0a, 0x16, 0x53, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x1a, 0x27, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x2e, 0x4d, 0x73, 0x67, 0x31, 0x42, 0x0b, 0x5a, 0x09, 0x2f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_multiple2_proto_rawDescOnce sync.Once file_multiple2_proto_rawDescData = file_multiple2_proto_rawDesc ) func file_multiple2_proto_rawDescGZIP() []byte { file_multiple2_proto_rawDescOnce.Do(func() { file_multiple2_proto_rawDescData = protoimpl.X.CompressGZIP(file_multiple2_proto_rawDescData) }) return file_multiple2_proto_rawDescData } var file_multiple2_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_multiple2_proto_goTypes = []interface{}{ (*Msg2)(nil), // 0: twirp.internal.twirptest.multiple.Msg2 (*Msg1)(nil), // 1: twirp.internal.twirptest.multiple.Msg1 } var file_multiple2_proto_depIdxs = []int32{ 0, // 0: twirp.internal.twirptest.multiple.Svc2.Send:input_type -> twirp.internal.twirptest.multiple.Msg2 1, // 1: twirp.internal.twirptest.multiple.Svc2.SamePackageProtoImport:input_type -> twirp.internal.twirptest.multiple.Msg1 0, // 2: twirp.internal.twirptest.multiple.Svc2.Send:output_type -> twirp.internal.twirptest.multiple.Msg2 1, // 3: twirp.internal.twirptest.multiple.Svc2.SamePackageProtoImport:output_type -> twirp.internal.twirptest.multiple.Msg1 2, // [2:4] is the sub-list for method output_type 0, // [0:2] 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_multiple2_proto_init() } func file_multiple2_proto_init() { if File_multiple2_proto != nil { return } file_multiple1_proto_init() if !protoimpl.UnsafeEnabled { file_multiple2_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg2); 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_multiple2_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_multiple2_proto_goTypes, DependencyIndexes: file_multiple2_proto_depIdxs, MessageInfos: file_multiple2_proto_msgTypes, }.Build() File_multiple2_proto = out.File file_multiple2_proto_rawDesc = nil file_multiple2_proto_goTypes = nil file_multiple2_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/multiple/multiple2.proto ================================================ syntax = "proto3"; // Multiple proto files in one package package twirp.internal.twirptest.multiple; option go_package = "/multiple"; import "multiple1.proto"; message Msg2 {} service Svc2 { rpc Send(Msg2) returns (Msg2); rpc SamePackageProtoImport(Msg1) returns (Msg1); } ================================================ FILE: internal/twirptest/multiple/multiple2.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: multiple2.proto // Multiple proto files in one package package multiple import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Svc2 Interface // ============== type Svc2 interface { Send(context.Context, *Msg2) (*Msg2, error) SamePackageProtoImport(context.Context, *Msg1) (*Msg1, error) } // ==================== // Svc2 Protobuf Client // ==================== type svc2ProtobufClient struct { client HTTPClient urls [2]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvc2ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.multiple", "Svc2") urls := [2]string{ serviceURL + "Send", serviceURL + "SamePackageProtoImport", } return &svc2ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2ProtobufClient) Send(ctx context.Context, in *Msg2) (*Msg2, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg2) (*Msg2, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg2) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg2) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2ProtobufClient) callSend(ctx context.Context, in *Msg2) (*Msg2, error) { out := new(Msg2) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } func (c *svc2ProtobufClient) SamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "SamePackageProtoImport") caller := c.callSamePackageProtoImport if c.interceptor != nil { caller = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return c.callSamePackageProtoImport(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2ProtobufClient) callSamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { out := new(Msg1) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Svc2 JSON Client // ================ type svc2JSONClient struct { client HTTPClient urls [2]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvc2JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.multiple", "Svc2") urls := [2]string{ serviceURL + "Send", serviceURL + "SamePackageProtoImport", } return &svc2JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2JSONClient) Send(ctx context.Context, in *Msg2) (*Msg2, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg2) (*Msg2, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg2) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg2) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2JSONClient) callSend(ctx context.Context, in *Msg2) (*Msg2, error) { out := new(Msg2) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } func (c *svc2JSONClient) SamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "SamePackageProtoImport") caller := c.callSamePackageProtoImport if c.interceptor != nil { caller = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return c.callSamePackageProtoImport(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2JSONClient) callSamePackageProtoImport(ctx context.Context, in *Msg1) (*Msg1, error) { out := new(Msg1) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[1], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Svc2 Server Handler // =================== type svc2Server struct { Svc2 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvc2Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvc2Server(svc Svc2, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svc2Server{ Svc2: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svc2Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svc2Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // Svc2PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const Svc2PathPrefix = "/twirp/twirp.internal.twirptest.multiple.Svc2/" func (s *svc2Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.multiple") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.multiple.Svc2" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return case "SamePackageProtoImport": s.serveSamePackageProtoImport(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svc2Server) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc2Server) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg2) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc2.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg2) (*Msg2, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg2) when calling interceptor") } return s.Svc2.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg2) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg2 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg2 and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg2) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc2.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg2) (*Msg2, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg2) when calling interceptor") } return s.Svc2.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg2) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg2) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg2 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg2 and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) serveSamePackageProtoImport(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSamePackageProtoImportJSON(ctx, resp, req) case "application/protobuf": s.serveSamePackageProtoImportProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc2Server) serveSamePackageProtoImportJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "SamePackageProtoImport") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg1) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc2.SamePackageProtoImport if s.interceptor != nil { handler = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return s.Svc2.SamePackageProtoImport(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg1 and nil error while calling SamePackageProtoImport. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) serveSamePackageProtoImportProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "SamePackageProtoImport") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg1) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc2.SamePackageProtoImport if s.interceptor != nil { handler = func(ctx context.Context, req *Msg1) (*Msg1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg1) when calling interceptor") } return s.Svc2.SamePackageProtoImport(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg1 and nil error while calling SamePackageProtoImport. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor1, 0 } func (s *svc2Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svc2Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.multiple", "Svc2") } var twirpFileDescriptor1 = []byte{ // 153 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0xcf, 0x2d, 0xcd, 0x29, 0xc9, 0x2c, 0xc8, 0x49, 0x35, 0xd2, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x52, 0x2c, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0x60, 0x2a, 0xa5, 0xe0, 0x7a, 0x0c, 0x21, 0x7a, 0x94, 0xd8, 0xb8, 0x58, 0x7c, 0x8b, 0xd3, 0x8d, 0x8c, 0xce, 0x30, 0x72, 0xb1, 0x04, 0x97, 0x25, 0x1b, 0x09, 0x45, 0x70, 0xb1, 0x04, 0xa7, 0xe6, 0xa5, 0x08, 0xa9, 0xeb, 0x11, 0x34, 0x4d, 0x0f, 0xa4, 0x53, 0x8a, 0x58, 0x85, 0x42, 0x59, 0x5c, 0x62, 0xc1, 0x89, 0xb9, 0xa9, 0x01, 0x89, 0xc9, 0xd9, 0x89, 0xe9, 0xa9, 0x01, 0x20, 0xeb, 0x3d, 0x73, 0x0b, 0xf2, 0x8b, 0x4a, 0x88, 0xb5, 0xcb, 0x90, 0x58, 0xbb, 0x0c, 0x9d, 0xb8, 0xa3, 0x38, 0xf5, 0x61, 0x22, 0x49, 0x6c, 0x60, 0xaf, 0x1a, 0x03, 0x02, 0x00, 0x00, 0xff, 0xff, 0x7b, 0x20, 0x14, 0xe1, 0x31, 0x01, 0x00, 0x00, } ================================================ FILE: internal/twirptest/multiple/multiple_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 multiple import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/no_package_name/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 no_package_name //go:generate protoc --go_out=module=github.com/twitchtv/twirp/internal/twirptest/no_package_name:. --twirp_out=module=github.com/twitchtv/twirp/internal/twirptest/no_package_name:. no_package_name.proto ================================================ FILE: internal/twirptest/no_package_name/no_package_name.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: no_package_name.proto package no_package_name import ( 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 Msg struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg) Reset() { *x = Msg{} if protoimpl.UnsafeEnabled { mi := &file_no_package_name_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg) ProtoMessage() {} func (x *Msg) ProtoReflect() protoreflect.Message { mi := &file_no_package_name_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 Msg.ProtoReflect.Descriptor instead. func (*Msg) Descriptor() ([]byte, []int) { return file_no_package_name_proto_rawDescGZIP(), []int{0} } var File_no_package_name_proto protoreflect.FileDescriptor var file_no_package_name_proto_rawDesc = []byte{ 0x0a, 0x15, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x19, 0x0a, 0x03, 0x53, 0x76, 0x63, 0x12, 0x12, 0x0a, 0x04, 0x53, 0x65, 0x6e, 0x64, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x3e, 0x5a, 0x3c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_no_package_name_proto_rawDescOnce sync.Once file_no_package_name_proto_rawDescData = file_no_package_name_proto_rawDesc ) func file_no_package_name_proto_rawDescGZIP() []byte { file_no_package_name_proto_rawDescOnce.Do(func() { file_no_package_name_proto_rawDescData = protoimpl.X.CompressGZIP(file_no_package_name_proto_rawDescData) }) return file_no_package_name_proto_rawDescData } var file_no_package_name_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_no_package_name_proto_goTypes = []interface{}{ (*Msg)(nil), // 0: Msg } var file_no_package_name_proto_depIdxs = []int32{ 0, // 0: Svc.Send:input_type -> Msg 0, // 1: Svc.Send:output_type -> Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_no_package_name_proto_init() } func file_no_package_name_proto_init() { if File_no_package_name_proto != nil { return } if !protoimpl.UnsafeEnabled { file_no_package_name_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg); 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_no_package_name_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_no_package_name_proto_goTypes, DependencyIndexes: file_no_package_name_proto_depIdxs, MessageInfos: file_no_package_name_proto_msgTypes, }.Build() File_no_package_name_proto = out.File file_no_package_name_proto_rawDesc = nil file_no_package_name_proto_goTypes = nil file_no_package_name_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/no_package_name/no_package_name.proto ================================================ syntax = "proto3"; // No package name option go_package = "github.com/twitchtv/twirp/internal/twirptest/no_package_name"; message Msg {} service Svc { rpc Send(Msg) returns(Msg); } ================================================ FILE: internal/twirptest/no_package_name/no_package_name.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: no_package_name.proto package no_package_name import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============= // Svc Interface // ============= type Svc interface { Send(context.Context, *Msg) (*Msg, error) } // =================== // Svc Protobuf Client // =================== type svcProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcProtobufClient creates a Protobuf client that implements the Svc interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvcProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcProtobufClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcProtobufClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =============== // Svc JSON Client // =============== type svcJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvcJSONClient creates a JSON client that implements the Svc interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvcJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Svc") urls := [1]string{ serviceURL + "Send", } return &svcJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svcJSONClient) Send(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithMethodName(ctx, "Send") caller := c.callSend if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callSend(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svcJSONClient) callSend(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================== // Svc Server Handler // ================== type svcServer struct { Svc interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvcServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvcServer(svc Svc, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svcServer{ Svc: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svcServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svcServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // SvcPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const SvcPathPrefix = "/twirp/Svc/" func (s *svcServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "Svc" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Send": s.serveSend(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svcServer) serveSend(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveSendJSON(ctx, resp, req) case "application/protobuf": s.serveSendProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svcServer) serveSendJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) serveSendProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Send") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc.Send if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Svc.Send(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Send. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svcServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svcServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svcServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "", "Svc") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 128 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcd, 0xcb, 0x8f, 0x2f, 0x48, 0x4c, 0xce, 0x4e, 0x4c, 0x4f, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x62, 0xe5, 0x62, 0xf6, 0x2d, 0x4e, 0x37, 0x92, 0xe4, 0x62, 0x0e, 0x2e, 0x4b, 0x16, 0x12, 0xe2, 0x62, 0x09, 0x4e, 0xcd, 0x4b, 0x11, 0x62, 0xd1, 0xf3, 0x2d, 0x4e, 0x97, 0x02, 0x93, 0x4e, 0x76, 0x51, 0x36, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x25, 0xe5, 0x99, 0x25, 0xc9, 0x19, 0x25, 0x65, 0x20, 0x46, 0x51, 0x81, 0x7e, 0x66, 0x5e, 0x49, 0x6a, 0x51, 0x5e, 0x62, 0x0e, 0x84, 0x5b, 0x92, 0x5a, 0x5c, 0xa2, 0x8f, 0x66, 0x4f, 0x12, 0x1b, 0xd8, 0x22, 0x63, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xaa, 0x74, 0xcd, 0x8f, 0x81, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/no_package_name_importer/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 no_package_name_importer import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/no_package_name_importer/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 no_package_name_importer //go:generate protoc --proto_path=../ --go_out=module=github.com/twitchtv/twirp/internal/twirptest:../ --twirp_out=module=github.com/twitchtv/twirp/internal/twirptest:../ ../no_package_name_importer/no_package_name_importer.proto ================================================ FILE: internal/twirptest/no_package_name_importer/no_package_name_importer.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: no_package_name_importer/no_package_name_importer.proto package no_package_name_importer import ( no_package_name "github.com/twitchtv/twirp/internal/twirptest/no_package_name" protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" ) 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) ) var File_no_package_name_importer_no_package_name_importer_proto protoreflect.FileDescriptor var file_no_package_name_importer_no_package_name_importer_proto_rawDesc = []byte{ 0x0a, 0x37, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x25, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x32, 0x1c, 0x0a, 0x04, 0x53, 0x76, 0x63, 0x32, 0x12, 0x14, 0x0a, 0x06, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x42, 0x47, 0x5a, 0x45, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x74, 0x77, 0x69, 0x74, 0x63, 0x68, 0x74, 0x76, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2f, 0x6e, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var file_no_package_name_importer_no_package_name_importer_proto_goTypes = []interface{}{ (*no_package_name.Msg)(nil), // 0: Msg } var file_no_package_name_importer_no_package_name_importer_proto_depIdxs = []int32{ 0, // 0: Svc2.Method:input_type -> Msg 0, // 1: Svc2.Method:output_type -> Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_no_package_name_importer_no_package_name_importer_proto_init() } func file_no_package_name_importer_no_package_name_importer_proto_init() { if File_no_package_name_importer_no_package_name_importer_proto != nil { return } type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_no_package_name_importer_no_package_name_importer_proto_rawDesc, NumEnums: 0, NumMessages: 0, NumExtensions: 0, NumServices: 1, }, GoTypes: file_no_package_name_importer_no_package_name_importer_proto_goTypes, DependencyIndexes: file_no_package_name_importer_no_package_name_importer_proto_depIdxs, }.Build() File_no_package_name_importer_no_package_name_importer_proto = out.File file_no_package_name_importer_no_package_name_importer_proto_rawDesc = nil file_no_package_name_importer_no_package_name_importer_proto_goTypes = nil file_no_package_name_importer_no_package_name_importer_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/no_package_name_importer/no_package_name_importer.proto ================================================ syntax = "proto3"; // Import another proto file that doesn't have a package name import "no_package_name/no_package_name.proto"; // import is relative to protoc's option --proto_path option go_package = "github.com/twitchtv/twirp/internal/twirptest/no_package_name_importer"; service Svc2 { rpc Method(Msg) returns (Msg); } ================================================ FILE: internal/twirptest/no_package_name_importer/no_package_name_importer.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: no_package_name_importer/no_package_name_importer.proto package no_package_name_importer import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import no_package_name "github.com/twitchtv/twirp/internal/twirptest/no_package_name" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Svc2 Interface // ============== type Svc2 interface { Method(context.Context, *no_package_name.Msg) (*no_package_name.Msg, error) } // ==================== // Svc2 Protobuf Client // ==================== type svc2ProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2ProtobufClient creates a Protobuf client that implements the Svc2 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewSvc2ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Svc2") urls := [1]string{ serviceURL + "Method", } return &svc2ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2ProtobufClient) Method(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Method") caller := c.callMethod if c.interceptor != nil { caller = func(ctx context.Context, req *no_package_name.Msg) (*no_package_name.Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*no_package_name.Msg) when calling interceptor") } return c.callMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*no_package_name.Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2ProtobufClient) callMethod(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { out := new(no_package_name.Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Svc2 JSON Client // ================ type svc2JSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewSvc2JSONClient creates a JSON client that implements the Svc2 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewSvc2JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Svc2 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Svc2") urls := [1]string{ serviceURL + "Method", } return &svc2JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *svc2JSONClient) Method(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithMethodName(ctx, "Method") caller := c.callMethod if c.interceptor != nil { caller = func(ctx context.Context, req *no_package_name.Msg) (*no_package_name.Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*no_package_name.Msg) when calling interceptor") } return c.callMethod(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*no_package_name.Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *svc2JSONClient) callMethod(ctx context.Context, in *no_package_name.Msg) (*no_package_name.Msg, error) { out := new(no_package_name.Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Svc2 Server Handler // =================== type svc2Server struct { Svc2 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewSvc2Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewSvc2Server(svc Svc2, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &svc2Server{ Svc2: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *svc2Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *svc2Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // Svc2PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const Svc2PathPrefix = "/twirp/Svc2/" func (s *svc2Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Svc2") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "Svc2" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Method": s.serveMethod(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *svc2Server) serveMethod(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveMethodJSON(ctx, resp, req) case "application/protobuf": s.serveMethodProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *svc2Server) serveMethodJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Method") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(no_package_name.Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Svc2.Method if s.interceptor != nil { handler = func(ctx context.Context, req *no_package_name.Msg) (*no_package_name.Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*no_package_name.Msg) when calling interceptor") } return s.Svc2.Method(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*no_package_name.Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *no_package_name.Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *no_package_name.Msg and nil error while calling Method. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) serveMethodProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Method") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(no_package_name.Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Svc2.Method if s.interceptor != nil { handler = func(ctx context.Context, req *no_package_name.Msg) (*no_package_name.Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*no_package_name.Msg) when calling interceptor") } return s.Svc2.Method(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*no_package_name.Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*no_package_name.Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *no_package_name.Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *no_package_name.Msg and nil error while calling Method. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *svc2Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *svc2Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *svc2Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "", "Svc2") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 143 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x32, 0xcf, 0xcb, 0x8f, 0x2f, 0x48, 0x4c, 0xce, 0x4e, 0x4c, 0x4f, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0x8d, 0xcf, 0xcc, 0x2d, 0xc8, 0x2f, 0x2a, 0x49, 0x2d, 0xd2, 0xc7, 0x25, 0xa1, 0x57, 0x50, 0x94, 0x5f, 0x92, 0x2f, 0xa5, 0x8a, 0x26, 0x8f, 0xae, 0x1e, 0xa2, 0xcc, 0x48, 0x86, 0x8b, 0x25, 0xb8, 0x2c, 0xd9, 0x48, 0x48, 0x84, 0x8b, 0xcd, 0x37, 0xb5, 0x24, 0x23, 0x3f, 0x45, 0x88, 0x45, 0xcf, 0xb7, 0x38, 0x5d, 0x0a, 0x4c, 0x3a, 0xb9, 0x47, 0xb9, 0xa6, 0x67, 0x96, 0x64, 0x94, 0x26, 0xe9, 0x25, 0xe7, 0xe7, 0xea, 0x97, 0x94, 0x67, 0x96, 0x24, 0x67, 0x94, 0x94, 0x81, 0x18, 0x45, 0x05, 0xfa, 0x99, 0x79, 0x25, 0xa9, 0x45, 0x79, 0x89, 0x39, 0x10, 0x6e, 0x49, 0x6a, 0x71, 0x09, 0x4e, 0x37, 0x25, 0xb1, 0x81, 0x6d, 0x33, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xef, 0x2f, 0x52, 0x09, 0xcf, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/service.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: service.proto package twirptest import ( 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 Hat struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"` Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"` Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` } func (x *Hat) Reset() { *x = Hat{} if protoimpl.UnsafeEnabled { mi := &file_service_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Hat) String() string { return protoimpl.X.MessageStringOf(x) } func (*Hat) ProtoMessage() {} func (x *Hat) ProtoReflect() protoreflect.Message { mi := &file_service_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 Hat.ProtoReflect.Descriptor instead. func (*Hat) Descriptor() ([]byte, []int) { return file_service_proto_rawDescGZIP(), []int{0} } func (x *Hat) GetSize() int32 { if x != nil { return x.Size } return 0 } func (x *Hat) GetColor() string { if x != nil { return x.Color } return "" } func (x *Hat) GetName() string { if x != nil { return x.Name } return "" } type Size struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Inches int32 `protobuf:"varint,1,opt,name=inches,proto3" json:"inches,omitempty"` } func (x *Size) Reset() { *x = Size{} if protoimpl.UnsafeEnabled { mi := &file_service_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Size) String() string { return protoimpl.X.MessageStringOf(x) } func (*Size) ProtoMessage() {} func (x *Size) ProtoReflect() protoreflect.Message { mi := &file_service_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 Size.ProtoReflect.Descriptor instead. func (*Size) Descriptor() ([]byte, []int) { return file_service_proto_rawDescGZIP(), []int{1} } func (x *Size) GetInches() int32 { if x != nil { return x.Inches } return 0 } var File_service_proto protoreflect.FileDescriptor var file_service_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x22, 0x43, 0x0a, 0x03, 0x48, 0x61, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x1e, 0x0a, 0x04, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x32, 0x57, 0x0a, 0x0b, 0x48, 0x61, 0x62, 0x65, 0x72, 0x64, 0x61, 0x73, 0x68, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x07, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x12, 0x1e, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x69, 0x7a, 0x65, 0x1a, 0x1d, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x48, 0x61, 0x74, 0x42, 0x0c, 0x5a, 0x0a, 0x2f, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_service_proto_rawDescOnce sync.Once file_service_proto_rawDescData = file_service_proto_rawDesc ) func file_service_proto_rawDescGZIP() []byte { file_service_proto_rawDescOnce.Do(func() { file_service_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_proto_rawDescData) }) return file_service_proto_rawDescData } var file_service_proto_msgTypes = make([]protoimpl.MessageInfo, 2) var file_service_proto_goTypes = []interface{}{ (*Hat)(nil), // 0: twirp.internal.twirptest.Hat (*Size)(nil), // 1: twirp.internal.twirptest.Size } var file_service_proto_depIdxs = []int32{ 1, // 0: twirp.internal.twirptest.Haberdasher.MakeHat:input_type -> twirp.internal.twirptest.Size 0, // 1: twirp.internal.twirptest.Haberdasher.MakeHat:output_type -> twirp.internal.twirptest.Hat 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_service_proto_init() } func file_service_proto_init() { if File_service_proto != nil { return } if !protoimpl.UnsafeEnabled { file_service_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Hat); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_service_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Size); 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_service_proto_rawDesc, NumEnums: 0, NumMessages: 2, NumExtensions: 0, NumServices: 1, }, GoTypes: file_service_proto_goTypes, DependencyIndexes: file_service_proto_depIdxs, MessageInfos: file_service_proto_msgTypes, }.Build() File_service_proto = out.File file_service_proto_rawDesc = nil file_service_proto_goTypes = nil file_service_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/service.proto ================================================ syntax = "proto3"; package twirp.internal.twirptest; option go_package = "/twirptest"; message Hat { int32 size = 1; string color = 2; string name = 3; } message Size { int32 inches = 1; } // A Haberdasher makes hats for clients. service Haberdasher { // MakeHat produces a hat of mysterious, randomly-selected color! rpc MakeHat(Size) returns (Hat); } ================================================ FILE: internal/twirptest/service.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: service.proto package twirptest import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ===================== // Haberdasher Interface // ===================== // A Haberdasher makes hats for clients. type Haberdasher interface { // MakeHat produces a hat of mysterious, randomly-selected color! MakeHat(context.Context, *Size) (*Hat, error) } // =========================== // Haberdasher Protobuf Client // =========================== type haberdasherProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherProtobufClient creates a Protobuf client that implements the Haberdasher interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewHaberdasherProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Haberdasher { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest", "Haberdasher") urls := [1]string{ serviceURL + "MakeHat", } return &haberdasherProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherProtobufClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithMethodName(ctx, "MakeHat") caller := c.callMakeHat if c.interceptor != nil { caller = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return c.callMakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherProtobufClient) callMakeHat(ctx context.Context, in *Size) (*Hat, error) { out := new(Hat) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ======================= // Haberdasher JSON Client // ======================= type haberdasherJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherJSONClient creates a JSON client that implements the Haberdasher interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewHaberdasherJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Haberdasher { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest", "Haberdasher") urls := [1]string{ serviceURL + "MakeHat", } return &haberdasherJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherJSONClient) MakeHat(ctx context.Context, in *Size) (*Hat, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithMethodName(ctx, "MakeHat") caller := c.callMakeHat if c.interceptor != nil { caller = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return c.callMakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherJSONClient) callMakeHat(ctx context.Context, in *Size) (*Hat, error) { out := new(Hat) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ========================== // Haberdasher Server Handler // ========================== type haberdasherServer struct { Haberdasher interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewHaberdasherServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewHaberdasherServer(svc Haberdasher, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &haberdasherServer{ Haberdasher: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *haberdasherServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *haberdasherServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // HaberdasherPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const HaberdasherPathPrefix = "/twirp/twirp.internal.twirptest.Haberdasher/" func (s *haberdasherServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest") ctx = ctxsetters.WithServiceName(ctx, "Haberdasher") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.Haberdasher" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "MakeHat": s.serveMakeHat(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *haberdasherServer) serveMakeHat(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveMakeHatJSON(ctx, resp, req) case "application/protobuf": s.serveMakeHatProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *haberdasherServer) serveMakeHatJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHat") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Size) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Haberdasher.MakeHat if s.interceptor != nil { handler = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return s.Haberdasher.MakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Hat func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Hat and nil error while calling MakeHat. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherServer) serveMakeHatProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHat") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Size) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Haberdasher.MakeHat if s.interceptor != nil { handler = func(ctx context.Context, req *Size) (*Hat, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Size) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Size) when calling interceptor") } return s.Haberdasher.MakeHat(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Hat) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Hat) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Hat func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Hat and nil error while calling MakeHat. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *haberdasherServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *haberdasherServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest", "Haberdasher") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 187 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x2d, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x28, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0x94, 0x9c, 0xb9, 0x98, 0x3d, 0x12, 0x4b, 0x84, 0x84, 0xb8, 0x58, 0x8a, 0x33, 0xab, 0x52, 0x25, 0x18, 0x15, 0x18, 0x35, 0x58, 0x83, 0xc0, 0x6c, 0x21, 0x11, 0x2e, 0xd6, 0xe4, 0xfc, 0x9c, 0xfc, 0x22, 0x09, 0x26, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x08, 0x07, 0xa4, 0x32, 0x2f, 0x31, 0x37, 0x55, 0x82, 0x19, 0x2c, 0x08, 0x66, 0x2b, 0xc9, 0x71, 0xb1, 0x04, 0x83, 0x74, 0x88, 0x71, 0xb1, 0x65, 0xe6, 0x25, 0x67, 0xa4, 0x16, 0x43, 0xcd, 0x81, 0xf2, 0x8c, 0xc2, 0xb9, 0xb8, 0x3d, 0x12, 0x93, 0x52, 0x8b, 0x52, 0x12, 0x8b, 0x33, 0x52, 0x8b, 0x84, 0x3c, 0xb8, 0xd8, 0x7d, 0x13, 0xb3, 0x53, 0x41, 0xf6, 0xca, 0xe9, 0xe1, 0x72, 0x99, 0x1e, 0xc8, 0x44, 0x29, 0x59, 0xdc, 0xf2, 0x1e, 0x89, 0x25, 0x4e, 0x3c, 0x51, 0x5c, 0xfa, 0x70, 0x91, 0x24, 0x36, 0xb0, 0x67, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xba, 0x05, 0x11, 0xed, 0xfd, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/service_method_same_name/compile_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 service_method_same_name import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/service_method_same_name/gen.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 service_method_same_name //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. service_method_same_name.proto ================================================ FILE: internal/twirptest/service_method_same_name/service_method_same_name.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: service_method_same_name.proto package service_method_same_name import ( 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 Msg struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *Msg) Reset() { *x = Msg{} if protoimpl.UnsafeEnabled { mi := &file_service_method_same_name_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Msg) String() string { return protoimpl.X.MessageStringOf(x) } func (*Msg) ProtoMessage() {} func (x *Msg) ProtoReflect() protoreflect.Message { mi := &file_service_method_same_name_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 Msg.ProtoReflect.Descriptor instead. func (*Msg) Descriptor() ([]byte, []int) { return file_service_method_same_name_proto_rawDescGZIP(), []int{0} } var File_service_method_same_name_proto protoreflect.FileDescriptor var file_service_method_same_name_proto_rawDesc = []byte{ 0x0a, 0x1e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x05, 0x0a, 0x03, 0x4d, 0x73, 0x67, 0x32, 0x1c, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x14, 0x0a, 0x04, 0x45, 0x63, 0x68, 0x6f, 0x12, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x1a, 0x04, 0x2e, 0x4d, 0x73, 0x67, 0x22, 0x00, 0x42, 0x1b, 0x5a, 0x19, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x73, 0x61, 0x6d, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_service_method_same_name_proto_rawDescOnce sync.Once file_service_method_same_name_proto_rawDescData = file_service_method_same_name_proto_rawDesc ) func file_service_method_same_name_proto_rawDescGZIP() []byte { file_service_method_same_name_proto_rawDescOnce.Do(func() { file_service_method_same_name_proto_rawDescData = protoimpl.X.CompressGZIP(file_service_method_same_name_proto_rawDescData) }) return file_service_method_same_name_proto_rawDescData } var file_service_method_same_name_proto_msgTypes = make([]protoimpl.MessageInfo, 1) var file_service_method_same_name_proto_goTypes = []interface{}{ (*Msg)(nil), // 0: Msg } var file_service_method_same_name_proto_depIdxs = []int32{ 0, // 0: Echo.Echo:input_type -> Msg 0, // 1: Echo.Echo:output_type -> Msg 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_service_method_same_name_proto_init() } func file_service_method_same_name_proto_init() { if File_service_method_same_name_proto != nil { return } if !protoimpl.UnsafeEnabled { file_service_method_same_name_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Msg); 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_service_method_same_name_proto_rawDesc, NumEnums: 0, NumMessages: 1, NumExtensions: 0, NumServices: 1, }, GoTypes: file_service_method_same_name_proto_goTypes, DependencyIndexes: file_service_method_same_name_proto_depIdxs, MessageInfos: file_service_method_same_name_proto_msgTypes, }.Build() File_service_method_same_name_proto = out.File file_service_method_same_name_proto_rawDesc = nil file_service_method_same_name_proto_goTypes = nil file_service_method_same_name_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/service_method_same_name/service_method_same_name.proto ================================================ syntax = "proto3"; // Test to make sure that a method with the same name as its service doesn't break. option go_package = "/service_method_same_name"; message Msg {} service Echo { rpc Echo(Msg) returns (Msg) {} } ================================================ FILE: internal/twirptest/service_method_same_name/service_method_same_name.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: service_method_same_name.proto package service_method_same_name import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ============== // Echo Interface // ============== type Echo interface { Echo(context.Context, *Msg) (*Msg, error) } // ==================== // Echo Protobuf Client // ==================== type echoProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewEchoProtobufClient creates a Protobuf client that implements the Echo interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewEchoProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Echo { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Echo") urls := [1]string{ serviceURL + "Echo", } return &echoProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *echoProtobufClient) Echo(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Echo") ctx = ctxsetters.WithMethodName(ctx, "Echo") caller := c.callEcho if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callEcho(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *echoProtobufClient) callEcho(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ================ // Echo JSON Client // ================ type echoJSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewEchoJSONClient creates a JSON client that implements the Echo interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewEchoJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) Echo { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) serviceURL += baseServicePath(pathPrefix, "", "Echo") urls := [1]string{ serviceURL + "Echo", } return &echoJSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *echoJSONClient) Echo(ctx context.Context, in *Msg) (*Msg, error) { ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Echo") ctx = ctxsetters.WithMethodName(ctx, "Echo") caller := c.callEcho if c.interceptor != nil { caller = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return c.callEcho(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *echoJSONClient) callEcho(ctx context.Context, in *Msg) (*Msg, error) { out := new(Msg) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // =================== // Echo Server Handler // =================== type echoServer struct { Echo interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewEchoServer builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewEchoServer(svc Echo, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &echoServer{ Echo: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *echoServer) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *echoServer) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // EchoPathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const EchoPathPrefix = "/twirp/Echo/" func (s *echoServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "") ctx = ctxsetters.WithServiceName(ctx, "Echo") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "Echo" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "Echo": s.serveEcho(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *echoServer) serveEcho(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveEchoJSON(ctx, resp, req) case "application/protobuf": s.serveEchoProtobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *echoServer) serveEchoJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Echo") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(Msg) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.Echo.Echo if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Echo.Echo(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Echo. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *echoServer) serveEchoProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "Echo") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(Msg) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.Echo.Echo if s.interceptor != nil { handler = func(ctx context.Context, req *Msg) (*Msg, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion req.(*Msg) when calling interceptor") } return s.Echo.Echo(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*Msg) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*Msg) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *Msg func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *Msg and nil error while calling Echo. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *echoServer) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *echoServer) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *echoServer) PathPrefix() string { return baseServicePath(s.pathPrefix, "", "Echo") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 97 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x2b, 0x4e, 0x2d, 0x2a, 0xcb, 0x4c, 0x4e, 0x8d, 0xcf, 0x4d, 0x2d, 0xc9, 0xc8, 0x4f, 0x89, 0x2f, 0x4e, 0xcc, 0x4d, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0xd5, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x62, 0xe5, 0x62, 0xf6, 0x2d, 0x4e, 0x37, 0x92, 0xe1, 0x62, 0x71, 0x4d, 0xce, 0xc8, 0x17, 0x12, 0x81, 0xd2, 0x2c, 0x7a, 0xbe, 0xc5, 0xe9, 0x52, 0x60, 0x52, 0x89, 0xc1, 0x49, 0x3a, 0x4a, 0x52, 0x1f, 0x97, 0x39, 0x49, 0x6c, 0x60, 0x83, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0x97, 0x74, 0x2e, 0x74, 0x6a, 0x00, 0x00, 0x00, } ================================================ FILE: internal/twirptest/service_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirptest import ( "bytes" "context" "crypto/tls" "errors" "fmt" "io" "log" "net/http" "net/http/httptest" "os" "reflect" "regexp" "strings" "sync" "testing" "time" pkgerrors "github.com/pkg/errors" "google.golang.org/protobuf/encoding/protojson" "github.com/twitchtv/twirp" "github.com/twitchtv/twirp/internal/descriptors" ) func TestServeJSON(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, nil)) defer s.Close() client := NewHaberdasherJSONClient(s.URL, http.DefaultClient) hat, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("JSON Client err=%q", err) } if hat.Size != 1 { t.Errorf("wrong hat size returned") } _, err = client.MakeHat(context.Background(), &Size{Inches: -1}) if err == nil { t.Errorf("JSON Client expected err, got nil") } } func TestServerJSONWithMalformedRequest(t *testing.T) { // Trivial Haberdasher server h := HaberdasherFunc(func(ctx context.Context, s *Size) (*Hat, error) { return &Hat{}, nil }) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() // Make JSON request with incorrectly-typed field reqJSON := `{"inches":"should_be_number"}` url := s.URL + HaberdasherPathPrefix + "MakeHat" resp, err := http.Post(url, "application/json", bytes.NewBufferString(reqJSON)) if err != nil { t.Fatalf("Unexpected error: %q", err.Error()) } defer func() { if err = resp.Body.Close(); err != nil { t.Fatalf("Closing body: %q", err.Error()) } }() // Make sure that a 400 status code was returned if resp.StatusCode != http.StatusBadRequest { t.Fatalf("Expected 400 BadRequest when sending malformed request, got %d", resp.StatusCode) } // Make sure the response is meaningful respBytes, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Could not even read bytes from response: %q", err.Error()) } if !strings.Contains(string(respBytes), "the json request could not be decoded") { t.Fatalf(`Expected response to contain "the json request could not be decoded", got: %q`, string(respBytes)) } } func TestServerJSONWithUnknownFields(t *testing.T) { // Haberdasher server that returns same size it was requested h := HaberdasherFunc(func(ctx context.Context, s *Size) (*Hat, error) { return &Hat{Size: s.Inches}, nil }) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() // Make JSON request with unknown fields ("size" should default to zero-value) reqJSON := `{"unknown_field1":"foo", "EXTRASTUFF":"bar"}` url := s.URL + HaberdasherPathPrefix + "MakeHat" resp, err := http.Post(url, "application/json", bytes.NewBufferString(reqJSON)) if err != nil { t.Fatalf("Unexpected error: %q", err.Error()) } defer func() { if err = resp.Body.Close(); err != nil { t.Fatalf("Closing body: %q", err.Error()) } }() // Make sure that the returned hat is valid and has empty (zero-value) size respBytes, err := io.ReadAll(resp.Body) // read manually first in case jsonpb.Unmarshal so it can be printed for debugging if err != nil { t.Fatalf("Could not even read bytes from response: %q", err.Error()) } hat := new(Hat) if err = protojson.Unmarshal(respBytes, hat); err != nil { t.Fatalf("Could not unmarshall response as Hat: %s", respBytes) } if hat.Size != 0 { t.Errorf("Expected empty size (zero-value), found %q", hat.Size) } } func TestServerProtobufMalformedRequest(t *testing.T) { // Trivial Haberdasher server h := HaberdasherFunc(func(ctx context.Context, s *Size) (*Hat, error) { return &Hat{}, nil }) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() url := s.URL + HaberdasherPathPrefix + "MakeHat" resp, err := http.Post(url, "application/protobuf", bytes.NewBuffer([]byte{1})) if err != nil { t.Fatalf("Unexpected error: %q", err.Error()) } defer func() { if err = resp.Body.Close(); err != nil { t.Fatalf("Closing body: %q", err.Error()) } }() // Make sure that a 400 status code was returned if resp.StatusCode != http.StatusBadRequest { t.Fatalf("Expected 400 BadRequest when sending malformed request, got %d", resp.StatusCode) } // Make sure the response is meaningful respBytes, err := io.ReadAll(resp.Body) if err != nil { t.Fatalf("Could not even read bytes from response: %q", err.Error()) } if !strings.Contains(string(respBytes), "the protobuf request could not be decoded") { t.Fatalf(`Expected response to contain "the protobuf request could not be decoded", got: %q`, string(respBytes)) } } func TestServeProtobuf(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() client := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) hat, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("Protobuf Client err=%q", err) } if hat.Size != 1 { t.Errorf("wrong hat size returned") } _, err = client.MakeHat(context.Background(), &Size{Inches: -1}) if err == nil { t.Errorf("Protobuf Client expected err, got nil") } } type contentTypeOverriderClient struct { contentType string base HTTPClient } func (c *contentTypeOverriderClient) Do(req *http.Request) (*http.Response, error) { req.Header.Set("Content-Type", c.contentType) return c.base.Do(req) } func TestContentTypes(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() makeClientWithMimeType := func(mime string) Haberdasher { return NewHaberdasherJSONClient(s.URL, &contentTypeOverriderClient{ contentType: mime, base: http.DefaultClient, }) } expectNoError := func(t *testing.T, mime string) { _, err := makeClientWithMimeType(mime).MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("Client using valid mime type %s err=%q", mime, err) } } validMimeTypes := []string{ "application/json; charset=UTF-8", "application/json", } for _, mime := range validMimeTypes { expectNoError(t, mime) } invalidMimeTypes := []string{ "application/jsonp", } for _, mime := range invalidMimeTypes { expectBadRouteError(t, makeClientWithMimeType(mime)) } } func TestDeadline(t *testing.T) { timeout := 1 * time.Millisecond responseTime := 50 * timeout h := SlowHatmaker(responseTime) s, client := ServerAndClient(h, nil) defer s.Close() ctx := context.Background() ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() done := make(chan struct{}) go func() { _, err := client.MakeHat(ctx, &Size{Inches: 1}) if err == nil { t.Errorf("should have timed out, but got nil err") } close(done) }() select { case <-done: // pass case <-time.After(responseTime): t.Errorf("should have timed out within %s, but %s has elapsed!", timeout, responseTime) } } // helper type for the requestRecorder to keep track of which hooks have been // called. type hookCall string const ( received hookCall = "RequestReceived" routed hookCall = "RequestRouted" prepared hookCall = "ResponsePrepared" sent hookCall = "ResponseSent" errored hookCall = "Error" ) type requestRecorder struct { sync.Mutex calls []hookCall } func (r *requestRecorder) reset() { r.Lock() r.calls = nil r.Unlock() } func (r *requestRecorder) assertHookCalls(t *testing.T, want []hookCall) { r.Lock() defer r.Unlock() if len(r.calls) != len(want) { t.Error("hook calls are wrong") t.Logf("have: %v", r.calls) t.Logf("want: %v", want) t.FailNow() } for i, haveCall := range r.calls { wantCall := want[i] if haveCall != wantCall { t.Error("hook calls are wrong") t.Logf("have: %v", r.calls) t.Logf("want: %v", want) t.FailNow() } } } func recorderHooks() (*twirp.ServerHooks, *requestRecorder) { recs := &requestRecorder{} hooks := &twirp.ServerHooks{ RequestReceived: func(ctx context.Context) (context.Context, error) { recs.Lock() recs.calls = append(recs.calls, received) recs.Unlock() return ctx, nil }, RequestRouted: func(ctx context.Context) (context.Context, error) { recs.Lock() recs.calls = append(recs.calls, routed) recs.Unlock() return ctx, nil }, ResponsePrepared: func(ctx context.Context) context.Context { recs.Lock() recs.calls = append(recs.calls, prepared) recs.Unlock() return ctx }, ResponseSent: func(ctx context.Context) { recs.Lock() recs.calls = append(recs.calls, sent) recs.Unlock() }, Error: func(ctx context.Context, _ twirp.Error) context.Context { recs.Lock() recs.calls = append(recs.calls, errored) recs.Unlock() return ctx }, } return hooks, recs } func TestHooks(t *testing.T) { hooks, recorder := recorderHooks() h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, hooks)) defer s.Close() client := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) t.Run("happy path", func(t *testing.T) { recorder.reset() _, clientErr := client.MakeHat(context.Background(), &Size{Inches: 1}) if clientErr != nil { t.Fatalf("client err=%q", clientErr) } recorder.assertHookCalls(t, []hookCall{ received, routed, prepared, sent, }) }) t.Run("application error", func(t *testing.T) { recorder.reset() _, clientErr := client.MakeHat(context.Background(), &Size{Inches: -1}) if clientErr == nil { t.Fatal("client err expected with negative Size parameter, but have nil") } recorder.assertHookCalls(t, []hookCall{ received, routed, errored, sent, }) }) t.Run("bad http method", func(t *testing.T) { recorder.reset() // Use a client that sends GET requests instead of POST. rw := &reqRewriter{ base: http.DefaultTransport, rewrite: func(r *http.Request) *http.Request { r.Method = "GET" return r }, } httpClient := &http.Client{Transport: rw} client := NewHaberdasherProtobufClient(s.URL, httpClient) _, clientErr := client.MakeHat(context.Background(), &Size{Inches: -1}) if clientErr == nil { t.Fatal("client err expected with bad HTTP method, but have nil") } recorder.assertHookCalls(t, []hookCall{ received, errored, sent, }) }) t.Run("bad url", func(t *testing.T) { recorder.reset() // Use a client that sends requests to the wrong URL rw := &reqRewriter{ base: http.DefaultTransport, rewrite: func(r *http.Request) *http.Request { r.URL.Path = r.URL.Path + "bogus" return r }, } httpClient := &http.Client{Transport: rw} client := NewHaberdasherProtobufClient(s.URL, httpClient) _, clientErr := client.MakeHat(context.Background(), &Size{Inches: -1}) if clientErr == nil { t.Fatal("client err expected with bad URL, but have nil") } recorder.assertHookCalls(t, []hookCall{ received, errored, sent, }) }) t.Run("missing headers", func(t *testing.T) { recorder.reset() // Use a client that sends requests without headers rw := &reqRewriter{ base: http.DefaultTransport, rewrite: func(r *http.Request) *http.Request { r.Header = make(http.Header) return r }, } httpClient := &http.Client{Transport: rw} client := NewHaberdasherProtobufClient(s.URL, httpClient) _, clientErr := client.MakeHat(context.Background(), &Size{Inches: -1}) if clientErr == nil { t.Fatal("client err expected with missing headers, but have nil") } recorder.assertHookCalls(t, []hookCall{ received, errored, sent, }) }) t.Run("partial request body", func(t *testing.T) { recorder.reset() // Use a client that sends 1 byte of the body and then stops rw := &reqRewriter{ base: http.DefaultTransport, rewrite: func(r *http.Request) *http.Request { r.ContentLength = 1 r.Body = io.NopCloser(io.LimitReader(r.Body, 1)) return r }, } httpClient := &http.Client{Transport: rw} client := NewHaberdasherProtobufClient(s.URL, httpClient) _, clientErr := client.MakeHat(context.Background(), &Size{Inches: -1}) if clientErr == nil { t.Fatal("client err expected with partial request body, but have nil") } recorder.assertHookCalls(t, []hookCall{ received, routed, errored, sent, }) }) } // Test that a Twirp server will work even if it receives a ServiceHooks with a // nil function for one of its hooks. func TestNilHooks(t *testing.T) { var testcase = func(hooks *twirp.ServerHooks) func(*testing.T) { return func(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, hooks)) defer s.Close() c := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) _, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("client err=%q", err) } } } h, _ := recorderHooks() h.RequestReceived = nil t.Run("nil RequestReceived", testcase(h)) h, _ = recorderHooks() h.RequestRouted = nil t.Run("nil RequestRouted", testcase(h)) h, _ = recorderHooks() h.ResponsePrepared = nil t.Run("nil ResponsePrepared", testcase(h)) h, _ = recorderHooks() h.ResponseSent = nil t.Run("nil ResponseSent", testcase(h)) h, _ = recorderHooks() h.Error = nil t.Run("nil Error", testcase(h)) } func TestErroringHooks(t *testing.T) { t.Run("RequestReceived error", func(t *testing.T) { // Set up hooks that error on request received. The request should be // aborted at that point, the Error hook should be triggered, and the client // should see an error. hooks := &twirp.ServerHooks{} hookErr := twirp.NewError(twirp.Unauthenticated, "error in hook") errorHookCalled := false hooks.RequestReceived = func(ctx context.Context) (context.Context, error) { return ctx, hookErr } hooks.RequestRouted = func(ctx context.Context) (context.Context, error) { t.Errorf("request was routed") return ctx, nil } hooks.Error = func(ctx context.Context, err twirp.Error) context.Context { if err != hookErr { t.Errorf("Error hook did not receive error from RequestReceived. have=%v, want=%v", err, hookErr) } errorHookCalled = true return ctx } h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, hooks)) defer s.Close() c := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) _, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatalf("client err=nil, expected=%v", hookErr) } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("client err type=%T, expected twirp.Error", err) } if twerr.Code() != twirp.Unauthenticated { t.Errorf("client err code=%v, expected=%v", twerr.Code(), twirp.Unauthenticated) } if !errorHookCalled { t.Error("Error hook was not triggered") } }) t.Run("RequestRouted error", func(t *testing.T) { // Set up hooks that error on request routed. The request should be aborted // at that point, the Error hook should be triggered, and the client should // see an error. hooks := &twirp.ServerHooks{} hookErr := twirp.NewError(twirp.Unauthenticated, "error in hook") errorHookCalled := false hooks.RequestRouted = func(ctx context.Context) (context.Context, error) { return ctx, hookErr } hooks.Error = func(ctx context.Context, err twirp.Error) context.Context { if err != hookErr { t.Errorf("Error hook did not receive error from RequestRouted. have=%v, want=%v", err, hookErr) } errorHookCalled = true return ctx } h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h, hooks)) defer s.Close() c := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) _, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatalf("client err=nil, expected=%v", hookErr) } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("client err type=%T, expected twirp.Error", err) } if twerr.Code() != twirp.Unauthenticated { t.Errorf("client err code=%v, expected=%v", twerr.Code(), twirp.Unauthenticated) } if !errorHookCalled { t.Error("Error hook was not triggered") } }) } func TestInterceptor(t *testing.T) { interceptor := func(next twirp.Method) twirp.Method { return func(ctx context.Context, request interface{}) (interface{}, error) { methodName, _ := twirp.MethodName(ctx) if methodName != "MakeHat" { return nil, fmt.Errorf("unexpected methodName: %q", methodName) } serviceName, _ := twirp.ServiceName(ctx) if serviceName != "Haberdasher" { return nil, fmt.Errorf("unexpected serviceName: %q", serviceName) } packageName, _ := twirp.PackageName(ctx) if packageName != "twirp.internal.twirptest" { return nil, fmt.Errorf("unexpected packageName: %q", packageName) } size, ok := request.(*Size) if !ok { return nil, fmt.Errorf("could not cast %T to a *Size", request) } size.Inches = size.Inches + 1 response, err := next(ctx, request) hat, ok := response.(*Hat) if ok && hat != nil { hat.Color = hat.Color + "x" return hat, err } return nil, err } } h := PickyHatmaker(3) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() client := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) hat, clientErr := client.MakeHat(context.Background(), &Size{Inches: 3}) if clientErr != nil { t.Fatalf("client err=%q", clientErr) } if hat.Size != 3 { t.Errorf("hat size expected=3 actual=%v", hat.Size) } s = httptest.NewServer( NewHaberdasherServer( h, twirp.WithServerInterceptors( interceptor, interceptor, ), ), ) defer s.Close() client = NewHaberdasherProtobufClient(s.URL, http.DefaultClient) hat, clientErr = client.MakeHat(context.Background(), &Size{Inches: 1}) if clientErr != nil { t.Fatalf("client err=%q", clientErr) } if hat.Size != 3 { t.Errorf("hat size expected=3 actual=%v", hat.Size) } if hat.Color != "bluexx" { t.Errorf("hat color expected=bluexx actual=%v", hat.Color) } _, clientErr = client.MakeHat(context.Background(), &Size{Inches: 3}) twerr, ok := clientErr.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", clientErr) } if twerr.Code() != twirp.InvalidArgument { t.Errorf("expected error type to be InvalidArgument, buf found %q", twerr.Code()) } } func TestInternalErrorPassing(t *testing.T) { e := twirp.InternalError("fatal :(") h := ErroringHatmaker(e) s, c := ServerAndClient(h, nil) defer s.Close() _, err := c.MakeHat(context.Background(), &Size{}) if err == nil { t.Fatal("expected err, have nil") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.Internal { t.Errorf("expected error type to be Internal, buf found %q", twerr.Code()) } if twerr.Meta("retryable") != "" { t.Errorf("expected error to be non-retryable, but it is (should not have meta)") } if twerr.Msg() != "fatal :(" { t.Errorf("expected error message to be passed through, but have=%q", twerr.Msg()) } } func TestErrorWithRetryableMeta(t *testing.T) { eMsg := "try again!" e := twirp.NewError(twirp.Unavailable, eMsg) e = e.WithMeta("retryable", "true") h := ErroringHatmaker(e) s, c := ServerAndClient(h, nil) defer s.Close() _, err := c.MakeHat(context.Background(), &Size{}) if err == nil { t.Fatal("expected err, have nil") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Meta("retryable") != "true" { t.Errorf("expected error to be retryable, but it isnt") } if twerr.Msg() != eMsg { t.Errorf("expected error Msg to be %q, but found %q", eMsg, twerr.Msg()) } } func TestErrorCodePassing(t *testing.T) { e := twirp.NewError(twirp.AlreadyExists, "hand-picked ErrorCode") h := ErroringHatmaker(e) s, c := ServerAndClient(h, nil) defer s.Close() _, err := c.MakeHat(context.Background(), &Size{}) if err == nil { t.Fatal("expected err, have nil") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.AlreadyExists { t.Errorf("expected ErrorCode to be passed through to the client to be %q, but have %q", twirp.AlreadyExists, twerr.Code()) } } // Non twirp errors returned by the servers should become twirp Internal errors. func TestNonTwirpErrorWrappedAsInternal(t *testing.T) { e := errors.New("I am not a twirp error, should become internal") h := ErroringHatmaker(e) s, c := ServerAndClient(h, nil) defer s.Close() _, err := c.MakeHat(context.Background(), &Size{}) if err == nil { t.Fatal("expected err, found nil") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected error type to be 'twirp.Error', but found %T", err) } if twerr.Code() != twirp.Internal { t.Errorf("expected ErrorCode to be %q, but found %q", twirp.Internal, twerr.Code()) } if twerr.Msg() != e.Error() { // NOTE: that twerr.Error() is not e.Error() because it has a "twirp error Internal: *" prefix t.Errorf("expected Msg to be %q, but found %q", e.Error(), twerr.Msg()) } } // Clients should be able to connect over HTTPS func TestConnectTLS(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewUnstartedServer(NewHaberdasherServer(h)) s.TLS = &tls.Config{} s.StartTLS() defer s.Close() if !strings.HasPrefix(s.URL, "https") { t.Fatal("test server not serving over HTTPS") } httpsClient := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, }, } client := NewHaberdasherJSONClient(s.URL, httpsClient) hat, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Fatalf("JSON Client err=%q", err) } if hat.Size != 1 { t.Errorf("wrong hat size returned") } _, err = client.MakeHat(context.Background(), &Size{Inches: -1}) if err == nil { t.Errorf("JSON Client expected err, got nil") } } func TestRoutingPathPrefix(t *testing.T) { ctx := context.Background() r := &Size{Inches: 1} myCustomPrefix := "/my/custom/prefix" h := PickyHatmaker(1) server := NewHaberdasherServer(h, twirp.WithServerPathPrefix(myCustomPrefix)) if have, want := server.PathPrefix(), "/my/custom/prefix/twirp.internal.twirptest.Haberdasher/"; have != want { t.Fatalf("invalid server.PathPrefix(), have=%q, want=%q", have, want) } var lastPath string pathTracker := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { lastPath = r.URL.Path server.ServeHTTP(w, r) }) s := httptest.NewServer(pathTracker) defer s.Close() // Clients need to use the same prefix to hit the service c1 := NewHaberdasherJSONClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix(myCustomPrefix)) if _, err := c1.MakeHat(ctx, r); err != nil { t.Fatalf("Routing err: %v", err) } if have, want := lastPath, "/my/custom/prefix/twirp.internal.twirptest.Haberdasher/MakeHat"; have != want { t.Fatalf("invalid URL path, have=%q, want=%q", have, want) } // Clients using the default "/twirp" prefix should not hit the service c2 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) if _, err := c2.MakeHat(ctx, r); err == nil { t.Fatalf("Expected bad_route error because service has a different path prefix, got nil") } if have, want := lastPath, "/twirp/twirp.internal.twirptest.Haberdasher/MakeHat"; have != want { t.Fatalf("invalid URL path, have=%q, want=%q", have, want) } // Clients using no prefix (empty) should not hit the service c3 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("")) if _, err := c3.MakeHat(ctx, r); err == nil { t.Fatalf("Expected bad_route error because service has a different path prefix, got nil") } if have, want := lastPath, "/twirp.internal.twirptest.Haberdasher/MakeHat"; have != want { t.Fatalf("invalid URL path, have=%q, want=%q", have, want) } } func TestRoutingPathPrefixDefault(t *testing.T) { ctx := context.Background() r := &Size{Inches: 1} server := NewHaberdasherServer(PickyHatmaker(1)) s := httptest.NewServer(server) defer s.Close() // Check default value if have, want := server.PathPrefix(), "/twirp/twirp.internal.twirptest.Haberdasher/"; have != want { t.Fatalf("invalid server.PathPrefix(), have=%q, want=%q", have, want) } // Clients use the /twirp prefix by default c1 := NewHaberdasherJSONClient(s.URL, http.DefaultClient) if _, err := c1.MakeHat(ctx, r); err != nil { t.Fatalf("Routing err: %v", err) } // Clients can specifically set the "/twirp" prefix c2 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/twirp")) if _, err := c2.MakeHat(ctx, r); err != nil { t.Fatalf("Routing err: %v", err) } // Clients using a different prefix do not hit the service c3 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/anotherprefix")) if _, err := c3.MakeHat(ctx, r); err == nil { t.Fatalf("Expected bad_route error because service has a different path prefix, got nil") } } // Twirp routes with prefixes: []/./ // using a mux to match the same prefix on the server func TestMuxingRoutingPathPrefixes(t *testing.T) { ctx := context.Background() mux := http.NewServeMux() // Handle route prefix, using the same prefix on the server: only hats of size 1 server1 := NewHaberdasherServer(PickyHatmaker(1), twirp.WithServerPathPrefix("/pickyone")) mux.Handle("/pickyone/", server1) // Handle route prefix, using the .PathPrefix() method on the server: only hats of size 99 server99 := NewHaberdasherServer(PickyHatmaker(99), twirp.WithServerPathPrefix("/pickyninenine")) mux.Handle(server99.PathPrefix(), server99) // Handle route with no prefix: hats of size zero server0 := NewHaberdasherServer(PickyHatmaker(0), twirp.WithServerPathPrefix("")) mux.Handle("/", server0) s := httptest.NewServer(mux) defer s.Close() // Client with default baseURL and /twirp prefix is not able to hit any service c1 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) if _, err := c1.MakeHat(ctx, &Size{Inches: 1}); err == nil { t.Fatalf("Expected routing error, got nil") } // Client with custom prefix hits one server, but not the others c2 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/pickyone")) if _, err := c2.MakeHat(ctx, &Size{Inches: 1}); err != nil { t.Fatalf("Unexpected err: %v", err) } if _, err := c2.MakeHat(ctx, &Size{Inches: 99}); err == nil { // PickyHatmaker(1) returns an error with size 99 t.Fatalf("Expected picky hat size error, got nil") } // Client with custom prefix on the picky 99 c3 := NewHaberdasherJSONClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/pickyninenine")) if _, err := c3.MakeHat(ctx, &Size{Inches: 99}); err != nil { t.Fatalf("Unexpected err: %v", err) } if _, err := c3.MakeHat(ctx, &Size{Inches: 1}); err == nil { // PickyHatmaker(99) returns an error with size 1 t.Fatalf("Expected picky hat size error, got nil") } // Client with mepty prefix should hit picky 0 c4 := NewHaberdasherJSONClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("")) if _, err := c4.MakeHat(ctx, &Size{Inches: 0}); err != nil { t.Fatalf("Unexpected err: %v", err) } if _, err := c4.MakeHat(ctx, &Size{Inches: 1}); err == nil { // PickyHatmaker(0) returns an error with size 1 t.Fatalf("Expected picky hat size error, got nil") } // Nested prefixes should not work, even if they math the mux routing rules. // This is needed to ensure backwards compatibility with the previous mandatory /twirp prefix. c5 := NewHaberdasherProtobufClient(s.URL, http.DefaultClient, twirp.WithClientPathPrefix("/pickyone/but/way/too/nested")) if _, err := c5.MakeHat(ctx, &Size{Inches: 1}); err == nil { // should return bad route error t.Fatalf("Expected bad route error, got nil") } else { twerr, ok := err.(twirp.Error) if !ok || twerr.Code() != twirp.BadRoute { t.Fatalf("Expected bad route error, got %v", err) } } } // It should be possible to serve twirp alongside non-twirp handlers func TestMuxingTwirpServerConst(t *testing.T) { // Create a twirp endpoint. twirpHandler := NewHaberdasherServer(PickyHatmaker(1)) testMuxingTwirpServer(t, HaberdasherPathPrefix, twirpHandler) } func TestMuxingTwirpServerPrefixMethod(t *testing.T) { // Create a twirp endpoint. twirpHandler := NewHaberdasherServer(PickyHatmaker(1)) testMuxingTwirpServer(t, twirpHandler.PathPrefix(), twirpHandler) } func testMuxingTwirpServer(t *testing.T, prefix string, handler TwirpServer) { // Create a healthcheck endpoint. Record that it got called in a boolean. healthcheckCalled := false healthcheck := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { healthcheckCalled = true w.WriteHeader(200) _, err := w.Write([]byte("Looking good, Louis!")) if err != nil { t.Errorf("err writing response: %s", err) } }) // Serve the healthcheck at /health and the twirp handler at the // provided URL prefix. mux := http.NewServeMux() mux.Handle("/health", healthcheck) mux.Handle(prefix, handler) s := httptest.NewServer(mux) defer s.Close() // Try to do a twirp request. It should get routed just fine. client := NewHaberdasherJSONClient(s.URL, http.DefaultClient) _, twerr := client.MakeHat(context.Background(), &Size{Inches: 1}) if twerr != nil { t.Errorf("twirp client err=%q", twerr) } // Try to request the /health endpoint. It should get routed just // fine too. resp, err := http.Get(s.URL + "/health") if err != nil { t.Errorf("health check endpoint err=%q", err) } else { if resp.StatusCode != 200 { body, err := io.ReadAll(resp.Body) t.Errorf("got a non-200 response from /health: %d", resp.StatusCode) t.Logf("response body: %s", body) t.Logf("response read err: %s", err) } if !healthcheckCalled { t.Error("health check endpoint was never called") } } } // Default ContextSource should be RequestContextSource, this means that // when serving in a mux with middleware, the modified request context should // be available on the method handler. func TestMuxingTwirpServerDefaultRequestContext(t *testing.T) { handlerCalled := false // to verity that the handler assertions were executed (avoid false positives) // Make a handler that can check if the context was modified twirpHandler := NewHaberdasherServer(HaberdasherFunc(func(ctx context.Context, s *Size) (*Hat, error) { handlerCalled = true // verify it was called if ctx.Value("modified by middleware") != "yes" { t.Error("expected ctx to be modified by the middleware") } return &Hat{Size: 999}, nil }), nil) // Wrap with middleware that modifies the request context middlewareWrapper := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r = r.WithContext(context.WithValue(r.Context(), "modified by middleware", "yes")) twirpHandler.ServeHTTP(w, r) }) // Serve in a mux mux := http.NewServeMux() mux.Handle(HaberdasherPathPrefix, middlewareWrapper) s := httptest.NewServer(mux) defer s.Close() // And make a request to run the expectations client := NewHaberdasherJSONClient(s.URL, http.DefaultClient) _, twerr := client.MakeHat(context.Background(), &Size{Inches: 1}) if twerr != nil { t.Errorf("twirp client err=%q", twerr) } if !handlerCalled { t.Error("For some reason the twirp request did not make it to the handler") } } // WriteError should allow middleware to easily respond with a properly formatted error response func TestWriteErrorFromHTTPMiddleware(t *testing.T) { // Make a fake server that returns a Twirp error from the HTTP stack, without using an actual Twirp implementation. mux := http.NewServeMux() mux.HandleFunc(HaberdasherPathPrefix+"MakeHat", func(w http.ResponseWriter, r *http.Request) { WriteError(w, twirp.NewError(twirp.Unauthenticated, "You Shall Not Pass!!!")) }) server := httptest.NewServer(mux) defer server.Close() // A Twirp client is still able to receive the error client := NewHaberdasherJSONClient(server.URL, http.DefaultClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatal("an error was expected") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.Unauthenticated { t.Errorf("twirp ErrorCode expected to be %q, but found %q", twirp.Unauthenticated, twerr.Code()) } if twerr.Msg() != "You Shall Not Pass!!!" { t.Errorf("twirp client err has unexpected message %q, want %q", twerr.Msg(), "You Shall Not Pass!!!") } } // WriteError wraps non-twirp errors as twirp.Internal func TestWriteErrorFromHTTPMiddlewareInternal(t *testing.T) { // Make a fake server that returns an error from the HTTP stack, without using an actual Twirp implementation. mux := http.NewServeMux() mux.HandleFunc(HaberdasherPathPrefix+"MakeHat", func(w http.ResponseWriter, r *http.Request) { WriteError(w, errors.New("should become a twirp.Internal")) }) server := httptest.NewServer(mux) defer server.Close() // A Twirp client is still able to receive the error as a twirp.Internal client := NewHaberdasherJSONClient(server.URL, http.DefaultClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatal("an error was expected") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.Internal { t.Errorf("twirp ErrorCode expected to be %q, but found %q", twirp.Internal, twerr.Code()) } if twerr.Msg() != "should become a twirp.Internal" { t.Errorf("twirp client err has unexpected message %q, want %q", twerr.Msg(), "should become a twirp.Internal") } } // If an application panics in its handler, it should return an internal error with "Internal service panic" msg. func TestPanicsReturnInternalErrors(t *testing.T) { hooks, recorder := recorderHooks() s := NewHaberdasherServer(PanickyHatmaker("OH NO!"), hooks) // Wrap the twirp server with a handler to stop the panicking from // crashing the httptest server and failing our test. h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r == nil { t.Error("http server never panicked") } }() s.ServeHTTP(w, r) }) server := httptest.NewServer(h) defer server.Close() client := NewHaberdasherJSONClient(server.URL, http.DefaultClient) hat, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Logf("hat: %+v", hat) t.Fatal("twirp client err is nil for panicking handler") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.Internal { t.Errorf("twirp ErrorCode expected to be %q, but found %q", twirp.Internal, twerr.Code()) } if twerr.Msg() != "Internal service panic" { t.Errorf("twirp client err has unexpected message %q, want %q", twerr.Msg(), "Internal service panic") } recorder.assertHookCalls(t, []hookCall{received, routed, errored, sent}) } // If an application panics in its handler, the Error hooks should trigger and have access to the panic source. func TestPanicsTriggerErrorHooks(t *testing.T) { panicValue := errors.New("This Is Fine Meme") errHookCalled := false errHook := &twirp.ServerHooks{ Error: func(ctx context.Context, twerr twirp.Error) context.Context { errHookCalled = true // The error should have a .Cause containing the panic value for inspection err := pkgerrors.Cause(twerr) if err != panicValue { t.Fatalf("Unexpected error cause from panic: %v", err) } return ctx }, } s := NewHaberdasherServer(PanickyHatmaker(panicValue), errHook) // Wrap the twirp server with a handler to stop the panicking from // crashing the httptest server and failing our test. h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if r := recover(); r == nil { t.Error("http server never panicked") } }() s.ServeHTTP(w, r) }) server := httptest.NewServer(h) defer server.Close() clients := map[string]Haberdasher{ "protobuf": NewHaberdasherProtobufClient(server.URL, http.DefaultClient), "json": NewHaberdasherJSONClient(server.URL, http.DefaultClient), } for name, c := range clients { _, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatalf("%s client: err was expected for panicking handler, found nil", name) } if !errHookCalled { t.Fatalf("%s client: expected error hook to be called for panicking handler", name) } errHookCalled = false // Reset for the next loop iteration twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("%s client: expected twirp.Error type error, have %T", name, err) } if twerr.Code() != twirp.Internal { t.Errorf("%s client: ErrorCode expected to be %q, but found %q", name, twirp.Internal, twerr.Code()) } if twerr.Msg() != "Internal service panic" { t.Errorf("%s client: err has unexpected message %q, want %q", name, twerr.Msg(), "Internal service panic") } } } func TestCustomRequestHeaders(t *testing.T) { // Create a set of headers to be sent on all requests customHeader := make(http.Header) customHeader.Set("key1", "val1") customHeader.Add("multikey", "val1") customHeader.Add("multikey", "val2") haberdasher := NewHaberdasherServer(PickyHatmaker(1)) // Make a wrapping handler that checks headers for this test handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // All key-vals in the custom header should appear in the request for k, v := range customHeader { if !reflect.DeepEqual(r.Header[k], v) { t.Errorf("missing header key=%q wanted-val=%q have-val=%q", k, v, r.Header[k]) } } haberdasher.ServeHTTP(w, r) }) s := httptest.NewServer(handler) defer s.Close() clients := map[string]Haberdasher{ "protobuf": NewHaberdasherProtobufClient(s.URL, http.DefaultClient), "json": NewHaberdasherJSONClient(s.URL, http.DefaultClient), } for name, c := range clients { t.Logf("client=%q", name) ctx := context.Background() ctx, err := twirp.WithHTTPRequestHeaders(ctx, customHeader) if err != nil { t.Fatalf("%q client WithHTTPRequestHeaders err=%q", name, err) } _, err = c.MakeHat(ctx, &Size{Inches: 1}) if err != nil { t.Errorf("%q client err=%q", name, err) } } } func TestCustomResponseHeaders(t *testing.T) { // service that adds headers key1 and key2 haberdasher := NewHaberdasherServer(HaberdasherFunc(func(ctx context.Context, s *Size) (*Hat, error) { var err error errMsg := "unexpected error returned by SetHTTPResponseHeader: " err = twirp.SetHTTPResponseHeader(ctx, "key1", "val1") if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.SetHTTPResponseHeader(ctx, "key2", "before_override") if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.SetHTTPResponseHeader(ctx, "key2", "val2") // should override if err != nil { t.Fatalf(errMsg + err.Error()) } childContext := context.WithValue(ctx, "foo", "var") err = twirp.SetHTTPResponseHeader(childContext, "key3", "val3") if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.SetHTTPResponseHeader(context.Background(), "key4", "should_be_ignored") if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.AddHTTPResponseHeader(ctx, "key5", "val5") if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.AddHTTPResponseHeader(ctx, "key5", "val7") // should append if err != nil { t.Fatalf(errMsg + err.Error()) } err = twirp.SetHTTPResponseHeader(context.Background(), "Content-Type", "should_return_error") if err == nil { t.Fatalf("SetHTTPResponseHeader expected to return an error on Content-Type header, found nil") } return &Hat{Size: 999}, nil }), nil) // Make a wrapping handler that checks header responses for this test handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { haberdasher.ServeHTTP(w, r) if w.Header().Get("key1") != "val1" { t.Errorf("expected 'key1' header to be 'val1', but found %q", w.Header().Get("key1")) } if w.Header().Get("key2") != "val2" { t.Errorf("expected 'key2' header to be 'val2', but found %q", w.Header().Get("key2")) } if w.Header().Get("key3") != "val3" { t.Errorf("expected 'key3' header to be 'val3', but found %q", w.Header().Get("key3")) } if w.Header().Get("key4") == "should_be_ignored" { t.Error("expected 'key4' header to be empty, it should be ignored if the context is not coming from the handler") } if w.Header().Get("key5") != "val5" { t.Errorf("expected 'key5' header to be 'val5', but found %q", w.Header().Get("key5")) } }) s := httptest.NewServer(handler) defer s.Close() c := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) resp, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("unexpected service error: %q", err) } if resp.Size != 999 { // make sure that the fake handler and its assertions were called t.Errorf("expected resp.Size to be 999 (coming from fake handler), but found %d", resp.Size) } } // A nil response should cause an 'Internal Error' response, not a // panic. func TestNilResponse(t *testing.T) { h := NewHaberdasherServer(NilHatmaker()) panicChecker := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if p := recover(); p != nil { t.Errorf("handler panicked: %s", p) } }() h.ServeHTTP(w, r) }) s := httptest.NewServer(panicChecker) defer s.Close() clients := map[string]Haberdasher{ "protobuf": NewHaberdasherProtobufClient(s.URL, http.DefaultClient), "json": NewHaberdasherJSONClient(s.URL, http.DefaultClient), } for name, c := range clients { _, err := c.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Errorf("%q client err=nil, which is unexpected", name) } } } var expectBadRouteError = func(t *testing.T, client Haberdasher) { _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Fatalf("err=nil, expected bad_route") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("err has type=%T, expected twirp.Error", err) } if twerr.Code() != twirp.BadRoute { t.Errorf("err has code=%v, expected %v", twerr.Code(), twirp.BadRoute) } } func TestBadRoute(t *testing.T) { h := PickyHatmaker(1) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() // Create a transport that we can use to force the wrong HTTP method and URL // in test cases. rw := &reqRewriter{base: http.DefaultTransport} httpClient := &http.Client{Transport: rw} clients := map[string]Haberdasher{ "json": NewHaberdasherJSONClient(s.URL, httpClient), "protobuf": NewHaberdasherProtobufClient(s.URL, httpClient), } for name, client := range clients { t.Run(name+" client", func(t *testing.T) { t.Run("good route", func(t *testing.T) { rw.rewrite = func(r *http.Request) *http.Request { return r } _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("unexpected error with vanilla client and transport: %v", err) } }) t.Run("bad URL path", func(t *testing.T) { rw.rewrite = func(r *http.Request) *http.Request { r.URL.Path = r.URL.Path + "bogus" return r } expectBadRouteError(t, client) }) t.Run("bad HTTP method", func(t *testing.T) { rw.rewrite = func(r *http.Request) *http.Request { r.Method = "GET" return r } expectBadRouteError(t, client) }) t.Run("bad content-type", func(t *testing.T) { rw.rewrite = func(r *http.Request) *http.Request { r.Header.Set("Content-Type", "application/bogus") return r } expectBadRouteError(t, client) }) }) } } // reqRewriter is a http.RoundTripper which can be used to mess with a request // before it actually gets sent. This is useful as a transport for http.Clients // in tests because it lets us modify the HTTP method, path, and headers of a // request, while still being sure that the other unchanged fields are set by a // generated client. type reqRewriter struct { base http.RoundTripper rewrite func(r *http.Request) *http.Request } func (rw *reqRewriter) RoundTrip(req *http.Request) (*http.Response, error) { req = rw.rewrite(req) return rw.base.RoundTrip(req) } func TestReflection(t *testing.T) { h := PickyHatmaker(1) s := NewHaberdasherServer(h) t.Run("ServiceDescriptor", func(t *testing.T) { fd, sd, err := descriptors.ServiceDescriptor(s) if err != nil { t.Fatalf("unable to load descriptor: %v", err) } if have, want := fd.GetPackage(), "twirp.internal.twirptest"; have != want { t.Errorf("bad package name, have=%q, want=%q", have, want) } if have, want := sd.GetName(), "Haberdasher"; have != want { t.Errorf("bad service name, have=%q, want=%q", have, want) } if len(sd.Method) != 1 { t.Errorf("unexpected number of methods, have=%d, want=1", len(sd.Method)) } if have, want := sd.Method[0].GetName(), "MakeHat"; have != want { t.Errorf("bad method name, have=%q, want=%q", have, want) } }) t.Run("ProtoGenTwirpVersion", func(t *testing.T) { // Should match whatever is in the file at protoc-gen-twirp/version.go file, err := os.ReadFile("../gen/version.go") if err != nil { t.Fatalf("unable to load version file: %v", err) } rexp, err := regexp.Compile(`const Version = "(.*)"`) if err != nil { t.Fatalf("unable to compile twirpVersion regex: %v", err) } matches := rexp.FindSubmatch(file) if matches == nil { t.Fatal("unable to find twirp version from version.go file") } want := string(matches[1]) have := s.ProtocGenTwirpVersion() if have != want { t.Errorf("bad version, have=%q, want=%q", have, want) } }) } func TestContextValues(t *testing.T) { h := HaberdasherFunc(func(ctx context.Context, _ *Size) (*Hat, error) { const ( wantPkg = "twirp.internal.twirptest" wantSvc = "Haberdasher" wantMethod = "MakeHat" ) if pkg, _ := twirp.PackageName(ctx); pkg != wantPkg { t.Errorf("twirp.PackageName(ctx) have=%q, want=%q", pkg, wantPkg) } if svc, _ := twirp.ServiceName(ctx); svc != wantSvc { t.Errorf("twirp.ServiceName(ctx) have=%q, want=%q", svc, wantSvc) } if meth, _ := twirp.MethodName(ctx); meth != wantMethod { t.Errorf("twirp.MethodName(ctx) have=%q, want=%q", meth, wantMethod) } return &Hat{}, nil }) s := httptest.NewServer(NewHaberdasherServer(h)) defer s.Close() client := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) _, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err != nil { t.Errorf("Client err=%q", err) } } func TestPanicFlushing(t *testing.T) { h := PanickyHatmaker("bang!") s := httptest.NewUnstartedServer(NewHaberdasherServer(h)) defer s.Close() // If the server config's ErrorLog is left nil, then it will log the panic and // a stack trace straight to stderr. Override it to log to test output. s.Config.ErrorLog = testLogger(t) s.Start() client := NewHaberdasherProtobufClient(s.URL, http.DefaultClient) hat, err := client.MakeHat(context.Background(), &Size{Inches: 1}) if err == nil { t.Logf("hat: %+v", hat) t.Fatal("twirp client err is nil for panicking handler") } twerr, ok := err.(twirp.Error) if !ok { t.Fatalf("expected twirp.Error type error, have %T", err) } if twerr.Code() != twirp.Internal { t.Errorf("twirp ErrorCode expected to be %q, but found %q", twirp.Internal, twerr.Code()) } if twerr.Msg() != "Internal service panic" { t.Errorf("twirp client err has unexpected message %q, want %q", twerr.Msg(), "Internal service panic") } } // testLogger creates a *log.Logger that writes log messages to the test's // output. This makes log messages appear only if the test fails, and makes them // align correctly for nested subtests. func testLogger(t *testing.T) *log.Logger { return log.New(testWriter{t}, "", log.LstdFlags) } type testWriter struct{ t *testing.T } func (w testWriter) Write(p []byte) (int, error) { w.t.Log(string(p)) return len(p), nil } type errReader struct{} func (errReader) Read(p []byte) (n int, err error) { return 0, fmt.Errorf("test error") } // Test failures when reading the request. // The request could be incomplete because the client timed out, which in most cases is signaled by // a context cancelation or timeout. In those cases, the twirp handled would properly identify and return those errors. func TestRequestBodyError(t *testing.T) { type contextUpdate func(ctx context.Context) (context.Context, context.CancelFunc) testCases := []struct { testname string expectedError twirp.ErrorCode errorString string requestType string contextFunc contextUpdate isContextCanceled bool }{ { testname: "ProtobufFailedToReadRequestBodyError", expectedError: twirp.Malformed, errorString: "failed to read request body", requestType: "application/protobuf", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return ctx, func() {} }, isContextCanceled: false, }, { testname: "ProtobufDeadlineExceededError", expectedError: twirp.DeadlineExceeded, errorString: "failed to read request: deadline exceeded", requestType: "application/protobuf", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return context.WithTimeout(ctx, 0*time.Millisecond) }, isContextCanceled: false, }, { testname: "ProtobufFailedToReadRequestBodyError", expectedError: twirp.Canceled, errorString: "failed to read request: context canceled", requestType: "application/protobuf", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return context.WithCancel(ctx) }, isContextCanceled: true, }, { testname: "JSONFailedToReadRequestBodyError", expectedError: twirp.Malformed, errorString: "the json request could not be decoded", requestType: "application/json", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return ctx, func() {} }, isContextCanceled: false, }, { testname: "JSONDeadlineExceededError", expectedError: twirp.DeadlineExceeded, errorString: "failed to read request: deadline exceeded", requestType: "application/json", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return context.WithTimeout(ctx, 0*time.Millisecond) }, isContextCanceled: false, }, { testname: "JSONFailedToReadRequestBodyError", expectedError: twirp.Canceled, errorString: "failed to read request: context canceled", requestType: "application/json", contextFunc: func(ctx context.Context) (context.Context, context.CancelFunc) { return context.WithCancel(ctx) }, isContextCanceled: true, }, } for _, tc := range testCases { t.Run(tc.testname, func(t *testing.T) { // test case validate request body read error handling var s Haberdasher hooks := &twirp.ServerHooks{Error: func(ctx context.Context, err twirp.Error) context.Context { if ctxErr := tc.expectedError; err.Code() != ctxErr { t.Errorf("twirp ErrorCode expected to be %q, but found %q", ctxErr, err.Code()) } if ctxErr := tc.errorString; err.Msg() != ctxErr { t.Errorf("twirp client err has unexpected message %q, want %q", err.Msg(), ctxErr) } return ctx }} server := NewHaberdasherServer(s, hooks) ctx := context.Background() ctx, cancel := tc.contextFunc(ctx) // Make a request, that will call endpoint method req, _ := http.NewRequest(http.MethodPost, "http://testing:8080/twirp/twirp.internal.twirptest.Haberdasher/MakeHat", errReader{}) req.Header.Set("Accept", tc.requestType) req.Header.Set("Content-Type", tc.requestType) // Associate the cancellable context we just created to the request req = req.WithContext(ctx) if tc.isContextCanceled { cancel() } else { defer cancel() } w := httptest.NewRecorder() server.ServeHTTP(w, req) // validate error code expectedErrCode := twirp.ServerHTTPStatusFromErrorCode(tc.expectedError) if w.Code != expectedErrCode { t.Errorf("HTTP ErrorCode expected to be %q, but found %q", expectedErrCode, w.Code) } // validate error message respBytes, err := io.ReadAll(w.Body) if err != nil { t.Fatalf("Could not even read bytes from response: %q", err.Error()) } expectedErrMessage := tc.errorString if !strings.Contains(string(respBytes), expectedErrMessage) { t.Errorf("HTTP client err has unexpected message %q, want %q", string(respBytes), expectedErrMessage) } }) } } ================================================ FILE: internal/twirptest/snake_case_names/compatibility_test.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 snake_case_names import ( context "context" "fmt" http "net/http" "net/http/httptest" "testing" twirp "github.com/twitchtv/twirp" ) type HaberdasherService struct{} func (h *HaberdasherService) MakeHatV1(ctx context.Context, s *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { return &MakeHatArgsV1_HatV1{ Size: s.Inches, }, nil } // When the proto definition contains service and/or method names with underscores (not following proto naming // best practices), Go clients will mistakenly convert routes into it's CamelCased versions, but clients in other // languages may keep the literal casing of the routes. This test makes a go client that would send CamelCased routes // and checks that the generated Go server remains backwards compatible and is able to handle those routes. func TestServiceMethodNamesCamelCase(t *testing.T) { s := httptest.NewServer(NewHaberdasherV1Server(&HaberdasherService{}, nil)) defer s.Close() client := NewHaberdasherV1ProtobufClient(s.URL, http.DefaultClient) hat, err := client.MakeHatV1(context.Background(), &MakeHatArgsV1_SizeV1{Inches: 1}) if err != nil { t.Fatalf("go protobuf client err=%q", err) } if hat.Size != 1 { t.Errorf("wrong hat size returned") } } type compatibilityTestClient struct { client *http.Client } func (t compatibilityTestClient) Do(req *http.Request) (*http.Response, error) { expectedPath := "/twirp/twirp.internal.twirptest.snake_case_names.Haberdasher_v1/MakeHat_v1" if req.URL.Path != expectedPath { return nil, fmt.Errorf("expected: %s, got: %s", expectedPath, req.URL.Path) } return t.client.Do(req) } // This test uses a fake client that checks if the routes are not camel cased, // and checks that the generated Go server is still able to handle those routes. func TestServiceMethodNamesUnderscores(t *testing.T) { s := httptest.NewServer(NewHaberdasherV1Server(&HaberdasherService{}, nil)) defer s.Close() client := NewHaberdasherV1ProtobufClient(s.URL, compatibilityTestClient{client: http.DefaultClient}, twirp.WithClientLiteralURLs(true)) hat, err := client.MakeHatV1(context.Background(), &MakeHatArgsV1_SizeV1{Inches: 1}) if err != nil { t.Fatalf("compatible protobuf client err=%q", err) } if hat.Size != 1 { t.Errorf("wrong hat size returned") } camelCasedClient := NewHaberdasherV1ProtobufClient(s.URL, compatibilityTestClient{client: http.DefaultClient}, twirp.WithClientLiteralURLs(false)) // default value, send CamelCased routes _, err = camelCasedClient.MakeHatV1(context.Background(), &MakeHatArgsV1_SizeV1{Inches: 1}) if err == nil { t.Fatalf("expected error raised by the compatibilityTestClient because routes are camelcased. Got nil.") } if err.Error() != "twirp error internal: failed to do request: expected: /twirp/twirp.internal.twirptest.snake_case_names.Haberdasher_v1/MakeHat_v1, got: /twirp/twirp.internal.twirptest.snake_case_names.HaberdasherV1/MakeHatV1" { t.Fatalf("expected error to be about the expected path, got err=%q", err) } } ================================================ FILE: internal/twirptest/snake_case_names/compile_test.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 snake_case_names import "testing" func TestCompilation(t *testing.T) { // Test passes if this package compiles } ================================================ FILE: internal/twirptest/snake_case_names/gen.go ================================================ // Copyright 2019 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 snake_case_names //go:generate protoc --go_out=paths=source_relative:. --twirp_out=paths=source_relative:. snake_case_names.proto ================================================ FILE: internal/twirptest/snake_case_names/snake_case_names.pb.go ================================================ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.26.0-devel // protoc v3.21.8 // source: snake_case_names.proto // Test that protoc-gen-twirp follows the same behavior as protoc-gen-go // for converting RPCs and message names from snake case to camel case. package snake_case_names import ( 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 MakeHatArgsV1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields } func (x *MakeHatArgsV1) Reset() { *x = MakeHatArgsV1{} if protoimpl.UnsafeEnabled { mi := &file_snake_case_names_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MakeHatArgsV1) String() string { return protoimpl.X.MessageStringOf(x) } func (*MakeHatArgsV1) ProtoMessage() {} func (x *MakeHatArgsV1) ProtoReflect() protoreflect.Message { mi := &file_snake_case_names_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 MakeHatArgsV1.ProtoReflect.Descriptor instead. func (*MakeHatArgsV1) Descriptor() ([]byte, []int) { return file_snake_case_names_proto_rawDescGZIP(), []int{0} } type MakeHatArgsV1_HatV1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Size int32 `protobuf:"varint,1,opt,name=size,proto3" json:"size,omitempty"` Color string `protobuf:"bytes,2,opt,name=color,proto3" json:"color,omitempty"` Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` } func (x *MakeHatArgsV1_HatV1) Reset() { *x = MakeHatArgsV1_HatV1{} if protoimpl.UnsafeEnabled { mi := &file_snake_case_names_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MakeHatArgsV1_HatV1) String() string { return protoimpl.X.MessageStringOf(x) } func (*MakeHatArgsV1_HatV1) ProtoMessage() {} func (x *MakeHatArgsV1_HatV1) ProtoReflect() protoreflect.Message { mi := &file_snake_case_names_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 MakeHatArgsV1_HatV1.ProtoReflect.Descriptor instead. func (*MakeHatArgsV1_HatV1) Descriptor() ([]byte, []int) { return file_snake_case_names_proto_rawDescGZIP(), []int{0, 0} } func (x *MakeHatArgsV1_HatV1) GetSize() int32 { if x != nil { return x.Size } return 0 } func (x *MakeHatArgsV1_HatV1) GetColor() string { if x != nil { return x.Color } return "" } func (x *MakeHatArgsV1_HatV1) GetName() string { if x != nil { return x.Name } return "" } type MakeHatArgsV1_SizeV1 struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Inches int32 `protobuf:"varint,1,opt,name=inches,proto3" json:"inches,omitempty"` } func (x *MakeHatArgsV1_SizeV1) Reset() { *x = MakeHatArgsV1_SizeV1{} if protoimpl.UnsafeEnabled { mi := &file_snake_case_names_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MakeHatArgsV1_SizeV1) String() string { return protoimpl.X.MessageStringOf(x) } func (*MakeHatArgsV1_SizeV1) ProtoMessage() {} func (x *MakeHatArgsV1_SizeV1) ProtoReflect() protoreflect.Message { mi := &file_snake_case_names_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 MakeHatArgsV1_SizeV1.ProtoReflect.Descriptor instead. func (*MakeHatArgsV1_SizeV1) Descriptor() ([]byte, []int) { return file_snake_case_names_proto_rawDescGZIP(), []int{0, 1} } func (x *MakeHatArgsV1_SizeV1) GetInches() int32 { if x != nil { return x.Inches } return 0 } var File_snake_case_names_proto protoreflect.FileDescriptor var file_snake_case_names_proto_rawDesc = []byte{ 0x0a, 0x16, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x29, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x7b, 0x0a, 0x0e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73, 0x5f, 0x76, 0x31, 0x1a, 0x46, 0x0a, 0x06, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x1a, 0x21, 0x0a, 0x07, 0x53, 0x69, 0x7a, 0x65, 0x5f, 0x76, 0x31, 0x12, 0x16, 0x0a, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x69, 0x6e, 0x63, 0x68, 0x65, 0x73, 0x32, 0xa4, 0x01, 0x0a, 0x0e, 0x48, 0x61, 0x62, 0x65, 0x72, 0x64, 0x61, 0x73, 0x68, 0x65, 0x72, 0x5f, 0x76, 0x31, 0x12, 0x91, 0x01, 0x0a, 0x0a, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x12, 0x41, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73, 0x5f, 0x76, 0x31, 0x2e, 0x53, 0x69, 0x7a, 0x65, 0x5f, 0x76, 0x31, 0x1a, 0x40, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x74, 0x77, 0x69, 0x72, 0x70, 0x74, 0x65, 0x73, 0x74, 0x2e, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x2e, 0x4d, 0x61, 0x6b, 0x65, 0x48, 0x61, 0x74, 0x41, 0x72, 0x67, 0x73, 0x5f, 0x76, 0x31, 0x2e, 0x48, 0x61, 0x74, 0x5f, 0x76, 0x31, 0x42, 0x14, 0x5a, 0x12, 0x2f, 0x3b, 0x73, 0x6e, 0x61, 0x6b, 0x65, 0x5f, 0x63, 0x61, 0x73, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( file_snake_case_names_proto_rawDescOnce sync.Once file_snake_case_names_proto_rawDescData = file_snake_case_names_proto_rawDesc ) func file_snake_case_names_proto_rawDescGZIP() []byte { file_snake_case_names_proto_rawDescOnce.Do(func() { file_snake_case_names_proto_rawDescData = protoimpl.X.CompressGZIP(file_snake_case_names_proto_rawDescData) }) return file_snake_case_names_proto_rawDescData } var file_snake_case_names_proto_msgTypes = make([]protoimpl.MessageInfo, 3) var file_snake_case_names_proto_goTypes = []interface{}{ (*MakeHatArgsV1)(nil), // 0: twirp.internal.twirptest.snake_case_names.MakeHatArgs_v1 (*MakeHatArgsV1_HatV1)(nil), // 1: twirp.internal.twirptest.snake_case_names.MakeHatArgs_v1.Hat_v1 (*MakeHatArgsV1_SizeV1)(nil), // 2: twirp.internal.twirptest.snake_case_names.MakeHatArgs_v1.Size_v1 } var file_snake_case_names_proto_depIdxs = []int32{ 2, // 0: twirp.internal.twirptest.snake_case_names.Haberdasher_v1.MakeHat_v1:input_type -> twirp.internal.twirptest.snake_case_names.MakeHatArgs_v1.Size_v1 1, // 1: twirp.internal.twirptest.snake_case_names.Haberdasher_v1.MakeHat_v1:output_type -> twirp.internal.twirptest.snake_case_names.MakeHatArgs_v1.Hat_v1 1, // [1:2] is the sub-list for method output_type 0, // [0:1] 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_snake_case_names_proto_init() } func file_snake_case_names_proto_init() { if File_snake_case_names_proto != nil { return } if !protoimpl.UnsafeEnabled { file_snake_case_names_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MakeHatArgsV1); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_snake_case_names_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MakeHatArgsV1_HatV1); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_snake_case_names_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MakeHatArgsV1_SizeV1); 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_snake_case_names_proto_rawDesc, NumEnums: 0, NumMessages: 3, NumExtensions: 0, NumServices: 1, }, GoTypes: file_snake_case_names_proto_goTypes, DependencyIndexes: file_snake_case_names_proto_depIdxs, MessageInfos: file_snake_case_names_proto_msgTypes, }.Build() File_snake_case_names_proto = out.File file_snake_case_names_proto_rawDesc = nil file_snake_case_names_proto_goTypes = nil file_snake_case_names_proto_depIdxs = nil } ================================================ FILE: internal/twirptest/snake_case_names/snake_case_names.proto ================================================ syntax = "proto3"; // Test that protoc-gen-twirp follows the same behavior as protoc-gen-go // for converting RPCs and message names from snake case to camel case. package twirp.internal.twirptest.snake_case_names; option go_package = "/;snake_case_names"; message MakeHatArgs_v1 { message Hat_v1 { int32 size = 1; string color = 2; string name = 3; } message Size_v1 { int32 inches = 1; } } // A Haberdasher makes hats for clients. service Haberdasher_v1 { rpc MakeHat_v1 (MakeHatArgs_v1.Size_v1) returns (MakeHatArgs_v1.Hat_v1); } ================================================ FILE: internal/twirptest/snake_case_names/snake_case_names.twirp.go ================================================ // Code generated by protoc-gen-twirp v8.1.3, DO NOT EDIT. // source: snake_case_names.proto // Test that protoc-gen-twirp follows the same behavior as protoc-gen-go // for converting RPCs and message names from snake case to camel case. package snake_case_names import context "context" import fmt "fmt" import http "net/http" import io "io" import json "encoding/json" import strconv "strconv" import strings "strings" import protojson "google.golang.org/protobuf/encoding/protojson" import proto "google.golang.org/protobuf/proto" import twirp "github.com/twitchtv/twirp" import ctxsetters "github.com/twitchtv/twirp/ctxsetters" import bytes "bytes" import errors "errors" import path "path" import url "net/url" // Version compatibility assertion. // If the constant is not defined in the package, that likely means // the package needs to be updated to work with this generated code. // See https://twitchtv.github.io/twirp/docs/version_matrix.html const _ = twirp.TwirpPackageMinVersion_8_1_0 // ======================= // HaberdasherV1 Interface // ======================= // A Haberdasher makes hats for clients. type HaberdasherV1 interface { MakeHatV1(context.Context, *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) } // ============================= // HaberdasherV1 Protobuf Client // ============================= type haberdasherV1ProtobufClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherV1ProtobufClient creates a Protobuf client that implements the HaberdasherV1 interface. // It communicates using Protobuf and can be configured with a custom HTTPClient. func NewHaberdasherV1ProtobufClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) HaberdasherV1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) if literalURLs { serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.snake_case_names", "Haberdasher_v1") } else { serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.snake_case_names", "HaberdasherV1") } urls := [1]string{ serviceURL + "MakeHatV1", } if literalURLs { urls = [1]string{ serviceURL + "MakeHat_v1", } } return &haberdasherV1ProtobufClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherV1ProtobufClient) MakeHatV1(ctx context.Context, in *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.snake_case_names") ctx = ctxsetters.WithServiceName(ctx, "HaberdasherV1") ctx = ctxsetters.WithMethodName(ctx, "MakeHatV1") caller := c.callMakeHatV1 if c.interceptor != nil { caller = func(ctx context.Context, req *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*MakeHatArgsV1_SizeV1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*MakeHatArgsV1_SizeV1) when calling interceptor") } return c.callMakeHatV1(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*MakeHatArgsV1_HatV1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*MakeHatArgsV1_HatV1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherV1ProtobufClient) callMakeHatV1(ctx context.Context, in *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { out := new(MakeHatArgsV1_HatV1) ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ========================= // HaberdasherV1 JSON Client // ========================= type haberdasherV1JSONClient struct { client HTTPClient urls [1]string interceptor twirp.Interceptor opts twirp.ClientOptions } // NewHaberdasherV1JSONClient creates a JSON client that implements the HaberdasherV1 interface. // It communicates using JSON and can be configured with a custom HTTPClient. func NewHaberdasherV1JSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientOption) HaberdasherV1 { if c, ok := client.(*http.Client); ok { client = withoutRedirects(c) } clientOpts := twirp.ClientOptions{} for _, o := range opts { o(&clientOpts) } // Using ReadOpt allows backwards and forwards compatibility with new options in the future literalURLs := false _ = clientOpts.ReadOpt("literalURLs", &literalURLs) var pathPrefix string if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } // Build method URLs: []/./ serviceURL := sanitizeBaseURL(baseURL) if literalURLs { serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.snake_case_names", "Haberdasher_v1") } else { serviceURL += baseServicePath(pathPrefix, "twirp.internal.twirptest.snake_case_names", "HaberdasherV1") } urls := [1]string{ serviceURL + "MakeHatV1", } if literalURLs { urls = [1]string{ serviceURL + "MakeHat_v1", } } return &haberdasherV1JSONClient{ client: client, urls: urls, interceptor: twirp.ChainInterceptors(clientOpts.Interceptors...), opts: clientOpts, } } func (c *haberdasherV1JSONClient) MakeHatV1(ctx context.Context, in *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.snake_case_names") ctx = ctxsetters.WithServiceName(ctx, "HaberdasherV1") ctx = ctxsetters.WithMethodName(ctx, "MakeHatV1") caller := c.callMakeHatV1 if c.interceptor != nil { caller = func(ctx context.Context, req *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { resp, err := c.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*MakeHatArgsV1_SizeV1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*MakeHatArgsV1_SizeV1) when calling interceptor") } return c.callMakeHatV1(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*MakeHatArgsV1_HatV1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*MakeHatArgsV1_HatV1) when calling interceptor") } return typedResp, err } return nil, err } } return caller(ctx, in) } func (c *haberdasherV1JSONClient) callMakeHatV1(ctx context.Context, in *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { out := new(MakeHatArgsV1_HatV1) ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[0], in, out) if err != nil { twerr, ok := err.(twirp.Error) if !ok { twerr = twirp.InternalErrorWith(err) } callClientError(ctx, c.opts.Hooks, twerr) return nil, err } callClientResponseReceived(ctx, c.opts.Hooks) return out, nil } // ============================ // HaberdasherV1 Server Handler // ============================ type haberdasherV1Server struct { HaberdasherV1 interceptor twirp.Interceptor hooks *twirp.ServerHooks pathPrefix string // prefix for routing jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names } // NewHaberdasherV1Server builds a TwirpServer that can be used as an http.Handler to handle // HTTP requests that are routed to the right method in the provided svc implementation. // The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks). func NewHaberdasherV1Server(svc HaberdasherV1, opts ...interface{}) TwirpServer { serverOpts := newServerOpts(opts) // Using ReadOpt allows backwards and forwards compatibility with new options in the future jsonSkipDefaults := false _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) jsonCamelCase := false _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase) var pathPrefix string if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok { pathPrefix = "/twirp" // default prefix } return &haberdasherV1Server{ HaberdasherV1: svc, hooks: serverOpts.Hooks, interceptor: twirp.ChainInterceptors(serverOpts.Interceptors...), pathPrefix: pathPrefix, jsonSkipDefaults: jsonSkipDefaults, jsonCamelCase: jsonCamelCase, } } // writeError writes an HTTP response with a valid Twirp error format, and triggers hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func (s *haberdasherV1Server) writeError(ctx context.Context, resp http.ResponseWriter, err error) { writeError(ctx, resp, err, s.hooks) } // handleRequestBodyError is used to handle error when the twirp server cannot read request func (s *haberdasherV1Server) handleRequestBodyError(ctx context.Context, resp http.ResponseWriter, msg string, err error) { if context.Canceled == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.Canceled, "failed to read request: context canceled")) return } if context.DeadlineExceeded == ctx.Err() { s.writeError(ctx, resp, twirp.NewError(twirp.DeadlineExceeded, "failed to read request: deadline exceeded")) return } s.writeError(ctx, resp, twirp.WrapError(malformedRequestError(msg), err)) } // HaberdasherV1PathPrefix is a convenience constant that may identify URL paths. // Should be used with caution, it only matches routes generated by Twirp Go clients, // with the default "/twirp" prefix and default CamelCase service and method names. // More info: https://twitchtv.github.io/twirp/docs/routing.html const HaberdasherV1PathPrefix = "/twirp/twirp.internal.twirptest.snake_case_names.HaberdasherV1/" func (s *haberdasherV1Server) ServeHTTP(resp http.ResponseWriter, req *http.Request) { ctx := req.Context() ctx = ctxsetters.WithPackageName(ctx, "twirp.internal.twirptest.snake_case_names") ctx = ctxsetters.WithServiceName(ctx, "HaberdasherV1") ctx = ctxsetters.WithResponseWriter(ctx, resp) var err error ctx, err = callRequestReceived(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } if req.Method != "POST" { msg := fmt.Sprintf("unsupported method %q (only POST is allowed)", req.Method) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } // Verify path format: []/./ prefix, pkgService, method := parseTwirpPath(req.URL.Path) if pkgService != "twirp.internal.twirptest.snake_case_names.Haberdasher_v1" && pkgService != "twirp.internal.twirptest.snake_case_names.HaberdasherV1" { msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } if prefix != s.pathPrefix { msg := fmt.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } switch method { case "MakeHat_v1", "MakeHatV1": s.serveMakeHatV1(ctx, resp, req) return default: msg := fmt.Sprintf("no handler for path %q", req.URL.Path) s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path)) return } } func (s *haberdasherV1Server) serveMakeHatV1(ctx context.Context, resp http.ResponseWriter, req *http.Request) { header := req.Header.Get("Content-Type") i := strings.Index(header, ";") if i == -1 { i = len(header) } switch strings.TrimSpace(strings.ToLower(header[:i])) { case "application/json": s.serveMakeHatV1JSON(ctx, resp, req) case "application/protobuf": s.serveMakeHatV1Protobuf(ctx, resp, req) default: msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type")) twerr := badRouteError(msg, req.Method, req.URL.Path) s.writeError(ctx, resp, twerr) } } func (s *haberdasherV1Server) serveMakeHatV1JSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHatV1") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } d := json.NewDecoder(req.Body) rawReqBody := json.RawMessage{} if err := d.Decode(&rawReqBody); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } reqContent := new(MakeHatArgsV1_SizeV1) unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil { s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err) return } handler := s.HaberdasherV1.MakeHatV1 if s.interceptor != nil { handler = func(ctx context.Context, req *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*MakeHatArgsV1_SizeV1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*MakeHatArgsV1_SizeV1) when calling interceptor") } return s.HaberdasherV1.MakeHatV1(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*MakeHatArgsV1_HatV1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*MakeHatArgsV1_HatV1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *MakeHatArgsV1_HatV1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *MakeHatArgsV1_HatV1 and nil error while calling MakeHatV1. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults} respBytes, err := marshaler.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/json") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherV1Server) serveMakeHatV1Protobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) { var err error ctx = ctxsetters.WithMethodName(ctx, "MakeHatV1") ctx, err = callRequestRouted(ctx, s.hooks) if err != nil { s.writeError(ctx, resp, err) return } buf, err := io.ReadAll(req.Body) if err != nil { s.handleRequestBodyError(ctx, resp, "failed to read request body", err) return } reqContent := new(MakeHatArgsV1_SizeV1) if err = proto.Unmarshal(buf, reqContent); err != nil { s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded")) return } handler := s.HaberdasherV1.MakeHatV1 if s.interceptor != nil { handler = func(ctx context.Context, req *MakeHatArgsV1_SizeV1) (*MakeHatArgsV1_HatV1, error) { resp, err := s.interceptor( func(ctx context.Context, req interface{}) (interface{}, error) { typedReq, ok := req.(*MakeHatArgsV1_SizeV1) if !ok { return nil, twirp.InternalError("failed type assertion req.(*MakeHatArgsV1_SizeV1) when calling interceptor") } return s.HaberdasherV1.MakeHatV1(ctx, typedReq) }, )(ctx, req) if resp != nil { typedResp, ok := resp.(*MakeHatArgsV1_HatV1) if !ok { return nil, twirp.InternalError("failed type assertion resp.(*MakeHatArgsV1_HatV1) when calling interceptor") } return typedResp, err } return nil, err } } // Call service method var respContent *MakeHatArgsV1_HatV1 func() { defer ensurePanicResponses(ctx, resp, s.hooks) respContent, err = handler(ctx, reqContent) }() if err != nil { s.writeError(ctx, resp, err) return } if respContent == nil { s.writeError(ctx, resp, twirp.InternalError("received a nil *MakeHatArgsV1_HatV1 and nil error while calling MakeHatV1. nil responses are not supported")) return } ctx = callResponsePrepared(ctx, s.hooks) respBytes, err := proto.Marshal(respContent) if err != nil { s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response")) return } ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK) resp.Header().Set("Content-Type", "application/protobuf") resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes))) resp.WriteHeader(http.StatusOK) if n, err := resp.Write(respBytes); err != nil { msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error()) twerr := twirp.NewError(twirp.Unknown, msg) ctx = callError(ctx, s.hooks, twerr) } callResponseSent(ctx, s.hooks) } func (s *haberdasherV1Server) ServiceDescriptor() ([]byte, int) { return twirpFileDescriptor0, 0 } func (s *haberdasherV1Server) ProtocGenTwirpVersion() string { return "v8.1.3" } // PathPrefix returns the base service path, in the form: "//./" // that is everything in a Twirp route except for the . This can be used for routing, // for example to identify the requests that are targeted to this service in a mux. func (s *haberdasherV1Server) PathPrefix() string { return baseServicePath(s.pathPrefix, "twirp.internal.twirptest.snake_case_names", "HaberdasherV1") } // ===== // Utils // ===== // HTTPClient is the interface used by generated clients to send HTTP requests. // It is fulfilled by *(net/http).Client, which is sufficient for most users. // Users can provide their own implementation for special retry policies. // // HTTPClient implementations should not follow redirects. Redirects are // automatically disabled if *(net/http).Client is passed to client // constructors. See the withoutRedirects function in this file for more // details. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } // TwirpServer is the interface generated server structs will support: they're // HTTP handlers with additional methods for accessing metadata about the // service. Those accessors are a low-level API for building reflection tools. // Most people can think of TwirpServers as just http.Handlers. type TwirpServer interface { http.Handler // ServiceDescriptor returns gzipped bytes describing the .proto file that // this service was generated from. Once unzipped, the bytes can be // unmarshalled as a // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto. // // The returned integer is the index of this particular service within that // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a // low-level field, expected to be used for reflection. ServiceDescriptor() ([]byte, int) // ProtocGenTwirpVersion is the semantic version string of the version of // twirp used to generate this file. ProtocGenTwirpVersion() string // PathPrefix returns the HTTP URL path prefix for all methods handled by this // service. This can be used with an HTTP mux to route Twirp requests. // The path prefix is in the form: "//./" // that is, everything in a Twirp route except for the at the end. PathPrefix() string } func newServerOpts(opts []interface{}) *twirp.ServerOptions { serverOpts := &twirp.ServerOptions{} for _, opt := range opts { switch o := opt.(type) { case twirp.ServerOption: o(serverOpts) case *twirp.ServerHooks: // backwards compatibility, allow to specify hooks as an argument twirp.WithServerHooks(o)(serverOpts) case nil: // backwards compatibility, allow nil value for the argument continue default: panic(fmt.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o)) } } return serverOpts } // WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta). // Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks. // If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err) func WriteError(resp http.ResponseWriter, err error) { writeError(context.Background(), resp, err, nil) } // writeError writes Twirp errors in the response and triggers hooks. func writeError(ctx context.Context, resp http.ResponseWriter, err error, hooks *twirp.ServerHooks) { // Convert to a twirp.Error. Non-twirp errors are converted to internal errors. var twerr twirp.Error if !errors.As(err, &twerr) { twerr = twirp.InternalErrorWith(err) } statusCode := twirp.ServerHTTPStatusFromErrorCode(twerr.Code()) ctx = ctxsetters.WithStatusCode(ctx, statusCode) ctx = callError(ctx, hooks, twerr) respBody := marshalErrorToJSON(twerr) resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON resp.Header().Set("Content-Length", strconv.Itoa(len(respBody))) resp.WriteHeader(statusCode) // set HTTP status code and send response _, writeErr := resp.Write(respBody) if writeErr != nil { // We have three options here. We could log the error, call the Error // hook, or just silently ignore the error. // // Logging is unacceptable because we don't have a user-controlled // logger; writing out to stderr without permission is too rude. // // Calling the Error hook would confuse users: it would mean the Error // hook got called twice for one request, which is likely to lead to // duplicated log messages and metrics, no matter how well we document // the behavior. // // Silently ignoring the error is our least-bad option. It's highly // likely that the connection is broken and the original 'err' says // so anyway. _ = writeErr } callResponseSent(ctx, hooks) } // sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed. // If the URL is unparsable, the baseURL is returned unchanged. func sanitizeBaseURL(baseURL string) string { u, err := url.Parse(baseURL) if err != nil { return baseURL // invalid URL will fail later when making requests } if u.Scheme == "" { u.Scheme = "http" } return u.String() } // baseServicePath composes the path prefix for the service (without ). // e.g.: baseServicePath("/twirp", "my.pkg", "MyService") // // returns => "/twirp/my.pkg.MyService/" // // e.g.: baseServicePath("", "", "MyService") // // returns => "/MyService/" func baseServicePath(prefix, pkg, service string) string { fullServiceName := service if pkg != "" { fullServiceName = pkg + "." + service } return path.Join("/", prefix, fullServiceName) + "/" } // parseTwirpPath extracts path components form a valid Twirp route. // Expected format: "[]/./" // e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat") func parseTwirpPath(path string) (string, string, string) { parts := strings.Split(path, "/") if len(parts) < 2 { return "", "", "" } method := parts[len(parts)-1] pkgService := parts[len(parts)-2] prefix := strings.Join(parts[0:len(parts)-2], "/") return prefix, pkgService, method } // getCustomHTTPReqHeaders retrieves a copy of any headers that are set in // a context through the twirp.WithHTTPRequestHeaders function. // If there are no headers set, or if they have the wrong type, nil is returned. func getCustomHTTPReqHeaders(ctx context.Context) http.Header { header, ok := twirp.HTTPRequestHeaders(ctx) if !ok || header == nil { return nil } copied := make(http.Header) for k, vv := range header { if vv == nil { copied[k] = nil continue } copied[k] = make([]string, len(vv)) copy(copied[k], vv) } return copied } // newRequest makes an http.Request from a client, adding common headers. func newRequest(ctx context.Context, url string, reqBody io.Reader, contentType string) (*http.Request, error) { req, err := http.NewRequest("POST", url, reqBody) if err != nil { return nil, err } req = req.WithContext(ctx) if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil { req.Header = customHeader } req.Header.Set("Accept", contentType) req.Header.Set("Content-Type", contentType) req.Header.Set("Twirp-Version", "v8.1.3") return req, nil } // JSON serialization for errors type twerrJSON struct { Code string `json:"code"` Msg string `json:"msg"` Meta map[string]string `json:"meta,omitempty"` } // marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body. // If serialization fails, it will use a descriptive Internal error instead. func marshalErrorToJSON(twerr twirp.Error) []byte { // make sure that msg is not too large msg := twerr.Msg() if len(msg) > 1e6 { msg = msg[:1e6] } tj := twerrJSON{ Code: string(twerr.Code()), Msg: msg, Meta: twerr.MetaMap(), } buf, err := json.Marshal(&tj) if err != nil { buf = []byte("{\"type\": \"" + twirp.Internal + "\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback } return buf } // errorFromResponse builds a twirp.Error from a non-200 HTTP response. // If the response has a valid serialized Twirp error, then it's returned. // If not, the response status code is used to generate a similar twirp // error. See twirpErrorFromIntermediary for more info on intermediary errors. func errorFromResponse(resp *http.Response) twirp.Error { statusCode := resp.StatusCode statusText := http.StatusText(statusCode) if isHTTPRedirect(statusCode) { // Unexpected redirect: it must be an error from an intermediary. // Twirp clients don't follow redirects automatically, Twirp only handles // POST requests, redirects should only happen on GET and HEAD requests. location := resp.Header.Get("Location") msg := fmt.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location) return twirpErrorFromIntermediary(statusCode, msg, location) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return wrapInternal(err, "failed to read server error response body") } var tj twerrJSON dec := json.NewDecoder(bytes.NewReader(respBodyBytes)) dec.DisallowUnknownFields() if err := dec.Decode(&tj); err != nil || tj.Code == "" { // Invalid JSON response; it must be an error from an intermediary. msg := fmt.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText) return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes)) } errorCode := twirp.ErrorCode(tj.Code) if !twirp.IsValidErrorCode(errorCode) { msg := "invalid type returned from server error response: " + tj.Code return twirp.InternalError(msg).WithMeta("body", string(respBodyBytes)) } twerr := twirp.NewError(errorCode, tj.Msg) for k, v := range tj.Meta { twerr = twerr.WithMeta(k, v) } return twerr } // twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors. // The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md. // Returned twirp Errors have some additional metadata for inspection. func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) twirp.Error { var code twirp.ErrorCode if isHTTPRedirect(status) { // 3xx code = twirp.Internal } else { switch status { case 400: // Bad Request code = twirp.Internal case 401: // Unauthorized code = twirp.Unauthenticated case 403: // Forbidden code = twirp.PermissionDenied case 404: // Not Found code = twirp.BadRoute case 429: // Too Many Requests code = twirp.ResourceExhausted case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout code = twirp.Unavailable default: // All other codes code = twirp.Unknown } } twerr := twirp.NewError(code, msg) twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary twerr = twerr.WithMeta("status_code", strconv.Itoa(status)) if isHTTPRedirect(status) { twerr = twerr.WithMeta("location", bodyOrLocation) } else { twerr = twerr.WithMeta("body", bodyOrLocation) } return twerr } func isHTTPRedirect(status int) bool { return status >= 300 && status <= 399 } // wrapInternal wraps an error with a prefix as an Internal error. // The original error cause is accessible by github.com/pkg/errors.Cause. func wrapInternal(err error, prefix string) twirp.Error { return twirp.InternalErrorWith(&wrappedError{prefix: prefix, cause: err}) } type wrappedError struct { prefix string cause error } func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() } func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors // ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal // error response (status 500), and error hooks are properly called with the panic wrapped as an error. // The panic is re-raised so it can be handled normally with middleware. func ensurePanicResponses(ctx context.Context, resp http.ResponseWriter, hooks *twirp.ServerHooks) { if r := recover(); r != nil { // Wrap the panic as an error so it can be passed to error hooks. // The original error is accessible from error hooks, but not visible in the response. err := errFromPanic(r) twerr := &internalWithCause{msg: "Internal service panic", cause: err} // Actually write the error writeError(ctx, resp, twerr, hooks) // If possible, flush the error to the wire. f, ok := resp.(http.Flusher) if ok { f.Flush() } panic(r) } } // errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error. func errFromPanic(p interface{}) error { if err, ok := p.(error); ok { return err } return fmt.Errorf("panic: %v", p) } // internalWithCause is a Twirp Internal error wrapping an original error cause, // but the original error message is not exposed on Msg(). The original error // can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap type internalWithCause struct { msg string cause error } func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error() } func (e *internalWithCause) Code() twirp.ErrorCode { return twirp.Internal } func (e *internalWithCause) Msg() string { return e.msg } func (e *internalWithCause) Meta(key string) string { return "" } func (e *internalWithCause) MetaMap() map[string]string { return nil } func (e *internalWithCause) WithMeta(key string, val string) twirp.Error { return e } // malformedRequestError is used when the twirp server cannot unmarshal a request func malformedRequestError(msg string) twirp.Error { return twirp.NewError(twirp.Malformed, msg) } // badRouteError is used when the twirp server cannot route a request func badRouteError(msg string, method, url string) twirp.Error { err := twirp.NewError(twirp.BadRoute, msg) err = err.WithMeta("twirp_invalid_route", method+" "+url) return err } // withoutRedirects makes sure that the POST request can not be redirected. // The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or // 303 response, and also 301s in go1.8. It redirects by making a second request, changing the // method to GET and removing the body. This produces very confusing error messages, so instead we // set a redirect policy that always errors. This stops Go from executing the redirect. // // We have to be a little careful in case the user-provided http.Client has its own CheckRedirect // policy - if so, we'll run through that policy first. // // Because this requires modifying the http.Client, we make a new copy of the client and return it. func withoutRedirects(in *http.Client) *http.Client { copy := *in copy.CheckRedirect = func(req *http.Request, via []*http.Request) error { if in.CheckRedirect != nil { // Run the input's redirect if it exists, in case it has side effects, but ignore any error it // returns, since we want to use ErrUseLastResponse. err := in.CheckRedirect(req, via) _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use. } return http.ErrUseLastResponse } return © } // doProtobufRequest makes a Protobuf request to the remote Twirp service. func doProtobufRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { reqBodyBytes, err := proto.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal proto request") } reqBody := bytes.NewBuffer(reqBodyBytes) if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, reqBody, "application/protobuf") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { _ = resp.Body.Close() }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } respBodyBytes, err := io.ReadAll(resp.Body) if err != nil { return ctx, wrapInternal(err, "failed to read response body") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if err = proto.Unmarshal(respBodyBytes, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal proto response") } return ctx, nil } // doJSONRequest makes a JSON request to the remote Twirp service. func doJSONRequest(ctx context.Context, client HTTPClient, hooks *twirp.ClientHooks, url string, in, out proto.Message) (_ context.Context, err error) { marshaler := &protojson.MarshalOptions{UseProtoNames: true} reqBytes, err := marshaler.Marshal(in) if err != nil { return ctx, wrapInternal(err, "failed to marshal json request") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } req, err := newRequest(ctx, url, bytes.NewReader(reqBytes), "application/json") if err != nil { return ctx, wrapInternal(err, "could not build request") } ctx, err = callClientRequestPrepared(ctx, hooks, req) if err != nil { return ctx, err } req = req.WithContext(ctx) resp, err := client.Do(req) if err != nil { return ctx, wrapInternal(err, "failed to do request") } defer func() { cerr := resp.Body.Close() if err == nil && cerr != nil { err = wrapInternal(cerr, "failed to close response body") } }() if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } if resp.StatusCode != 200 { return ctx, errorFromResponse(resp) } d := json.NewDecoder(resp.Body) rawRespBody := json.RawMessage{} if err := d.Decode(&rawRespBody); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true} if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil { return ctx, wrapInternal(err, "failed to unmarshal json response") } if err = ctx.Err(); err != nil { return ctx, wrapInternal(err, "aborted because context was done") } return ctx, nil } // Call twirp.ServerHooks.RequestReceived if the hook is available func callRequestReceived(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestReceived == nil { return ctx, nil } return h.RequestReceived(ctx) } // Call twirp.ServerHooks.RequestRouted if the hook is available func callRequestRouted(ctx context.Context, h *twirp.ServerHooks) (context.Context, error) { if h == nil || h.RequestRouted == nil { return ctx, nil } return h.RequestRouted(ctx) } // Call twirp.ServerHooks.ResponsePrepared if the hook is available func callResponsePrepared(ctx context.Context, h *twirp.ServerHooks) context.Context { if h == nil || h.ResponsePrepared == nil { return ctx } return h.ResponsePrepared(ctx) } // Call twirp.ServerHooks.ResponseSent if the hook is available func callResponseSent(ctx context.Context, h *twirp.ServerHooks) { if h == nil || h.ResponseSent == nil { return } h.ResponseSent(ctx) } // Call twirp.ServerHooks.Error if the hook is available func callError(ctx context.Context, h *twirp.ServerHooks, err twirp.Error) context.Context { if h == nil || h.Error == nil { return ctx } return h.Error(ctx, err) } func callClientResponseReceived(ctx context.Context, h *twirp.ClientHooks) { if h == nil || h.ResponseReceived == nil { return } h.ResponseReceived(ctx) } func callClientRequestPrepared(ctx context.Context, h *twirp.ClientHooks, req *http.Request) (context.Context, error) { if h == nil || h.RequestPrepared == nil { return ctx, nil } return h.RequestPrepared(ctx, req) } func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error) { if h == nil || h.Error == nil { return } h.Error(ctx, err) } var twirpFileDescriptor0 = []byte{ // 227 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0x2b, 0xce, 0x4b, 0xcc, 0x4e, 0x8d, 0x4f, 0x4e, 0x2c, 0x4e, 0x8d, 0xcf, 0x4b, 0xcc, 0x4d, 0x2d, 0xd6, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xd2, 0x2c, 0x29, 0xcf, 0x2c, 0x2a, 0xd0, 0xcb, 0xcc, 0x2b, 0x49, 0x2d, 0xca, 0x4b, 0xcc, 0xd1, 0x03, 0x73, 0x4b, 0x52, 0x8b, 0x4b, 0xf4, 0xd0, 0x35, 0x28, 0x55, 0x73, 0xf1, 0xf9, 0x26, 0x66, 0xa7, 0x7a, 0x24, 0x96, 0x38, 0x16, 0xa5, 0x17, 0xc7, 0x97, 0x19, 0x4a, 0xb9, 0x71, 0xb1, 0x79, 0x24, 0x96, 0xc4, 0x97, 0x19, 0x0a, 0x09, 0x71, 0xb1, 0x14, 0x67, 0x56, 0xa5, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xb0, 0x06, 0x81, 0xd9, 0x42, 0x22, 0x5c, 0xac, 0xc9, 0xf9, 0x39, 0xf9, 0x45, 0x12, 0x4c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x10, 0x0e, 0x48, 0x25, 0xc8, 0x38, 0x09, 0x66, 0xb0, 0x20, 0x98, 0x2d, 0xa5, 0xc8, 0xc5, 0x1e, 0x9c, 0x59, 0x95, 0x0a, 0x32, 0x48, 0x8c, 0x8b, 0x2d, 0x33, 0x2f, 0x39, 0x23, 0xb5, 0x18, 0x6a, 0x14, 0x94, 0x67, 0xb4, 0x84, 0x91, 0x8b, 0xcf, 0x23, 0x31, 0x29, 0xb5, 0x28, 0x25, 0xb1, 0x38, 0x23, 0xb5, 0x08, 0xa4, 0x74, 0x22, 0x23, 0x17, 0x17, 0xd4, 0x41, 0x20, 0xae, 0xa3, 0x1e, 0xd1, 0x5e, 0xd1, 0x43, 0xf5, 0x87, 0x1e, 0xd4, 0x72, 0x29, 0x07, 0xf2, 0x8d, 0x80, 0x38, 0xc2, 0x49, 0x24, 0x4a, 0x48, 0xdf, 0x1a, 0x5d, 0x6d, 0x12, 0x1b, 0x38, 0xac, 0x8d, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xb7, 0x11, 0xfe, 0x5d, 0x85, 0x01, 0x00, 0x00, } ================================================ FILE: license_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "bytes" "io" "os" "path/filepath" "regexp" "strings" "testing" ) var headerCopyright = regexp.MustCompile(`// Copyright \d{4} Twitch Interactive, Inc. All Rights Reserved.`) const headerLicense = ` // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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. ` var generatedCodeMatcher = regexp.MustCompile("// Code generated .* DO NOT EDIT") func TestSourceCodeLicenseHeaders(t *testing.T) { err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error { if err != nil { return err } if path == "_tools" || path == "vendor" { return filepath.SkipDir } if !strings.HasSuffix(path, ".go") { // Skip non-go files. return nil } if strings.HasSuffix(path, ".twirp.go") || strings.HasSuffix(path, ".pb.go") { return nil } file, err := os.Open(path) if err != nil { return err } fileBytes, err := io.ReadAll(file) if err != nil { return err } fileBuf := bytes.NewReader(fileBytes) if generatedCodeMatcher.MatchReader(fileBuf) { // Skip generated files. return nil } _, err = fileBuf.Seek(0, io.SeekStart) if err != nil { return err } if !headerCopyright.MatchReader(fileBuf) { t.Errorf("%v is missing licensing header", path) return nil } if !bytes.Contains(fileBytes, []byte(headerLicense)) { t.Errorf("%v is missing licensing header", path) } return nil }) if err != nil { t.Fatalf("error scanning directory for source code files: %v", err) } } ================================================ FILE: protoc-gen-twirp/command_line.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "fmt" "strings" ) type commandLineParams struct { importMap map[string]string // Mapping from .proto file name to import path. paths string // paths flag, used to control file output directory. module string // module flag, Go import path prefix that is removed from the output filename. importPrefix string // prefix added to imported package file names. } // parseCommandLineParams breaks the comma-separated list of key=value pairs // in the parameter (a member of the request protobuf) into a key/value map. // It then sets command line parameter mappings defined by those entries. func parseCommandLineParams(parameter string) (*commandLineParams, error) { ps := make(map[string]string) for _, p := range strings.Split(parameter, ",") { if p == "" { continue } i := strings.Index(p, "=") if i < 0 { return nil, fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", p) } k := p[0:i] v := p[i+1:] if v == "" { return nil, fmt.Errorf("invalid parameter %q: expected format of parameter to be k=v", k) } ps[k] = v } clp := &commandLineParams{ importMap: make(map[string]string), } for k, v := range ps { switch { // Support import map 'M' prefix: https://developers.google.com/protocol-buffers/docs/reference/go-generated case len(k) > 0 && k[0] == 'M': clp.importMap[k[1:]] = v // 1 is the length of 'M'. case len(k) > 0 && strings.HasPrefix(k, "go_import_mapping@"): // twirp specific version of M parameters clp.importMap[k[18:]] = v // 18 is the length of 'go_import_mapping@'. case k == "paths": switch v { case "import": // this is the default behavior; the output file is placed in a directory named after the option go_package case "source_relative": // the directory prefix on the option go_package is removed from the output filename (only the last part is used) clp.paths = "source_relative" default: return nil, fmt.Errorf("invalid command line flag %s=%s", k, v) } // If the module={PREFIX} flag is specified, the prefix is removed from the option go_package on the output filename case k == "module": clp.module = v // Deprecated, but may still be useful when working with old versions of protoc-gen-go case k == "import_prefix": clp.importPrefix = v default: return nil, fmt.Errorf("invalid command line flag %s=%s", k, v) } } return clp, nil } ================================================ FILE: protoc-gen-twirp/command_line_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "errors" "reflect" "testing" ) func TestParseCommandLineParams(t *testing.T) { tests := []struct { name string parameter string params *commandLineParams err error }{ { "no parameters", "", &commandLineParams{ importMap: map[string]string{}, }, nil, }, { "unknown parameter", "kkk=vvv", nil, errors.New(`invalid command line flag kkk=vvv`), }, { "empty parameter value - no equals sign", "import_prefix", nil, errors.New(`invalid parameter "import_prefix": expected format of parameter to be k=v`), }, { "empty parameter value - no value", "import_prefix=", nil, errors.New(`invalid parameter "import_prefix": expected format of parameter to be k=v`), }, { "import_prefix parameter", "import_prefix=github.com/example/repo", &commandLineParams{ importMap: map[string]string{}, importPrefix: "github.com/example/repo", }, nil, }, { "single import parameter starting with 'M'", "Mrpcutil/empty.proto=github.com/example/rpcutil", &commandLineParams{ importMap: map[string]string{ "rpcutil/empty.proto": "github.com/example/rpcutil", }, }, nil, }, { "multiple import parameters starting with 'M'", "Mrpcutil/empty.proto=github.com/example/rpcutil,Mrpc/haberdasher/service.proto=github.com/example/rpc/haberdasher", &commandLineParams{ importMap: map[string]string{ "rpcutil/empty.proto": "github.com/example/rpcutil", "rpc/haberdasher/service.proto": "github.com/example/rpc/haberdasher", }, }, nil, }, { "single import parameter starting with 'go_import_mapping@'", "go_import_mapping@rpcutil/empty.proto=github.com/example/rpcutil", &commandLineParams{ importMap: map[string]string{ "rpcutil/empty.proto": "github.com/example/rpcutil", }, }, nil, }, { "multiple import parameters starting with 'go_import_mapping@'", "go_import_mapping@rpcutil/empty.proto=github.com/example/rpcutil,go_import_mapping@rpc/haberdasher/service.proto=github.com/example/rpc/haberdasher", &commandLineParams{ importMap: map[string]string{ "rpcutil/empty.proto": "github.com/example/rpcutil", "rpc/haberdasher/service.proto": "github.com/example/rpc/haberdasher", }, }, nil, }, { "paths import", "paths=import", &commandLineParams{ importMap: map[string]string{}, }, nil, }, { "paths source_relative", "paths=source_relative", &commandLineParams{ importMap: map[string]string{}, paths: "source_relative", }, nil, }, { "paths invalidstuff", "paths=invalidstuff", nil, errors.New(`invalid command line flag paths=invalidstuff`), }, { "module parameter", "module=foo/bar/fizz", &commandLineParams{ importMap: map[string]string{}, module: "foo/bar/fizz", }, nil, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { params, err := parseCommandLineParams(tt.parameter) switch { case err != nil: if tt.err == nil { t.Fatal(err) } if err.Error() != tt.err.Error() { t.Errorf("got error = %v, want %v", err, tt.err) } case err == nil: if tt.err != nil { t.Errorf("got error = %v, want %v", err, tt.err) } } if !reflect.DeepEqual(params, tt.params) { t.Errorf("got params = %+v, want %+v", params, tt.params) } }) } } ================================================ FILE: protoc-gen-twirp/generator.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "bufio" "bytes" "compress/gzip" "fmt" "go/parser" "go/printer" "go/token" "path" "sort" "strconv" "strings" "google.golang.org/protobuf/proto" descriptor "google.golang.org/protobuf/types/descriptorpb" plugin "google.golang.org/protobuf/types/pluginpb" "github.com/pkg/errors" "github.com/twitchtv/twirp/internal/gen" "github.com/twitchtv/twirp/internal/gen/stringutils" "github.com/twitchtv/twirp/internal/gen/typemap" ) type twirp struct { filesHandled int reg *typemap.Registry // Map to record whether we've built each package pkgs map[string]string pkgNamesInUse map[string]bool importPrefix string // String to prefix to imported package file names. importMap map[string]string // Mapping from .proto file name to import path. // Package output: sourceRelativePaths bool // instruction on where to write output files modulePrefix string // Package naming: genPkgName string // Name of the package that we're generating fileToGoPackageName map[*descriptor.FileDescriptorProto]string // List of files that were inputs to the generator. We need to hold this in // the struct so we can write a header for the file that lists its inputs. genFiles []*descriptor.FileDescriptorProto // Output buffer that holds the bytes we want to write out for a single file. // Gets reset after working on a file. output *bytes.Buffer } func newGenerator() *twirp { t := &twirp{ pkgs: make(map[string]string), pkgNamesInUse: make(map[string]bool), importMap: make(map[string]string), fileToGoPackageName: make(map[*descriptor.FileDescriptorProto]string), output: bytes.NewBuffer(nil), } return t } func (t *twirp) Generate(in *plugin.CodeGeneratorRequest) *plugin.CodeGeneratorResponse { params, err := parseCommandLineParams(in.GetParameter()) if err != nil { gen.Fail("could not parse parameters passed to --twirp_out", err.Error()) } t.importPrefix = params.importPrefix t.importMap = params.importMap t.sourceRelativePaths = params.paths == "source_relative" t.modulePrefix = params.module t.genFiles = gen.FilesToGenerate(in) // Collect information on types. t.reg = typemap.New(in.ProtoFile) // Register names of packages that we import. t.registerPackageName("bytes") t.registerPackageName("strings") t.registerPackageName("path") t.registerPackageName("ctxsetters") t.registerPackageName("context") t.registerPackageName("http") t.registerPackageName("io") t.registerPackageName("json") t.registerPackageName("protojson") t.registerPackageName("proto") t.registerPackageName("strconv") t.registerPackageName("twirp") t.registerPackageName("url") t.registerPackageName("fmt") t.registerPackageName("errors") // Time to figure out package names of objects defined in protobuf. First, // we'll figure out the name for the package we're generating. genPkgName, err := deduceGenPkgName(t.genFiles) if err != nil { gen.Fail(err.Error()) } t.genPkgName = genPkgName // We also need to figure out the fully import path of the package we're // generating. It's possible to import proto definitions from different .proto // files which will be generated into the same Go package, which we need to // detect (and can only detect if files use fully-specified go_package // options). genPkgImportPath, _, _ := goPackageOption(t.genFiles[0]) // Next, we need to pick names for all the files that are dependencies. for _, f := range in.ProtoFile { // Is this is a file we are generating? If yes, it gets the shared package name. if fileDescSliceContains(t.genFiles, f) { t.fileToGoPackageName[f] = t.genPkgName continue } // Is this is an imported .proto file which has the same fully-specified // go_package as the targeted file for generation? If yes, it gets the // shared package name too. if genPkgImportPath != "" { importPath, _, _ := goPackageOption(f) if importPath == genPkgImportPath { t.fileToGoPackageName[f] = t.genPkgName continue } } // This is a dependency from a different go_package. Use its package name. name := f.GetPackage() if name == "" { name = stringutils.BaseName(f.GetName()) } name = stringutils.CleanIdentifier(name) alias := t.registerPackageName(name) t.fileToGoPackageName[f] = alias } // Showtime! Generate the response. resp := new(plugin.CodeGeneratorResponse) resp.SupportedFeatures = proto.Uint64(uint64(plugin.CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL)) for _, f := range t.genFiles { respFile := t.generate(f) if respFile != nil { resp.File = append(resp.File, respFile) } } return resp } func (t *twirp) registerPackageName(name string) (alias string) { alias = name i := 1 for t.pkgNamesInUse[alias] { alias = name + strconv.Itoa(i) i++ } t.pkgNamesInUse[alias] = true t.pkgs[name] = alias return alias } // deduceGenPkgName figures out the go package name to use for generated code. // Will try to use the explicit go_package setting in a file (if set, must be // consistent in all files). If no files have go_package set, then use the // protobuf package name (must be consistent in all files) func deduceGenPkgName(genFiles []*descriptor.FileDescriptorProto) (string, error) { var genPkgName string for _, f := range genFiles { name, explicit := goPackageName(f) if explicit { name = stringutils.CleanIdentifier(name) if genPkgName != "" && genPkgName != name { // Make sure they're all set consistently. return "", errors.Errorf("files have conflicting go_package settings, must be the same: %q and %q", genPkgName, name) } genPkgName = name } } if genPkgName != "" { return genPkgName, nil } // If there is no explicit setting, then check the implicit package name // (derived from the protobuf package name) of the files and make sure it's // consistent. for _, f := range genFiles { name, _ := goPackageName(f) name = stringutils.CleanIdentifier(name) if genPkgName != "" && genPkgName != name { return "", errors.Errorf("files have conflicting package names, must be the same or overridden with go_package: %q and %q", genPkgName, name) } genPkgName = name } // All the files have the same name, so we're good. return genPkgName, nil } func (t *twirp) generate(file *descriptor.FileDescriptorProto) *plugin.CodeGeneratorResponse_File { resp := new(plugin.CodeGeneratorResponse_File) if len(file.Service) == 0 { return nil } t.generateFileHeader(file) t.generateImports(file) if t.filesHandled == 0 { t.generateUtilImports() } t.generateVersionCheck(file) // For each service, generate client stubs and server for i, service := range file.Service { t.generateService(file, service, i) } // Util functions only generated once per package if t.filesHandled == 0 { t.generateUtils() } t.generateFileDescriptor(file) resp.Name = proto.String(t.goFileName(file)) resp.Content = proto.String(t.formattedOutput()) t.output.Reset() t.filesHandled++ return resp } func (t *twirp) generateVersionCheck(file *descriptor.FileDescriptorProto) { t.P(`// Version compatibility assertion.`) t.P(`// If the constant is not defined in the package, that likely means`) t.P(`// the package needs to be updated to work with this generated code.`) t.P(`// See https://twitchtv.github.io/twirp/docs/version_matrix.html`) t.P(`const _ = `, t.pkgs["twirp"], `.TwirpPackageMinVersion_8_1_0`) } func (t *twirp) generateFileHeader(file *descriptor.FileDescriptorProto) { t.P("// Code generated by protoc-gen-twirp ", gen.Version, ", DO NOT EDIT.") t.P("// source: ", file.GetName()) t.P() comment, err := t.reg.FileComments(file) if err == nil && comment.Leading != "" { for _, line := range strings.Split(comment.Leading, "\n") { if line != "" { t.P("// " + strings.TrimPrefix(line, " ")) } } t.P() } t.P(`package `, t.genPkgName) t.P() } func (t *twirp) generateImports(file *descriptor.FileDescriptorProto) { if len(file.Service) == 0 { return } // stdlib imports t.P(`import `, t.pkgs["context"], ` "context"`) t.P(`import `, t.pkgs["fmt"], ` "fmt"`) t.P(`import `, t.pkgs["http"], ` "net/http"`) t.P(`import `, t.pkgs["io"], ` "io"`) t.P(`import `, t.pkgs["json"], ` "encoding/json"`) t.P(`import `, t.pkgs["strconv"], ` "strconv"`) t.P(`import `, t.pkgs["strings"], ` "strings"`) t.P() // dependency imports t.P(`import `, t.pkgs["protojson"], ` "google.golang.org/protobuf/encoding/protojson"`) t.P(`import `, t.pkgs["proto"], ` "google.golang.org/protobuf/proto"`) t.P(`import `, t.pkgs["twirp"], ` "github.com/twitchtv/twirp"`) t.P(`import `, t.pkgs["ctxsetters"], ` "github.com/twitchtv/twirp/ctxsetters"`) t.P() // It's legal to import a message and use it as an input or output for a // method. Make sure to import the package of any such message. First, dedupe // them. deps := make(map[string]string) // Map of package name to quoted import path. ourImportPath := path.Dir(t.goFileName(file)) for _, s := range file.Service { for _, m := range s.Method { defs := []*typemap.MessageDefinition{ t.reg.MethodInputDefinition(m), t.reg.MethodOutputDefinition(m), } for _, def := range defs { importPath, _ := parseGoPackageOption(def.File.GetOptions().GetGoPackage()) if importPath == "" { // no option go_package importPath := path.Dir(t.goFileName(def.File)) // use the dirname of the Go filename as import path if importPath == ourImportPath { continue } } if substitution, ok := t.importMap[def.File.GetName()]; ok { importPath = substitution } importPath = t.importPrefix + importPath pkg := t.goPackageName(def.File) if pkg != t.genPkgName { deps[pkg] = strconv.Quote(importPath) } } } } pkgs := make([]string, 0, len(deps)) for pkg := range deps { pkgs = append(pkgs, pkg) } sort.Strings(pkgs) for _, pkg := range pkgs { t.P(`import `, pkg, ` `, deps[pkg]) } if len(deps) > 0 { t.P() } } // generateUtilImports are imports that are only used on utility functions. // If there are multiple proto files being generated, they are only included in the first one of them. func (t *twirp) generateUtilImports() { t.P(`import `, t.pkgs["bytes"], ` "bytes"`) t.P(`import `, t.pkgs["errors"], ` "errors"`) t.P(`import `, t.pkgs["path"], ` "path"`) t.P(`import `, t.pkgs["url"], ` "net/url"`) } // Generate utility functions used in Twirp code. // These functions are generated only once per package; when generating for // multiple services they are declared only once. func (t *twirp) generateUtils() { t.sectionComment(`Utils`) t.P(`// HTTPClient is the interface used by generated clients to send HTTP requests.`) t.P(`// It is fulfilled by *(net/http).Client, which is sufficient for most users.`) t.P(`// Users can provide their own implementation for special retry policies.`) t.P(`// `) t.P(`// HTTPClient implementations should not follow redirects. Redirects are`) t.P(`// automatically disabled if *(net/http).Client is passed to client`) t.P(`// constructors. See the withoutRedirects function in this file for more`) t.P(`// details.`) t.P(`type HTTPClient interface {`) t.P(` Do(req *`, t.pkgs["http"], `.Request) (*`, t.pkgs["http"], `.Response, error)`) t.P(`}`) t.P() t.P(`// TwirpServer is the interface generated server structs will support: they're`) t.P(`// HTTP handlers with additional methods for accessing metadata about the`) t.P(`// service. Those accessors are a low-level API for building reflection tools.`) t.P(`// Most people can think of TwirpServers as just http.Handlers.`) t.P(`type TwirpServer interface {`) t.P(` `, t.pkgs["http"], `.Handler`) t.P() t.P(` // ServiceDescriptor returns gzipped bytes describing the .proto file that`) t.P(` // this service was generated from. Once unzipped, the bytes can be`) t.P(` // unmarshalled as a`) t.P(` // google.golang.org/protobuf/types/descriptorpb.FileDescriptorProto.`) t.P(` //`) t.P(` // The returned integer is the index of this particular service within that`) t.P(` // FileDescriptorProto's 'Service' slice of ServiceDescriptorProtos. This is a`) t.P(` // low-level field, expected to be used for reflection.`) t.P(` ServiceDescriptor() ([]byte, int)`) t.P() t.P(` // ProtocGenTwirpVersion is the semantic version string of the version of`) t.P(` // twirp used to generate this file.`) t.P(` ProtocGenTwirpVersion() string`) t.P() t.P(` // PathPrefix returns the HTTP URL path prefix for all methods handled by this`) t.P(` // service. This can be used with an HTTP mux to route Twirp requests.`) t.P(` // The path prefix is in the form: "//./"`) t.P(` // that is, everything in a Twirp route except for the at the end.`) t.P(` PathPrefix() string`) t.P(`}`) t.P() t.P(`func newServerOpts(opts []interface{}) *`, t.pkgs["twirp"], `.ServerOptions {`) t.P(` serverOpts := &`, t.pkgs["twirp"], `.ServerOptions{}`) t.P(` for _, opt := range opts {`) t.P(` switch o := opt.(type) {`) t.P(` case `, t.pkgs["twirp"], `.ServerOption:`) t.P(` o(serverOpts)`) t.P(` case *`, t.pkgs["twirp"], `.ServerHooks: // backwards compatibility, allow to specify hooks as an argument`) t.P(` twirp.WithServerHooks(o)(serverOpts)`) t.P(` case nil: // backwards compatibility, allow nil value for the argument`) t.P(` continue`) t.P(` default:`) t.P(` panic(`, t.pkgs["fmt"], `.Sprintf("Invalid option type %T, please use a twirp.ServerOption", o))`) t.P(` }`) t.P(` }`) t.P(` return serverOpts`) t.P(`}`) t.P() t.P(`// WriteError writes an HTTP response with a valid Twirp error format (code, msg, meta).`) t.P(`// Useful outside of the Twirp server (e.g. http middleware), but does not trigger hooks.`) t.P(`// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err)`) t.P(`func WriteError(resp `, t.pkgs["http"], `.ResponseWriter, err error) {`) t.P(` writeError(`, t.pkgs["context"], `.Background(), resp, err, nil)`) t.P(`}`) t.P() t.P(`// writeError writes Twirp errors in the response and triggers hooks.`) t.P(`func writeError(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, err error, hooks *`, t.pkgs["twirp"], `.ServerHooks) {`) t.P(` // Convert to a twirp.Error. Non-twirp errors are converted to internal errors.`) t.P(` var twerr `, t.pkgs["twirp"], `.Error`) t.P(` if !`, t.pkgs["errors"], `.As(err, &twerr) {`) t.P(` twerr = `, t.pkgs["twirp"], `.InternalErrorWith(err)`) t.P(` }`) t.P(` `) t.P(` statusCode := `, t.pkgs["twirp"], `.ServerHTTPStatusFromErrorCode(twerr.Code())`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithStatusCode(ctx, statusCode)`) t.P(` ctx = callError(ctx, hooks, twerr)`) t.P(` `) t.P(` respBody := marshalErrorToJSON(twerr)`) t.P(` `) t.P(` resp.Header().Set("Content-Type", "application/json") // Error responses are always JSON`) t.P(` resp.Header().Set("Content-Length", strconv.Itoa(len(respBody)))`) t.P(` resp.WriteHeader(statusCode) // set HTTP status code and send response`) t.P(` `) t.P(` _, writeErr := resp.Write(respBody)`) t.P(` if writeErr != nil {`) t.P(` // We have three options here. We could log the error, call the Error`) t.P(` // hook, or just silently ignore the error.`) t.P(` //`) t.P(` // Logging is unacceptable because we don't have a user-controlled `) t.P(` // logger; writing out to stderr without permission is too rude.`) t.P(` //`) t.P(` // Calling the Error hook would confuse users: it would mean the Error`) t.P(` // hook got called twice for one request, which is likely to lead to`) t.P(` // duplicated log messages and metrics, no matter how well we document`) t.P(` // the behavior.`) t.P(` //`) t.P(` // Silently ignoring the error is our least-bad option. It's highly`) t.P(` // likely that the connection is broken and the original 'err' says`) t.P(` // so anyway.`) t.P(` _ = writeErr`) t.P(` }`) t.P(` `) t.P(` callResponseSent(ctx, hooks)`) t.P(`}`) t.P() t.P(`// sanitizeBaseURL parses the baseURL, and adds the "http" scheme if needed.`) t.P(`// If the URL is unparsable, the baseURL is returned unchanged.`) t.P(`func sanitizeBaseURL(baseURL string) string {`) t.P(` u, err := `, t.pkgs["url"], `.Parse(baseURL)`) t.P(` if err != nil {`) t.P(` return baseURL // invalid URL will fail later when making requests`) t.P(` }`) t.P(` if u.Scheme == "" {`) t.P(` u.Scheme = "http"`) t.P(` }`) t.P(` return u.String()`) t.P(`}`) t.P() t.P(`// baseServicePath composes the path prefix for the service (without ).`) t.P(`// e.g.: baseServicePath("/twirp", "my.pkg", "MyService")`) t.P(`// returns => "/twirp/my.pkg.MyService/"`) t.P(`// e.g.: baseServicePath("", "", "MyService")`) t.P(`// returns => "/MyService/"`) t.P(`func baseServicePath(prefix, pkg, service string) string {`) t.P(` fullServiceName := service`) t.P(` if pkg != "" {`) t.P(` fullServiceName = pkg + "." + service`) t.P(` }`) t.P(` return path.Join("/", prefix, fullServiceName) + "/"`) t.P(`}`) t.P() t.P(`// parseTwirpPath extracts path components form a valid Twirp route.`) t.P(`// Expected format: "[]/./"`) t.P(`// e.g.: prefix, pkgService, method := parseTwirpPath("/twirp/pkg.Svc/MakeHat")`) t.P(`func parseTwirpPath(path string) (string, string, string) {`) t.P(` parts := `, t.pkgs["strings"], `.Split(path, "/")`) t.P(` if len(parts) < 2 {`) t.P(` return "", "", ""`) t.P(` }`) t.P(` method := parts[len(parts)-1]`) t.P(` pkgService := parts[len(parts)-2]`) t.P(` prefix := `, t.pkgs["strings"], `.Join(parts[0:len(parts)-2], "/")`) t.P(` return prefix, pkgService, method`) t.P(`}`) t.P() t.P(`// getCustomHTTPReqHeaders retrieves a copy of any headers that are set in`) t.P(`// a context through the twirp.WithHTTPRequestHeaders function.`) t.P(`// If there are no headers set, or if they have the wrong type, nil is returned.`) t.P(`func getCustomHTTPReqHeaders(ctx `, t.pkgs["context"], `.Context) `, t.pkgs["http"], `.Header {`) t.P(` header, ok := `, t.pkgs["twirp"], `.HTTPRequestHeaders(ctx)`) t.P(` if !ok || header == nil {`) t.P(` return nil`) t.P(` }`) t.P(` copied := make(`, t.pkgs["http"], `.Header)`) t.P(` for k, vv := range header {`) t.P(` if vv == nil {`) t.P(` copied[k] = nil`) t.P(` continue`) t.P(` }`) t.P(` copied[k] = make([]string, len(vv))`) t.P(` copy(copied[k], vv)`) t.P(` }`) t.P(` return copied`) t.P(`}`) t.P() t.P(`// newRequest makes an http.Request from a client, adding common headers.`) t.P(`func newRequest(ctx `, t.pkgs["context"], `.Context, url string, reqBody io.Reader, contentType string) (*`, t.pkgs["http"], `.Request, error) {`) t.P(` req, err := `, t.pkgs["http"], `.NewRequest("POST", url, reqBody)`) t.P(` if err != nil {`) t.P(` return nil, err`) t.P(` }`) t.P(` req = req.WithContext(ctx)`) t.P(` if customHeader := getCustomHTTPReqHeaders(ctx); customHeader != nil {`) t.P(` req.Header = customHeader`) t.P(` }`) t.P(` req.Header.Set("Accept", contentType)`) t.P(` req.Header.Set("Content-Type", contentType)`) t.P(` req.Header.Set("Twirp-Version", "`, gen.Version, `")`) t.P(` return req, nil`) t.P(`}`) t.P() t.P(`// JSON serialization for errors`) t.P(`type twerrJSON struct {`) t.P(" Code string `json:\"code\"`") t.P(" Msg string `json:\"msg\"`") t.P(" Meta map[string]string `json:\"meta,omitempty\"`") t.P(`}`) t.P() t.P(`// marshalErrorToJSON returns JSON from a twirp.Error, that can be used as HTTP error response body.`) t.P(`// If serialization fails, it will use a descriptive Internal error instead.`) t.P(`func marshalErrorToJSON(twerr `, t.pkgs["twirp"], `.Error) []byte {`) t.P(` // make sure that msg is not too large`) t.P(` msg := twerr.Msg()`) t.P(` if len(msg) > 1e6 {`) t.P(` msg = msg[:1e6]`) t.P(` }`) t.P(``) t.P(` tj := twerrJSON{`) t.P(` Code: string(twerr.Code()),`) t.P(` Msg: msg,`) t.P(` Meta: twerr.MetaMap(),`) t.P(` }`) t.P(``) t.P(` buf, err := `, t.pkgs["json"], `.Marshal(&tj)`) t.P(` if err != nil {`) t.P(` buf = []byte("{\"type\": \"" + `, t.pkgs["twirp"], `.Internal +"\", \"msg\": \"There was an error but it could not be serialized into JSON\"}") // fallback`) t.P(` }`) t.P(``) t.P(` return buf`) t.P(`}`) t.P() t.P(`// errorFromResponse builds a twirp.Error from a non-200 HTTP response.`) t.P(`// If the response has a valid serialized Twirp error, then it's returned.`) t.P(`// If not, the response status code is used to generate a similar twirp`) t.P(`// error. See twirpErrorFromIntermediary for more info on intermediary errors.`) t.P(`func errorFromResponse(resp *`, t.pkgs["http"], `.Response) `, t.pkgs["twirp"], `.Error {`) t.P(` statusCode := resp.StatusCode`) t.P(` statusText := `, t.pkgs["http"], `.StatusText(statusCode)`) t.P(``) t.P(` if isHTTPRedirect(statusCode) {`) t.P(` // Unexpected redirect: it must be an error from an intermediary.`) t.P(` // Twirp clients don't follow redirects automatically, Twirp only handles`) t.P(` // POST requests, redirects should only happen on GET and HEAD requests.`) t.P(` location := resp.Header.Get("Location")`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("unexpected HTTP status code %d %q received, Location=%q", statusCode, statusText, location)`) t.P(` return twirpErrorFromIntermediary(statusCode, msg, location)`) t.P(` }`) t.P(``) t.P(` respBodyBytes, err := `, t.pkgs["io"], `.ReadAll(resp.Body)`) t.P(` if err != nil {`) t.P(` return wrapInternal(err, "failed to read server error response body")`) t.P(` }`) t.P(``) t.P(` var tj twerrJSON`) t.P(` dec := `, t.pkgs["json"], `.NewDecoder(`, t.pkgs["bytes"], `.NewReader(respBodyBytes))`) t.P(` dec.DisallowUnknownFields()`) t.P(` if err := dec.Decode(&tj); err != nil || tj.Code == "" {`) t.P(` // Invalid JSON response; it must be an error from an intermediary.`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("Error from intermediary with HTTP status code %d %q", statusCode, statusText)`) t.P(` return twirpErrorFromIntermediary(statusCode, msg, string(respBodyBytes))`) t.P(` }`) t.P(``) t.P(` errorCode := `, t.pkgs["twirp"], `.ErrorCode(tj.Code)`) t.P(` if !`, t.pkgs["twirp"], `.IsValidErrorCode(errorCode) {`) t.P(` msg := "invalid type returned from server error response: "+tj.Code`) t.P(` return `, t.pkgs["twirp"], `.InternalError(msg).WithMeta("body", string(respBodyBytes))`) t.P(` }`) t.P(``) t.P(` twerr := `, t.pkgs["twirp"], `.NewError(errorCode, tj.Msg)`) t.P(` for k, v := range(tj.Meta) {`) t.P(` twerr = twerr.WithMeta(k, v)`) t.P(` }`) t.P(` return twerr`) t.P(`}`) t.P() t.P(`// twirpErrorFromIntermediary maps HTTP errors from non-twirp sources to twirp errors.`) t.P(`// The mapping is similar to gRPC: https://github.com/grpc/grpc/blob/master/doc/http-grpc-status-mapping.md.`) t.P(`// Returned twirp Errors have some additional metadata for inspection.`) t.P(`func twirpErrorFromIntermediary(status int, msg string, bodyOrLocation string) `, t.pkgs["twirp"], `.Error {`) t.P(` var code `, t.pkgs["twirp"], `.ErrorCode`) t.P(` if isHTTPRedirect(status) { // 3xx`) t.P(` code = `, t.pkgs["twirp"], `.Internal`) t.P(` } else {`) t.P(` switch status {`) t.P(` case 400: // Bad Request`) t.P(` code = `, t.pkgs["twirp"], `.Internal`) t.P(` case 401: // Unauthorized`) t.P(` code = `, t.pkgs["twirp"], `.Unauthenticated`) t.P(` case 403: // Forbidden`) t.P(` code = `, t.pkgs["twirp"], `.PermissionDenied`) t.P(` case 404: // Not Found`) t.P(` code = `, t.pkgs["twirp"], `.BadRoute`) t.P(` case 429: // Too Many Requests`) t.P(` code = `, t.pkgs["twirp"], `.ResourceExhausted`) t.P(` case 502, 503, 504: // Bad Gateway, Service Unavailable, Gateway Timeout`) t.P(` code = `, t.pkgs["twirp"], `.Unavailable`) t.P(` default: // All other codes`) t.P(` code = `, t.pkgs["twirp"], `.Unknown`) t.P(` }`) t.P(` }`) t.P(``) t.P(` twerr := `, t.pkgs["twirp"], `.NewError(code, msg)`) t.P(` twerr = twerr.WithMeta("http_error_from_intermediary", "true") // to easily know if this error was from intermediary`) t.P(` twerr = twerr.WithMeta("status_code", `, t.pkgs["strconv"], `.Itoa(status))`) t.P(` if isHTTPRedirect(status) {`) t.P(` twerr = twerr.WithMeta("location", bodyOrLocation)`) t.P(` } else {`) t.P(` twerr = twerr.WithMeta("body", bodyOrLocation)`) t.P(` }`) t.P(` return twerr`) t.P(`}`) t.P() t.P(`func isHTTPRedirect(status int) bool {`) t.P(` return status >= 300 && status <= 399`) t.P(`}`) t.P() t.P(`// wrapInternal wraps an error with a prefix as an Internal error.`) t.P(`// The original error cause is accessible by github.com/pkg/errors.Cause.`) t.P(`func wrapInternal(err error, prefix string) `, t.pkgs["twirp"], `.Error {`) t.P(` return `, t.pkgs["twirp"], `.InternalErrorWith(&wrappedError{prefix: prefix, cause: err})`) t.P(`}`) t.P(`type wrappedError struct {`) t.P(` prefix string`) t.P(` cause error`) t.P(`}`) t.P(`func (e *wrappedError) Error() string { return e.prefix + ": " + e.cause.Error() }`) t.P(`func (e *wrappedError) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As `) t.P(`func (e *wrappedError) Cause() error { return e.cause } // for github.com/pkg/errors`) t.P() t.P(`// ensurePanicResponses makes sure that rpc methods causing a panic still result in a Twirp Internal`) t.P(`// error response (status 500), and error hooks are properly called with the panic wrapped as an error.`) t.P(`// The panic is re-raised so it can be handled normally with middleware.`) t.P(`func ensurePanicResponses(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, hooks *`, t.pkgs["twirp"], `.ServerHooks) {`) t.P(` if r := recover(); r != nil {`) t.P(` // Wrap the panic as an error so it can be passed to error hooks.`) t.P(` // The original error is accessible from error hooks, but not visible in the response.`) t.P(` err := errFromPanic(r)`) t.P(` twerr := &internalWithCause{msg: "Internal service panic", cause: err}`) t.P(` // Actually write the error`) t.P(` writeError(ctx, resp, twerr, hooks)`) t.P(` // If possible, flush the error to the wire.`) t.P(` f, ok := resp.(`, t.pkgs["http"], `.Flusher)`) t.P(` if ok {`) t.P(` f.Flush()`) t.P(` }`) t.P(``) t.P(` panic(r)`) t.P(` }`) t.P(`}`) t.P(``) t.P(`// errFromPanic returns the typed error if the recovered panic is an error, otherwise formats as error.`) t.P(`func errFromPanic(p interface{}) error {`) t.P(` if err, ok := p.(error); ok {`) t.P(` return err`) t.P(` }`) t.P(` return fmt.Errorf("panic: %v", p)`) t.P(`}`) t.P(``) t.P(`// internalWithCause is a Twirp Internal error wrapping an original error cause,`) t.P(`// but the original error message is not exposed on Msg(). The original error`) t.P(`// can be checked with go1.13+ errors.Is/As, and also by (github.com/pkg/errors).Unwrap`) t.P(`type internalWithCause struct {`) t.P(` msg string`) t.P(` cause error`) t.P(`}`) t.P(`func (e *internalWithCause) Unwrap() error { return e.cause } // for go1.13 + errors.Is/As`) t.P(`func (e *internalWithCause) Cause() error { return e.cause } // for github.com/pkg/errors`) t.P(`func (e *internalWithCause) Error() string { return e.msg + ": " + e.cause.Error()}`) t.P(`func (e *internalWithCause) Code() `, t.pkgs["twirp"], `.ErrorCode { return `, t.pkgs["twirp"], `.Internal }`) t.P(`func (e *internalWithCause) Msg() string { return e.msg }`) t.P(`func (e *internalWithCause) Meta(key string) string { return "" }`) t.P(`func (e *internalWithCause) MetaMap() map[string]string { return nil }`) t.P(`func (e *internalWithCause) WithMeta(key string, val string) `, t.pkgs["twirp"], `.Error { return e }`) t.P() t.P(`// malformedRequestError is used when the twirp server cannot unmarshal a request`) t.P(`func malformedRequestError(msg string) `, t.pkgs["twirp"], `.Error {`) t.P(` return `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.Malformed, msg)`) t.P(`}`) t.P() t.P(`// badRouteError is used when the twirp server cannot route a request`) t.P(`func badRouteError(msg string, method, url string) `, t.pkgs["twirp"], `.Error {`) t.P(` err := `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.BadRoute, msg)`) t.P(` err = err.WithMeta("twirp_invalid_route", method+" "+url)`) t.P(` return err`) t.P(`}`) t.P() t.P(`// withoutRedirects makes sure that the POST request can not be redirected.`) t.P(`// The standard library will, by default, redirect requests (including POSTs) if it gets a 302 or`) t.P(`// 303 response, and also 301s in go1.8. It redirects by making a second request, changing the`) t.P(`// method to GET and removing the body. This produces very confusing error messages, so instead we`) t.P(`// set a redirect policy that always errors. This stops Go from executing the redirect.`) t.P(`//`) t.P(`// We have to be a little careful in case the user-provided http.Client has its own CheckRedirect`) t.P(`// policy - if so, we'll run through that policy first.`) t.P(`//`) t.P(`// Because this requires modifying the http.Client, we make a new copy of the client and return it.`) t.P(`func withoutRedirects(in *`, t.pkgs["http"], `.Client) *`, t.pkgs["http"], `.Client {`) t.P(` copy := *in`) t.P(` copy.CheckRedirect = func(req *`, t.pkgs["http"], `.Request, via []*`, t.pkgs["http"], `.Request) error {`) t.P(` if in.CheckRedirect != nil {`) t.P(` // Run the input's redirect if it exists, in case it has side effects, but ignore any error it`) t.P(` // returns, since we want to use ErrUseLastResponse.`) t.P(` err := in.CheckRedirect(req, via)`) t.P(` _ = err // Silly, but this makes sure generated code passes errcheck -blank, which some people use.`) t.P(` }`) t.P(` return `, t.pkgs["http"], `.ErrUseLastResponse`) t.P(` }`) t.P(` return ©`) t.P(`}`) t.P() t.P(`// doProtobufRequest makes a Protobuf request to the remote Twirp service.`) t.P(`func doProtobufRequest(ctx `, t.pkgs["context"], `.Context, client HTTPClient, hooks *`, t.pkgs["twirp"], `.ClientHooks, url string, in, out `, t.pkgs["proto"], `.Message) (_ `, t.pkgs["context"], `.Context, err error) {`) t.P(` reqBodyBytes, err := `, t.pkgs["proto"], `.Marshal(in)`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to marshal proto request")`) t.P(` }`) t.P(` reqBody := `, t.pkgs["bytes"], `.NewBuffer(reqBodyBytes)`) t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P() t.P(` req, err := newRequest(ctx, url, reqBody, "application/protobuf")`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "could not build request")`) t.P(` }`) t.P(` ctx, err = callClientRequestPrepared(ctx, hooks, req)`) t.P(` if err != nil {`) t.P(` return ctx, err`) t.P(` }`) t.P() t.P(` req = req.WithContext(ctx)`) t.P(` resp, err := client.Do(req)`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to do request")`) t.P(` }`) t.P(` defer func() { _ = resp.Body.Close() }()`) t.P() t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P() t.P(` if resp.StatusCode != 200 {`) t.P(` return ctx, errorFromResponse(resp)`) t.P(` }`) t.P() t.P(` respBodyBytes, err := `, t.pkgs["io"], `.ReadAll(resp.Body)`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to read response body")`) t.P(` }`) t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P() t.P(` if err = `, t.pkgs["proto"], `.Unmarshal(respBodyBytes, out); err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to unmarshal proto response")`) t.P(` }`) t.P(` return ctx, nil`) t.P(`}`) t.P() t.P(`// doJSONRequest makes a JSON request to the remote Twirp service.`) t.P(`func doJSONRequest(ctx `, t.pkgs["context"], `.Context, client HTTPClient, hooks *`, t.pkgs["twirp"], `.ClientHooks, url string, in, out `, t.pkgs["proto"], `.Message) (_ `, t.pkgs["context"], `.Context, err error) {`) t.P(` marshaler := &`, t.pkgs["protojson"], `.MarshalOptions{UseProtoNames: true}`) t.P(` reqBytes, err := marshaler.Marshal(in)`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to marshal json request")`) t.P(` }`) t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P() t.P(` req, err := newRequest(ctx, url, `, t.pkgs["bytes"], `.NewReader(reqBytes), "application/json")`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "could not build request")`) t.P(` }`) t.P(` ctx, err = callClientRequestPrepared(ctx, hooks, req)`) t.P(` if err != nil {`) t.P(` return ctx, err`) t.P(` }`) t.P() t.P(` req = req.WithContext(ctx)`) t.P(` resp, err := client.Do(req)`) t.P(` if err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to do request")`) t.P(` }`) t.P() t.P(` defer func() {`) t.P(` cerr := resp.Body.Close()`) t.P(` if err == nil && cerr != nil {`) t.P(` err = wrapInternal(cerr, "failed to close response body")`) t.P(` }`) t.P(` }()`) t.P() t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P() t.P(` if resp.StatusCode != 200 {`) t.P(` return ctx, errorFromResponse(resp)`) t.P(` }`) t.P() t.P(` d := `, t.pkgs["json"], `.NewDecoder(resp.Body)`) t.P(` rawRespBody := `, t.pkgs["json"], `.RawMessage{}`) t.P(` if err := d.Decode(&rawRespBody); err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to unmarshal json response")`) t.P(` }`) t.P(` unmarshaler := `, t.pkgs["protojson"], `.UnmarshalOptions{DiscardUnknown: true}`) t.P(` if err = unmarshaler.Unmarshal(rawRespBody, out); err != nil {`) t.P(` return ctx, wrapInternal(err, "failed to unmarshal json response")`) t.P(` }`) t.P(` if err = ctx.Err(); err != nil {`) t.P(` return ctx, wrapInternal(err, "aborted because context was done")`) t.P(` }`) t.P(` return ctx, nil`) t.P(`}`) t.P() t.P(`// Call twirp.ServerHooks.RequestReceived if the hook is available`) t.P(`func callRequestReceived(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ServerHooks) (`, t.pkgs["context"], `.Context, error) {`) t.P(` if h == nil || h.RequestReceived == nil {`) t.P(` return ctx, nil`) t.P(` }`) t.P(` return h.RequestReceived(ctx)`) t.P(`}`) t.P() t.P(`// Call twirp.ServerHooks.RequestRouted if the hook is available`) t.P(`func callRequestRouted(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ServerHooks) (`, t.pkgs["context"], `.Context, error) {`) t.P(` if h == nil || h.RequestRouted == nil {`) t.P(` return ctx, nil`) t.P(` }`) t.P(` return h.RequestRouted(ctx)`) t.P(`}`) t.P() t.P(`// Call twirp.ServerHooks.ResponsePrepared if the hook is available`) t.P(`func callResponsePrepared(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ServerHooks) `, t.pkgs["context"], `.Context {`) t.P(` if h == nil || h.ResponsePrepared == nil {`) t.P(` return ctx`) t.P(` }`) t.P(` return h.ResponsePrepared(ctx)`) t.P(`}`) t.P() t.P(`// Call twirp.ServerHooks.ResponseSent if the hook is available`) t.P(`func callResponseSent(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ServerHooks) {`) t.P(` if h == nil || h.ResponseSent == nil {`) t.P(` return`) t.P(` }`) t.P(` h.ResponseSent(ctx)`) t.P(`}`) t.P() t.P(`// Call twirp.ServerHooks.Error if the hook is available`) t.P(`func callError(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ServerHooks, err `, t.pkgs["twirp"], `.Error) `, t.pkgs["context"], `.Context {`) t.P(` if h == nil || h.Error == nil {`) t.P(` return ctx`) t.P(` }`) t.P(` return h.Error(ctx, err)`) t.P(`}`) t.P() t.generateClientHooks() } // P forwards to g.gen.P, which prints output. func (t *twirp) P(args ...string) { for _, v := range args { t.output.WriteString(v) } t.output.WriteByte('\n') } // Big header comments to makes it easier to visually parse a generated file. func (t *twirp) sectionComment(sectionTitle string) { t.P() t.P(`// `, strings.Repeat("=", len(sectionTitle))) t.P(`// `, sectionTitle) t.P(`// `, strings.Repeat("=", len(sectionTitle))) t.P() } func (t *twirp) generateService(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto, index int) { servName := serviceNameCamelCased(service) t.sectionComment(servName + ` Interface`) t.generateTwirpInterface(file, service) t.sectionComment(servName + ` Protobuf Client`) t.generateClient("Protobuf", file, service) t.sectionComment(servName + ` JSON Client`) t.generateClient("JSON", file, service) // Server t.sectionComment(servName + ` Server Handler`) t.generateServer(file, service) } func (t *twirp) generateTwirpInterface(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { servName := serviceNameCamelCased(service) comments, err := t.reg.ServiceComments(file, service) if err == nil { t.printComments(comments) } t.P(`type `, servName, ` interface {`) for _, method := range service.Method { comments, err = t.reg.MethodComments(file, service, method) if err == nil { t.printComments(comments) } t.P(t.generateSignature(method)) t.P() } t.P(`}`) } func (t *twirp) generateSignature(method *descriptor.MethodDescriptorProto) string { methName := methodNameCamelCased(method) inputType := t.goTypeName(method.GetInputType()) outputType := t.goTypeName(method.GetOutputType()) return fmt.Sprintf(` %s(%s.Context, *%s) (*%s, error)`, methName, t.pkgs["context"], inputType, outputType) } // valid names: 'JSON', 'Protobuf' func (t *twirp) generateClient(name string, file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { servPkg := pkgName(file) servName := serviceNameCamelCased(service) structName := unexported(servName) + name + "Client" newClientFunc := "New" + servName + name + "Client" servNameLit := serviceNameLiteral(service) servNameCc := servName methCnt := strconv.Itoa(len(service.Method)) t.P(`type `, structName, ` struct {`) t.P(` client HTTPClient`) t.P(` urls [`, methCnt, `]string`) t.P(` interceptor `, t.pkgs["twirp"], `.Interceptor`) t.P(` opts `, t.pkgs["twirp"], `.ClientOptions`) t.P(`}`) t.P() t.P(`// `, newClientFunc, ` creates a `, name, ` client that implements the `, servName, ` interface.`) t.P(`// It communicates using `, name, ` and can be configured with a custom HTTPClient.`) t.P(`func `, newClientFunc, `(baseURL string, client HTTPClient, opts ...`, t.pkgs["twirp"], `.ClientOption) `, servName, ` {`) t.P(` if c, ok := client.(*`, t.pkgs["http"], `.Client); ok {`) t.P(` client = withoutRedirects(c)`) t.P(` }`) t.P() t.P(` clientOpts := `, t.pkgs["twirp"], `.ClientOptions{}`) t.P(` for _, o := range opts {`) t.P(` o(&clientOpts)`) t.P(` }`) t.P() t.P(` // Using ReadOpt allows backwards and forwards compatibility with new options in the future`) t.P(` literalURLs := false`) t.P(` _ = clientOpts.ReadOpt("literalURLs", &literalURLs)`) t.P(` var pathPrefix string`) t.P(` if ok := clientOpts.ReadOpt("pathPrefix", &pathPrefix); !ok {`) t.P(` pathPrefix = "/twirp" // default prefix`) t.P(` }`) t.P() if len(service.Method) > 0 { t.P(` // Build method URLs: []/./`) t.P(` serviceURL := sanitizeBaseURL(baseURL)`) if servNameLit == servNameCc { t.P(` serviceURL += baseServicePath(pathPrefix, "`, servPkg, `", "`, servNameCc, `")`) } else { // proto service name is not CamelCased, then it needs to check client option to decide if needs to change case t.P(` if literalURLs {`) t.P(` serviceURL += baseServicePath(pathPrefix, "`, servPkg, `", "`, servNameLit, `")`) t.P(` } else {`) t.P(` serviceURL += baseServicePath(pathPrefix, "`, servPkg, `", "`, servNameCc, `")`) t.P(` }`) } } t.P(` urls := [`, methCnt, `]string{`) for _, method := range service.Method { t.P(` serviceURL + "`, methodNameCamelCased(method), `",`) } t.P(` }`) allMethodsCamelCased := true for _, method := range service.Method { methNameLit := methodNameLiteral(method) methNameCc := methodNameCamelCased(method) if methNameCc != methNameLit { allMethodsCamelCased = false break } } if !allMethodsCamelCased { t.P(` if literalURLs {`) t.P(` urls = [`, methCnt, `]string{`) for _, method := range service.Method { t.P(` serviceURL + "`, methodNameLiteral(method), `",`) } t.P(` }`) t.P(` }`) } t.P() t.P(` return &`, structName, `{`) t.P(` client: client,`) t.P(` urls: urls,`) t.P(` interceptor: `, t.pkgs["twirp"], `.ChainInterceptors(clientOpts.Interceptors...),`) t.P(` opts: clientOpts,`) t.P(` }`) t.P(`}`) t.P() for i, method := range service.Method { methName := methodNameCamelCased(method) pkgName := pkgName(file) inputType := t.goTypeName(method.GetInputType()) outputType := t.goTypeName(method.GetOutputType()) t.P(`func (c *`, structName, `) `, methName, `(ctx `, t.pkgs["context"], `.Context, in *`, inputType, `) (*`, outputType, `, error) {`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithPackageName(ctx, "`, pkgName, `")`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithServiceName(ctx, "`, servName, `")`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithMethodName(ctx, "`, methName, `")`) t.P(` caller := c.call`, methName) t.P(` if c.interceptor != nil {`) t.generateClientInterceptorCaller(method) t.P(` }`) t.P(` return caller(ctx, in)`) t.P(`}`) t.P() t.P(`func (c *`, structName, `) call`, methName, `(ctx `, t.pkgs["context"], `.Context, in *`, inputType, `) (*`, outputType, `, error) {`) t.P(` out := new(`, outputType, `)`) t.P(` ctx, err := do`, name, `Request(ctx, c.client, c.opts.Hooks, c.urls[`, strconv.Itoa(i), `], in, out)`) t.P(` if err != nil {`) t.P(` twerr, ok := err.(`, t.pkgs["twirp"], `.Error)`) t.P(` if !ok {`) t.P(` twerr = `, t.pkgs["twirp"], `.InternalErrorWith(err)`) t.P(` }`) t.P(` callClientError(ctx, c.opts.Hooks, twerr)`) t.P(` return nil, err`) t.P(` }`) t.P() t.P(` callClientResponseReceived(ctx, c.opts.Hooks)`) t.P() t.P(` return out, nil`) t.P(`}`) t.P() } } func (t *twirp) generateClientHooks() { t.P(`func callClientResponseReceived(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ClientHooks) {`) t.P(` if h == nil || h.ResponseReceived == nil {`) t.P(` return`) t.P(` }`) t.P(` h.ResponseReceived(ctx)`) t.P(`}`) t.P() t.P(`func callClientRequestPrepared(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ClientHooks, req *`, t.pkgs["http"], `.Request) (`, t.pkgs["context"], `.Context, error) {`) t.P(` if h == nil || h.RequestPrepared == nil {`) t.P(` return ctx, nil`) t.P(` }`) t.P(` return h.RequestPrepared(ctx, req)`) t.P(`}`) t.P() t.P(`func callClientError(ctx `, t.pkgs["context"], `.Context, h *`, t.pkgs["twirp"], `.ClientHooks, err `, t.pkgs["twirp"], `.Error) {`) t.P(` if h == nil || h.Error == nil {`) t.P(` return`) t.P(` }`) t.P(` h.Error(ctx, err)`) t.P(`}`) } func (t *twirp) generateServer(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { servName := serviceNameCamelCased(service) // Server implementation. servStruct := serviceStruct(service) t.P(`type `, servStruct, ` struct {`) t.P(` `, servName) t.P(` interceptor `, t.pkgs["twirp"], `.Interceptor`) t.P(` hooks *`, t.pkgs["twirp"], `.ServerHooks`) t.P(` pathPrefix string // prefix for routing`) t.P(` jsonSkipDefaults bool // do not include unpopulated fields (default values) in the response`) t.P(` jsonCamelCase bool // JSON fields are serialized as lowerCamelCase rather than keeping the original proto names`) t.P(`}`) t.P() // Constructor for server implementation t.P(`// New`, servName, `Server builds a TwirpServer that can be used as an http.Handler to handle`) t.P(`// HTTP requests that are routed to the right method in the provided svc implementation.`) t.P(`// The opts are twirp.ServerOption modifiers, for example twirp.WithServerHooks(hooks).`) t.P(`func New`, servName, `Server(svc `, servName, `, opts ...interface{}) TwirpServer {`) t.P(` serverOpts := newServerOpts(opts)`) t.P() t.P(` // Using ReadOpt allows backwards and forwards compatibility with new options in the future`) t.P(` jsonSkipDefaults := false`) t.P(` _ = serverOpts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults)`) t.P(` jsonCamelCase := false`) t.P(` _ = serverOpts.ReadOpt("jsonCamelCase", &jsonCamelCase)`) t.P(` var pathPrefix string`) t.P(` if ok := serverOpts.ReadOpt("pathPrefix", &pathPrefix); !ok {`) t.P(` pathPrefix = "/twirp" // default prefix`) t.P(` }`) t.P() t.P(` return &`, servStruct, `{`) t.P(` `, servName, `: svc,`) t.P(` hooks: serverOpts.Hooks,`) t.P(` interceptor: `, t.pkgs["twirp"], `.ChainInterceptors(serverOpts.Interceptors...),`) t.P(` pathPrefix: pathPrefix,`) t.P(` jsonSkipDefaults: jsonSkipDefaults,`) t.P(` jsonCamelCase: jsonCamelCase,`) t.P(` }`) t.P(`}`) t.P() // Write Errors t.P(`// writeError writes an HTTP response with a valid Twirp error format, and triggers hooks.`) t.P(`// If err is not a twirp.Error, it will get wrapped with twirp.InternalErrorWith(err)`) t.P(`func (s *`, servStruct, `) writeError(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, err error) {`) t.P(` writeError(ctx, resp, err, s.hooks)`) t.P(`}`) t.P() // Write request body read issue t.P(`// handleRequestBodyError is used to handle error when the twirp server cannot read request`) t.P(`func (s *`, servStruct, `) handleRequestBodyError(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, msg string, err error) {`) t.P(` if `, t.pkgs["context"], `.Canceled == ctx.Err() {`) t.P(` s.writeError(ctx, resp, `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.Canceled, "failed to read request: context canceled"))`) t.P(` return`) t.P(` } `) t.P(` if `, t.pkgs["context"], `.DeadlineExceeded == ctx.Err() {`) t.P(` s.writeError(ctx, resp, `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.DeadlineExceeded, "failed to read request: deadline exceeded"))`) t.P(` return`) t.P(` }`) t.P(` s.writeError(ctx, resp, `, t.pkgs["twirp"], `.WrapError(malformedRequestError(msg), err))`) t.P(`}`) t.P() // Routing. t.generateServerRouting(servStruct, file, service) // Methods. for _, method := range service.Method { t.generateServerMethod(service, method) } t.generateServiceMetadataAccessors(file, service) } func (t *twirp) generateServerRouting(servStruct string, file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { pkgName := pkgName(file) servName := serviceNameCamelCased(service) pkgServNameLit := pkgServiceNameLiteral(file, service) pkgServNameCc := pkgServiceNameCamelCased(file, service) t.P(`// `, servName, `PathPrefix is a convenience constant that may identify URL paths.`) t.P(`// Should be used with caution, it only matches routes generated by Twirp Go clients,`) t.P(`// with the default "/twirp" prefix and default CamelCase service and method names.`) t.P(`// More info: https://twitchtv.github.io/twirp/docs/routing.html`) t.P(`const `, servName, `PathPrefix = "/twirp/`, pkgServNameCc, `/"`) t.P() t.P(`func (s *`, servStruct, `) ServeHTTP(resp `, t.pkgs["http"], `.ResponseWriter, req *`, t.pkgs["http"], `.Request) {`) t.P(` ctx := req.Context()`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithPackageName(ctx, "`, pkgName, `")`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithServiceName(ctx, "`, servName, `")`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithResponseWriter(ctx, resp)`) t.P() t.P(` var err error`) t.P(` ctx, err = callRequestReceived(ctx, s.hooks)`) t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, err)`) t.P(` return`) t.P(` }`) t.P() t.P(` if req.Method != "POST" {`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("unsupported method %q (only POST is allowed)", req.Method)`) t.P(` s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))`) t.P(` return`) t.P(` }`) t.P() t.P(` // Verify path format: []/./`) t.P(` prefix, pkgService, method := parseTwirpPath(req.URL.Path)`) if pkgServNameLit == pkgServNameCc { t.P(` if pkgService != `, strconv.Quote(pkgServNameLit), ` {`) } else { // proto service name is not CamelCased, but need to support CamelCased routes for Go clients (https://github.com/twitchtv/twirp/pull/257) t.P(` if pkgService != `, strconv.Quote(pkgServNameLit), ` && pkgService != `, strconv.Quote(pkgServNameCc), ` {`) } t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("no handler for path %q", req.URL.Path)`) t.P(` s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))`) t.P(` return`) t.P(` }`) t.P(` if prefix != s.pathPrefix {`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("invalid path prefix %q, expected %q, on path %q", prefix, s.pathPrefix, req.URL.Path)`) t.P(` s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))`) t.P(` return`) t.P(` }`) t.P() t.P(` switch method {`) for _, method := range service.Method { methNameLit := methodNameLiteral(method) methNameCc := methodNameCamelCased(method) if methNameCc == methNameLit { t.P(` case `, strconv.Quote(methNameLit), `:`) } else { // proto method name is not CamelCased, but need to support CamelCased routes for Go clients (https://github.com/twitchtv/twirp/pull/257) t.P(` case `, strconv.Quote(methNameLit), `, `, strconv.Quote(methNameCc), `:`) } t.P(` s.serve`, methNameCc, `(ctx, resp, req)`) t.P(` return`) } t.P(` default:`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("no handler for path %q", req.URL.Path)`) t.P(` s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))`) t.P(` return`) t.P(` }`) t.P(`}`) t.P() } func (t *twirp) generateServerMethod(service *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) { methName := methodNameCamelCased(method) servStruct := serviceStruct(service) t.P(`func (s *`, servStruct, `) serve`, methName, `(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, req *`, t.pkgs["http"], `.Request) {`) t.P(` header := req.Header.Get("Content-Type")`) t.P(` i := `, t.pkgs["strings"], `.Index(header, ";")`) t.P(` if i == -1 {`) t.P(` i = len(header)`) t.P(` }`) t.P(` switch `, t.pkgs["strings"], `.TrimSpace(`, t.pkgs["strings"], `.ToLower(header[:i])) {`) t.P(` case "application/json":`) t.P(` s.serve`, methName, `JSON(ctx, resp, req)`) t.P(` case "application/protobuf":`) t.P(` s.serve`, methName, `Protobuf(ctx, resp, req)`) t.P(` default:`) t.P(` msg := `, t.pkgs["fmt"], `.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type"))`) t.P(` twerr := badRouteError(msg, req.Method, req.URL.Path)`) t.P(` s.writeError(ctx, resp, twerr)`) t.P(` }`) t.P(`}`) t.P() t.generateServerJSONMethod(service, method) t.generateServerProtobufMethod(service, method) } func (t *twirp) generateServerJSONMethod(service *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) { servStruct := serviceStruct(service) methName := methodNameCamelCased(method) servName := serviceNameCamelCased(service) t.P(`func (s *`, servStruct, `) serve`, methName, `JSON(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, req *`, t.pkgs["http"], `.Request) {`) t.P(` var err error`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithMethodName(ctx, "`, methName, `")`) t.P(` ctx, err = callRequestRouted(ctx, s.hooks)`) t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, err)`) t.P(` return`) t.P(` }`) t.P() t.P(` d := `, t.pkgs["json"], `.NewDecoder(req.Body)`) t.P(` rawReqBody := `, t.pkgs["json"], `.RawMessage{}`) t.P(` if err := d.Decode(&rawReqBody); err != nil {`) t.P(` s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)`) t.P(` return`) t.P(` }`) t.P(` reqContent := new(`, t.goTypeName(method.GetInputType()), `)`) t.P(` unmarshaler := `, t.pkgs["protojson"], `.UnmarshalOptions{DiscardUnknown: true}`) t.P(` if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil {`) t.P(` s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)`) t.P(` return`) t.P(` }`) t.P() t.P(` handler := s.`, servName, `.`, methName) t.P(` if s.interceptor != nil {`) t.generateServerInterceptorHandler(service, method) t.P(` }`) t.P() t.P(` // Call service method`) t.P(` var respContent *`, t.goTypeName(method.GetOutputType())) t.P(` func() {`) t.P(` defer ensurePanicResponses(ctx, resp, s.hooks)`) t.P(` respContent, err = handler(ctx, reqContent)`) t.P(` }()`) t.P() t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, err)`) t.P(` return`) t.P(` }`) t.P(` if respContent == nil {`) t.P(` s.writeError(ctx, resp, `, t.pkgs["twirp"], `.InternalError("received a nil *`, t.goTypeName(method.GetOutputType()), ` and nil error while calling `, methName, `. nil responses are not supported"))`) t.P(` return`) t.P(` }`) t.P() t.P(` ctx = callResponsePrepared(ctx, s.hooks)`) t.P() t.P(` marshaler := &`, t.pkgs["protojson"], `.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults}`) t.P(` respBytes, err := marshaler.Marshal(respContent)`) t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response"))`) t.P(` return`) t.P(` }`) t.P() t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithStatusCode(ctx, `, t.pkgs["http"], `.StatusOK)`) t.P(` resp.Header().Set("Content-Type", "application/json")`) t.P(` resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))`) t.P(` resp.WriteHeader(`, t.pkgs["http"], `.StatusOK)`) t.P() t.P(` if n, err := resp.Write(respBytes); err != nil {`) t.P(` msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())`) t.P(` twerr := `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.Unknown, msg)`) t.P(` ctx = callError(ctx, s.hooks, twerr)`) t.P(` }`) t.P(` callResponseSent(ctx, s.hooks)`) t.P(`}`) t.P() } func (t *twirp) generateServerProtobufMethod(service *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) { servStruct := serviceStruct(service) methName := methodNameCamelCased(method) servName := serviceNameCamelCased(service) t.P(`func (s *`, servStruct, `) serve`, methName, `Protobuf(ctx `, t.pkgs["context"], `.Context, resp `, t.pkgs["http"], `.ResponseWriter, req *`, t.pkgs["http"], `.Request) {`) t.P(` var err error`) t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithMethodName(ctx, "`, methName, `")`) t.P(` ctx, err = callRequestRouted(ctx, s.hooks)`) t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, err)`) t.P(` return`) t.P(` }`) t.P() t.P(` buf, err := `, t.pkgs["io"], `.ReadAll(req.Body)`) t.P(` if err != nil {`) t.P(` s.handleRequestBodyError(ctx, resp, "failed to read request body", err)`) t.P(` return`) t.P(` }`) t.P(` reqContent := new(`, t.goTypeName(method.GetInputType()), `)`) t.P(` if err = `, t.pkgs["proto"], `.Unmarshal(buf, reqContent); err != nil {`) t.P(` s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded"))`) t.P(` return`) t.P(` }`) t.P() t.P(` handler := s.`, servName, `.`, methName) t.P(` if s.interceptor != nil {`) t.generateServerInterceptorHandler(service, method) t.P(` }`) t.P() t.P(` // Call service method`) t.P(` var respContent *`, t.goTypeName(method.GetOutputType())) t.P(` func() {`) t.P(` defer ensurePanicResponses(ctx, resp, s.hooks)`) t.P(` respContent, err = handler(ctx, reqContent)`) t.P(` }()`) t.P() t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, err)`) t.P(` return`) t.P(` }`) t.P(` if respContent == nil {`) t.P(` s.writeError(ctx, resp, `, t.pkgs["twirp"], `.InternalError("received a nil *`, t.goTypeName(method.GetOutputType()), ` and nil error while calling `, methName, `. nil responses are not supported"))`) t.P(` return`) t.P(` }`) t.P() t.P(` ctx = callResponsePrepared(ctx, s.hooks)`) t.P() t.P(` respBytes, err := `, t.pkgs["proto"], `.Marshal(respContent)`) t.P(` if err != nil {`) t.P(` s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response"))`) t.P(` return`) t.P(` }`) t.P() t.P(` ctx = `, t.pkgs["ctxsetters"], `.WithStatusCode(ctx, `, t.pkgs["http"], `.StatusOK)`) t.P(` resp.Header().Set("Content-Type", "application/protobuf")`) t.P(` resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))`) t.P(` resp.WriteHeader(`, t.pkgs["http"], `.StatusOK)`) t.P(` if n, err := resp.Write(respBytes); err != nil {`) t.P(` msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())`) t.P(` twerr := `, t.pkgs["twirp"], `.NewError(`, t.pkgs["twirp"], `.Unknown, msg)`) t.P(` ctx = callError(ctx, s.hooks, twerr)`) t.P(` }`) t.P(` callResponseSent(ctx, s.hooks)`) t.P(`}`) t.P() } func (t *twirp) generateClientInterceptorCaller(method *descriptor.MethodDescriptorProto) { methName := methodNameCamelCased(method) t.generateInterceptorFunc("c", "caller", "c.call"+methName, method) } func (t *twirp) generateServerInterceptorHandler(service *descriptor.ServiceDescriptorProto, method *descriptor.MethodDescriptorProto) { methName := methodNameCamelCased(method) servName := serviceNameCamelCased(service) t.generateInterceptorFunc("s", "handler", "s."+servName+"."+methName, method) } func (t *twirp) generateInterceptorFunc( receiverName string, varName string, delegateFuncName string, method *descriptor.MethodDescriptorProto, ) { inputType := t.goTypeName(method.GetInputType()) outputType := t.goTypeName(method.GetOutputType()) t.P(` `, varName, ` = func(ctx `, t.pkgs["context"], `.Context, req *`, inputType, `) (*`, outputType, `, error) {`) t.P(` resp, err := `, receiverName, `.interceptor(`) t.P(` func(ctx `, t.pkgs["context"], ` .Context, req interface{}) (interface{}, error) {`) t.P(` typedReq, ok := req.(*`, inputType, `)`) t.P(` if !ok {`) t.P(` return nil, `, t.pkgs["twirp"], `.InternalError("failed type assertion req.(*`, inputType, `) when calling interceptor")`) t.P(` }`) t.P(` return `, delegateFuncName, `(ctx, typedReq)`) t.P(` },`) t.P(` )(ctx, req)`) t.P(` if resp != nil {`) t.P(` typedResp, ok := resp.(*`, outputType, `)`) t.P(` if !ok {`) t.P(` return nil, `, t.pkgs["twirp"], `.InternalError("failed type assertion resp.(*`, outputType, `) when calling interceptor")`) t.P(` }`) t.P(` return typedResp, err`) t.P(` }`) t.P(` return nil, err`) t.P(` }`) } // serviceMetadataVarName is the variable name used in generated code to refer // to the compressed bytes of this descriptor. It is not exported, so it is only // valid inside the generated package. // // protoc-gen-go writes its own version of this file, but so does // protoc-gen-gogo - with a different name! Twirp aims to be compatible with // both; the simplest way forward is to write the file descriptor again as // another variable that we control. func (t *twirp) serviceMetadataVarName() string { return fmt.Sprintf("twirpFileDescriptor%d", t.filesHandled) } func (t *twirp) generateServiceMetadataAccessors(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) { servStruct := serviceStruct(service) servPkg := pkgName(file) index := 0 for i, s := range file.Service { if s.GetName() == service.GetName() { index = i } } t.P(`func (s *`, servStruct, `) ServiceDescriptor() ([]byte, int) {`) t.P(` return `, t.serviceMetadataVarName(), `, `, strconv.Itoa(index)) t.P(`}`) t.P() t.P(`func (s *`, servStruct, `) ProtocGenTwirpVersion() (string) {`) t.P(` return `, strconv.Quote(gen.Version)) t.P(`}`) t.P() t.P(`// PathPrefix returns the base service path, in the form: "//./"`) t.P(`// that is everything in a Twirp route except for the . This can be used for routing,`) t.P(`// for example to identify the requests that are targeted to this service in a mux.`) t.P(`func (s *`, servStruct, `) PathPrefix() (string) {`) servName := serviceNameCamelCased(service) // it should be serviceNameLiteral(service), but needs to use CamelCase routes for backwards compatibility t.P(` return baseServicePath(s.pathPrefix, "`, servPkg, `", "`, servName, `") `) t.P(`}`) } func (t *twirp) generateFileDescriptor(file *descriptor.FileDescriptorProto) { // Copied straight of of protoc-gen-go, which trims out comments. pb := proto.Clone(file).(*descriptor.FileDescriptorProto) pb.SourceCodeInfo = nil b, err := proto.Marshal(pb) if err != nil { gen.Fail(err.Error()) } var buf bytes.Buffer w, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) _, _ = w.Write(b) w.Close() b = buf.Bytes() v := t.serviceMetadataVarName() t.P() t.P("var ", v, " = []byte{") t.P(" // ", fmt.Sprintf("%d", len(b)), " bytes of a gzipped FileDescriptorProto") for len(b) > 0 { n := 16 if n > len(b) { n = len(b) } s := "" for _, c := range b[:n] { s += fmt.Sprintf("0x%02x,", c) } t.P(` `, s) b = b[n:] } t.P("}") } func (t *twirp) printComments(comments typemap.DefinitionComments) bool { text := strings.TrimSuffix(comments.Leading, "\n") if len(strings.TrimSpace(text)) == 0 { return false } split := strings.Split(text, "\n") for _, line := range split { t.P("// ", strings.TrimPrefix(line, " ")) } return len(split) > 0 } // Given a protobuf name for a Message, return the Go name we will use for that // type, including its package prefix. func (t *twirp) goTypeName(protoName string) string { def := t.reg.MessageDefinition(protoName) if def == nil { gen.Fail("could not find message for", protoName) } var prefix string if pkg := t.goPackageName(def.File); pkg != t.genPkgName { prefix = pkg + "." } var name string for _, parent := range def.Lineage() { name += stringutils.CamelCase(parent.Descriptor.GetName()) + "_" } name += stringutils.CamelCase(def.Descriptor.GetName()) return prefix + name } func (t *twirp) goPackageName(file *descriptor.FileDescriptorProto) string { return t.fileToGoPackageName[file] } func (t *twirp) formattedOutput() string { // Reformat generated code. fset := token.NewFileSet() raw := t.output.Bytes() ast, err := parser.ParseFile(fset, "", raw, parser.ParseComments) if err != nil { // Print out the bad code with line numbers. // This should never happen in practice, but it can while changing generated code, // so consider this a debugging aid. var src bytes.Buffer s := bufio.NewScanner(bytes.NewReader(raw)) for line := 1; s.Scan(); line++ { fmt.Fprintf(&src, "%5d\t%s\n", line, s.Bytes()) } gen.Fail("bad Go source code was generated:", err.Error(), "\n"+src.String()) } out := bytes.NewBuffer(nil) err = (&printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8}).Fprint(out, fset, ast) if err != nil { gen.Fail("generated Go source code could not be reformatted:", err.Error()) } return out.String() } func unexported(s string) string { return strings.ToLower(s[:1]) + s[1:] } func pkgName(file *descriptor.FileDescriptorProto) string { return file.GetPackage() } func serviceNameCamelCased(service *descriptor.ServiceDescriptorProto) string { return stringutils.CamelCase(service.GetName()) } func serviceNameLiteral(service *descriptor.ServiceDescriptorProto) string { return service.GetName() } func pkgServiceNameCamelCased(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) string { name := serviceNameCamelCased(service) if pkg := pkgName(file); pkg != "" { name = pkg + "." + name } return name } func pkgServiceNameLiteral(file *descriptor.FileDescriptorProto, service *descriptor.ServiceDescriptorProto) string { name := serviceNameLiteral(service) if pkg := pkgName(file); pkg != "" { name = pkg + "." + name } return name } func serviceStruct(service *descriptor.ServiceDescriptorProto) string { return unexported(serviceNameCamelCased(service)) + "Server" } func methodNameCamelCased(method *descriptor.MethodDescriptorProto) string { return stringutils.CamelCase(method.GetName()) } func methodNameLiteral(method *descriptor.MethodDescriptorProto) string { return method.GetName() } func fileDescSliceContains(slice []*descriptor.FileDescriptorProto, f *descriptor.FileDescriptorProto) bool { for _, sf := range slice { if f == sf { return true } } return false } ================================================ FILE: protoc-gen-twirp/generator_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "os" "os/exec" "testing" "google.golang.org/protobuf/proto" plugin "google.golang.org/protobuf/types/pluginpb" ) func TestGenerateParseCommandLineParamsError(t *testing.T) { if os.Getenv("BE_CRASHER") == "1" { g := &twirp{} g.Generate(&plugin.CodeGeneratorRequest{ Parameter: proto.String("invalid"), }) return } cmd := exec.Command(os.Args[0], "-test.run=TestGenerateParseCommandLineParamsError") cmd.Env = append(os.Environ(), "BE_CRASHER=1") err := cmd.Run() if e, ok := err.(*exec.ExitError); ok && !e.Success() { return } t.Fatalf("process ran with err %v, want exit status 1", err) } ================================================ FILE: protoc-gen-twirp/go_naming.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "path" "strings" descriptor "google.golang.org/protobuf/types/descriptorpb" "github.com/twitchtv/twirp/internal/gen/stringutils" ) // goPackageOption interprets the file's go_package option. // If there is no go_package, it returns ("", "", false). // If there's a simple name, it returns ("", pkg, true). // If the option implies an import path, it returns (impPath, pkg, true). func goPackageOption(f *descriptor.FileDescriptorProto) (impPath, pkg string, ok bool) { pkg = f.GetOptions().GetGoPackage() if pkg == "" { return "", "", false } if bits := strings.Split(pkg, ";"); len(bits) == 2 { return bits[0], bits[1], true } // The presence of a slash implies there's an import path. slash := strings.LastIndex(pkg, "/") if slash < 0 { return "", pkg, true } impPath, pkg = pkg, pkg[slash+1:] // A semicolon-delimited suffix overrides the package name. sc := strings.IndexByte(impPath, ';') if sc < 0 { return impPath, pkg, true } impPath, pkg = impPath[:sc], impPath[sc+1:] return impPath, pkg, true } // goPackageName returns the Go package name to use in the generated Go file. // The result explicitly reports whether the name came from an option go_package // statement. If explicit is false, the name was derived from the protocol // buffer's package statement or the input file name. func goPackageName(f *descriptor.FileDescriptorProto) (name string, explicit bool) { // Does the file have a "go_package" option? if _, pkg, ok := goPackageOption(f); ok { return pkg, true } // Does the file have a package clause? if pkg := f.GetPackage(); pkg != "" { return pkg, false } // Use the file base name. return stringutils.BaseName(f.GetName()), false } // goFileName returns the output name for the generated Go file. func (t *twirp) goFileName(f *descriptor.FileDescriptorProto) string { name := *f.Name // proto file name if ext := path.Ext(name); ext == ".proto" || ext == ".protodevel" { name = name[:len(name)-len(ext)] // remove extension } name += ".twirp.go" // add twirp extension // with paths=source_relative, the directory is the same as the proto file if t.sourceRelativePaths { return name } // otherwise, the directory is taken from the option go_package if impPath, _, ok := goPackageOption(f); ok && impPath != "" { if t.modulePrefix != "" { impPath = strings.TrimPrefix(strings.TrimPrefix(impPath, t.modulePrefix), "/") } // Replace the existing dirname with the import path from go_package _, name = path.Split(name) name = path.Join(impPath, name) return name } return name } func parseGoPackageOption(v string) (importPath, packageName string) { // Allowed formats: // option go_package = "foo"; // option go_package = "github.com/example/foo"; // option go_package = "github.com/example/foo;bar"; semicolonPos := strings.Index(v, ";") if semicolonPos > -1 { importPath = v[:semicolonPos] packageName = v[semicolonPos+1:] return } if strings.Contains(v, "/") { importPath = v _, packageName = path.Split(v) return } importPath = "" packageName = v return } ================================================ FILE: protoc-gen-twirp/go_naming_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "testing" descriptor "google.golang.org/protobuf/types/descriptorpb" ) func TestParseGoPackageOption(t *testing.T) { testcase := func(in, wantImport, wantPkg string) func(*testing.T) { return func(t *testing.T) { haveImport, havePkg := parseGoPackageOption(in) if haveImport != wantImport { t.Errorf("wrong importPath, have=%q want=%q", haveImport, wantImport) } if havePkg != wantPkg { t.Errorf("wrong packageName, have=%q want=%q", havePkg, wantPkg) } } } t.Run("empty string", testcase("", "", "")) t.Run("bare package", testcase("foo", "", "foo")) t.Run("full import", testcase("github.com/example/foo", "github.com/example/foo", "foo")) t.Run("full import with override", testcase("github.com/example/foo;bar", "github.com/example/foo", "bar")) t.Run("non dotted import with package", testcase("foo;bar", "foo", "bar")) } func TestGoPackageOption(t *testing.T) { testcase := func(in, wantImport, wantPkg string, wantOK bool) func(*testing.T) { return func(t *testing.T) { haveImport, havePkg, haveOK := goPackageOption(&descriptor.FileDescriptorProto{ Options: &descriptor.FileOptions{ GoPackage: &in, }, }) if wantOK != haveOK { t.Errorf("wrong ok, have=%t want=%t", haveOK, wantOK) } if haveImport != wantImport { t.Errorf("wrong importPath, have=%q want=%q", haveImport, wantImport) } if havePkg != wantPkg { t.Errorf("wrong packageName, have=%q want=%q", havePkg, wantPkg) } } } t.Run("empty string", testcase("", "", "", false)) t.Run("bare package", testcase("foo", "", "foo", true)) t.Run("full import", testcase("github.com/example/foo", "github.com/example/foo", "foo", true)) t.Run("full import with override", testcase("github.com/example/foo;bar", "github.com/example/foo", "bar", true)) t.Run("non dotted import with package", testcase("foo;bar", "foo", "bar", true)) } func TestGoFileName(t *testing.T) { testcase := func(srcrelpaths bool, modprefix, fname, gopkg, wantName string) func(t2 *testing.T) { return func(t *testing.T) { f := &descriptor.FileDescriptorProto{ Name: &fname, Options: &descriptor.FileOptions{ GoPackage: &gopkg, }, } tw := &twirp{ sourceRelativePaths: srcrelpaths, modulePrefix: modprefix, } if name := tw.goFileName(f); name != wantName { t.Errorf("wrong goFileName, have=%q want=%q", name, wantName) } } } t.Run("paths=source_relative", testcase(true, "", "rpc/v1/service.proto", "example.com/module/package/rpc/v1", "rpc/v1/service.twirp.go")) t.Run("paths=import,module=example.com/module/package", testcase(false, "example.com/module/package", "rpc/v1/service.proto", "example.com/module/package/rpc/v1", "rpc/v1/service.twirp.go")) t.Run("paths=import,module=example.com/module/package/", testcase(false, "example.com/module/package/", "rpc/v1/service.proto", "example.com/module/package/rpc/v1", "rpc/v1/service.twirp.go")) } ================================================ FILE: protoc-gen-twirp/main.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 main import ( "flag" "fmt" "os" "github.com/twitchtv/twirp/internal/gen" ) func main() { versionFlag := flag.Bool("version", false, "print version and exit") flag.Parse() if *versionFlag { fmt.Println(gen.Version) os.Exit(0) } g := newGenerator() gen.Main(g) } ================================================ FILE: server_options.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "reflect" ) // ServerOption is a functional option for extending a Twirp service. type ServerOption func(*ServerOptions) // WithServerHooks defines the hooks for a Twirp server. func WithServerHooks(hooks *ServerHooks) ServerOption { return func(opts *ServerOptions) { opts.Hooks = hooks } } // WithServerInterceptors defines the interceptors for a Twirp server. func WithServerInterceptors(interceptors ...Interceptor) ServerOption { return func(opts *ServerOptions) { opts.Interceptors = append(opts.Interceptors, interceptors...) } } // WithServerPathPrefix specifies a different prefix for routing. // If not specified, the "/twirp" prefix is used by default. // An empty value "" can be specified to use no prefix. // The clients must be configured to send requests using the same prefix. // URL format: "[]/./" // More info on Twirp docs: https://twitchtv.github.io/twirp/docs/routing.html func WithServerPathPrefix(prefix string) ServerOption { return func(opts *ServerOptions) { opts.setOpt("pathPrefix", prefix) opts.pathPrefix = &prefix // for code generated before v8.1.0 } } // WithServerJSONSkipDefaults configures JSON serialization to skip // unpopulated or default values in JSON responses, which results in // smaller response sizes. This was the default before v7 and can be // enabled for full backwards compatibility if required. // This is now disabled by default, because JSON serialization is // commonly used for manual debugging, in which case it is useful // to see the full shape of the response. // See: https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson // See: https://developers.google.com/protocol-buffers/docs/proto3#json func WithServerJSONSkipDefaults(skipDefaults bool) ServerOption { return func(opts *ServerOptions) { opts.setOpt("jsonSkipDefaults", skipDefaults) opts.JSONSkipDefaults = skipDefaults // for code generated before v8.1.0 } } // WithServerJSONCamelCaseNames configures JSON serialization to use the // default proto3 JSON encoding (lowerCamelCase) rather than the original // proto field names. Twirp uses the original proto field names by default, // because JSON encoding is often used for manual debugging of the API, // but this option allows better compatibility with other proto-json parsers. // See: https://pkg.go.dev/google.golang.org/protobuf/encoding/protojson // See: https://developers.google.com/protocol-buffers/docs/proto3#json func WithServerJSONCamelCaseNames(jsonCamelCase bool) ServerOption { return func(opts *ServerOptions) { opts.setOpt("jsonCamelCase", jsonCamelCase) } } // ServerHooks is a container for callbacks that can instrument a // Twirp-generated server. These callbacks all accept a context and return a // context. They can use this to add to the request context as it threads // through the system, appending values or deadlines to it. // // The RequestReceived and RequestRouted hooks are special: they can return // errors. If they return a non-nil error, handling for that request will be // stopped at that point. The Error hook will be triggered, and the error will // be sent to the client. This can be used for stuff like auth checks before // deserializing a request. // // The RequestReceived hook is always called first, and it is called for every // request that the Twirp server handles. The last hook to be called in a // request's lifecycle is always ResponseSent, even in the case of an error. // // Details on the timing of each hook are documented as comments on the fields // of the ServerHooks type. type ServerHooks struct { // RequestReceived is called as soon as a request enters the Twirp // server at the earliest available moment. RequestReceived func(context.Context) (context.Context, error) // RequestRouted is called when a request has been routed to a // particular method of the Twirp server. RequestRouted func(context.Context) (context.Context, error) // ResponsePrepared is called when a request has been handled and a // response is ready to be sent to the client. ResponsePrepared func(context.Context) context.Context // ResponseSent is called when all bytes of a response (including an error // response) have been written. Because the ResponseSent hook is terminal, it // does not return a context. ResponseSent func(context.Context) // Error hook is called when an error occurs while handling a request. The // Error is passed as argument to the hook. Error func(context.Context, Error) context.Context } // ChainHooks creates a new *ServerHooks which chains the callbacks in // each of the constituent hooks passed in. Each hook function will be // called in the order of the ServerHooks values passed in. // // For the erroring hooks, RequestReceived and RequestRouted, any returned // errors prevent processing by later hooks. func ChainHooks(hooks ...*ServerHooks) *ServerHooks { if len(hooks) == 0 { return nil } if len(hooks) == 1 { return hooks[0] } return &ServerHooks{ RequestReceived: func(ctx context.Context) (context.Context, error) { var err error for _, h := range hooks { if h != nil && h.RequestReceived != nil { ctx, err = h.RequestReceived(ctx) if err != nil { return ctx, err } } } return ctx, nil }, RequestRouted: func(ctx context.Context) (context.Context, error) { var err error for _, h := range hooks { if h != nil && h.RequestRouted != nil { ctx, err = h.RequestRouted(ctx) if err != nil { return ctx, err } } } return ctx, nil }, ResponsePrepared: func(ctx context.Context) context.Context { for _, h := range hooks { if h != nil && h.ResponsePrepared != nil { ctx = h.ResponsePrepared(ctx) } } return ctx }, ResponseSent: func(ctx context.Context) { for _, h := range hooks { if h != nil && h.ResponseSent != nil { h.ResponseSent(ctx) } } }, Error: func(ctx context.Context, twerr Error) context.Context { for _, h := range hooks { if h != nil && h.Error != nil { ctx = h.Error(ctx, twerr) } } return ctx }, } } // ServerOptions encapsulate the configurable parameters on a Twirp server. // This type is meant to be used only by generated code. type ServerOptions struct { // Untyped options map. The methods setOpt and ReadOpt are used to set // and read options. The options are untyped so when a new option is added, // newly generated code can still work with older versions of the runtime. m map[string]interface{} Hooks *ServerHooks Interceptors []Interceptor // Properties below are only used by code that was // generated by older versions of Twirp (before v8.1.0). // New options with standard types added in the future // don't need new properties, they should use ReadOpt. JSONSkipDefaults bool pathPrefix *string } // ReadOpt extracts an option to a pointer value, // returns true if the option exists and was extracted. // This method is meant to be used by generated code, // keeping the type dependency outside of the runtime. // // Usage example: // // opts.setOpt("fooOpt", 123) // var foo int // ok := opts.ReadOpt("fooOpt", &int) // func (opts *ServerOptions) ReadOpt(key string, out interface{}) bool { val, ok := opts.m[key] if !ok { return false } rout := reflect.ValueOf(out) if rout.Kind() != reflect.Ptr { panic("ReadOpt(key, out); out must be a pointer but it was not") } rout.Elem().Set(reflect.ValueOf(val)) return true } // setOpt adds an option key/value. It is used by ServerOption helpers. // The value can be extracted with ReadOpt by passing a pointer to the same type. func (opts *ServerOptions) setOpt(key string, val interface{}) { if opts.m == nil { opts.m = make(map[string]interface{}) } opts.m[key] = val } // PathPrefix() is used only by clients generated before v8.1.0 func (opts *ServerOptions) PathPrefix() string { if opts.pathPrefix == nil { return "/twirp" // default prefix } return *opts.pathPrefix } ================================================ FILE: server_options_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "context" "reflect" "testing" ) func TestServerOptionsReadOpt(t *testing.T) { opts := &ServerOptions{} ok := false var fooNum int ok = opts.ReadOpt("fooNum", &fooNum) if ok { t.Errorf("option 'fooNum' does not exist, opts.ReadOpt should have returned false") } opts.setOpt("fooNum", 455) ok = opts.ReadOpt("fooNum", &fooNum) if !ok || fooNum != 455 { t.Errorf("option 'fooNum' expected to be 455") } var jsonSkipDefaults bool ok = opts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) if ok { t.Errorf("option 'jsonSkipDefaults' does not exist, opts.ReadOpt should have returned false") } WithServerJSONSkipDefaults(true)(opts) ok = opts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) if !ok || !jsonSkipDefaults { t.Errorf("option 'jsonSkipDefaults' expected to be true, ok: %v, val: %v", ok, jsonSkipDefaults) } WithServerJSONSkipDefaults(false)(opts) ok = opts.ReadOpt("jsonSkipDefaults", &jsonSkipDefaults) if !ok || jsonSkipDefaults { t.Errorf("option 'jsonSkipDefaults' expected to be false, ok: %v, val: %v", ok, jsonSkipDefaults) } } func TestChainHooks(t *testing.T) { var ( hook1 = new(ServerHooks) hook2 = new(ServerHooks) hook3 = new(ServerHooks) ) const key = "key" hook1.RequestReceived = func(ctx context.Context) (context.Context, error) { return context.WithValue(ctx, key, []string{"hook1"}), nil } hook2.RequestReceived = func(ctx context.Context) (context.Context, error) { v := ctx.Value(key).([]string) return context.WithValue(ctx, key, append(v, "hook2")), nil } hook3.RequestReceived = func(ctx context.Context) (context.Context, error) { v := ctx.Value(key).([]string) return context.WithValue(ctx, key, append(v, "hook3")), nil } hook1.RequestRouted = func(ctx context.Context) (context.Context, error) { return context.WithValue(ctx, key, []string{"hook1"}), nil } hook2.ResponsePrepared = func(ctx context.Context) context.Context { return context.WithValue(ctx, key, []string{"hook2"}) } chain := ChainHooks(hook1, hook2, hook3) ctx := context.Background() // When all three chained hooks have a handler, all should be called in order. want := []string{"hook1", "hook2", "hook3"} haveCtx, err := chain.RequestReceived(ctx) if err != nil { t.Fatalf("RequestReceived chain has unexpected err %v", err) } have := haveCtx.Value(key) if !reflect.DeepEqual(want, have) { t.Errorf("RequestReceived chain has unexpected ctx, have=%v, want=%v", have, want) } // When only the first chained hook has a handler, it should be called, and // there should be no panic. want = []string{"hook1"} haveCtx, err = chain.RequestRouted(ctx) if err != nil { t.Fatalf("RequestRouted chain has unexpected err %v", err) } have = haveCtx.Value(key) if !reflect.DeepEqual(want, have) { t.Errorf("RequestRouted chain has unexpected ctx, have=%v, want=%v", have, want) } // When only the second chained hook has a handler, it should be called, and // there should be no panic. want = []string{"hook2"} have = chain.ResponsePrepared(ctx).Value(key) if !reflect.DeepEqual(want, have) { t.Errorf("RequestRouted chain has unexpected ctx, have=%v, want=%v", have, want) } // When none of the chained hooks has a handler there should be no panic. chain.ResponseSent(ctx) } func TestWithServerPathPrefix(t *testing.T) { opts := &ServerOptions{} // Default value if have, want := opts.PathPrefix(), "/twirp"; have != want { t.Errorf("unexpected default PathPrefix() on ServerOptions, have: %q, want: %q", have, want) } // Set a different prefix WithServerPathPrefix("/newprfx/foobar")(opts) if have, want := opts.PathPrefix(), "/newprfx/foobar"; have != want { t.Errorf("unexpected value after WithServerPathPrefix, have: %q, want: %q", have, want) } // Use empty value for no-prefix WithServerPathPrefix("")(opts) if have, want := opts.PathPrefix(), ""; have != want { t.Errorf("unexpected value after WithServerPathPrefix, have: %q, want: %q", have, want) } } func TestWithJSONSkipDefaults(t *testing.T) { opts := &ServerOptions{} WithServerJSONSkipDefaults(true)(opts) if !opts.JSONSkipDefaults { t.Errorf("opts.JSONSkipDefaults expected to be true, but it is false") } WithServerJSONSkipDefaults(false)(opts) if opts.JSONSkipDefaults { t.Errorf("opts.JSONSkipDefaults expected to be false, but it is true") } } ================================================ FILE: tools.json ================================================ { "Tools": [ { "Repository": "github.com/kisielk/errcheck", "Commit": "db0ca22445717d1b2c51ac1034440e0a2a2de645" }, { "Repository": "github.com/twitchtv/retool", "Commit": "6f6d4930d88c40e23d2b54d12e64f0444e1fb4ef" }, { "Repository": "google.golang.org/protobuf/cmd/protoc-gen-go", "Commit": "fc9592f7ac4bade8f83e636263f8f07715c698d1" } ], "RetoolVersion": "1.3.5" } ================================================ FILE: vendor/github.com/davecgh/go-spew/LICENSE ================================================ ISC License Copyright (c) 2012-2016 Dave Collins Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/bypass.go ================================================ // Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. // +build !js,!appengine,!safe,!disableunsafe package spew import ( "reflect" "unsafe" ) const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = false // ptrSize is the size of a pointer on the current arch. ptrSize = unsafe.Sizeof((*byte)(nil)) ) var ( // offsetPtr, offsetScalar, and offsetFlag are the offsets for the // internal reflect.Value fields. These values are valid before golang // commit ecccf07e7f9d which changed the format. The are also valid // after commit 82f48826c6c7 which changed the format again to mirror // the original format. Code in the init function updates these offsets // as necessary. offsetPtr = uintptr(ptrSize) offsetScalar = uintptr(0) offsetFlag = uintptr(ptrSize * 2) // flagKindWidth and flagKindShift indicate various bits that the // reflect package uses internally to track kind information. // // flagRO indicates whether or not the value field of a reflect.Value is // read-only. // // flagIndir indicates whether the value field of a reflect.Value is // the actual data or a pointer to the data. // // These values are valid before golang commit 90a7c3c86944 which // changed their positions. Code in the init function updates these // flags as necessary. flagKindWidth = uintptr(5) flagKindShift = uintptr(flagKindWidth - 1) flagRO = uintptr(1 << 0) flagIndir = uintptr(1 << 1) ) func init() { // Older versions of reflect.Value stored small integers directly in the // ptr field (which is named val in the older versions). Versions // between commits ecccf07e7f9d and 82f48826c6c7 added a new field named // scalar for this purpose which unfortunately came before the flag // field, so the offset of the flag field is different for those // versions. // // This code constructs a new reflect.Value from a known small integer // and checks if the size of the reflect.Value struct indicates it has // the scalar field. When it does, the offsets are updated accordingly. vv := reflect.ValueOf(0xf00) if unsafe.Sizeof(vv) == (ptrSize * 4) { offsetScalar = ptrSize * 2 offsetFlag = ptrSize * 3 } // Commit 90a7c3c86944 changed the flag positions such that the low // order bits are the kind. This code extracts the kind from the flags // field and ensures it's the correct type. When it's not, the flag // order has been changed to the newer format, so the flags are updated // accordingly. upf := unsafe.Pointer(uintptr(unsafe.Pointer(&vv)) + offsetFlag) upfv := *(*uintptr)(upf) flagKindMask := uintptr((1<>flagKindShift != uintptr(reflect.Int) { flagKindShift = 0 flagRO = 1 << 5 flagIndir = 1 << 6 // Commit adf9b30e5594 modified the flags to separate the // flagRO flag into two bits which specifies whether or not the // field is embedded. This causes flagIndir to move over a bit // and means that flagRO is the combination of either of the // original flagRO bit and the new bit. // // This code detects the change by extracting what used to be // the indirect bit to ensure it's set. When it's not, the flag // order has been changed to the newer format, so the flags are // updated accordingly. if upfv&flagIndir == 0 { flagRO = 3 << 5 flagIndir = 1 << 7 } } } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses // the typical safety restrictions preventing access to unaddressable and // unexported data. It works by digging the raw pointer to the underlying // value out of the protected value and generating a new unprotected (unsafe) // reflect.Value to it. // // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. func unsafeReflectValue(v reflect.Value) (rv reflect.Value) { indirects := 1 vt := v.Type() upv := unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetPtr) rvf := *(*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetFlag)) if rvf&flagIndir != 0 { vt = reflect.PtrTo(v.Type()) indirects++ } else if offsetScalar != 0 { // The value is in the scalar field when it's not one of the // reference types. switch vt.Kind() { case reflect.Uintptr: case reflect.Chan: case reflect.Func: case reflect.Map: case reflect.Ptr: case reflect.UnsafePointer: default: upv = unsafe.Pointer(uintptr(unsafe.Pointer(&v)) + offsetScalar) } } pv := reflect.NewAt(vt, upv) rv = pv for i := 0; i < indirects; i++ { rv = rv.Elem() } return rv } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/bypasssafe.go ================================================ // Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. // +build js appengine safe disableunsafe package spew import "reflect" const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = true ) // unsafeReflectValue typically converts the passed reflect.Value into a one // that bypasses the typical safety restrictions preventing access to // unaddressable and unexported data. However, doing this relies on access to // the unsafe package. This is a stub version which simply returns the passed // reflect.Value when the unsafe package is not available. func unsafeReflectValue(v reflect.Value) reflect.Value { return v } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/common.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "reflect" "sort" "strconv" ) // Some constants in the form of bytes to avoid string overhead. This mirrors // the technique used in the fmt package. var ( panicBytes = []byte("(PANIC=") plusBytes = []byte("+") iBytes = []byte("i") trueBytes = []byte("true") falseBytes = []byte("false") interfaceBytes = []byte("(interface {})") commaNewlineBytes = []byte(",\n") newlineBytes = []byte("\n") openBraceBytes = []byte("{") openBraceNewlineBytes = []byte("{\n") closeBraceBytes = []byte("}") asteriskBytes = []byte("*") colonBytes = []byte(":") colonSpaceBytes = []byte(": ") openParenBytes = []byte("(") closeParenBytes = []byte(")") spaceBytes = []byte(" ") pointerChainBytes = []byte("->") nilAngleBytes = []byte("") maxNewlineBytes = []byte("\n") maxShortBytes = []byte("") circularBytes = []byte("") circularShortBytes = []byte("") invalidAngleBytes = []byte("") openBracketBytes = []byte("[") closeBracketBytes = []byte("]") percentBytes = []byte("%") precisionBytes = []byte(".") openAngleBytes = []byte("<") closeAngleBytes = []byte(">") openMapBytes = []byte("map[") closeMapBytes = []byte("]") lenEqualsBytes = []byte("len=") capEqualsBytes = []byte("cap=") ) // hexDigits is used to map a decimal value to a hex digit. var hexDigits = "0123456789abcdef" // catchPanic handles any panics that might occur during the handleMethods // calls. func catchPanic(w io.Writer, v reflect.Value) { if err := recover(); err != nil { w.Write(panicBytes) fmt.Fprintf(w, "%v", err) w.Write(closeParenBytes) } } // handleMethods attempts to call the Error and String methods on the underlying // type the passed reflect.Value represents and outputes the result to Writer w. // // It handles panics in any called methods by catching and displaying the error // as the formatted value. func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { // We need an interface to check if the type implements the error or // Stringer interface. However, the reflect package won't give us an // interface on certain things like unexported struct fields in order // to enforce visibility rules. We use unsafe, when it's available, // to bypass these restrictions since this package does not mutate the // values. if !v.CanInterface() { if UnsafeDisabled { return false } v = unsafeReflectValue(v) } // Choose whether or not to do error and Stringer interface lookups against // the base type or a pointer to the base type depending on settings. // Technically calling one of these methods with a pointer receiver can // mutate the value, however, types which choose to satisify an error or // Stringer interface with a pointer receiver should not be mutating their // state inside these interface methods. if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { v = unsafeReflectValue(v) } if v.CanAddr() { v = v.Addr() } // Is it an error or Stringer? switch iface := v.Interface().(type) { case error: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.Error())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.Error())) return true case fmt.Stringer: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.String())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.String())) return true } return false } // printBool outputs a boolean value as true or false to Writer w. func printBool(w io.Writer, val bool) { if val { w.Write(trueBytes) } else { w.Write(falseBytes) } } // printInt outputs a signed integer value to Writer w. func printInt(w io.Writer, val int64, base int) { w.Write([]byte(strconv.FormatInt(val, base))) } // printUint outputs an unsigned integer value to Writer w. func printUint(w io.Writer, val uint64, base int) { w.Write([]byte(strconv.FormatUint(val, base))) } // printFloat outputs a floating point value using the specified precision, // which is expected to be 32 or 64bit, to Writer w. func printFloat(w io.Writer, val float64, precision int) { w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) } // printComplex outputs a complex value using the specified float precision // for the real and imaginary parts to Writer w. func printComplex(w io.Writer, c complex128, floatPrecision int) { r := real(c) w.Write(openParenBytes) w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) i := imag(c) if i >= 0 { w.Write(plusBytes) } w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) w.Write(iBytes) w.Write(closeParenBytes) } // printHexPtr outputs a uintptr formatted as hexidecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. num := uint64(p) if num == 0 { w.Write(nilAngleBytes) return } // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix buf := make([]byte, 18) // It's simpler to construct the hex string right to left. base := uint64(16) i := len(buf) - 1 for num >= base { buf[i] = hexDigits[num%base] num /= base i-- } buf[i] = hexDigits[num] // Add '0x' prefix. i-- buf[i] = 'x' i-- buf[i] = '0' // Strip unused leading bytes. buf = buf[i:] w.Write(buf) } // valuesSorter implements sort.Interface to allow a slice of reflect.Value // elements to be sorted. type valuesSorter struct { values []reflect.Value strings []string // either nil or same len and values cs *ConfigState } // newValuesSorter initializes a valuesSorter instance, which holds a set of // surrogate keys on which the data should be sorted. It uses flags in // ConfigState to decide if and how to populate those surrogate keys. func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { vs := &valuesSorter{values: values, cs: cs} if canSortSimply(vs.values[0].Kind()) { return vs } if !cs.DisableMethods { vs.strings = make([]string, len(values)) for i := range vs.values { b := bytes.Buffer{} if !handleMethods(cs, &b, vs.values[i]) { vs.strings = nil break } vs.strings[i] = b.String() } } if vs.strings == nil && cs.SpewKeys { vs.strings = make([]string, len(values)) for i := range vs.values { vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) } } return vs } // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted // directly, or whether it should be considered for sorting by surrogate keys // (if the ConfigState allows it). func canSortSimply(kind reflect.Kind) bool { // This switch parallels valueSortLess, except for the default case. switch kind { case reflect.Bool: return true case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return true case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return true case reflect.Float32, reflect.Float64: return true case reflect.String: return true case reflect.Uintptr: return true case reflect.Array: return true } return false } // Len returns the number of values in the slice. It is part of the // sort.Interface implementation. func (s *valuesSorter) Len() int { return len(s.values) } // Swap swaps the values at the passed indices. It is part of the // sort.Interface implementation. func (s *valuesSorter) Swap(i, j int) { s.values[i], s.values[j] = s.values[j], s.values[i] if s.strings != nil { s.strings[i], s.strings[j] = s.strings[j], s.strings[i] } } // valueSortLess returns whether the first value should sort before the second // value. It is used by valueSorter.Less as part of the sort.Interface // implementation. func valueSortLess(a, b reflect.Value) bool { switch a.Kind() { case reflect.Bool: return !a.Bool() && b.Bool() case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return a.Int() < b.Int() case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return a.Uint() < b.Uint() case reflect.Float32, reflect.Float64: return a.Float() < b.Float() case reflect.String: return a.String() < b.String() case reflect.Uintptr: return a.Uint() < b.Uint() case reflect.Array: // Compare the contents of both arrays. l := a.Len() for i := 0; i < l; i++ { av := a.Index(i) bv := b.Index(i) if av.Interface() == bv.Interface() { continue } return valueSortLess(av, bv) } } return a.String() < b.String() } // Less returns whether the value at index i should sort before the // value at index j. It is part of the sort.Interface implementation. func (s *valuesSorter) Less(i, j int) bool { if s.strings == nil { return valueSortLess(s.values[i], s.values[j]) } return s.strings[i] < s.strings[j] } // sortValues is a sort function that handles both native types and any type that // can be converted to error or Stringer. Other inputs are sorted according to // their Value.String() value to ensure display stability. func sortValues(values []reflect.Value, cs *ConfigState) { if len(values) == 0 { return } sort.Sort(newValuesSorter(values, cs)) } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/config.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "os" ) // ConfigState houses the configuration options used by spew to format and // display values. There is a global instance, Config, that is used to control // all top-level Formatter and Dump functionality. Each ConfigState instance // provides methods equivalent to the top-level functions. // // The zero value for ConfigState provides no indentation. You would typically // want to set it to a space or a tab. // // Alternatively, you can use NewDefaultConfig to get a ConfigState instance // with default settings. See the documentation of NewDefaultConfig for default // values. type ConfigState struct { // Indent specifies the string to use for each indentation level. The // global config instance that all top-level functions use set this to a // single space by default. If you would like more indentation, you might // set this to a tab with "\t" or perhaps two spaces with " ". Indent string // MaxDepth controls the maximum number of levels to descend into nested // data structures. The default, 0, means there is no limit. // // NOTE: Circular data structures are properly detected, so it is not // necessary to set this value unless you specifically want to limit deeply // nested data structures. MaxDepth int // DisableMethods specifies whether or not error and Stringer interfaces are // invoked for types that implement them. DisableMethods bool // DisablePointerMethods specifies whether or not to check for and invoke // error and Stringer interfaces on types which only accept a pointer // receiver when the current type is not a pointer. // // NOTE: This might be an unsafe action since calling one of these methods // with a pointer receiver could technically mutate the value, however, // in practice, types which choose to satisify an error or Stringer // interface with a pointer receiver should not be mutating their state // inside these interface methods. As a result, this option relies on // access to the unsafe package, so it will not have any effect when // running in environments without access to the unsafe package such as // Google App Engine or with the "safe" build tag specified. DisablePointerMethods bool // DisablePointerAddresses specifies whether to disable the printing of // pointer addresses. This is useful when diffing data structures in tests. DisablePointerAddresses bool // DisableCapacities specifies whether to disable the printing of capacities // for arrays, slices, maps and channels. This is useful when diffing // data structures in tests. DisableCapacities bool // ContinueOnMethod specifies whether or not recursion should continue once // a custom error or Stringer interface is invoked. The default, false, // means it will print the results of invoking the custom error or Stringer // interface and return immediately instead of continuing to recurse into // the internals of the data type. // // NOTE: This flag does not have any effect if method invocation is disabled // via the DisableMethods or DisablePointerMethods options. ContinueOnMethod bool // SortKeys specifies map keys should be sorted before being printed. Use // this to have a more deterministic, diffable output. Note that only // native types (bool, int, uint, floats, uintptr and string) and types // that support the error or Stringer interfaces (if methods are // enabled) are supported, with other types sorted according to the // reflect.Value.String() output which guarantees display stability. SortKeys bool // SpewKeys specifies that, as a last resort attempt, map keys should // be spewed to strings and sorted by those strings. This is only // considered if SortKeys is true. SpewKeys bool } // Config is the active configuration of the top-level functions. // The configuration can be changed by modifying the contents of spew.Config. var Config = ConfigState{Indent: " "} // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the formatted string as a value that satisfies error. See NewFormatter // for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, c.convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, c.convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, c.convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a Formatter interface returned by c.NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, c.convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Print(a ...interface{}) (n int, err error) { return fmt.Print(c.convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, c.convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Println(a ...interface{}) (n int, err error) { return fmt.Println(c.convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprint(a ...interface{}) string { return fmt.Sprint(c.convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, c.convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a Formatter interface returned by c.NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintln(a ...interface{}) string { return fmt.Sprintln(c.convertArgs(a)...) } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as c.Printf, c.Println, or c.Printf. */ func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { return newFormatter(c, v) } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { fdump(c, w, a...) } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by modifying the public members of c. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func (c *ConfigState) Dump(a ...interface{}) { fdump(c, os.Stdout, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func (c *ConfigState) Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(c, &buf, a...) return buf.String() } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a spew Formatter interface using // the ConfigState associated with s. func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = newFormatter(c, arg) } return formatters } // NewDefaultConfig returns a ConfigState with the following default settings. // // Indent: " " // MaxDepth: 0 // DisableMethods: false // DisablePointerMethods: false // ContinueOnMethod: false // SortKeys: false func NewDefaultConfig() *ConfigState { return &ConfigState{Indent: " "} } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/doc.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Package spew implements a deep pretty printer for Go data structures to aid in debugging. A quick overview of the additional features spew provides over the built-in printing facilities for Go data types are as follows: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output (only when using Dump style) There are two different approaches spew allows for dumping Go data structures: * Dump style which prints with newlines, customizable indentation, and additional debug information such as types and all pointer addresses used to indirect to the final value * A custom Formatter interface that integrates cleanly with the standard fmt package and replaces %v, %+v, %#v, and %#+v to provide inline printing similar to the default %v while providing the additional functionality outlined above and passing unsupported format verbs such as %x and %q along to fmt Quick Start This section demonstrates how to quickly get started with spew. See the sections below for further details on formatting and configuration options. To dump a variable with full newlines, indentation, type, and pointer information use Dump, Fdump, or Sdump: spew.Dump(myVar1, myVar2, ...) spew.Fdump(someWriter, myVar1, myVar2, ...) str := spew.Sdump(myVar1, myVar2, ...) Alternatively, if you would prefer to use format strings with a compacted inline printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses): spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) Configuration Options Configuration of spew is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the spew.Config global. It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration options. See the ConfigState documentation for more details. The following configuration options are available: * Indent String to use for each indentation level for Dump functions. It is a single space by default. A popular alternative is "\t". * MaxDepth Maximum number of levels to descend into nested data structures. There is no limit by default. * DisableMethods Disables invocation of error and Stringer interface methods. Method invocation is enabled by default. * DisablePointerMethods Disables invocation of error and Stringer interface methods on types which only accept pointer receivers from non-pointer variables. Pointer method invocation is enabled by default. * DisablePointerAddresses DisablePointerAddresses specifies whether to disable the printing of pointer addresses. This is useful when diffing data structures in tests. * DisableCapacities DisableCapacities specifies whether to disable the printing of capacities for arrays, slices, maps and channels. This is useful when diffing data structures in tests. * ContinueOnMethod Enables recursion into types after invoking error and Stringer interface methods. Recursion after method invocation is disabled by default. * SortKeys Specifies map keys should be sorted before being printed. Use this to have a more deterministic, diffable output. Note that only native types (bool, int, uint, floats, uintptr and string) and types which implement error or Stringer interfaces are supported with other types sorted according to the reflect.Value.String() output which guarantees display stability. Natural map order is used by default. * SpewKeys Specifies that, as a last resort attempt, map keys should be spewed to strings and sorted by those strings. This is only considered if SortKeys is true. Dump Usage Simply call spew.Dump with a list of variables you want to dump: spew.Dump(myVar1, myVar2, ...) You may also call spew.Fdump if you would prefer to output to an arbitrary io.Writer. For example, to dump to standard error: spew.Fdump(os.Stderr, myVar1, myVar2, ...) A third option is to call spew.Sdump to get the formatted output as a string: str := spew.Sdump(myVar1, myVar2, ...) Sample Dump Output See the Dump example for details on the setup of the types and variables being shown here. (main.Foo) { unexportedField: (*main.Bar)(0xf84002e210)({ flag: (main.Flag) flagTwo, data: (uintptr) }), ExportedField: (map[interface {}]interface {}) (len=1) { (string) (len=3) "one": (bool) true } } Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C command as shown. ([]uint8) (len=32 cap=32) { 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 00000020 31 32 |12| } Custom Formatter Spew provides a custom formatter that implements the fmt.Formatter interface so that it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Custom Formatter Usage The simplest way to make use of the spew custom formatter is to call one of the convenience functions such as spew.Printf, spew.Println, or spew.Printf. The functions have syntax you are most likely already familiar with: spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Println(myVar, myVar2) spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) See the Index for the full list convenience functions. Sample Formatter Output Double pointer to a uint8: %v: <**>5 %+v: <**>(0xf8400420d0->0xf8400420c8)5 %#v: (**uint8)5 %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 Pointer to circular struct with a uint8 field and a pointer to itself: %v: <*>{1 <*>} %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} See the Printf example for details on the setup of variables being shown here. Errors Since it is possible for custom Stringer/error interfaces to panic, spew detects them and handles them internally by printing the panic information inline with the output. Since spew is intended to provide deep pretty printing capabilities on structures, it intentionally does not return any errors. */ package spew ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/dump.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "encoding/hex" "fmt" "io" "os" "reflect" "regexp" "strconv" "strings" ) var ( // uint8Type is a reflect.Type representing a uint8. It is used to // convert cgo types to uint8 slices for hexdumping. uint8Type = reflect.TypeOf(uint8(0)) // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. cCharRE = regexp.MustCompile("^.*\\._Ctype_char$") // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. cUnsignedCharRE = regexp.MustCompile("^.*\\._Ctype_unsignedchar$") // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. cUint8tCharRE = regexp.MustCompile("^.*\\._Ctype_uint8_t$") ) // dumpState contains information about the state of a dump operation. type dumpState struct { w io.Writer depth int pointers map[uintptr]int ignoreNextType bool ignoreNextIndent bool cs *ConfigState } // indent performs indentation according to the depth level and cs.Indent // option. func (d *dumpState) indent() { if d.ignoreNextIndent { d.ignoreNextIndent = false return } d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) } // unpackValue returns values inside of non-nil interfaces when possible. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface && !v.IsNil() { v = v.Elem() } return v } // dumpPtr handles formatting of pointers by indirecting them as necessary. func (d *dumpState) dumpPtr(v reflect.Value) { // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range d.pointers { if depth >= d.depth { delete(d.pointers, k) } } // Keep list of all dereferenced pointers to show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by dereferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := d.pointers[addr]; ok && pd < d.depth { cycleFound = true indirects-- break } d.pointers[addr] = d.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type information. d.w.Write(openParenBytes) d.w.Write(bytes.Repeat(asteriskBytes, indirects)) d.w.Write([]byte(ve.Type().String())) d.w.Write(closeParenBytes) // Display pointer information. if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { d.w.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { d.w.Write(pointerChainBytes) } printHexPtr(d.w, addr) } d.w.Write(closeParenBytes) } // Display dereferenced value. d.w.Write(openParenBytes) switch { case nilFound == true: d.w.Write(nilAngleBytes) case cycleFound == true: d.w.Write(circularBytes) default: d.ignoreNextType = true d.dump(ve) } d.w.Write(closeParenBytes) } // dumpSlice handles formatting of arrays and slices. Byte (uint8 under // reflection) arrays and slices are dumped in hexdump -C fashion. func (d *dumpState) dumpSlice(v reflect.Value) { // Determine whether this type should be hex dumped or not. Also, // for types which should be hexdumped, try to use the underlying data // first, then fall back to trying to convert them to a uint8 slice. var buf []uint8 doConvert := false doHexDump := false numEntries := v.Len() if numEntries > 0 { vt := v.Index(0).Type() vts := vt.String() switch { // C types that need to be converted. case cCharRE.MatchString(vts): fallthrough case cUnsignedCharRE.MatchString(vts): fallthrough case cUint8tCharRE.MatchString(vts): doConvert = true // Try to use existing uint8 slices and fall back to converting // and copying if that fails. case vt.Kind() == reflect.Uint8: // We need an addressable interface to convert the type // to a byte slice. However, the reflect package won't // give us an interface on certain things like // unexported struct fields in order to enforce // visibility rules. We use unsafe, when available, to // bypass these restrictions since this package does not // mutate the values. vs := v if !vs.CanInterface() || !vs.CanAddr() { vs = unsafeReflectValue(vs) } if !UnsafeDisabled { vs = vs.Slice(0, numEntries) // Use the existing uint8 slice if it can be // type asserted. iface := vs.Interface() if slice, ok := iface.([]uint8); ok { buf = slice doHexDump = true break } } // The underlying data needs to be converted if it can't // be type asserted to a uint8 slice. doConvert = true } // Copy and convert the underlying type if needed. if doConvert && vt.ConvertibleTo(uint8Type) { // Convert and copy each element into a uint8 byte // slice. buf = make([]uint8, numEntries) for i := 0; i < numEntries; i++ { vv := v.Index(i) buf[i] = uint8(vv.Convert(uint8Type).Uint()) } doHexDump = true } } // Hexdump the entire slice as needed. if doHexDump { indent := strings.Repeat(d.cs.Indent, d.depth) str := indent + hex.Dump(buf) str = strings.Replace(str, "\n", "\n"+indent, -1) str = strings.TrimRight(str, d.cs.Indent) d.w.Write([]byte(str)) return } // Recursively call dump for each item. for i := 0; i < numEntries; i++ { d.dump(d.unpackValue(v.Index(i))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } // dump is the main workhorse for dumping a value. It uses the passed reflect // value to figure out what kind of object we are dealing with and formats it // appropriately. It is a recursive function, however circular data structures // are detected and handled properly. func (d *dumpState) dump(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { d.w.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { d.indent() d.dumpPtr(v) return } // Print type information unless already handled elsewhere. if !d.ignoreNextType { d.indent() d.w.Write(openParenBytes) d.w.Write([]byte(v.Type().String())) d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } d.ignoreNextType = false // Display length and capacity if the built-in len and cap functions // work with the value's kind and the len/cap itself is non-zero. valueLen, valueCap := 0, 0 switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Chan: valueLen, valueCap = v.Len(), v.Cap() case reflect.Map, reflect.String: valueLen = v.Len() } if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { d.w.Write(openParenBytes) if valueLen != 0 { d.w.Write(lenEqualsBytes) printInt(d.w, int64(valueLen), 10) } if !d.cs.DisableCapacities && valueCap != 0 { if valueLen != 0 { d.w.Write(spaceBytes) } d.w.Write(capEqualsBytes) printInt(d.w, int64(valueCap), 10) } d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } // Call Stringer/error interfaces if they exist and the handle methods flag // is enabled if !d.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(d.cs, d.w, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(d.w, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(d.w, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(d.w, v.Uint(), 10) case reflect.Float32: printFloat(d.w, v.Float(), 32) case reflect.Float64: printFloat(d.w, v.Float(), 64) case reflect.Complex64: printComplex(d.w, v.Complex(), 32) case reflect.Complex128: printComplex(d.w, v.Complex(), 64) case reflect.Slice: if v.IsNil() { d.w.Write(nilAngleBytes) break } fallthrough case reflect.Array: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { d.dumpSlice(v) } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.String: d.w.Write([]byte(strconv.Quote(v.String()))) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { d.w.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { d.w.Write(nilAngleBytes) break } d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { numEntries := v.Len() keys := v.MapKeys() if d.cs.SortKeys { sortValues(keys, d.cs) } for i, key := range keys { d.dump(d.unpackValue(key)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.MapIndex(key))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Struct: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { vt := v.Type() numFields := v.NumField() for i := 0; i < numFields; i++ { d.indent() vtf := vt.Field(i) d.w.Write([]byte(vtf.Name)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.Field(i))) if i < (numFields - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(d.w, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(d.w, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it in case any new // types are added. default: if v.CanInterface() { fmt.Fprintf(d.w, "%v", v.Interface()) } else { fmt.Fprintf(d.w, "%v", v.String()) } } } // fdump is a helper function to consolidate the logic from the various public // methods which take varying writers and config states. func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { for _, arg := range a { if arg == nil { w.Write(interfaceBytes) w.Write(spaceBytes) w.Write(nilAngleBytes) w.Write(newlineBytes) continue } d := dumpState{w: w, cs: cs} d.pointers = make(map[uintptr]int) d.dump(reflect.ValueOf(arg)) d.w.Write(newlineBytes) } } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func Fdump(w io.Writer, a ...interface{}) { fdump(&Config, w, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(&Config, &buf, a...) return buf.String() } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: * Pointers are dereferenced and followed * Circular data structures are detected and handled properly * Custom Stringer/error interfaces are optionally invoked, including on unexported types * Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables * Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by an exported package global, spew.Config. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func Dump(a ...interface{}) { fdump(&Config, os.Stdout, a...) } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/format.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "reflect" "strconv" "strings" ) // supportedFlags is a list of all the character flags supported by fmt package. const supportedFlags = "0-+# " // formatState implements the fmt.Formatter interface and contains information // about the state of a formatting operation. The NewFormatter function can // be used to get a new Formatter which can be used directly as arguments // in standard fmt package printing calls. type formatState struct { value interface{} fs fmt.State depth int pointers map[uintptr]int ignoreNextType bool cs *ConfigState } // buildDefaultFormat recreates the original format string without precision // and width information to pass in to fmt.Sprintf in the case of an // unrecognized type. Unless new types are added to the language, this // function won't ever be called. func (f *formatState) buildDefaultFormat() (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } buf.WriteRune('v') format = buf.String() return format } // constructOrigFormat recreates the original format string including precision // and width information to pass along to the standard fmt package. This allows // automatic deferral of all format strings this package doesn't support. func (f *formatState) constructOrigFormat(verb rune) (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } if width, ok := f.fs.Width(); ok { buf.WriteString(strconv.Itoa(width)) } if precision, ok := f.fs.Precision(); ok { buf.Write(precisionBytes) buf.WriteString(strconv.Itoa(precision)) } buf.WriteRune(verb) format = buf.String() return format } // unpackValue returns values inside of non-nil interfaces when possible and // ensures that types for values which have been unpacked from an interface // are displayed when the show types flag is also set. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (f *formatState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface { f.ignoreNextType = false if !v.IsNil() { v = v.Elem() } } return v } // formatPtr handles formatting of pointers by indirecting them as necessary. func (f *formatState) formatPtr(v reflect.Value) { // Display nil if top level pointer is nil. showTypes := f.fs.Flag('#') if v.IsNil() && (!showTypes || f.ignoreNextType) { f.fs.Write(nilAngleBytes) return } // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range f.pointers { if depth >= f.depth { delete(f.pointers, k) } } // Keep list of all dereferenced pointers to possibly show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by derferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := f.pointers[addr]; ok && pd < f.depth { cycleFound = true indirects-- break } f.pointers[addr] = f.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type or indirection level depending on flags. if showTypes && !f.ignoreNextType { f.fs.Write(openParenBytes) f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) f.fs.Write([]byte(ve.Type().String())) f.fs.Write(closeParenBytes) } else { if nilFound || cycleFound { indirects += strings.Count(ve.Type().String(), "*") } f.fs.Write(openAngleBytes) f.fs.Write([]byte(strings.Repeat("*", indirects))) f.fs.Write(closeAngleBytes) } // Display pointer information depending on flags. if f.fs.Flag('+') && (len(pointerChain) > 0) { f.fs.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { f.fs.Write(pointerChainBytes) } printHexPtr(f.fs, addr) } f.fs.Write(closeParenBytes) } // Display dereferenced value. switch { case nilFound == true: f.fs.Write(nilAngleBytes) case cycleFound == true: f.fs.Write(circularShortBytes) default: f.ignoreNextType = true f.format(ve) } } // format is the main workhorse for providing the Formatter interface. It // uses the passed reflect value to figure out what kind of object we are // dealing with and formats it appropriately. It is a recursive function, // however circular data structures are detected and handled properly. func (f *formatState) format(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { f.fs.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { f.formatPtr(v) return } // Print type information unless already handled elsewhere. if !f.ignoreNextType && f.fs.Flag('#') { f.fs.Write(openParenBytes) f.fs.Write([]byte(v.Type().String())) f.fs.Write(closeParenBytes) } f.ignoreNextType = false // Call Stringer/error interfaces if they exist and the handle methods // flag is enabled. if !f.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(f.cs, f.fs, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(f.fs, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(f.fs, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(f.fs, v.Uint(), 10) case reflect.Float32: printFloat(f.fs, v.Float(), 32) case reflect.Float64: printFloat(f.fs, v.Float(), 64) case reflect.Complex64: printComplex(f.fs, v.Complex(), 32) case reflect.Complex128: printComplex(f.fs, v.Complex(), 64) case reflect.Slice: if v.IsNil() { f.fs.Write(nilAngleBytes) break } fallthrough case reflect.Array: f.fs.Write(openBracketBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { numEntries := v.Len() for i := 0; i < numEntries; i++ { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(v.Index(i))) } } f.depth-- f.fs.Write(closeBracketBytes) case reflect.String: f.fs.Write([]byte(v.String())) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { f.fs.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { f.fs.Write(nilAngleBytes) break } f.fs.Write(openMapBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { keys := v.MapKeys() if f.cs.SortKeys { sortValues(keys, f.cs) } for i, key := range keys { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(key)) f.fs.Write(colonBytes) f.ignoreNextType = true f.format(f.unpackValue(v.MapIndex(key))) } } f.depth-- f.fs.Write(closeMapBytes) case reflect.Struct: numFields := v.NumField() f.fs.Write(openBraceBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { vt := v.Type() for i := 0; i < numFields; i++ { if i > 0 { f.fs.Write(spaceBytes) } vtf := vt.Field(i) if f.fs.Flag('+') || f.fs.Flag('#') { f.fs.Write([]byte(vtf.Name)) f.fs.Write(colonBytes) } f.format(f.unpackValue(v.Field(i))) } } f.depth-- f.fs.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(f.fs, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(f.fs, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it if any get added. default: format := f.buildDefaultFormat() if v.CanInterface() { fmt.Fprintf(f.fs, format, v.Interface()) } else { fmt.Fprintf(f.fs, format, v.String()) } } } // Format satisfies the fmt.Formatter interface. See NewFormatter for usage // details. func (f *formatState) Format(fs fmt.State, verb rune) { f.fs = fs // Use standard formatting for verbs that are not v. if verb != 'v' { format := f.constructOrigFormat(verb) fmt.Fprintf(fs, format, f.value) return } if f.value == nil { if fs.Flag('#') { fs.Write(interfaceBytes) } fs.Write(nilAngleBytes) return } f.format(reflect.ValueOf(f.value)) } // newFormatter is a helper function to consolidate the logic from the various // public methods which take varying config states. func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { fs := &formatState{value: v, cs: cs} fs.pointers = make(map[uintptr]int) return fs } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as Printf, Println, or Fprintf. */ func NewFormatter(v interface{}) fmt.Formatter { return newFormatter(&Config, v) } ================================================ FILE: vendor/github.com/davecgh/go-spew/spew/spew.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "fmt" "io" ) // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the formatted string as a value that satisfies error. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a default Formatter interface returned by NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) func Print(a ...interface{}) (n int, err error) { return fmt.Print(convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) func Println(a ...interface{}) (n int, err error) { return fmt.Println(convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprint(a ...interface{}) string { return fmt.Sprint(convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintln(a ...interface{}) string { return fmt.Sprintln(convertArgs(a)...) } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a default spew Formatter interface. func convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = NewFormatter(arg) } return formatters } ================================================ FILE: vendor/github.com/pkg/errors/LICENSE ================================================ Copyright (c) 2015, Dave Cheney All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 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 HOLDER 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. ================================================ FILE: vendor/github.com/pkg/errors/errors.go ================================================ // Package errors provides simple error handling primitives. // // The traditional error handling idiom in Go is roughly akin to // // if err != nil { // return err // } // // which applied recursively up the call stack results in error reports // without context or debugging information. The errors package allows // programmers to add context to the failure path in their code in a way // that does not destroy the original value of the error. // // Adding context to an error // // The errors.Wrap function returns a new error that adds context to the // original error by recording a stack trace at the point Wrap is called, // and the supplied message. For example // // _, err := ioutil.ReadAll(r) // if err != nil { // return errors.Wrap(err, "read failed") // } // // If additional control is required the errors.WithStack and errors.WithMessage // functions destructure errors.Wrap into its component operations of annotating // an error with a stack trace and an a message, respectively. // // Retrieving the cause of an error // // Using errors.Wrap constructs a stack of errors, adding context to the // preceding error. Depending on the nature of the error it may be necessary // to reverse the operation of errors.Wrap to retrieve the original error // for inspection. Any error value which implements this interface // // type causer interface { // Cause() error // } // // can be inspected by errors.Cause. errors.Cause will recursively retrieve // the topmost error which does not implement causer, which is assumed to be // the original cause. For example: // // switch err := errors.Cause(err).(type) { // case *MyError: // // handle specifically // default: // // unknown error // } // // causer interface is not exported by this package, but is considered a part // of stable public API. // // Formatted printing of errors // // All error values returned from this package implement fmt.Formatter and can // be formatted by the fmt package. The following verbs are supported // // %s print the error. If the error has a Cause it will be // printed recursively // %v see %s // %+v extended format. Each Frame of the error's StackTrace will // be printed in detail. // // Retrieving the stack trace of an error or wrapper // // New, Errorf, Wrap, and Wrapf record a stack trace at the point they are // invoked. This information can be retrieved with the following interface. // // type stackTracer interface { // StackTrace() errors.StackTrace // } // // Where errors.StackTrace is defined as // // type StackTrace []Frame // // The Frame type represents a call site in the stack trace. Frame supports // the fmt.Formatter interface that can be used for printing information about // the stack trace of this error. For example: // // if err, ok := err.(stackTracer); ok { // for _, f := range err.StackTrace() { // fmt.Printf("%+s:%d", f) // } // } // // stackTracer interface is not exported by this package, but is considered a part // of stable public API. // // See the documentation for Frame.Format for more details. package errors import ( "fmt" "io" ) // New returns an error with the supplied message. // New also records the stack trace at the point it was called. func New(message string) error { return &fundamental{ msg: message, stack: callers(), } } // Errorf formats according to a format specifier and returns the string // as a value that satisfies error. // Errorf also records the stack trace at the point it was called. func Errorf(format string, args ...interface{}) error { return &fundamental{ msg: fmt.Sprintf(format, args...), stack: callers(), } } // fundamental is an error that has a message and a stack, but no caller. type fundamental struct { msg string *stack } func (f *fundamental) Error() string { return f.msg } func (f *fundamental) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { io.WriteString(s, f.msg) f.stack.Format(s, verb) return } fallthrough case 's': io.WriteString(s, f.msg) case 'q': fmt.Fprintf(s, "%q", f.msg) } } // WithStack annotates err with a stack trace at the point WithStack was called. // If err is nil, WithStack returns nil. func WithStack(err error) error { if err == nil { return nil } return &withStack{ err, callers(), } } type withStack struct { error *stack } func (w *withStack) Cause() error { return w.error } func (w *withStack) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { fmt.Fprintf(s, "%+v", w.Cause()) w.stack.Format(s, verb) return } fallthrough case 's': io.WriteString(s, w.Error()) case 'q': fmt.Fprintf(s, "%q", w.Error()) } } // Wrap returns an error annotating err with a stack trace // at the point Wrap is called, and the supplied message. // If err is nil, Wrap returns nil. func Wrap(err error, message string) error { if err == nil { return nil } err = &withMessage{ cause: err, msg: message, } return &withStack{ err, callers(), } } // Wrapf returns an error annotating err with a stack trace // at the point Wrapf is call, and the format specifier. // If err is nil, Wrapf returns nil. func Wrapf(err error, format string, args ...interface{}) error { if err == nil { return nil } err = &withMessage{ cause: err, msg: fmt.Sprintf(format, args...), } return &withStack{ err, callers(), } } // WithMessage annotates err with a new message. // If err is nil, WithMessage returns nil. func WithMessage(err error, message string) error { if err == nil { return nil } return &withMessage{ cause: err, msg: message, } } type withMessage struct { cause error msg string } func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } func (w *withMessage) Cause() error { return w.cause } func (w *withMessage) Format(s fmt.State, verb rune) { switch verb { case 'v': if s.Flag('+') { fmt.Fprintf(s, "%+v\n", w.Cause()) io.WriteString(s, w.msg) return } fallthrough case 's', 'q': io.WriteString(s, w.Error()) } } // Cause returns the underlying cause of the error, if possible. // An error value has a cause if it implements the following // interface: // // type causer interface { // Cause() error // } // // If the error does not implement Cause, the original error will // be returned. If the error is nil, nil will be returned without further // investigation. func Cause(err error) error { type causer interface { Cause() error } for err != nil { cause, ok := err.(causer) if !ok { break } err = cause.Cause() } return err } ================================================ FILE: vendor/github.com/pkg/errors/stack.go ================================================ package errors import ( "fmt" "io" "path" "runtime" "strings" ) // Frame represents a program counter inside a stack frame. type Frame uintptr // pc returns the program counter for this frame; // multiple frames may have the same PC value. func (f Frame) pc() uintptr { return uintptr(f) - 1 } // file returns the full path to the file that contains the // function for this Frame's pc. func (f Frame) file() string { fn := runtime.FuncForPC(f.pc()) if fn == nil { return "unknown" } file, _ := fn.FileLine(f.pc()) return file } // line returns the line number of source code of the // function for this Frame's pc. func (f Frame) line() int { fn := runtime.FuncForPC(f.pc()) if fn == nil { return 0 } _, line := fn.FileLine(f.pc()) return line } // Format formats the frame according to the fmt.Formatter interface. // // %s source file // %d source line // %n function name // %v equivalent to %s:%d // // Format accepts flags that alter the printing of some verbs, as follows: // // %+s path of source file relative to the compile time GOPATH // %+v equivalent to %+s:%d func (f Frame) Format(s fmt.State, verb rune) { switch verb { case 's': switch { case s.Flag('+'): pc := f.pc() fn := runtime.FuncForPC(pc) if fn == nil { io.WriteString(s, "unknown") } else { file, _ := fn.FileLine(pc) fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file) } default: io.WriteString(s, path.Base(f.file())) } case 'd': fmt.Fprintf(s, "%d", f.line()) case 'n': name := runtime.FuncForPC(f.pc()).Name() io.WriteString(s, funcname(name)) case 'v': f.Format(s, 's') io.WriteString(s, ":") f.Format(s, 'd') } } // StackTrace is stack of Frames from innermost (newest) to outermost (oldest). type StackTrace []Frame func (st StackTrace) Format(s fmt.State, verb rune) { switch verb { case 'v': switch { case s.Flag('+'): for _, f := range st { fmt.Fprintf(s, "\n%+v", f) } case s.Flag('#'): fmt.Fprintf(s, "%#v", []Frame(st)) default: fmt.Fprintf(s, "%v", []Frame(st)) } case 's': fmt.Fprintf(s, "%s", []Frame(st)) } } // stack represents a stack of program counters. type stack []uintptr func (s *stack) Format(st fmt.State, verb rune) { switch verb { case 'v': switch { case st.Flag('+'): for _, pc := range *s { f := Frame(pc) fmt.Fprintf(st, "\n%+v", f) } } } } func (s *stack) StackTrace() StackTrace { f := make([]Frame, len(*s)) for i := 0; i < len(f); i++ { f[i] = Frame((*s)[i]) } return f } func callers() *stack { const depth = 32 var pcs [depth]uintptr n := runtime.Callers(3, pcs[:]) var st stack = pcs[0:n] return &st } // funcname removes the path prefix component of a function's name reported by func.Name(). func funcname(name string) string { i := strings.LastIndex(name, "/") name = name[i+1:] i = strings.Index(name, ".") return name[i+1:] } func trimGOPATH(name, file string) string { // Here we want to get the source file path relative to the compile time // GOPATH. As of Go 1.6.x there is no direct way to know the compiled // GOPATH at runtime, but we can infer the number of path segments in the // GOPATH. We note that fn.Name() returns the function name qualified by // the import path, which does not include the GOPATH. Thus we can trim // segments from the beginning of the file path until the number of path // separators remaining is one more than the number of path separators in // the function name. For example, given: // // GOPATH /home/user // file /home/user/src/pkg/sub/file.go // fn.Name() pkg/sub.Type.Method // // We want to produce: // // pkg/sub/file.go // // From this we can easily see that fn.Name() has one less path separator // than our desired output. We count separators from the end of the file // path until it finds two more than in the function name and then move // one character forward to preserve the initial path segment without a // leading separator. const sep = "/" goal := strings.Count(name, sep) + 2 i := len(file) for n := 0; n < goal; n++ { i = strings.LastIndex(file[:i], sep) if i == -1 { // not enough separators found, set i so that the slice expression // below leaves file unmodified i = -len(sep) break } } // get back to 0 or trim the leading separator file = file[i+len(sep):] return file } ================================================ FILE: vendor/github.com/pmezard/go-difflib/LICENSE ================================================ Copyright (c) 2013, Patrick Mezard All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. The names of its contributors may not 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 HOLDER 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. ================================================ FILE: vendor/github.com/pmezard/go-difflib/difflib/difflib.go ================================================ // Package difflib is a partial port of Python difflib module. // // It provides tools to compare sequences of strings and generate textual diffs. // // The following class and functions have been ported: // // - SequenceMatcher // // - unified_diff // // - context_diff // // Getting unified diffs was the main goal of the port. Keep in mind this code // is mostly suitable to output text differences in a human friendly way, there // are no guarantees generated diffs are consumable by patch(1). package difflib import ( "bufio" "bytes" "fmt" "io" "strings" ) func min(a, b int) int { if a < b { return a } return b } func max(a, b int) int { if a > b { return a } return b } func calculateRatio(matches, length int) float64 { if length > 0 { return 2.0 * float64(matches) / float64(length) } return 1.0 } type Match struct { A int B int Size int } type OpCode struct { Tag byte I1 int I2 int J1 int J2 int } // SequenceMatcher compares sequence of strings. The basic // algorithm predates, and is a little fancier than, an algorithm // published in the late 1980's by Ratcliff and Obershelp under the // hyperbolic name "gestalt pattern matching". The basic idea is to find // the longest contiguous matching subsequence that contains no "junk" // elements (R-O doesn't address junk). The same idea is then applied // recursively to the pieces of the sequences to the left and to the right // of the matching subsequence. This does not yield minimal edit // sequences, but does tend to yield matches that "look right" to people. // // SequenceMatcher tries to compute a "human-friendly diff" between two // sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the // longest *contiguous* & junk-free matching subsequence. That's what // catches peoples' eyes. The Windows(tm) windiff has another interesting // notion, pairing up elements that appear uniquely in each sequence. // That, and the method here, appear to yield more intuitive difference // reports than does diff. This method appears to be the least vulnerable // to synching up on blocks of "junk lines", though (like blank lines in // ordinary text files, or maybe "

" lines in HTML files). That may be // because this is the only method of the 3 that has a *concept* of // "junk" . // // Timing: Basic R-O is cubic time worst case and quadratic time expected // case. SequenceMatcher is quadratic time for the worst case and has // expected-case behavior dependent in a complicated way on how many // elements the sequences have in common; best case time is linear. type SequenceMatcher struct { a []string b []string b2j map[string][]int IsJunk func(string) bool autoJunk bool bJunk map[string]struct{} matchingBlocks []Match fullBCount map[string]int bPopular map[string]struct{} opCodes []OpCode } func NewMatcher(a, b []string) *SequenceMatcher { m := SequenceMatcher{autoJunk: true} m.SetSeqs(a, b) return &m } func NewMatcherWithJunk(a, b []string, autoJunk bool, isJunk func(string) bool) *SequenceMatcher { m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} m.SetSeqs(a, b) return &m } // Set two sequences to be compared. func (m *SequenceMatcher) SetSeqs(a, b []string) { m.SetSeq1(a) m.SetSeq2(b) } // Set the first sequence to be compared. The second sequence to be compared is // not changed. // // SequenceMatcher computes and caches detailed information about the second // sequence, so if you want to compare one sequence S against many sequences, // use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other // sequences. // // See also SetSeqs() and SetSeq2(). func (m *SequenceMatcher) SetSeq1(a []string) { if &a == &m.a { return } m.a = a m.matchingBlocks = nil m.opCodes = nil } // Set the second sequence to be compared. The first sequence to be compared is // not changed. func (m *SequenceMatcher) SetSeq2(b []string) { if &b == &m.b { return } m.b = b m.matchingBlocks = nil m.opCodes = nil m.fullBCount = nil m.chainB() } func (m *SequenceMatcher) chainB() { // Populate line -> index mapping b2j := map[string][]int{} for i, s := range m.b { indices := b2j[s] indices = append(indices, i) b2j[s] = indices } // Purge junk elements m.bJunk = map[string]struct{}{} if m.IsJunk != nil { junk := m.bJunk for s, _ := range b2j { if m.IsJunk(s) { junk[s] = struct{}{} } } for s, _ := range junk { delete(b2j, s) } } // Purge remaining popular elements popular := map[string]struct{}{} n := len(m.b) if m.autoJunk && n >= 200 { ntest := n/100 + 1 for s, indices := range b2j { if len(indices) > ntest { popular[s] = struct{}{} } } for s, _ := range popular { delete(b2j, s) } } m.bPopular = popular m.b2j = b2j } func (m *SequenceMatcher) isBJunk(s string) bool { _, ok := m.bJunk[s] return ok } // Find longest matching block in a[alo:ahi] and b[blo:bhi]. // // If IsJunk is not defined: // // Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where // alo <= i <= i+k <= ahi // blo <= j <= j+k <= bhi // and for all (i',j',k') meeting those conditions, // k >= k' // i <= i' // and if i == i', j <= j' // // In other words, of all maximal matching blocks, return one that // starts earliest in a, and of all those maximal matching blocks that // start earliest in a, return the one that starts earliest in b. // // If IsJunk is defined, first the longest matching block is // determined as above, but with the additional restriction that no // junk element appears in the block. Then that block is extended as // far as possible by matching (only) junk elements on both sides. So // the resulting block never matches on junk except as identical junk // happens to be adjacent to an "interesting" match. // // If no blocks match, return (alo, blo, 0). func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { // CAUTION: stripping common prefix or suffix would be incorrect. // E.g., // ab // acab // Longest matching block is "ab", but if common prefix is // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so // strip, so ends up claiming that ab is changed to acab by // inserting "ca" in the middle. That's minimal but unintuitive: // "it's obvious" that someone inserted "ac" at the front. // Windiff ends up at the same place as diff, but by pairing up // the unique 'b's and then matching the first two 'a's. besti, bestj, bestsize := alo, blo, 0 // find longest junk-free match // during an iteration of the loop, j2len[j] = length of longest // junk-free match ending with a[i-1] and b[j] j2len := map[int]int{} for i := alo; i != ahi; i++ { // look at all instances of a[i] in b; note that because // b2j has no junk keys, the loop is skipped if a[i] is junk newj2len := map[int]int{} for _, j := range m.b2j[m.a[i]] { // a[i] matches b[j] if j < blo { continue } if j >= bhi { break } k := j2len[j-1] + 1 newj2len[j] = k if k > bestsize { besti, bestj, bestsize = i-k+1, j-k+1, k } } j2len = newj2len } // Extend the best by non-junk elements on each end. In particular, // "popular" non-junk elements aren't in b2j, which greatly speeds // the inner loop above, but also means "the best" match so far // doesn't contain any junk *or* popular non-junk elements. for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && !m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } // Now that we have a wholly interesting match (albeit possibly // empty!), we may as well suck up the matching junk on each // side of it too. Can't think of a good reason not to, and it // saves post-processing the (possibly considerable) expense of // figuring out what to do with it. In the case of an empty // interesting match, this is clearly the right thing to do, // because no other kind of match is possible in the regions. for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } return Match{A: besti, B: bestj, Size: bestsize} } // Return list of triples describing matching subsequences. // // Each triple is of the form (i, j, n), and means that // a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in // i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are // adjacent triples in the list, and the second is not the last triple in the // list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe // adjacent equal blocks. // // The last triple is a dummy, (len(a), len(b), 0), and is the only // triple with n==0. func (m *SequenceMatcher) GetMatchingBlocks() []Match { if m.matchingBlocks != nil { return m.matchingBlocks } var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { match := m.findLongestMatch(alo, ahi, blo, bhi) i, j, k := match.A, match.B, match.Size if match.Size > 0 { if alo < i && blo < j { matched = matchBlocks(alo, i, blo, j, matched) } matched = append(matched, match) if i+k < ahi && j+k < bhi { matched = matchBlocks(i+k, ahi, j+k, bhi, matched) } } return matched } matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) // It's possible that we have adjacent equal blocks in the // matching_blocks list now. nonAdjacent := []Match{} i1, j1, k1 := 0, 0, 0 for _, b := range matched { // Is this block adjacent to i1, j1, k1? i2, j2, k2 := b.A, b.B, b.Size if i1+k1 == i2 && j1+k1 == j2 { // Yes, so collapse them -- this just increases the length of // the first block by the length of the second, and the first // block so lengthened remains the block to compare against. k1 += k2 } else { // Not adjacent. Remember the first block (k1==0 means it's // the dummy we started with), and make the second block the // new block to compare against. if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } i1, j1, k1 = i2, j2, k2 } } if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) m.matchingBlocks = nonAdjacent return m.matchingBlocks } // Return list of 5-tuples describing how to turn a into b. // // Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple // has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the // tuple preceding it, and likewise for j1 == the previous j2. // // The tags are characters, with these meanings: // // 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] // // 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. // // 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. // // 'e' (equal): a[i1:i2] == b[j1:j2] func (m *SequenceMatcher) GetOpCodes() []OpCode { if m.opCodes != nil { return m.opCodes } i, j := 0, 0 matching := m.GetMatchingBlocks() opCodes := make([]OpCode, 0, len(matching)) for _, m := range matching { // invariant: we've pumped out correct diffs to change // a[:i] into b[:j], and the next matching block is // a[ai:ai+size] == b[bj:bj+size]. So we need to pump // out a diff to change a[i:ai] into b[j:bj], pump out // the matching block, and move (i,j) beyond the match ai, bj, size := m.A, m.B, m.Size tag := byte(0) if i < ai && j < bj { tag = 'r' } else if i < ai { tag = 'd' } else if j < bj { tag = 'i' } if tag > 0 { opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) } i, j = ai+size, bj+size // the list of matching blocks is terminated by a // sentinel with size 0 if size > 0 { opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) } } m.opCodes = opCodes return m.opCodes } // Isolate change clusters by eliminating ranges with no changes. // // Return a generator of groups with up to n lines of context. // Each group is in the same format as returned by GetOpCodes(). func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { if n < 0 { n = 3 } codes := m.GetOpCodes() if len(codes) == 0 { codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} } // Fixup leading and trailing groups if they show no changes. if codes[0].Tag == 'e' { c := codes[0] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} } if codes[len(codes)-1].Tag == 'e' { c := codes[len(codes)-1] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} } nn := n + n groups := [][]OpCode{} group := []OpCode{} for _, c := range codes { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 // End the current group and start a new one whenever // there is a large range with no changes. if c.Tag == 'e' && i2-i1 > nn { group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}) groups = append(groups, group) group = []OpCode{} i1, j1 = max(i1, i2-n), max(j1, j2-n) } group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) } if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { groups = append(groups, group) } return groups } // Return a measure of the sequences' similarity (float in [0,1]). // // Where T is the total number of elements in both sequences, and // M is the number of matches, this is 2.0*M / T. // Note that this is 1 if the sequences are identical, and 0 if // they have nothing in common. // // .Ratio() is expensive to compute if you haven't already computed // .GetMatchingBlocks() or .GetOpCodes(), in which case you may // want to try .QuickRatio() or .RealQuickRation() first to get an // upper bound. func (m *SequenceMatcher) Ratio() float64 { matches := 0 for _, m := range m.GetMatchingBlocks() { matches += m.Size } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() relatively quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute. func (m *SequenceMatcher) QuickRatio() float64 { // viewing a and b as multisets, set matches to the cardinality // of their intersection; this counts the number of matches // without regard to order, so is clearly an upper bound if m.fullBCount == nil { m.fullBCount = map[string]int{} for _, s := range m.b { m.fullBCount[s] = m.fullBCount[s] + 1 } } // avail[x] is the number of times x appears in 'b' less the // number of times we've seen it in 'a' so far ... kinda avail := map[string]int{} matches := 0 for _, s := range m.a { n, ok := avail[s] if !ok { n = m.fullBCount[s] } avail[s] = n - 1 if n > 0 { matches += 1 } } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() very quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute than either .Ratio() or .QuickRatio(). func (m *SequenceMatcher) RealQuickRatio() float64 { la, lb := len(m.a), len(m.b) return calculateRatio(min(la, lb), la+lb) } // Convert range to the "ed" format func formatRangeUnified(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 1 { return fmt.Sprintf("%d", beginning) } if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } return fmt.Sprintf("%d,%d", beginning, length) } // Unified diff parameters type UnifiedDiff struct { A []string // First sequence lines FromFile string // First file name FromDate string // First file time B []string // Second sequence lines ToFile string // Second file name ToDate string // Second file time Eol string // Headers end of line, defaults to LF Context int // Number of context lines } // Compare two sequences of lines; generate the delta as a unified diff. // // Unified diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by 'n' which // defaults to three. // // By default, the diff control lines (those with ---, +++, or @@) are // created with a trailing newline. This is helpful so that inputs // created from file.readlines() result in diffs that are suitable for // file.writelines() since both the inputs and outputs have trailing // newlines. // // For inputs that do not have trailing newlines, set the lineterm // argument to "" so that the output will be uniformly newline free. // // The unidiff format normally has a header for filenames and modification // times. Any or all of these may be specified using strings for // 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. // The modification times are normally expressed in the ISO 8601 format. func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() wf := func(format string, args ...interface{}) error { _, err := buf.WriteString(fmt.Sprintf(format, args...)) return err } ws := func(s string) error { _, err := buf.WriteString(s) return err } if len(diff.Eol) == 0 { diff.Eol = "\n" } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } if diff.FromFile != "" || diff.ToFile != "" { err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) if err != nil { return err } err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) if err != nil { return err } } } first, last := g[0], g[len(g)-1] range1 := formatRangeUnified(first.I1, last.I2) range2 := formatRangeUnified(first.J1, last.J2) if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { return err } for _, c := range g { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 if c.Tag == 'e' { for _, line := range diff.A[i1:i2] { if err := ws(" " + line); err != nil { return err } } continue } if c.Tag == 'r' || c.Tag == 'd' { for _, line := range diff.A[i1:i2] { if err := ws("-" + line); err != nil { return err } } } if c.Tag == 'r' || c.Tag == 'i' { for _, line := range diff.B[j1:j2] { if err := ws("+" + line); err != nil { return err } } } } } return nil } // Like WriteUnifiedDiff but returns the diff a string. func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { w := &bytes.Buffer{} err := WriteUnifiedDiff(w, diff) return string(w.Bytes()), err } // Convert range to the "ed" format. func formatRangeContext(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } if length <= 1 { return fmt.Sprintf("%d", beginning) } return fmt.Sprintf("%d,%d", beginning, beginning+length-1) } type ContextDiff UnifiedDiff // Compare two sequences of lines; generate the delta as a context diff. // // Context diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by diff.Context // which defaults to three. // // By default, the diff control lines (those with *** or ---) are // created with a trailing newline. // // For inputs that do not have trailing newlines, set the diff.Eol // argument to "" so that the output will be uniformly newline free. // // The context diff format normally has a header for filenames and // modification times. Any or all of these may be specified using // strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. // The modification times are normally expressed in the ISO 8601 format. // If not specified, the strings default to blanks. func WriteContextDiff(writer io.Writer, diff ContextDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() var diffErr error wf := func(format string, args ...interface{}) { _, err := buf.WriteString(fmt.Sprintf(format, args...)) if diffErr == nil && err != nil { diffErr = err } } ws := func(s string) { _, err := buf.WriteString(s) if diffErr == nil && err != nil { diffErr = err } } if len(diff.Eol) == 0 { diff.Eol = "\n" } prefix := map[byte]string{ 'i': "+ ", 'd': "- ", 'r': "! ", 'e': " ", } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } if diff.FromFile != "" || diff.ToFile != "" { wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) } } first, last := g[0], g[len(g)-1] ws("***************" + diff.Eol) range1 := formatRangeContext(first.I1, last.I2) wf("*** %s ****%s", range1, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'd' { for _, cc := range g { if cc.Tag == 'i' { continue } for _, line := range diff.A[cc.I1:cc.I2] { ws(prefix[cc.Tag] + line) } } break } } range2 := formatRangeContext(first.J1, last.J2) wf("--- %s ----%s", range2, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'i' { for _, cc := range g { if cc.Tag == 'd' { continue } for _, line := range diff.B[cc.J1:cc.J2] { ws(prefix[cc.Tag] + line) } } break } } } return diffErr } // Like WriteContextDiff but returns the diff a string. func GetContextDiffString(diff ContextDiff) (string, error) { w := &bytes.Buffer{} err := WriteContextDiff(w, diff) return string(w.Bytes()), err } // Split a string on "\n" while preserving them. The output can be used // as input for UnifiedDiff and ContextDiff structures. func SplitLines(s string) []string { lines := strings.SplitAfter(s, "\n") lines[len(lines)-1] += "\n" return lines } ================================================ FILE: vendor/github.com/stretchr/testify/LICENSE ================================================ Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell Please consider promoting this project if you find it useful. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: vendor/github.com/stretchr/testify/assert/assertion_format.go ================================================ /* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package assert import ( http "net/http" url "net/url" time "time" ) // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { return Condition(t, comp, append([]interface{}{msg}, args...)...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { return Contains(t, s, contains, append([]interface{}{msg}, args...)...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { return DirExists(t, path, append([]interface{}{msg}, args...)...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) // // Returns whether the assertion was successful (true) or not (false). func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { return Empty(t, object, append([]interface{}{msg}, args...)...) } // Equalf asserts that two objects are equal. // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) } // EqualValuesf asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } // // Returns whether the assertion was successful (true) or not (false). func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { return Error(t, err, append([]interface{}{msg}, args...)...) } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { return False(t, value, append([]interface{}{msg}, args...)...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { return FileExists(t, path, append([]interface{}{msg}, args...)...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { return Len(t, object, length, append([]interface{}{msg}, args...)...) } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { return Nil(t, object, append([]interface{}{msg}, args...)...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { return NoError(t, err, append([]interface{}{msg}, args...)...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { return NotEmpty(t, object, append([]interface{}{msg}, args...)...) } // NotEqualf asserts that the specified values are NOT equal. // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { return NotNil(t, object, append([]interface{}{msg}, args...)...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { return NotPanics(t, f, append([]interface{}{msg}, args...)...) } // NotRegexpf asserts that a specified regexp does not match a string. // // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) } // NotSubsetf asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) } // NotZerof asserts that i is not the zero value for its type and returns the truth. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { return NotZero(t, i, append([]interface{}{msg}, args...)...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { return Panics(t, f, append([]interface{}{msg}, args...)...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) } // Subsetf asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { return Subset(t, list, subset, append([]interface{}{msg}, args...)...) } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { return True(t, value, append([]interface{}{msg}, args...)...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // Zerof asserts that i is the zero value for its type and returns the truth. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { return Zero(t, i, append([]interface{}{msg}, args...)...) } ================================================ FILE: vendor/github.com/stretchr/testify/assert/assertion_forward.go ================================================ /* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package assert import ( http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { return Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { return Conditionf(a.t, comp, msg, args...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { return Contains(a.t, s, contains, msgAndArgs...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { return Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { return DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { return DirExistsf(a.t, path, msg, args...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { return ElementsMatch(a.t, listA, listB, msgAndArgs...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { return ElementsMatchf(a.t, listA, listB, msg, args...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { return Empty(a.t, object, msgAndArgs...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { return Emptyf(a.t, object, msg, args...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { return EqualError(a.t, theError, errString, msgAndArgs...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { return EqualErrorf(a.t, theError, errString, msg, args...) } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return EqualValues(a.t, expected, actual, msgAndArgs...) } // EqualValuesf asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return EqualValuesf(a.t, expected, actual, msg, args...) } // Equalf asserts that two objects are equal. // // a.Equalf(123, 123, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return Equalf(a.t, expected, actual, msg, args...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err) { // assert.Equal(t, expectedError, err) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { return Error(a.t, err, msgAndArgs...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { return Errorf(a.t, err, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { return Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { return FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { return FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { return Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { return False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { return Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { return FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { return FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { return HTTPError(a.t, handler, method, url, values, msgAndArgs...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPErrorf(a.t, handler, method, url, values, msg, args...) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { return Implements(a.t, interfaceObject, object, msgAndArgs...) } // Implementsf asserts that an object is implemented by the specified interface. // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { return Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { return InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { return IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { return IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { return JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { return JSONEqf(a.t, expected, actual, msg, args...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { return Len(a.t, object, length, msgAndArgs...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { return Lenf(a.t, object, length, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { return Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { return Nilf(a.t, object, msg, args...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { return NoError(a.t, err, msgAndArgs...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { return NoErrorf(a.t, err, msg, args...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { return NotContains(a.t, s, contains, msgAndArgs...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { return NotContainsf(a.t, s, contains, msg, args...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { return NotEmpty(a.t, object, msgAndArgs...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { return NotEmptyf(a.t, object, msg, args...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { return NotEqual(a.t, expected, actual, msgAndArgs...) } // NotEqualf asserts that the specified values are NOT equal. // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { return NotEqualf(a.t, expected, actual, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { return NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { return NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { return NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { return NotPanicsf(a.t, f, msg, args...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { return NotRegexp(a.t, rx, str, msgAndArgs...) } // NotRegexpf asserts that a specified regexp does not match a string. // // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { return NotRegexpf(a.t, rx, str, msg, args...) } // NotSubset asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { return NotSubset(a.t, list, subset, msgAndArgs...) } // NotSubsetf asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { return NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { return NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { return NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { return Panics(a.t, f, msgAndArgs...) } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { return PanicsWithValue(a.t, expected, f, msgAndArgs...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { return PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { return Panicsf(a.t, f, msg, args...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { return Regexp(a.t, rx, str, msgAndArgs...) } // Regexpf asserts that a specified regexp matches a string. // // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { return Regexpf(a.t, rx, str, msg, args...) } // Subset asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { return Subset(a.t, list, subset, msgAndArgs...) } // Subsetf asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { return Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { return True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { return Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { return WithinDurationf(a.t, expected, actual, delta, msg, args...) } // Zero asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { return Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { return Zerof(a.t, i, msg, args...) } ================================================ FILE: vendor/github.com/stretchr/testify/assert/assertions.go ================================================ package assert import ( "bufio" "bytes" "encoding/json" "errors" "fmt" "math" "os" "reflect" "regexp" "runtime" "strings" "time" "unicode" "unicode/utf8" "github.com/davecgh/go-spew/spew" "github.com/pmezard/go-difflib/difflib" ) //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_format.go.tmpl // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) } // Comparison a custom function that returns true on success and false on failure type Comparison func() (success bool) /* Helper functions */ // ObjectsAreEqual determines if two objects are considered equal. // // This function does no assertion of any kind. func ObjectsAreEqual(expected, actual interface{}) bool { if expected == nil || actual == nil { return expected == actual } if exp, ok := expected.([]byte); ok { act, ok := actual.([]byte) if !ok { return false } else if exp == nil || act == nil { return exp == nil && act == nil } return bytes.Equal(exp, act) } return reflect.DeepEqual(expected, actual) } // ObjectsAreEqualValues gets whether two objects are equal, or if their // values are equal. func ObjectsAreEqualValues(expected, actual interface{}) bool { if ObjectsAreEqual(expected, actual) { return true } actualType := reflect.TypeOf(actual) if actualType == nil { return false } expectedValue := reflect.ValueOf(expected) if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { // Attempt comparison after type conversion return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) } return false } /* CallerInfo is necessary because the assert functions use the testing object internally, causing it to print the file:line of the assert method, rather than where the problem actually occurred in calling code.*/ // CallerInfo returns an array of strings containing the file and line number // of each stack frame leading from the current test to the assert call that // failed. func CallerInfo() []string { pc := uintptr(0) file := "" line := 0 ok := false name := "" callers := []string{} for i := 0; ; i++ { pc, file, line, ok = runtime.Caller(i) if !ok { // The breaks below failed to terminate the loop, and we ran off the // end of the call stack. break } // This is a huge edge case, but it will panic if this is the case, see #180 if file == "" { break } f := runtime.FuncForPC(pc) if f == nil { break } name = f.Name() // testing.tRunner is the standard library function that calls // tests. Subtests are called directly by tRunner, without going through // the Test/Benchmark/Example function that contains the t.Run calls, so // with subtests we should break when we hit tRunner, without adding it // to the list of callers. if name == "testing.tRunner" { break } parts := strings.Split(file, "/") file = parts[len(parts)-1] if len(parts) > 1 { dir := parts[len(parts)-2] if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { callers = append(callers, fmt.Sprintf("%s:%d", file, line)) } } // Drop the package segments := strings.Split(name, ".") name = segments[len(segments)-1] if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Example") { break } } return callers } // Stolen from the `go test` tool. // isTest tells whether name looks like a test (or benchmark, according to prefix). // It is a Test (say) if there is a character after Test that is not a lower-case letter. // We don't want TesticularCancer. func isTest(name, prefix string) bool { if !strings.HasPrefix(name, prefix) { return false } if len(name) == len(prefix) { // "Test" is ok return true } rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) return !unicode.IsLower(rune) } // getWhitespaceString returns a string that is long enough to overwrite the default // output from the go testing framework. func getWhitespaceString() string { _, file, line, ok := runtime.Caller(1) if !ok { return "" } parts := strings.Split(file, "/") file = parts[len(parts)-1] return strings.Repeat(" ", len(fmt.Sprintf("%s:%d: ", file, line))) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { if len(msgAndArgs) == 0 || msgAndArgs == nil { return "" } if len(msgAndArgs) == 1 { return msgAndArgs[0].(string) } if len(msgAndArgs) > 1 { return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) } return "" } // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). // The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { // no need to align first line because it starts at the correct location (after the label) if i != 0 { // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab outBuf.WriteString("\n\r\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } outBuf.WriteString(scanner.Text()) } return outBuf.String() } type failNower interface { FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { Fail(t, failureMessage, msgAndArgs...) // We cannot extend TestingT with FailNow() and // maintain backwards compatibility, so we fallback // to panicking when FailNow is not available in // TestingT. // See issue #263 if t, ok := t.(failNower); ok { t.FailNow() } else { panic("test failed and t is missing `FailNow()`") } return false } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { content := []labeledContent{ {"Error Trace", strings.Join(CallerInfo(), "\n\r\t\t\t")}, {"Error", failureMessage}, } // Add test name if the Go version supports it if n, ok := t.(interface { Name() string }); ok { content = append(content, labeledContent{"Test", n.Name()}) } message := messageFromMsgAndArgs(msgAndArgs...) if len(message) > 0 { content = append(content, labeledContent{"Messages", message}) } t.Errorf("%s", "\r"+getWhitespaceString()+labeledOutput(content...)) return false } type labeledContent struct { label string content string } // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: // // \r\t{{label}}:{{align_spaces}}\t{{content}}\n // // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this // alignment is achieved, "\t{{content}}\n" is added for the output. // // If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. func labeledOutput(content ...labeledContent) string { longestLabel := 0 for _, v := range content { if len(v.label) > longestLabel { longestLabel = len(v.label) } } var output string for _, v := range content { output += "\r\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" } return output } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { interfaceType := reflect.TypeOf(interfaceObject).Elem() if object == nil { return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) } if !reflect.TypeOf(object).Implements(interfaceType) { return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) } return true } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) } return true } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", expected, actual, err), msgAndArgs...) } if !ObjectsAreEqual(expected, actual) { diff := diff(expected, actual) expected, actual = formatUnequalValues(expected, actual) return Fail(t, fmt.Sprintf("Not equal: \n"+ "expected: %s\n"+ "actual : %s%s", expected, actual, diff), msgAndArgs...) } return true } // formatUnequalValues takes two values of arbitrary types and returns string // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed // with the type name, and the value will be enclosed in parenthesis similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { return fmt.Sprintf("%T(%#v)", expected, expected), fmt.Sprintf("%T(%#v)", actual, actual) } return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual) } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if !ObjectsAreEqualValues(expected, actual) { diff := diff(expected, actual) expected, actual = formatUnequalValues(expected, actual) return Fail(t, fmt.Sprintf("Not equal: \n"+ "expected: %s\n"+ "actual : %s%s", expected, actual, diff), msgAndArgs...) } return true } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { return Fail(t, fmt.Sprintf("Types expected to match exactly\n\r\t%v != %v", aType, bType), msgAndArgs...) } return Equal(t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) // // Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if !isNil(object) { return true } return Fail(t, "Expected value not to be nil.", msgAndArgs...) } // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { return true } value := reflect.ValueOf(object) kind := value.Kind() if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { return true } return false } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) // // Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if isNil(object) { return true } return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) } // isEmpty gets whether the specified object is considered empty or not. func isEmpty(object interface{}) bool { // get nil case out of the way if object == nil { return true } objValue := reflect.ValueOf(object) switch objValue.Kind() { // collection types are empty when they have no element case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: return objValue.Len() == 0 // pointers are empty if nil or if the value they point to is empty case reflect.Ptr: if objValue.IsNil() { return true } deref := objValue.Elem().Interface() return isEmpty(deref) // for all other types, compare against the zero value default: zero := reflect.Zero(objValue.Type()) return reflect.DeepEqual(object, zero.Interface()) } } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) // // Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := isEmpty(object) if !pass { Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) } return pass } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := !isEmpty(object) if !pass { Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) } return pass } // getLen try to get length of object. // return (false, 0) if impossible. func getLen(x interface{}) (ok bool, length int) { v := reflect.ValueOf(x) defer func() { if e := recover(); e != nil { ok = false } }() return true, v.Len() } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) // // Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { ok, l := getLen(object) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } // True asserts that the specified value is true. // // assert.True(t, myBool) // // Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value != true { return Fail(t, "Should be true", msgAndArgs...) } return true } // False asserts that the specified value is false. // // assert.False(t, myBool) // // Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value != false { return Fail(t, "Should be false", msgAndArgs...) } return true } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", expected, actual, err), msgAndArgs...) } if ObjectsAreEqual(expected, actual) { return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) } return true } // containsElement try loop over the list check if the list includes the element. // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. func includeElement(list interface{}, element interface{}) (ok, found bool) { listValue := reflect.ValueOf(list) elementValue := reflect.ValueOf(element) defer func() { if e := recover(); e != nil { ok = false found = false } }() if reflect.TypeOf(list).Kind() == reflect.String { return true, strings.Contains(listValue.String(), elementValue.String()) } if reflect.TypeOf(list).Kind() == reflect.Map { mapKeys := listValue.MapKeys() for i := 0; i < len(mapKeys); i++ { if ObjectsAreEqual(mapKeys[i].Interface(), element) { return true, true } } return true, false } for i := 0; i < listValue.Len(); i++ { if ObjectsAreEqual(listValue.Index(i).Interface(), element) { return true, true } } return true, false } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") // // Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { ok, found := includeElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } if !found { return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) } return true } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") // // Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { ok, found := includeElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) } if found { return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) } return true } // Subset asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if subset == nil { return true // we consider nil to be equal to the nil set } subsetValue := reflect.ValueOf(subset) defer func() { if e := recover(); e != nil { ok = false } }() listKind := reflect.TypeOf(list).Kind() subsetKind := reflect.TypeOf(subset).Kind() if listKind != reflect.Array && listKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } if subsetKind != reflect.Array && subsetKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() ok, found := includeElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } if !found { return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) } } return true } // NotSubset asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if subset == nil { return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) } subsetValue := reflect.ValueOf(subset) defer func() { if e := recover(); e != nil { ok = false } }() listKind := reflect.TypeOf(list).Kind() subsetKind := reflect.TypeOf(subset).Kind() if listKind != reflect.Array && listKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } if subsetKind != reflect.Array && subsetKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } for i := 0; i < subsetValue.Len(); i++ { element := subsetValue.Index(i).Interface() ok, found := includeElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } if !found { return true } } return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])) // // Returns whether the assertion was successful (true) or not (false). func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { if isEmpty(listA) && isEmpty(listB) { return true } aKind := reflect.TypeOf(listA).Kind() bKind := reflect.TypeOf(listB).Kind() if aKind != reflect.Array && aKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) } if bKind != reflect.Array && bKind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) } aValue := reflect.ValueOf(listA) bValue := reflect.ValueOf(listB) aLen := aValue.Len() bLen := bValue.Len() if aLen != bLen { return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) } // Mark indexes in bValue that we already used visited := make([]bool, bLen) for i := 0; i < aLen; i++ { element := aValue.Index(i).Interface() found := false for j := 0; j < bLen; j++ { if visited[j] { continue } if ObjectsAreEqual(bValue.Index(j).Interface(), element) { visited[j] = true found = true break } } if !found { return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) } } return true } // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { result := comp() if !result { Fail(t, "Condition failed!", msgAndArgs...) } return result } // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics // methods, and represents a simple func that takes no arguments, and returns nothing. type PanicTestFunc func() // didPanic returns true if the function passed to it panics. Otherwise, it returns false. func didPanic(f PanicTestFunc) (bool, interface{}) { didPanic := false var message interface{} func() { defer func() { if message = recover(); message != nil { didPanic = true } }() // call the target function f() }() return didPanic, message } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if funcDidPanic, panicValue := didPanic(f); !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { funcDidPanic, panicValue := didPanic(f) if !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) } if panicValue != expected { return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%v\n\r\tPanic value:\t%v", f, expected, panicValue), msgAndArgs...) } return true } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) // // Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if funcDidPanic, panicValue := didPanic(f); funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should not panic\n\r\tPanic value:\t%v", f, panicValue), msgAndArgs...) } return true } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) // // Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { dt := expected.Sub(actual) if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } func toFloat(x interface{}) (float64, bool) { var xf float64 xok := true switch xn := x.(type) { case uint8: xf = float64(xn) case uint16: xf = float64(xn) case uint32: xf = float64(xn) case uint64: xf = float64(xn) case int: xf = float64(xn) case int8: xf = float64(xn) case int16: xf = float64(xn) case int32: xf = float64(xn) case int64: xf = float64(xn) case float32: xf = float64(xn) case float64: xf = float64(xn) case time.Duration: xf = float64(xn) default: xok = false } return xf, xok } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { af, aok := toFloat(expected) bf, bok := toFloat(actual) if !aok || !bok { return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) } if math.IsNaN(af) { return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) } if math.IsNaN(bf) { return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) } dt := af - bf if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) } actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) for i := 0; i < actualSlice.Len(); i++ { result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) if !result { return result } } return true } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Map || reflect.TypeOf(expected).Kind() != reflect.Map { return Fail(t, "Arguments must be maps", msgAndArgs...) } expectedMap := reflect.ValueOf(expected) actualMap := reflect.ValueOf(actual) if expectedMap.Len() != actualMap.Len() { return Fail(t, "Arguments must have the same numbe of keys", msgAndArgs...) } for _, k := range expectedMap.MapKeys() { ev := expectedMap.MapIndex(k) av := actualMap.MapIndex(k) if !ev.IsValid() { return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) } if !av.IsValid() { return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) } if !InDelta( t, ev.Interface(), av.Interface(), delta, msgAndArgs..., ) { return false } } return true } func calcRelativeError(expected, actual interface{}) (float64, error) { af, aok := toFloat(expected) if !aok { return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) } if af == 0 { return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") } bf, bok := toFloat(actual) if !bok { return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) } return math.Abs(af-bf) / math.Abs(af), nil } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { return Fail(t, err.Error(), msgAndArgs...) } if actualEpsilon > epsilon { return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) } return true } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) } actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) for i := 0; i < actualSlice.Len(); i++ { result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) if !result { return result } } return true } /* Errors */ // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { if err != nil { return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) } return true } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } // // Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { if err == nil { return Fail(t, "An error is expected but got nil.", msgAndArgs...) } return true } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) // // Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { if !Error(t, theError, msgAndArgs...) { return false } expected := errString actual := theError.Error() // don't need to use deep equals here, we know they are both strings if expected != actual { return Fail(t, fmt.Sprintf("Error message not equal:\n"+ "expected: %q\n"+ "actual : %q", expected, actual), msgAndArgs...) } return true } // matchRegexp return true if a specified regexp matches a string. func matchRegexp(rx interface{}, str interface{}) bool { var r *regexp.Regexp if rr, ok := rx.(*regexp.Regexp); ok { r = rr } else { r = regexp.MustCompile(fmt.Sprint(rx)) } return (r.FindStringIndex(fmt.Sprint(str)) != nil) } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { match := matchRegexp(rx, str) if !match { Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) } return match } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { match := matchRegexp(rx, str) if match { Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) } return !match } // Zero asserts that i is the zero value for its type and returns the truth. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) } return true } // NotZero asserts that i is not the zero value for its type and returns the truth. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) } return true } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) } return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) } if info.IsDir() { return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) } return true } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) } return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) } if !info.IsDir() { return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) } return true } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { var expectedJSONAsInterface, actualJSONAsInterface interface{} if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) } if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) } return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) } func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { t := reflect.TypeOf(v) k := t.Kind() if k == reflect.Ptr { t = t.Elem() k = t.Kind() } return t, k } // diff returns a diff of both values as long as both are of the same type and // are a struct, map, slice or array. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { if expected == nil || actual == nil { return "" } et, ek := typeAndKind(expected) at, _ := typeAndKind(actual) if et != at { return "" } if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array { return "" } e := spewConfig.Sdump(expected) a := spewConfig.Sdump(actual) diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), B: difflib.SplitLines(a), FromFile: "Expected", FromDate: "", ToFile: "Actual", ToDate: "", Context: 1, }) return "\n\nDiff:\n" + diff } // validateEqualArgs checks whether provided arguments can be safely used in the // Equal/NotEqual functions. func validateEqualArgs(expected, actual interface{}) error { if isFunction(expected) || isFunction(actual) { return errors.New("cannot take func type as argument") } return nil } func isFunction(arg interface{}) bool { if arg == nil { return false } return reflect.TypeOf(arg).Kind() == reflect.Func } var spewConfig = spew.ConfigState{ Indent: " ", DisablePointerAddresses: true, DisableCapacities: true, SortKeys: true, } ================================================ FILE: vendor/github.com/stretchr/testify/assert/doc.go ================================================ // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // // Example Usage // // The following is a complete example using assert in a standard test function: // import ( // "testing" // "github.com/stretchr/testify/assert" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(t, a, b, "The two words should be the same.") // // } // // if you assert many times, use the format below: // // import ( // "testing" // "github.com/stretchr/testify/assert" // ) // // func TestSomething(t *testing.T) { // assert := assert.New(t) // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(a, b, "The two words should be the same.") // } // // Assertions // // Assertions allow you to easily write test code, and are global funcs in the `assert` package. // All assertion functions take, as the first argument, the `*testing.T` object provided by the // testing framework. This allows the assertion funcs to write the failings and other details to // the correct place. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package assert ================================================ FILE: vendor/github.com/stretchr/testify/assert/errors.go ================================================ package assert import ( "errors" ) // AnError is an error instance useful for testing. If the code does not care // about error specifics, and only needs to return the error for example, this // error should be used to make the test code more readable. var AnError = errors.New("assert.AnError general error for testing") ================================================ FILE: vendor/github.com/stretchr/testify/assert/forward_assertions.go ================================================ package assert // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate go run ../_codegen/main.go -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs ================================================ FILE: vendor/github.com/stretchr/testify/assert/http_assertions.go ================================================ package assert import ( "fmt" "net/http" "net/http/httptest" "net/url" "strings" ) // httpCode is a helper that returns HTTP code of the response. It returns -1 and // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) if err != nil { return -1, err } handler(w, req) return w.Code, nil } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) return false } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) } return isSuccessCode } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) return false } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) } return isRedirectCode } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) return false } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) } return isErrorCode } // HTTPBody is a helper that returns HTTP body of the response. It returns // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) if err != nil { return "" } handler(w, req) return w.Body.String() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if !contains { Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) } return contains } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if contains { Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) } return !contains } ================================================ FILE: vendor/github.com/stretchr/testify/require/doc.go ================================================ // Package require implements the same assertions as the `assert` package but // stops test execution when a test fails. // // Example Usage // // The following is a complete example using require in a standard test function: // import ( // "testing" // "github.com/stretchr/testify/require" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // require.Equal(t, a, b, "The two words should be the same.") // // } // // Assertions // // The `require` package have same global functions as in the `assert` package, // but instead of returning a boolean result they call `t.FailNow()`. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package require ================================================ FILE: vendor/github.com/stretchr/testify/require/forward_requirements.go ================================================ package require // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate go run ../_codegen/main.go -output-package=require -template=require_forward.go.tmpl -include-format-funcs ================================================ FILE: vendor/github.com/stretchr/testify/require/require.go ================================================ /* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package require import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { if !assert.Condition(t, comp, msgAndArgs...) { t.FailNow() } } // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { if !assert.Conditionf(t, comp, msg, args...) { t.FailNow() } } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") // // Returns whether the assertion was successful (true) or not (false). func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if !assert.Contains(t, s, contains, msgAndArgs...) { t.FailNow() } } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if !assert.Containsf(t, s, contains, msg, args...) { t.FailNow() } } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { if !assert.DirExists(t, path, msgAndArgs...) { t.FailNow() } } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { if !assert.DirExistsf(t, path, msg, args...) { t.FailNow() } } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2])) // // Returns whether the assertion was successful (true) or not (false). func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { if !assert.ElementsMatch(t, listA, listB, msgAndArgs...) { t.FailNow() } } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) // // Returns whether the assertion was successful (true) or not (false). func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { if !assert.ElementsMatchf(t, listA, listB, msg, args...) { t.FailNow() } } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) // // Returns whether the assertion was successful (true) or not (false). func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.Empty(t, object, msgAndArgs...) { t.FailNow() } } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if !assert.Emptyf(t, object, msg, args...) { t.FailNow() } } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.Equal(t, expected, actual, msgAndArgs...) { t.FailNow() } } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) // // Returns whether the assertion was successful (true) or not (false). func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { if !assert.EqualError(t, theError, errString, msgAndArgs...) { t.FailNow() } } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { if !assert.EqualErrorf(t, theError, errString, msg, args...) { t.FailNow() } } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.EqualValues(t, expected, actual, msgAndArgs...) { t.FailNow() } } // EqualValuesf asserts that two objects are equal or convertable to the same types // and equal. // // assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if !assert.EqualValuesf(t, expected, actual, msg, args...) { t.FailNow() } } // Equalf asserts that two objects are equal. // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if !assert.Equalf(t, expected, actual, msg, args...) { t.FailNow() } } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } // // Returns whether the assertion was successful (true) or not (false). func Error(t TestingT, err error, msgAndArgs ...interface{}) { if !assert.Error(t, err, msgAndArgs...) { t.FailNow() } } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } // // Returns whether the assertion was successful (true) or not (false). func Errorf(t TestingT, err error, msg string, args ...interface{}) { if !assert.Errorf(t, err, msg, args...) { t.FailNow() } } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.Exactly(t, expected, actual, msgAndArgs...) { t.FailNow() } } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if !assert.Exactlyf(t, expected, actual, msg, args...) { t.FailNow() } } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if !assert.Fail(t, failureMessage, msgAndArgs...) { t.FailNow() } } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if !assert.FailNow(t, failureMessage, msgAndArgs...) { t.FailNow() } } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { if !assert.FailNowf(t, failureMessage, msg, args...) { t.FailNow() } } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { if !assert.Failf(t, failureMessage, msg, args...) { t.FailNow() } } // False asserts that the specified value is false. // // assert.False(t, myBool) // // Returns whether the assertion was successful (true) or not (false). func False(t TestingT, value bool, msgAndArgs ...interface{}) { if !assert.False(t, value, msgAndArgs...) { t.FailNow() } } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Falsef(t TestingT, value bool, msg string, args ...interface{}) { if !assert.Falsef(t, value, msg, args...) { t.FailNow() } } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { if !assert.FileExists(t, path, msgAndArgs...) { t.FailNow() } } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { if !assert.FileExistsf(t, path, msg, args...) { t.FailNow() } } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if !assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { t.FailNow() } } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if !assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { t.FailNow() } } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if !assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { t.FailNow() } } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContainsf(t, myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if !assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { t.FailNow() } } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if !assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { t.FailNow() } } // HTTPErrorf asserts that a specified handler returns an error status code. // // assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if !assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { t.FailNow() } } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if !assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { t.FailNow() } } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if !assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { t.FailNow() } } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if !assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { t.FailNow() } } // HTTPSuccessf asserts that a specified handler returns a success status code. // // assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if !assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { t.FailNow() } } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if !assert.Implements(t, interfaceObject, object, msgAndArgs...) { t.FailNow() } } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if !assert.Implementsf(t, interfaceObject, object, msg, args...) { t.FailNow() } } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InDelta(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if !assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { t.FailNow() } } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if !assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if !assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { t.FailNow() } } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) // // Returns whether the assertion was successful (true) or not (false). func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if !assert.InDeltaf(t, expected, actual, delta, msg, args...) { t.FailNow() } } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if !assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { t.FailNow() } } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if !assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { t.FailNow() } } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if !assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { t.FailNow() } } // InEpsilonf asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if !assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { t.FailNow() } } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if !assert.IsType(t, expectedType, object, msgAndArgs...) { t.FailNow() } } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { if !assert.IsTypef(t, expectedType, object, msg, args...) { t.FailNow() } } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { if !assert.JSONEq(t, expected, actual, msgAndArgs...) { t.FailNow() } } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { if !assert.JSONEqf(t, expected, actual, msg, args...) { t.FailNow() } } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) // // Returns whether the assertion was successful (true) or not (false). func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { if !assert.Len(t, object, length, msgAndArgs...) { t.FailNow() } } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { if !assert.Lenf(t, object, length, msg, args...) { t.FailNow() } } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) // // Returns whether the assertion was successful (true) or not (false). func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.Nil(t, object, msgAndArgs...) { t.FailNow() } } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { if !assert.Nilf(t, object, msg, args...) { t.FailNow() } } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoError(t TestingT, err error, msgAndArgs ...interface{}) { if !assert.NoError(t, err, msgAndArgs...) { t.FailNow() } } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { if !assert.NoErrorf(t, err, msg, args...) { t.FailNow() } } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") // // Returns whether the assertion was successful (true) or not (false). func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if !assert.NotContains(t, s, contains, msgAndArgs...) { t.FailNow() } } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if !assert.NotContainsf(t, s, contains, msg, args...) { t.FailNow() } } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.NotEmpty(t, object, msgAndArgs...) { t.FailNow() } } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if !assert.NotEmptyf(t, object, msg, args...) { t.FailNow() } } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if !assert.NotEqual(t, expected, actual, msgAndArgs...) { t.FailNow() } } // NotEqualf asserts that the specified values are NOT equal. // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if !assert.NotEqualf(t, expected, actual, msg, args...) { t.FailNow() } } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) // // Returns whether the assertion was successful (true) or not (false). func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if !assert.NotNil(t, object, msgAndArgs...) { t.FailNow() } } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { if !assert.NotNilf(t, object, msg, args...) { t.FailNow() } } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) // // Returns whether the assertion was successful (true) or not (false). func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if !assert.NotPanics(t, f, msgAndArgs...) { t.FailNow() } } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if !assert.NotPanicsf(t, f, msg, args...) { t.FailNow() } } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if !assert.NotRegexp(t, rx, str, msgAndArgs...) { t.FailNow() } } // NotRegexpf asserts that a specified regexp does not match a string. // // assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if !assert.NotRegexpf(t, rx, str, msg, args...) { t.FailNow() } } // NotSubset asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if !assert.NotSubset(t, list, subset, msgAndArgs...) { t.FailNow() } } // NotSubsetf asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if !assert.NotSubsetf(t, list, subset, msg, args...) { t.FailNow() } } // NotZero asserts that i is not the zero value for its type and returns the truth. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if !assert.NotZero(t, i, msgAndArgs...) { t.FailNow() } } // NotZerof asserts that i is not the zero value for its type and returns the truth. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { if !assert.NotZerof(t, i, msg, args...) { t.FailNow() } } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if !assert.Panics(t, f, msgAndArgs...) { t.FailNow() } } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if !assert.PanicsWithValue(t, expected, f, msgAndArgs...) { t.FailNow() } } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { if !assert.PanicsWithValuef(t, expected, f, msg, args...) { t.FailNow() } } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if !assert.Panicsf(t, f, msg, args...) { t.FailNow() } } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if !assert.Regexp(t, rx, str, msgAndArgs...) { t.FailNow() } } // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if !assert.Regexpf(t, rx, str, msg, args...) { t.FailNow() } } // Subset asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if !assert.Subset(t, list, subset, msgAndArgs...) { t.FailNow() } } // Subsetf asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if !assert.Subsetf(t, list, subset, msg, args...) { t.FailNow() } } // True asserts that the specified value is true. // // assert.True(t, myBool) // // Returns whether the assertion was successful (true) or not (false). func True(t TestingT, value bool, msgAndArgs ...interface{}) { if !assert.True(t, value, msgAndArgs...) { t.FailNow() } } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func Truef(t TestingT, value bool, msg string, args ...interface{}) { if !assert.Truef(t, value, msg, args...) { t.FailNow() } } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) // // Returns whether the assertion was successful (true) or not (false). func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if !assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { t.FailNow() } } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { if !assert.WithinDurationf(t, expected, actual, delta, msg, args...) { t.FailNow() } } // Zero asserts that i is the zero value for its type and returns the truth. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if !assert.Zero(t, i, msgAndArgs...) { t.FailNow() } } // Zerof asserts that i is the zero value for its type and returns the truth. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { if !assert.Zerof(t, i, msg, args...) { t.FailNow() } } ================================================ FILE: vendor/github.com/stretchr/testify/require/require_forward.go ================================================ /* * CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen * THIS FILE MUST NOT BE EDITED BY HAND */ package require import ( assert "github.com/stretchr/testify/assert" http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { Conditionf(a.t, comp, msg, args...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { Contains(a.t, s, contains, msgAndArgs...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { DirExistsf(a.t, path, msg, args...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2])) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { ElementsMatch(a.t, listA, listB, msgAndArgs...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted")) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { ElementsMatchf(a.t, listA, listB, msg, args...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { Empty(a.t, object, msgAndArgs...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { Emptyf(a.t, object, msg, args...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { EqualError(a.t, theError, errString, msgAndArgs...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { EqualErrorf(a.t, theError, errString, msg, args...) } // EqualValues asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { EqualValues(a.t, expected, actual, msgAndArgs...) } // EqualValuesf asserts that two objects are equal or convertable to the same types // and equal. // // a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { EqualValuesf(a.t, expected, actual, msg, args...) } // Equalf asserts that two objects are equal. // // a.Equalf(123, 123, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { Equalf(a.t, expected, actual, msg, args...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err) { // assert.Equal(t, expectedError, err) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { Error(a.t, err, msgAndArgs...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { Errorf(a.t, err, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { FileExistsf(a.t, path, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContainsf(myHandler, "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { HTTPError(a.t, handler, method, url, values, msgAndArgs...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { HTTPErrorf(a.t, handler, method, url, values, msg, args...) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { Implements(a.t, interfaceObject, object, msgAndArgs...) } // Implementsf asserts that an object is implemented by the specified interface. // // a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, (22 / 7.0), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, (22 / 7.0, "error message %s", "formatted"), 0.01) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { JSONEqf(a.t, expected, actual, msg, args...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { Len(a.t, object, length, msgAndArgs...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { Lenf(a.t, object, length, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { Nilf(a.t, object, msg, args...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { NoError(a.t, err, msgAndArgs...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { NoErrorf(a.t, err, msg, args...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { NotContains(a.t, s, contains, msgAndArgs...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { NotContainsf(a.t, s, contains, msg, args...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { NotEmpty(a.t, object, msgAndArgs...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { NotEmptyf(a.t, object, msg, args...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2) // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { NotEqual(a.t, expected, actual, msgAndArgs...) } // NotEqualf asserts that the specified values are NOT equal. // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { NotEqualf(a.t, expected, actual, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { NotPanicsf(a.t, f, msg, args...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { NotRegexp(a.t, rx, str, msgAndArgs...) } // NotRegexpf asserts that a specified regexp does not match a string. // // a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { NotRegexpf(a.t, rx, str, msg, args...) } // NotSubset asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { NotSubset(a.t, list, subset, msgAndArgs...) } // NotSubsetf asserts that the specified list(array, slice...) contains not all // elements given in the specified subset(array, slice...). // // a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type and returns the truth. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { Panics(a.t, f, msgAndArgs...) } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { PanicsWithValue(a.t, expected, f, msgAndArgs...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { Panicsf(a.t, f, msg, args...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { Regexp(a.t, rx, str, msgAndArgs...) } // Regexpf asserts that a specified regexp matches a string. // // a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { Regexpf(a.t, rx, str, msg, args...) } // Subset asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { Subset(a.t, list, subset, msgAndArgs...) } // Subsetf asserts that the specified list(array, slice...) contains all // elements given in the specified subset(array, slice...). // // a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { WithinDurationf(a.t, expected, actual, delta, msg, args...) } // Zero asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type and returns the truth. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { Zerof(a.t, i, msg, args...) } ================================================ FILE: vendor/github.com/stretchr/testify/require/requirements.go ================================================ package require // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) FailNow() } //go:generate go run ../_codegen/main.go -output-package=require -template=require.go.tmpl -include-format-funcs ================================================ FILE: vendor/google.golang.org/protobuf/AUTHORS ================================================ # This source code refers to The Go Authors for copyright purposes. # The master list of authors is in the main Go distribution, # visible at https://tip.golang.org/AUTHORS. ================================================ FILE: vendor/google.golang.org/protobuf/CONTRIBUTORS ================================================ # This source code was written by the Go contributors. # The master list of contributors is in the main Go distribution, # visible at https://tip.golang.org/CONTRIBUTORS. ================================================ FILE: vendor/google.golang.org/protobuf/LICENSE ================================================ Copyright (c) 2018 The Go Authors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: vendor/google.golang.org/protobuf/PATENTS ================================================ Additional IP Rights Grant (Patents) "This implementation" means the copyrightable works distributed by Google as part of the Go project. Google 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, transfer and otherwise run, modify and propagate the contents of this implementation of Go, where such license applies only to those patent claims, both currently owned or controlled by Google and acquired in the future, licensable by Google that are necessarily infringed by this implementation of Go. This grant does not include claims that would be infringed only as a consequence of further modification of this implementation. If you or your agent or exclusive licensee institute or order or agree to the institution of patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that this implementation of Go or any code incorporated within this implementation of Go constitutes direct or contributory patent infringement, or inducement of patent infringement, then any patent rights granted to you under this License for this implementation of Go shall terminate as of the date such litigation is filed. ================================================ FILE: vendor/google.golang.org/protobuf/encoding/protojson/decode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protojson import ( "encoding/base64" "fmt" "math" "strconv" "strings" "google.golang.org/protobuf/internal/encoding/json" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/set" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // Unmarshal reads the given []byte into the given proto.Message. // The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m proto.Message) error { return UnmarshalOptions{}.Unmarshal(b, m) } // UnmarshalOptions is a configurable JSON format parser. type UnmarshalOptions struct { pragma.NoUnkeyedLiterals // If AllowPartial is set, input for messages that will result in missing // required fields will not return an error. AllowPartial bool // If DiscardUnknown is set, unknown fields are ignored. DiscardUnknown bool // Resolver is used for looking up types when unmarshaling // google.protobuf.Any messages or extension fields. // If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.MessageTypeResolver protoregistry.ExtensionTypeResolver } } // Unmarshal reads the given []byte and populates the given proto.Message // using options in the UnmarshalOptions object. // It will clear the message first before setting the fields. // If it returns an error, the given message may be partially set. // The provided message must be mutable (e.g., a non-nil pointer to a message). func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { return o.unmarshal(b, m) } // unmarshal is a centralized function that all unmarshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { proto.Reset(m) if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } dec := decoder{json.NewDecoder(b), o} if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { return err } // Check for EOF. tok, err := dec.Read() if err != nil { return err } if tok.Kind() != json.EOF { return dec.unexpectedTokenError(tok) } if o.AllowPartial { return nil } return proto.CheckInitialized(m) } type decoder struct { *json.Decoder opts UnmarshalOptions } // newError returns an error object with position info. func (d decoder) newError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("(line %d:%d): ", line, column) return errors.New(head+f, x...) } // unexpectedTokenError returns a syntax error for the given unexpected token. func (d decoder) unexpectedTokenError(tok json.Token) error { return d.syntaxError(tok.Pos(), "unexpected token %s", tok.RawString()) } // syntaxError returns a syntax error for given position. func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) return errors.New(head+f, x...) } // unmarshalMessage unmarshals a message into the given protoreflect.Message. func (d decoder) unmarshalMessage(m pref.Message, skipTypeURL bool) error { if unmarshal := wellKnownTypeUnmarshaler(m.Descriptor().FullName()); unmarshal != nil { return unmarshal(d, m) } tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.ObjectOpen { return d.unexpectedTokenError(tok) } messageDesc := m.Descriptor() if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { return errors.New("no support for proto1 MessageSets") } var seenNums set.Ints var seenOneofs set.Ints fieldDescs := messageDesc.Fields() for { // Read field name. tok, err := d.Read() if err != nil { return err } switch tok.Kind() { default: return d.unexpectedTokenError(tok) case json.ObjectClose: return nil case json.Name: // Continue below. } name := tok.Name() // Unmarshaling a non-custom embedded message in Any will contain the // JSON field "@type" which should be skipped because it is not a field // of the embedded message, but simply an artifact of the Any format. if skipTypeURL && name == "@type" { d.Read() continue } // Get the FieldDescriptor. var fd pref.FieldDescriptor if strings.HasPrefix(name, "[") && strings.HasSuffix(name, "]") { // Only extension names are in [name] format. extName := pref.FullName(name[1 : len(name)-1]) extType, err := d.opts.Resolver.FindExtensionByName(extName) if err != nil && err != protoregistry.NotFound { return d.newError(tok.Pos(), "unable to resolve %s: %v", tok.RawString(), err) } if extType != nil { fd = extType.TypeDescriptor() if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) } } } else { // The name can either be the JSON name or the proto field name. fd = fieldDescs.ByJSONName(name) if fd == nil { fd = fieldDescs.ByTextName(name) } } if flags.ProtoLegacy { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } } if fd == nil { // Field is unknown. if d.opts.DiscardUnknown { if err := d.skipJSONValue(); err != nil { return err } continue } return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) } // Do not allow duplicate fields. num := uint64(fd.Number()) if seenNums.Has(num) { return d.newError(tok.Pos(), "duplicate field %v", tok.RawString()) } seenNums.Set(num) // No need to set values for JSON null unless the field type is // google.protobuf.Value or google.protobuf.NullValue. if tok, _ := d.Peek(); tok.Kind() == json.Null && !isKnownValue(fd) && !isNullValue(fd) { d.Read() continue } switch { case fd.IsList(): list := m.Mutable(fd).List() if err := d.unmarshalList(list, fd); err != nil { return err } case fd.IsMap(): mmap := m.Mutable(fd).Map() if err := d.unmarshalMap(mmap, fd); err != nil { return err } default: // If field is a oneof, check if it has already been set. if od := fd.ContainingOneof(); od != nil { idx := uint64(od.Index()) if seenOneofs.Has(idx) { return d.newError(tok.Pos(), "error parsing %s, oneof %v is already set", tok.RawString(), od.FullName()) } seenOneofs.Set(idx) } // Required or optional fields. if err := d.unmarshalSingular(m, fd); err != nil { return err } } } } func isKnownValue(fd pref.FieldDescriptor) bool { md := fd.Message() return md != nil && md.FullName() == genid.Value_message_fullname } func isNullValue(fd pref.FieldDescriptor) bool { ed := fd.Enum() return ed != nil && ed.FullName() == genid.NullValue_enum_fullname } // unmarshalSingular unmarshals to the non-repeated field specified // by the given FieldDescriptor. func (d decoder) unmarshalSingular(m pref.Message, fd pref.FieldDescriptor) error { var val pref.Value var err error switch fd.Kind() { case pref.MessageKind, pref.GroupKind: val = m.NewField(fd) err = d.unmarshalMessage(val.Message(), false) default: val, err = d.unmarshalScalar(fd) } if err != nil { return err } m.Set(fd, val) return nil } // unmarshalScalar unmarshals to a scalar/enum protoreflect.Value specified by // the given FieldDescriptor. func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) { const b32 int = 32 const b64 int = 64 tok, err := d.Read() if err != nil { return pref.Value{}, err } kind := fd.Kind() switch kind { case pref.BoolKind: if tok.Kind() == json.Bool { return pref.ValueOfBool(tok.Bool()), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if v, ok := unmarshalInt(tok, b32); ok { return v, nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if v, ok := unmarshalInt(tok, b64); ok { return v, nil } case pref.Uint32Kind, pref.Fixed32Kind: if v, ok := unmarshalUint(tok, b32); ok { return v, nil } case pref.Uint64Kind, pref.Fixed64Kind: if v, ok := unmarshalUint(tok, b64); ok { return v, nil } case pref.FloatKind: if v, ok := unmarshalFloat(tok, b32); ok { return v, nil } case pref.DoubleKind: if v, ok := unmarshalFloat(tok, b64); ok { return v, nil } case pref.StringKind: if tok.Kind() == json.String { return pref.ValueOfString(tok.ParsedString()), nil } case pref.BytesKind: if v, ok := unmarshalBytes(tok); ok { return v, nil } case pref.EnumKind: if v, ok := unmarshalEnum(tok, fd); ok { return v, nil } default: panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", kind)) } return pref.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) } func unmarshalInt(tok json.Token, bitSize int) (pref.Value, bool) { switch tok.Kind() { case json.Number: return getInt(tok, bitSize) case json.String: // Decode number from string. s := strings.TrimSpace(tok.ParsedString()) if len(s) != len(tok.ParsedString()) { return pref.Value{}, false } dec := json.NewDecoder([]byte(s)) tok, err := dec.Read() if err != nil { return pref.Value{}, false } return getInt(tok, bitSize) } return pref.Value{}, false } func getInt(tok json.Token, bitSize int) (pref.Value, bool) { n, ok := tok.Int(bitSize) if !ok { return pref.Value{}, false } if bitSize == 32 { return pref.ValueOfInt32(int32(n)), true } return pref.ValueOfInt64(n), true } func unmarshalUint(tok json.Token, bitSize int) (pref.Value, bool) { switch tok.Kind() { case json.Number: return getUint(tok, bitSize) case json.String: // Decode number from string. s := strings.TrimSpace(tok.ParsedString()) if len(s) != len(tok.ParsedString()) { return pref.Value{}, false } dec := json.NewDecoder([]byte(s)) tok, err := dec.Read() if err != nil { return pref.Value{}, false } return getUint(tok, bitSize) } return pref.Value{}, false } func getUint(tok json.Token, bitSize int) (pref.Value, bool) { n, ok := tok.Uint(bitSize) if !ok { return pref.Value{}, false } if bitSize == 32 { return pref.ValueOfUint32(uint32(n)), true } return pref.ValueOfUint64(n), true } func unmarshalFloat(tok json.Token, bitSize int) (pref.Value, bool) { switch tok.Kind() { case json.Number: return getFloat(tok, bitSize) case json.String: s := tok.ParsedString() switch s { case "NaN": if bitSize == 32 { return pref.ValueOfFloat32(float32(math.NaN())), true } return pref.ValueOfFloat64(math.NaN()), true case "Infinity": if bitSize == 32 { return pref.ValueOfFloat32(float32(math.Inf(+1))), true } return pref.ValueOfFloat64(math.Inf(+1)), true case "-Infinity": if bitSize == 32 { return pref.ValueOfFloat32(float32(math.Inf(-1))), true } return pref.ValueOfFloat64(math.Inf(-1)), true } // Decode number from string. if len(s) != len(strings.TrimSpace(s)) { return pref.Value{}, false } dec := json.NewDecoder([]byte(s)) tok, err := dec.Read() if err != nil { return pref.Value{}, false } return getFloat(tok, bitSize) } return pref.Value{}, false } func getFloat(tok json.Token, bitSize int) (pref.Value, bool) { n, ok := tok.Float(bitSize) if !ok { return pref.Value{}, false } if bitSize == 32 { return pref.ValueOfFloat32(float32(n)), true } return pref.ValueOfFloat64(n), true } func unmarshalBytes(tok json.Token) (pref.Value, bool) { if tok.Kind() != json.String { return pref.Value{}, false } s := tok.ParsedString() enc := base64.StdEncoding if strings.ContainsAny(s, "-_") { enc = base64.URLEncoding } if len(s)%4 != 0 { enc = enc.WithPadding(base64.NoPadding) } b, err := enc.DecodeString(s) if err != nil { return pref.Value{}, false } return pref.ValueOfBytes(b), true } func unmarshalEnum(tok json.Token, fd pref.FieldDescriptor) (pref.Value, bool) { switch tok.Kind() { case json.String: // Lookup EnumNumber based on name. s := tok.ParsedString() if enumVal := fd.Enum().Values().ByName(pref.Name(s)); enumVal != nil { return pref.ValueOfEnum(enumVal.Number()), true } case json.Number: if n, ok := tok.Int(32); ok { return pref.ValueOfEnum(pref.EnumNumber(n)), true } case json.Null: // This is only valid for google.protobuf.NullValue. if isNullValue(fd) { return pref.ValueOfEnum(0), true } } return pref.Value{}, false } func (d decoder) unmarshalList(list pref.List, fd pref.FieldDescriptor) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.ArrayOpen { return d.unexpectedTokenError(tok) } switch fd.Kind() { case pref.MessageKind, pref.GroupKind: for { tok, err := d.Peek() if err != nil { return err } if tok.Kind() == json.ArrayClose { d.Read() return nil } val := list.NewElement() if err := d.unmarshalMessage(val.Message(), false); err != nil { return err } list.Append(val) } default: for { tok, err := d.Peek() if err != nil { return err } if tok.Kind() == json.ArrayClose { d.Read() return nil } val, err := d.unmarshalScalar(fd) if err != nil { return err } list.Append(val) } } return nil } func (d decoder) unmarshalMap(mmap pref.Map, fd pref.FieldDescriptor) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.ObjectOpen { return d.unexpectedTokenError(tok) } // Determine ahead whether map entry is a scalar type or a message type in // order to call the appropriate unmarshalMapValue func inside the for loop // below. var unmarshalMapValue func() (pref.Value, error) switch fd.MapValue().Kind() { case pref.MessageKind, pref.GroupKind: unmarshalMapValue = func() (pref.Value, error) { val := mmap.NewValue() if err := d.unmarshalMessage(val.Message(), false); err != nil { return pref.Value{}, err } return val, nil } default: unmarshalMapValue = func() (pref.Value, error) { return d.unmarshalScalar(fd.MapValue()) } } Loop: for { // Read field name. tok, err := d.Read() if err != nil { return err } switch tok.Kind() { default: return d.unexpectedTokenError(tok) case json.ObjectClose: break Loop case json.Name: // Continue. } // Unmarshal field name. pkey, err := d.unmarshalMapKey(tok, fd.MapKey()) if err != nil { return err } // Check for duplicate field name. if mmap.Has(pkey) { return d.newError(tok.Pos(), "duplicate map key %v", tok.RawString()) } // Read and unmarshal field value. pval, err := unmarshalMapValue() if err != nil { return err } mmap.Set(pkey, pval) } return nil } // unmarshalMapKey converts given token of Name kind into a protoreflect.MapKey. // A map key type is any integral or string type. func (d decoder) unmarshalMapKey(tok json.Token, fd pref.FieldDescriptor) (pref.MapKey, error) { const b32 = 32 const b64 = 64 const base10 = 10 name := tok.Name() kind := fd.Kind() switch kind { case pref.StringKind: return pref.ValueOfString(name).MapKey(), nil case pref.BoolKind: switch name { case "true": return pref.ValueOfBool(true).MapKey(), nil case "false": return pref.ValueOfBool(false).MapKey(), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if n, err := strconv.ParseInt(name, base10, b32); err == nil { return pref.ValueOfInt32(int32(n)).MapKey(), nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if n, err := strconv.ParseInt(name, base10, b64); err == nil { return pref.ValueOfInt64(int64(n)).MapKey(), nil } case pref.Uint32Kind, pref.Fixed32Kind: if n, err := strconv.ParseUint(name, base10, b32); err == nil { return pref.ValueOfUint32(uint32(n)).MapKey(), nil } case pref.Uint64Kind, pref.Fixed64Kind: if n, err := strconv.ParseUint(name, base10, b64); err == nil { return pref.ValueOfUint64(uint64(n)).MapKey(), nil } default: panic(fmt.Sprintf("invalid kind for map key: %v", kind)) } return pref.MapKey{}, d.newError(tok.Pos(), "invalid value for %v key: %s", kind, tok.RawString()) } ================================================ FILE: vendor/google.golang.org/protobuf/encoding/protojson/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protojson marshals and unmarshals protocol buffer messages as JSON // format. It follows the guide at // https://developers.google.com/protocol-buffers/docs/proto3#json. // // This package produces a different output than the standard "encoding/json" // package, which does not operate correctly on protocol buffer messages. package protojson ================================================ FILE: vendor/google.golang.org/protobuf/encoding/protojson/encode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protojson import ( "encoding/base64" "fmt" "google.golang.org/protobuf/internal/encoding/json" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) const defaultIndent = " " // Format formats the message as a multiline string. // This function is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func Format(m proto.Message) string { return MarshalOptions{Multiline: true}.Format(m) } // Marshal writes the given proto.Message in JSON format using default options. // Do not depend on the output being stable. It may change over time across // different versions of the program. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{}.Marshal(m) } // MarshalOptions is a configurable JSON format marshaler. type MarshalOptions struct { pragma.NoUnkeyedLiterals // Multiline specifies whether the marshaler should format the output in // indented-form with every textual element on a new line. // If Indent is an empty string, then an arbitrary indent is chosen. Multiline bool // Indent specifies the set of indentation characters to use in a multiline // formatted output such that every entry is preceded by Indent and // terminated by a newline. If non-empty, then Multiline is treated as true. // Indent can only be composed of space or tab characters. Indent string // AllowPartial allows messages that have missing required fields to marshal // without returning an error. If AllowPartial is false (the default), // Marshal will return error if there are any missing required fields. AllowPartial bool // UseProtoNames uses proto field name instead of lowerCamelCase name in JSON // field names. UseProtoNames bool // UseEnumNumbers emits enum values as numbers. UseEnumNumbers bool // EmitUnpopulated specifies whether to emit unpopulated fields. It does not // emit unpopulated oneof fields or unpopulated extension fields. // The JSON value emitted for unpopulated fields are as follows: // ╔═══════╤════════════════════════════╗ // ║ JSON │ Protobuf field ║ // ╠═══════╪════════════════════════════╣ // ║ false │ proto3 boolean fields ║ // ║ 0 │ proto3 numeric fields ║ // ║ "" │ proto3 string/bytes fields ║ // ║ null │ proto2 scalar fields ║ // ║ null │ message fields ║ // ║ [] │ list fields ║ // ║ {} │ map fields ║ // ╚═══════╧════════════════════════════╝ EmitUnpopulated bool // Resolver is used for looking up types when expanding google.protobuf.Any // messages. If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.ExtensionTypeResolver protoregistry.MessageTypeResolver } } // Format formats the message as a string. // This method is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func (o MarshalOptions) Format(m proto.Message) string { if m == nil || !m.ProtoReflect().IsValid() { return "" // invalid syntax, but okay since this is for debugging } o.AllowPartial = true b, _ := o.Marshal(m) return string(b) } // Marshal marshals the given proto.Message in the JSON format using options in // MarshalOptions. Do not depend on the output being stable. It may change over // time across different versions of the program. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { return o.marshal(m) } // marshal is a centralized function that all marshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for marshal that do not go through this. func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { if o.Multiline && o.Indent == "" { o.Indent = defaultIndent } if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } internalEnc, err := json.NewEncoder(o.Indent) if err != nil { return nil, err } // Treat nil message interface as an empty message, // in which case the output in an empty JSON object. if m == nil { return []byte("{}"), nil } enc := encoder{internalEnc, o} if err := enc.marshalMessage(m.ProtoReflect(), ""); err != nil { return nil, err } if o.AllowPartial { return enc.Bytes(), nil } return enc.Bytes(), proto.CheckInitialized(m) } type encoder struct { *json.Encoder opts MarshalOptions } // typeFieldDesc is a synthetic field descriptor used for the "@type" field. var typeFieldDesc = func() protoreflect.FieldDescriptor { var fd filedesc.Field fd.L0.FullName = "@type" fd.L0.Index = -1 fd.L1.Cardinality = protoreflect.Optional fd.L1.Kind = protoreflect.StringKind return &fd }() // typeURLFieldRanger wraps a protoreflect.Message and modifies its Range method // to additionally iterate over a synthetic field for the type URL. type typeURLFieldRanger struct { order.FieldRanger typeURL string } func (m typeURLFieldRanger) Range(f func(pref.FieldDescriptor, pref.Value) bool) { if !f(typeFieldDesc, pref.ValueOfString(m.typeURL)) { return } m.FieldRanger.Range(f) } // unpopulatedFieldRanger wraps a protoreflect.Message and modifies its Range // method to additionally iterate over unpopulated fields. type unpopulatedFieldRanger struct{ pref.Message } func (m unpopulatedFieldRanger) Range(f func(pref.FieldDescriptor, pref.Value) bool) { fds := m.Descriptor().Fields() for i := 0; i < fds.Len(); i++ { fd := fds.Get(i) if m.Has(fd) || fd.ContainingOneof() != nil { continue // ignore populated fields and fields within a oneofs } v := m.Get(fd) isProto2Scalar := fd.Syntax() == pref.Proto2 && fd.Default().IsValid() isSingularMessage := fd.Cardinality() != pref.Repeated && fd.Message() != nil if isProto2Scalar || isSingularMessage { v = pref.Value{} // use invalid value to emit null } if !f(fd, v) { return } } m.Message.Range(f) } // marshalMessage marshals the fields in the given protoreflect.Message. // If the typeURL is non-empty, then a synthetic "@type" field is injected // containing the URL as the value. func (e encoder) marshalMessage(m pref.Message, typeURL string) error { if !flags.ProtoLegacy && messageset.IsMessageSet(m.Descriptor()) { return errors.New("no support for proto1 MessageSets") } if marshal := wellKnownTypeMarshaler(m.Descriptor().FullName()); marshal != nil { return marshal(e, m) } e.StartObject() defer e.EndObject() var fields order.FieldRanger = m if e.opts.EmitUnpopulated { fields = unpopulatedFieldRanger{m} } if typeURL != "" { fields = typeURLFieldRanger{fields, typeURL} } var err error order.RangeFields(fields, order.IndexNameFieldOrder, func(fd pref.FieldDescriptor, v pref.Value) bool { name := fd.JSONName() if e.opts.UseProtoNames { name = fd.TextName() } if err = e.WriteName(name); err != nil { return false } if err = e.marshalValue(v, fd); err != nil { return false } return true }) return err } // marshalValue marshals the given protoreflect.Value. func (e encoder) marshalValue(val pref.Value, fd pref.FieldDescriptor) error { switch { case fd.IsList(): return e.marshalList(val.List(), fd) case fd.IsMap(): return e.marshalMap(val.Map(), fd) default: return e.marshalSingular(val, fd) } } // marshalSingular marshals the given non-repeated field value. This includes // all scalar types, enums, messages, and groups. func (e encoder) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error { if !val.IsValid() { e.WriteNull() return nil } switch kind := fd.Kind(); kind { case pref.BoolKind: e.WriteBool(val.Bool()) case pref.StringKind: if e.WriteString(val.String()) != nil { return errors.InvalidUTF8(string(fd.FullName())) } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: e.WriteInt(val.Int()) case pref.Uint32Kind, pref.Fixed32Kind: e.WriteUint(val.Uint()) case pref.Int64Kind, pref.Sint64Kind, pref.Uint64Kind, pref.Sfixed64Kind, pref.Fixed64Kind: // 64-bit integers are written out as JSON string. e.WriteString(val.String()) case pref.FloatKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 32) case pref.DoubleKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 64) case pref.BytesKind: e.WriteString(base64.StdEncoding.EncodeToString(val.Bytes())) case pref.EnumKind: if fd.Enum().FullName() == genid.NullValue_enum_fullname { e.WriteNull() } else { desc := fd.Enum().Values().ByNumber(val.Enum()) if e.opts.UseEnumNumbers || desc == nil { e.WriteInt(int64(val.Enum())) } else { e.WriteString(string(desc.Name())) } } case pref.MessageKind, pref.GroupKind: if err := e.marshalMessage(val.Message(), ""); err != nil { return err } default: panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind)) } return nil } // marshalList marshals the given protoreflect.List. func (e encoder) marshalList(list pref.List, fd pref.FieldDescriptor) error { e.StartArray() defer e.EndArray() for i := 0; i < list.Len(); i++ { item := list.Get(i) if err := e.marshalSingular(item, fd); err != nil { return err } } return nil } // marshalMap marshals given protoreflect.Map. func (e encoder) marshalMap(mmap pref.Map, fd pref.FieldDescriptor) error { e.StartObject() defer e.EndObject() var err error order.RangeEntries(mmap, order.GenericKeyOrder, func(k pref.MapKey, v pref.Value) bool { if err = e.WriteName(k.String()); err != nil { return false } if err = e.marshalSingular(v, fd.MapValue()); err != nil { return false } return true }) return err } ================================================ FILE: vendor/google.golang.org/protobuf/encoding/protojson/well_known_types.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protojson import ( "bytes" "fmt" "math" "strconv" "strings" "time" "google.golang.org/protobuf/internal/encoding/json" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" ) type marshalFunc func(encoder, pref.Message) error // wellKnownTypeMarshaler returns a marshal function if the message type // has specialized serialization behavior. It returns nil otherwise. func wellKnownTypeMarshaler(name pref.FullName) marshalFunc { if name.Parent() == genid.GoogleProtobuf_package { switch name.Name() { case genid.Any_message_name: return encoder.marshalAny case genid.Timestamp_message_name: return encoder.marshalTimestamp case genid.Duration_message_name: return encoder.marshalDuration case genid.BoolValue_message_name, genid.Int32Value_message_name, genid.Int64Value_message_name, genid.UInt32Value_message_name, genid.UInt64Value_message_name, genid.FloatValue_message_name, genid.DoubleValue_message_name, genid.StringValue_message_name, genid.BytesValue_message_name: return encoder.marshalWrapperType case genid.Struct_message_name: return encoder.marshalStruct case genid.ListValue_message_name: return encoder.marshalListValue case genid.Value_message_name: return encoder.marshalKnownValue case genid.FieldMask_message_name: return encoder.marshalFieldMask case genid.Empty_message_name: return encoder.marshalEmpty } } return nil } type unmarshalFunc func(decoder, pref.Message) error // wellKnownTypeUnmarshaler returns a unmarshal function if the message type // has specialized serialization behavior. It returns nil otherwise. func wellKnownTypeUnmarshaler(name pref.FullName) unmarshalFunc { if name.Parent() == genid.GoogleProtobuf_package { switch name.Name() { case genid.Any_message_name: return decoder.unmarshalAny case genid.Timestamp_message_name: return decoder.unmarshalTimestamp case genid.Duration_message_name: return decoder.unmarshalDuration case genid.BoolValue_message_name, genid.Int32Value_message_name, genid.Int64Value_message_name, genid.UInt32Value_message_name, genid.UInt64Value_message_name, genid.FloatValue_message_name, genid.DoubleValue_message_name, genid.StringValue_message_name, genid.BytesValue_message_name: return decoder.unmarshalWrapperType case genid.Struct_message_name: return decoder.unmarshalStruct case genid.ListValue_message_name: return decoder.unmarshalListValue case genid.Value_message_name: return decoder.unmarshalKnownValue case genid.FieldMask_message_name: return decoder.unmarshalFieldMask case genid.Empty_message_name: return decoder.unmarshalEmpty } } return nil } // The JSON representation of an Any message uses the regular representation of // the deserialized, embedded message, with an additional field `@type` which // contains the type URL. If the embedded message type is well-known and has a // custom JSON representation, that representation will be embedded adding a // field `value` which holds the custom JSON in addition to the `@type` field. func (e encoder) marshalAny(m pref.Message) error { fds := m.Descriptor().Fields() fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) fdValue := fds.ByNumber(genid.Any_Value_field_number) if !m.Has(fdType) { if !m.Has(fdValue) { // If message is empty, marshal out empty JSON object. e.StartObject() e.EndObject() return nil } else { // Return error if type_url field is not set, but value is set. return errors.New("%s: %v is not set", genid.Any_message_fullname, genid.Any_TypeUrl_field_name) } } typeVal := m.Get(fdType) valueVal := m.Get(fdValue) // Resolve the type in order to unmarshal value field. typeURL := typeVal.String() emt, err := e.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return errors.New("%s: unable to resolve %q: %v", genid.Any_message_fullname, typeURL, err) } em := emt.New() err = proto.UnmarshalOptions{ AllowPartial: true, // never check required fields inside an Any Resolver: e.opts.Resolver, }.Unmarshal(valueVal.Bytes(), em.Interface()) if err != nil { return errors.New("%s: unable to unmarshal %q: %v", genid.Any_message_fullname, typeURL, err) } // If type of value has custom JSON encoding, marshal out a field "value" // with corresponding custom JSON encoding of the embedded message as a // field. if marshal := wellKnownTypeMarshaler(emt.Descriptor().FullName()); marshal != nil { e.StartObject() defer e.EndObject() // Marshal out @type field. e.WriteName("@type") if err := e.WriteString(typeURL); err != nil { return err } e.WriteName("value") return marshal(e, em) } // Else, marshal out the embedded message's fields in this Any object. if err := e.marshalMessage(em, typeURL); err != nil { return err } return nil } func (d decoder) unmarshalAny(m pref.Message) error { // Peek to check for json.ObjectOpen to avoid advancing a read. start, err := d.Peek() if err != nil { return err } if start.Kind() != json.ObjectOpen { return d.unexpectedTokenError(start) } // Use another decoder to parse the unread bytes for @type field. This // avoids advancing a read from current decoder because the current JSON // object may contain the fields of the embedded type. dec := decoder{d.Clone(), UnmarshalOptions{}} tok, err := findTypeURL(dec) switch err { case errEmptyObject: // An empty JSON object translates to an empty Any message. d.Read() // Read json.ObjectOpen. d.Read() // Read json.ObjectClose. return nil case errMissingType: if d.opts.DiscardUnknown { // Treat all fields as unknowns, similar to an empty object. return d.skipJSONValue() } // Use start.Pos() for line position. return d.newError(start.Pos(), err.Error()) default: if err != nil { return err } } typeURL := tok.ParsedString() emt, err := d.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return d.newError(tok.Pos(), "unable to resolve %v: %q", tok.RawString(), err) } // Create new message for the embedded message type and unmarshal into it. em := emt.New() if unmarshal := wellKnownTypeUnmarshaler(emt.Descriptor().FullName()); unmarshal != nil { // If embedded message is a custom type, // unmarshal the JSON "value" field into it. if err := d.unmarshalAnyValue(unmarshal, em); err != nil { return err } } else { // Else unmarshal the current JSON object into it. if err := d.unmarshalMessage(em, true); err != nil { return err } } // Serialize the embedded message and assign the resulting bytes to the // proto value field. b, err := proto.MarshalOptions{ AllowPartial: true, // No need to check required fields inside an Any. Deterministic: true, }.Marshal(em.Interface()) if err != nil { return d.newError(start.Pos(), "error in marshaling Any.value field: %v", err) } fds := m.Descriptor().Fields() fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) fdValue := fds.ByNumber(genid.Any_Value_field_number) m.Set(fdType, pref.ValueOfString(typeURL)) m.Set(fdValue, pref.ValueOfBytes(b)) return nil } var errEmptyObject = fmt.Errorf(`empty object`) var errMissingType = fmt.Errorf(`missing "@type" field`) // findTypeURL returns the token for the "@type" field value from the given // JSON bytes. It is expected that the given bytes start with json.ObjectOpen. // It returns errEmptyObject if the JSON object is empty or errMissingType if // @type field does not exist. It returns other error if the @type field is not // valid or other decoding issues. func findTypeURL(d decoder) (json.Token, error) { var typeURL string var typeTok json.Token numFields := 0 // Skip start object. d.Read() Loop: for { tok, err := d.Read() if err != nil { return json.Token{}, err } switch tok.Kind() { case json.ObjectClose: if typeURL == "" { // Did not find @type field. if numFields > 0 { return json.Token{}, errMissingType } return json.Token{}, errEmptyObject } break Loop case json.Name: numFields++ if tok.Name() != "@type" { // Skip value. if err := d.skipJSONValue(); err != nil { return json.Token{}, err } continue } // Return error if this was previously set already. if typeURL != "" { return json.Token{}, d.newError(tok.Pos(), `duplicate "@type" field`) } // Read field value. tok, err := d.Read() if err != nil { return json.Token{}, err } if tok.Kind() != json.String { return json.Token{}, d.newError(tok.Pos(), `@type field value is not a string: %v`, tok.RawString()) } typeURL = tok.ParsedString() if typeURL == "" { return json.Token{}, d.newError(tok.Pos(), `@type field contains empty value`) } typeTok = tok } } return typeTok, nil } // skipJSONValue parses a JSON value (null, boolean, string, number, object and // array) in order to advance the read to the next JSON value. It relies on // the decoder returning an error if the types are not in valid sequence. func (d decoder) skipJSONValue() error { tok, err := d.Read() if err != nil { return err } // Only need to continue reading for objects and arrays. switch tok.Kind() { case json.ObjectOpen: for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case json.ObjectClose: return nil case json.Name: // Skip object field value. if err := d.skipJSONValue(); err != nil { return err } } } case json.ArrayOpen: for { tok, err := d.Peek() if err != nil { return err } switch tok.Kind() { case json.ArrayClose: d.Read() return nil default: // Skip array item. if err := d.skipJSONValue(); err != nil { return err } } } } return nil } // unmarshalAnyValue unmarshals the given custom-type message from the JSON // object's "value" field. func (d decoder) unmarshalAnyValue(unmarshal unmarshalFunc, m pref.Message) error { // Skip ObjectOpen, and start reading the fields. d.Read() var found bool // Used for detecting duplicate "value". for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case json.ObjectClose: if !found { return d.newError(tok.Pos(), `missing "value" field`) } return nil case json.Name: switch tok.Name() { case "@type": // Skip the value as this was previously parsed already. d.Read() case "value": if found { return d.newError(tok.Pos(), `duplicate "value" field`) } // Unmarshal the field value into the given message. if err := unmarshal(d, m); err != nil { return err } found = true default: if d.opts.DiscardUnknown { if err := d.skipJSONValue(); err != nil { return err } continue } return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) } } } } // Wrapper types are encoded as JSON primitives like string, number or boolean. func (e encoder) marshalWrapperType(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.WrapperValue_Value_field_number) val := m.Get(fd) return e.marshalSingular(val, fd) } func (d decoder) unmarshalWrapperType(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.WrapperValue_Value_field_number) val, err := d.unmarshalScalar(fd) if err != nil { return err } m.Set(fd, val) return nil } // The JSON representation for Empty is an empty JSON object. func (e encoder) marshalEmpty(pref.Message) error { e.StartObject() e.EndObject() return nil } func (d decoder) unmarshalEmpty(pref.Message) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.ObjectOpen { return d.unexpectedTokenError(tok) } for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case json.ObjectClose: return nil case json.Name: if d.opts.DiscardUnknown { if err := d.skipJSONValue(); err != nil { return err } continue } return d.newError(tok.Pos(), "unknown field %v", tok.RawString()) default: return d.unexpectedTokenError(tok) } } } // The JSON representation for Struct is a JSON object that contains the encoded // Struct.fields map and follows the serialization rules for a map. func (e encoder) marshalStruct(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.Struct_Fields_field_number) return e.marshalMap(m.Get(fd).Map(), fd) } func (d decoder) unmarshalStruct(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.Struct_Fields_field_number) return d.unmarshalMap(m.Mutable(fd).Map(), fd) } // The JSON representation for ListValue is JSON array that contains the encoded // ListValue.values repeated field and follows the serialization rules for a // repeated field. func (e encoder) marshalListValue(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.ListValue_Values_field_number) return e.marshalList(m.Get(fd).List(), fd) } func (d decoder) unmarshalListValue(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.ListValue_Values_field_number) return d.unmarshalList(m.Mutable(fd).List(), fd) } // The JSON representation for a Value is dependent on the oneof field that is // set. Each of the field in the oneof has its own custom serialization rule. A // Value message needs to be a oneof field set, else it is an error. func (e encoder) marshalKnownValue(m pref.Message) error { od := m.Descriptor().Oneofs().ByName(genid.Value_Kind_oneof_name) fd := m.WhichOneof(od) if fd == nil { return errors.New("%s: none of the oneof fields is set", genid.Value_message_fullname) } if fd.Number() == genid.Value_NumberValue_field_number { if v := m.Get(fd).Float(); math.IsNaN(v) || math.IsInf(v, 0) { return errors.New("%s: invalid %v value", genid.Value_NumberValue_field_fullname, v) } } return e.marshalSingular(m.Get(fd), fd) } func (d decoder) unmarshalKnownValue(m pref.Message) error { tok, err := d.Peek() if err != nil { return err } var fd pref.FieldDescriptor var val pref.Value switch tok.Kind() { case json.Null: d.Read() fd = m.Descriptor().Fields().ByNumber(genid.Value_NullValue_field_number) val = pref.ValueOfEnum(0) case json.Bool: tok, err := d.Read() if err != nil { return err } fd = m.Descriptor().Fields().ByNumber(genid.Value_BoolValue_field_number) val = pref.ValueOfBool(tok.Bool()) case json.Number: tok, err := d.Read() if err != nil { return err } fd = m.Descriptor().Fields().ByNumber(genid.Value_NumberValue_field_number) var ok bool val, ok = unmarshalFloat(tok, 64) if !ok { return d.newError(tok.Pos(), "invalid %v: %v", genid.Value_message_fullname, tok.RawString()) } case json.String: // A JSON string may have been encoded from the number_value field, // e.g. "NaN", "Infinity", etc. Parsing a proto double type also allows // for it to be in JSON string form. Given this custom encoding spec, // however, there is no way to identify that and hence a JSON string is // always assigned to the string_value field, which means that certain // encoding cannot be parsed back to the same field. tok, err := d.Read() if err != nil { return err } fd = m.Descriptor().Fields().ByNumber(genid.Value_StringValue_field_number) val = pref.ValueOfString(tok.ParsedString()) case json.ObjectOpen: fd = m.Descriptor().Fields().ByNumber(genid.Value_StructValue_field_number) val = m.NewField(fd) if err := d.unmarshalStruct(val.Message()); err != nil { return err } case json.ArrayOpen: fd = m.Descriptor().Fields().ByNumber(genid.Value_ListValue_field_number) val = m.NewField(fd) if err := d.unmarshalListValue(val.Message()); err != nil { return err } default: return d.newError(tok.Pos(), "invalid %v: %v", genid.Value_message_fullname, tok.RawString()) } m.Set(fd, val) return nil } // The JSON representation for a Duration is a JSON string that ends in the // suffix "s" (indicating seconds) and is preceded by the number of seconds, // with nanoseconds expressed as fractional seconds. // // Durations less than one second are represented with a 0 seconds field and a // positive or negative nanos field. For durations of one second or more, a // non-zero value for the nanos field must be of the same sign as the seconds // field. // // Duration.seconds must be from -315,576,000,000 to +315,576,000,000 inclusive. // Duration.nanos must be from -999,999,999 to +999,999,999 inclusive. const ( secondsInNanos = 999999999 maxSecondsInDuration = 315576000000 ) func (e encoder) marshalDuration(m pref.Message) error { fds := m.Descriptor().Fields() fdSeconds := fds.ByNumber(genid.Duration_Seconds_field_number) fdNanos := fds.ByNumber(genid.Duration_Nanos_field_number) secsVal := m.Get(fdSeconds) nanosVal := m.Get(fdNanos) secs := secsVal.Int() nanos := nanosVal.Int() if secs < -maxSecondsInDuration || secs > maxSecondsInDuration { return errors.New("%s: seconds out of range %v", genid.Duration_message_fullname, secs) } if nanos < -secondsInNanos || nanos > secondsInNanos { return errors.New("%s: nanos out of range %v", genid.Duration_message_fullname, nanos) } if (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0) { return errors.New("%s: signs of seconds and nanos do not match", genid.Duration_message_fullname) } // Generated output always contains 0, 3, 6, or 9 fractional digits, // depending on required precision, followed by the suffix "s". var sign string if secs < 0 || nanos < 0 { sign, secs, nanos = "-", -1*secs, -1*nanos } x := fmt.Sprintf("%s%d.%09d", sign, secs, nanos) x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, ".000") e.WriteString(x + "s") return nil } func (d decoder) unmarshalDuration(m pref.Message) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.String { return d.unexpectedTokenError(tok) } secs, nanos, ok := parseDuration(tok.ParsedString()) if !ok { return d.newError(tok.Pos(), "invalid %v value %v", genid.Duration_message_fullname, tok.RawString()) } // Validate seconds. No need to validate nanos because parseDuration would // have covered that already. if secs < -maxSecondsInDuration || secs > maxSecondsInDuration { return d.newError(tok.Pos(), "%v value out of range: %v", genid.Duration_message_fullname, tok.RawString()) } fds := m.Descriptor().Fields() fdSeconds := fds.ByNumber(genid.Duration_Seconds_field_number) fdNanos := fds.ByNumber(genid.Duration_Nanos_field_number) m.Set(fdSeconds, pref.ValueOfInt64(secs)) m.Set(fdNanos, pref.ValueOfInt32(nanos)) return nil } // parseDuration parses the given input string for seconds and nanoseconds value // for the Duration JSON format. The format is a decimal number with a suffix // 's'. It can have optional plus/minus sign. There needs to be at least an // integer or fractional part. Fractional part is limited to 9 digits only for // nanoseconds precision, regardless of whether there are trailing zero digits. // Example values are 1s, 0.1s, 1.s, .1s, +1s, -1s, -.1s. func parseDuration(input string) (int64, int32, bool) { b := []byte(input) size := len(b) if size < 2 { return 0, 0, false } if b[size-1] != 's' { return 0, 0, false } b = b[:size-1] // Read optional plus/minus symbol. var neg bool switch b[0] { case '-': neg = true b = b[1:] case '+': b = b[1:] } if len(b) == 0 { return 0, 0, false } // Read the integer part. var intp []byte switch { case b[0] == '0': b = b[1:] case '1' <= b[0] && b[0] <= '9': intp = b[0:] b = b[1:] n := 1 for len(b) > 0 && '0' <= b[0] && b[0] <= '9' { n++ b = b[1:] } intp = intp[:n] case b[0] == '.': // Continue below. default: return 0, 0, false } hasFrac := false var frac [9]byte if len(b) > 0 { if b[0] != '.' { return 0, 0, false } // Read the fractional part. b = b[1:] n := 0 for len(b) > 0 && n < 9 && '0' <= b[0] && b[0] <= '9' { frac[n] = b[0] n++ b = b[1:] } // It is not valid if there are more bytes left. if len(b) > 0 { return 0, 0, false } // Pad fractional part with 0s. for i := n; i < 9; i++ { frac[i] = '0' } hasFrac = true } var secs int64 if len(intp) > 0 { var err error secs, err = strconv.ParseInt(string(intp), 10, 64) if err != nil { return 0, 0, false } } var nanos int64 if hasFrac { nanob := bytes.TrimLeft(frac[:], "0") if len(nanob) > 0 { var err error nanos, err = strconv.ParseInt(string(nanob), 10, 32) if err != nil { return 0, 0, false } } } if neg { if secs > 0 { secs = -secs } if nanos > 0 { nanos = -nanos } } return secs, int32(nanos), true } // The JSON representation for a Timestamp is a JSON string in the RFC 3339 // format, i.e. "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" where // {year} is always expressed using four digits while {month}, {day}, {hour}, // {min}, and {sec} are zero-padded to two digits each. The fractional seconds, // which can go up to 9 digits, up to 1 nanosecond resolution, is optional. The // "Z" suffix indicates the timezone ("UTC"); the timezone is required. Encoding // should always use UTC (as indicated by "Z") and a decoder should be able to // accept both UTC and other timezones (as indicated by an offset). // // Timestamp.seconds must be from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59Z // inclusive. // Timestamp.nanos must be from 0 to 999,999,999 inclusive. const ( maxTimestampSeconds = 253402300799 minTimestampSeconds = -62135596800 ) func (e encoder) marshalTimestamp(m pref.Message) error { fds := m.Descriptor().Fields() fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number) fdNanos := fds.ByNumber(genid.Timestamp_Nanos_field_number) secsVal := m.Get(fdSeconds) nanosVal := m.Get(fdNanos) secs := secsVal.Int() nanos := nanosVal.Int() if secs < minTimestampSeconds || secs > maxTimestampSeconds { return errors.New("%s: seconds out of range %v", genid.Timestamp_message_fullname, secs) } if nanos < 0 || nanos > secondsInNanos { return errors.New("%s: nanos out of range %v", genid.Timestamp_message_fullname, nanos) } // Uses RFC 3339, where generated output will be Z-normalized and uses 0, 3, // 6 or 9 fractional digits. t := time.Unix(secs, nanos).UTC() x := t.Format("2006-01-02T15:04:05.000000000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, "000") x = strings.TrimSuffix(x, ".000") e.WriteString(x + "Z") return nil } func (d decoder) unmarshalTimestamp(m pref.Message) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.String { return d.unexpectedTokenError(tok) } t, err := time.Parse(time.RFC3339Nano, tok.ParsedString()) if err != nil { return d.newError(tok.Pos(), "invalid %v value %v", genid.Timestamp_message_fullname, tok.RawString()) } // Validate seconds. No need to validate nanos because time.Parse would have // covered that already. secs := t.Unix() if secs < minTimestampSeconds || secs > maxTimestampSeconds { return d.newError(tok.Pos(), "%v value out of range: %v", genid.Timestamp_message_fullname, tok.RawString()) } fds := m.Descriptor().Fields() fdSeconds := fds.ByNumber(genid.Timestamp_Seconds_field_number) fdNanos := fds.ByNumber(genid.Timestamp_Nanos_field_number) m.Set(fdSeconds, pref.ValueOfInt64(secs)) m.Set(fdNanos, pref.ValueOfInt32(int32(t.Nanosecond()))) return nil } // The JSON representation for a FieldMask is a JSON string where paths are // separated by a comma. Fields name in each path are converted to/from // lower-camel naming conventions. Encoding should fail if the path name would // end up differently after a round-trip. func (e encoder) marshalFieldMask(m pref.Message) error { fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number) list := m.Get(fd).List() paths := make([]string, 0, list.Len()) for i := 0; i < list.Len(); i++ { s := list.Get(i).String() if !pref.FullName(s).IsValid() { return errors.New("%s contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s) } // Return error if conversion to camelCase is not reversible. cc := strs.JSONCamelCase(s) if s != strs.JSONSnakeCase(cc) { return errors.New("%s contains irreversible value %q", genid.FieldMask_Paths_field_fullname, s) } paths = append(paths, cc) } e.WriteString(strings.Join(paths, ",")) return nil } func (d decoder) unmarshalFieldMask(m pref.Message) error { tok, err := d.Read() if err != nil { return err } if tok.Kind() != json.String { return d.unexpectedTokenError(tok) } str := strings.TrimSpace(tok.ParsedString()) if str == "" { return nil } paths := strings.Split(str, ",") fd := m.Descriptor().Fields().ByNumber(genid.FieldMask_Paths_field_number) list := m.Mutable(fd).List() for _, s0 := range paths { s := strs.JSONSnakeCase(s0) if strings.Contains(s0, "_") || !pref.FullName(s).IsValid() { return d.newError(tok.Pos(), "%v contains invalid path: %q", genid.FieldMask_Paths_field_fullname, s0) } list.Append(pref.ValueOfString(s)) } return nil } ================================================ FILE: vendor/google.golang.org/protobuf/encoding/prototext/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package prototext import ( "fmt" "unicode/utf8" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/set" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // Unmarshal reads the given []byte into the given proto.Message. // The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m proto.Message) error { return UnmarshalOptions{}.Unmarshal(b, m) } // UnmarshalOptions is a configurable textproto format unmarshaler. type UnmarshalOptions struct { pragma.NoUnkeyedLiterals // AllowPartial accepts input for messages that will result in missing // required fields. If AllowPartial is false (the default), Unmarshal will // return error if there are any missing required fields. AllowPartial bool // DiscardUnknown specifies whether to ignore unknown fields when parsing. // An unknown field is any field whose field name or field number does not // resolve to any known or extension field in the message. // By default, unmarshal rejects unknown fields as an error. DiscardUnknown bool // Resolver is used for looking up types when unmarshaling // google.protobuf.Any messages or extension fields. // If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.MessageTypeResolver protoregistry.ExtensionTypeResolver } } // Unmarshal reads the given []byte and populates the given proto.Message // using options in the UnmarshalOptions object. // The provided message must be mutable (e.g., a non-nil pointer to a message). func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { return o.unmarshal(b, m) } // unmarshal is a centralized function that all unmarshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { proto.Reset(m) if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } dec := decoder{text.NewDecoder(b), o} if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { return err } if o.AllowPartial { return nil } return proto.CheckInitialized(m) } type decoder struct { *text.Decoder opts UnmarshalOptions } // newError returns an error object with position info. func (d decoder) newError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("(line %d:%d): ", line, column) return errors.New(head+f, x...) } // unexpectedTokenError returns a syntax error for the given unexpected token. func (d decoder) unexpectedTokenError(tok text.Token) error { return d.syntaxError(tok.Pos(), "unexpected token: %s", tok.RawString()) } // syntaxError returns a syntax error for given position. func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { line, column := d.Position(pos) head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) return errors.New(head+f, x...) } // unmarshalMessage unmarshals into the given protoreflect.Message. func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error { messageDesc := m.Descriptor() if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { return errors.New("no support for proto1 MessageSets") } if messageDesc.FullName() == genid.Any_message_fullname { return d.unmarshalAny(m, checkDelims) } if checkDelims { tok, err := d.Read() if err != nil { return err } if tok.Kind() != text.MessageOpen { return d.unexpectedTokenError(tok) } } var seenNums set.Ints var seenOneofs set.Ints fieldDescs := messageDesc.Fields() for { // Read field name. tok, err := d.Read() if err != nil { return err } switch typ := tok.Kind(); typ { case text.Name: // Continue below. case text.EOF: if checkDelims { return text.ErrUnexpectedEOF } return nil default: if checkDelims && typ == text.MessageClose { return nil } return d.unexpectedTokenError(tok) } // Resolve the field descriptor. var name pref.Name var fd pref.FieldDescriptor var xt pref.ExtensionType var xtErr error var isFieldNumberName bool switch tok.NameKind() { case text.IdentName: name = pref.Name(tok.IdentName()) fd = fieldDescs.ByTextName(string(name)) case text.TypeName: // Handle extensions only. This code path is not for Any. xt, xtErr = d.opts.Resolver.FindExtensionByName(pref.FullName(tok.TypeName())) case text.FieldNumber: isFieldNumberName = true num := pref.FieldNumber(tok.FieldNumber()) if !num.IsValid() { return d.newError(tok.Pos(), "invalid field number: %d", num) } fd = fieldDescs.ByNumber(num) if fd == nil { xt, xtErr = d.opts.Resolver.FindExtensionByNumber(messageDesc.FullName(), num) } } if xt != nil { fd = xt.TypeDescriptor() if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) } } else if xtErr != nil && xtErr != protoregistry.NotFound { return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) } if flags.ProtoLegacy { if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { fd = nil // reset since the weak reference is not linked in } } // Handle unknown fields. if fd == nil { if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) { d.skipValue() continue } return d.newError(tok.Pos(), "unknown field: %v", tok.RawString()) } // Handle fields identified by field number. if isFieldNumberName { // TODO: Add an option to permit parsing field numbers. // // This requires careful thought as the MarshalOptions.EmitUnknown // option allows formatting unknown fields as the field number and the // best-effort textual representation of the field value. In that case, // it may not be possible to unmarshal the value from a parser that does // have information about the unknown field. return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString()) } switch { case fd.IsList(): kind := fd.Kind() if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } list := m.Mutable(fd).List() if err := d.unmarshalList(fd, list); err != nil { return err } case fd.IsMap(): mmap := m.Mutable(fd).Map() if err := d.unmarshalMap(fd, mmap); err != nil { return err } default: kind := fd.Kind() if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } // If field is a oneof, check if it has already been set. if od := fd.ContainingOneof(); od != nil { idx := uint64(od.Index()) if seenOneofs.Has(idx) { return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName()) } seenOneofs.Set(idx) } num := uint64(fd.Number()) if seenNums.Has(num) { return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString()) } if err := d.unmarshalSingular(fd, m); err != nil { return err } seenNums.Set(num) } } return nil } // unmarshalSingular unmarshals a non-repeated field value specified by the // given FieldDescriptor. func (d decoder) unmarshalSingular(fd pref.FieldDescriptor, m pref.Message) error { var val pref.Value var err error switch fd.Kind() { case pref.MessageKind, pref.GroupKind: val = m.NewField(fd) err = d.unmarshalMessage(val.Message(), true) default: val, err = d.unmarshalScalar(fd) } if err == nil { m.Set(fd, val) } return err } // unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the // given FieldDescriptor. func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) { tok, err := d.Read() if err != nil { return pref.Value{}, err } if tok.Kind() != text.Scalar { return pref.Value{}, d.unexpectedTokenError(tok) } kind := fd.Kind() switch kind { case pref.BoolKind: if b, ok := tok.Bool(); ok { return pref.ValueOfBool(b), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if n, ok := tok.Int32(); ok { return pref.ValueOfInt32(n), nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if n, ok := tok.Int64(); ok { return pref.ValueOfInt64(n), nil } case pref.Uint32Kind, pref.Fixed32Kind: if n, ok := tok.Uint32(); ok { return pref.ValueOfUint32(n), nil } case pref.Uint64Kind, pref.Fixed64Kind: if n, ok := tok.Uint64(); ok { return pref.ValueOfUint64(n), nil } case pref.FloatKind: if n, ok := tok.Float32(); ok { return pref.ValueOfFloat32(n), nil } case pref.DoubleKind: if n, ok := tok.Float64(); ok { return pref.ValueOfFloat64(n), nil } case pref.StringKind: if s, ok := tok.String(); ok { if strs.EnforceUTF8(fd) && !utf8.ValidString(s) { return pref.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8") } return pref.ValueOfString(s), nil } case pref.BytesKind: if b, ok := tok.String(); ok { return pref.ValueOfBytes([]byte(b)), nil } case pref.EnumKind: if lit, ok := tok.Enum(); ok { // Lookup EnumNumber based on name. if enumVal := fd.Enum().Values().ByName(pref.Name(lit)); enumVal != nil { return pref.ValueOfEnum(enumVal.Number()), nil } } if num, ok := tok.Int32(); ok { return pref.ValueOfEnum(pref.EnumNumber(num)), nil } default: panic(fmt.Sprintf("invalid scalar kind %v", kind)) } return pref.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) } // unmarshalList unmarshals into given protoreflect.List. A list value can // either be in [] syntax or simply just a single scalar/message value. func (d decoder) unmarshalList(fd pref.FieldDescriptor, list pref.List) error { tok, err := d.Peek() if err != nil { return err } switch fd.Kind() { case pref.MessageKind, pref.GroupKind: switch tok.Kind() { case text.ListOpen: d.Read() for { tok, err := d.Peek() if err != nil { return err } switch tok.Kind() { case text.ListClose: d.Read() return nil case text.MessageOpen: pval := list.NewElement() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return err } list.Append(pval) default: return d.unexpectedTokenError(tok) } } case text.MessageOpen: pval := list.NewElement() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return err } list.Append(pval) return nil } default: switch tok.Kind() { case text.ListOpen: d.Read() for { tok, err := d.Peek() if err != nil { return err } switch tok.Kind() { case text.ListClose: d.Read() return nil case text.Scalar: pval, err := d.unmarshalScalar(fd) if err != nil { return err } list.Append(pval) default: return d.unexpectedTokenError(tok) } } case text.Scalar: pval, err := d.unmarshalScalar(fd) if err != nil { return err } list.Append(pval) return nil } } return d.unexpectedTokenError(tok) } // unmarshalMap unmarshals into given protoreflect.Map. A map value is a // textproto message containing {key: , value: }. func (d decoder) unmarshalMap(fd pref.FieldDescriptor, mmap pref.Map) error { // Determine ahead whether map entry is a scalar type or a message type in // order to call the appropriate unmarshalMapValue func inside // unmarshalMapEntry. var unmarshalMapValue func() (pref.Value, error) switch fd.MapValue().Kind() { case pref.MessageKind, pref.GroupKind: unmarshalMapValue = func() (pref.Value, error) { pval := mmap.NewValue() if err := d.unmarshalMessage(pval.Message(), true); err != nil { return pref.Value{}, err } return pval, nil } default: unmarshalMapValue = func() (pref.Value, error) { return d.unmarshalScalar(fd.MapValue()) } } tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.MessageOpen: return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue) case text.ListOpen: for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.ListClose: return nil case text.MessageOpen: if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil { return err } default: return d.unexpectedTokenError(tok) } } default: return d.unexpectedTokenError(tok) } } // unmarshalMap unmarshals into given protoreflect.Map. A map value is a // textproto message containing {key: , value: }. func (d decoder) unmarshalMapEntry(fd pref.FieldDescriptor, mmap pref.Map, unmarshalMapValue func() (pref.Value, error)) error { var key pref.MapKey var pval pref.Value Loop: for { // Read field name. tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.Name: if tok.NameKind() != text.IdentName { if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString()) } d.skipValue() continue Loop } // Continue below. case text.MessageClose: break Loop default: return d.unexpectedTokenError(tok) } switch name := pref.Name(tok.IdentName()); name { case genid.MapEntry_Key_field_name: if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } if key.IsValid() { return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) } val, err := d.unmarshalScalar(fd.MapKey()) if err != nil { return err } key = val.MapKey() case genid.MapEntry_Value_field_name: if kind := fd.MapValue().Kind(); (kind != pref.MessageKind) && (kind != pref.GroupKind) { if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } } if pval.IsValid() { return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) } pval, err = unmarshalMapValue() if err != nil { return err } default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "unknown map entry field %q", name) } d.skipValue() } } if !key.IsValid() { key = fd.MapKey().Default().MapKey() } if !pval.IsValid() { switch fd.MapValue().Kind() { case pref.MessageKind, pref.GroupKind: // If value field is not set for message/group types, construct an // empty one as default. pval = mmap.NewValue() default: pval = fd.MapValue().Default() } } mmap.Set(key, pval) return nil } // unmarshalAny unmarshals an Any textproto. It can either be in expanded form // or non-expanded form. func (d decoder) unmarshalAny(m pref.Message, checkDelims bool) error { var typeURL string var bValue []byte var seenTypeUrl bool var seenValue bool var isExpanded bool if checkDelims { tok, err := d.Read() if err != nil { return err } if tok.Kind() != text.MessageOpen { return d.unexpectedTokenError(tok) } } Loop: for { // Read field name. Can only have 3 possible field names, i.e. type_url, // value and type URL name inside []. tok, err := d.Read() if err != nil { return err } if typ := tok.Kind(); typ != text.Name { if checkDelims { if typ == text.MessageClose { break Loop } } else if typ == text.EOF { break Loop } return d.unexpectedTokenError(tok) } switch tok.NameKind() { case text.IdentName: // Both type_url and value fields require field separator :. if !tok.HasSeparator() { return d.syntaxError(tok.Pos(), "missing field separator :") } switch name := pref.Name(tok.IdentName()); name { case genid.Any_TypeUrl_field_name: if seenTypeUrl { return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname) } if isExpanded { return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) } tok, err := d.Read() if err != nil { return err } var ok bool typeURL, ok = tok.String() if !ok { return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString()) } seenTypeUrl = true case genid.Any_Value_field_name: if seenValue { return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname) } if isExpanded { return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) } tok, err := d.Read() if err != nil { return err } s, ok := tok.String() if !ok { return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString()) } bValue = []byte(s) seenValue = true default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) } } case text.TypeName: if isExpanded { return d.newError(tok.Pos(), "cannot have more than one type") } if seenTypeUrl { return d.newError(tok.Pos(), "conflict with type_url field") } typeURL = tok.TypeName() var err error bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos()) if err != nil { return err } isExpanded = true default: if !d.opts.DiscardUnknown { return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) } } } fds := m.Descriptor().Fields() if len(typeURL) > 0 { m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), pref.ValueOfString(typeURL)) } if len(bValue) > 0 { m.Set(fds.ByNumber(genid.Any_Value_field_number), pref.ValueOfBytes(bValue)) } return nil } func (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) { mt, err := d.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err) } // Create new message for the embedded message type and unmarshal the value // field into it. m := mt.New() if err := d.unmarshalMessage(m, true); err != nil { return nil, err } // Serialize the embedded message and return the resulting bytes. b, err := proto.MarshalOptions{ AllowPartial: true, // Never check required fields inside an Any. Deterministic: true, }.Marshal(m.Interface()) if err != nil { return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err) } return b, nil } // skipValue makes the decoder parse a field value in order to advance the read // to the next field. It relies on Read returning an error if the types are not // in valid sequence. func (d decoder) skipValue() error { tok, err := d.Read() if err != nil { return err } // Only need to continue reading for messages and lists. switch tok.Kind() { case text.MessageOpen: return d.skipMessageValue() case text.ListOpen: for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.ListClose: return nil case text.MessageOpen: return d.skipMessageValue() default: // Skip items. This will not validate whether skipped values are // of the same type or not, same behavior as C++ // TextFormat::Parser::AllowUnknownField(true) version 3.8.0. if err := d.skipValue(); err != nil { return err } } } } return nil } // skipMessageValue makes the decoder parse and skip over all fields in a // message. It assumes that the previous read type is MessageOpen. func (d decoder) skipMessageValue() error { for { tok, err := d.Read() if err != nil { return err } switch tok.Kind() { case text.MessageClose: return nil case text.Name: if err := d.skipValue(); err != nil { return err } } } } ================================================ FILE: vendor/google.golang.org/protobuf/encoding/prototext/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package prototext marshals and unmarshals protocol buffer messages as the // textproto format. package prototext ================================================ FILE: vendor/google.golang.org/protobuf/encoding/prototext/encode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package prototext import ( "fmt" "strconv" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/encoding/text" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) const defaultIndent = " " // Format formats the message as a multiline string. // This function is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func Format(m proto.Message) string { return MarshalOptions{Multiline: true}.Format(m) } // Marshal writes the given proto.Message in textproto format using default // options. Do not depend on the output being stable. It may change over time // across different versions of the program. func Marshal(m proto.Message) ([]byte, error) { return MarshalOptions{}.Marshal(m) } // MarshalOptions is a configurable text format marshaler. type MarshalOptions struct { pragma.NoUnkeyedLiterals // Multiline specifies whether the marshaler should format the output in // indented-form with every textual element on a new line. // If Indent is an empty string, then an arbitrary indent is chosen. Multiline bool // Indent specifies the set of indentation characters to use in a multiline // formatted output such that every entry is preceded by Indent and // terminated by a newline. If non-empty, then Multiline is treated as true. // Indent can only be composed of space or tab characters. Indent string // EmitASCII specifies whether to format strings and bytes as ASCII only // as opposed to using UTF-8 encoding when possible. EmitASCII bool // allowInvalidUTF8 specifies whether to permit the encoding of strings // with invalid UTF-8. This is unexported as it is intended to only // be specified by the Format method. allowInvalidUTF8 bool // AllowPartial allows messages that have missing required fields to marshal // without returning an error. If AllowPartial is false (the default), // Marshal will return error if there are any missing required fields. AllowPartial bool // EmitUnknown specifies whether to emit unknown fields in the output. // If specified, the unmarshaler may be unable to parse the output. // The default is to exclude unknown fields. EmitUnknown bool // Resolver is used for looking up types when expanding google.protobuf.Any // messages. If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { protoregistry.ExtensionTypeResolver protoregistry.MessageTypeResolver } } // Format formats the message as a string. // This method is only intended for human consumption and ignores errors. // Do not depend on the output being stable. It may change over time across // different versions of the program. func (o MarshalOptions) Format(m proto.Message) string { if m == nil || !m.ProtoReflect().IsValid() { return "" // invalid syntax, but okay since this is for debugging } o.allowInvalidUTF8 = true o.AllowPartial = true o.EmitUnknown = true b, _ := o.Marshal(m) return string(b) } // Marshal writes the given proto.Message in textproto format using options in // MarshalOptions object. Do not depend on the output being stable. It may // change over time across different versions of the program. func (o MarshalOptions) Marshal(m proto.Message) ([]byte, error) { return o.marshal(m) } // marshal is a centralized function that all marshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for marshal that do not go through this. func (o MarshalOptions) marshal(m proto.Message) ([]byte, error) { var delims = [2]byte{'{', '}'} if o.Multiline && o.Indent == "" { o.Indent = defaultIndent } if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } internalEnc, err := text.NewEncoder(o.Indent, delims, o.EmitASCII) if err != nil { return nil, err } // Treat nil message interface as an empty message, // in which case there is nothing to output. if m == nil { return []byte{}, nil } enc := encoder{internalEnc, o} err = enc.marshalMessage(m.ProtoReflect(), false) if err != nil { return nil, err } out := enc.Bytes() if len(o.Indent) > 0 && len(out) > 0 { out = append(out, '\n') } if o.AllowPartial { return out, nil } return out, proto.CheckInitialized(m) } type encoder struct { *text.Encoder opts MarshalOptions } // marshalMessage marshals the given protoreflect.Message. func (e encoder) marshalMessage(m pref.Message, inclDelims bool) error { messageDesc := m.Descriptor() if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { return errors.New("no support for proto1 MessageSets") } if inclDelims { e.StartMessage() defer e.EndMessage() } // Handle Any expansion. if messageDesc.FullName() == genid.Any_message_fullname { if e.marshalAny(m) { return nil } // If unable to expand, continue on to marshal Any as a regular message. } // Marshal fields. var err error order.RangeFields(m, order.IndexNameFieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { if err = e.marshalField(fd.TextName(), v, fd); err != nil { return false } return true }) if err != nil { return err } // Marshal unknown fields. if e.opts.EmitUnknown { e.marshalUnknown(m.GetUnknown()) } return nil } // marshalField marshals the given field with protoreflect.Value. func (e encoder) marshalField(name string, val pref.Value, fd pref.FieldDescriptor) error { switch { case fd.IsList(): return e.marshalList(name, val.List(), fd) case fd.IsMap(): return e.marshalMap(name, val.Map(), fd) default: e.WriteName(name) return e.marshalSingular(val, fd) } } // marshalSingular marshals the given non-repeated field value. This includes // all scalar types, enums, messages, and groups. func (e encoder) marshalSingular(val pref.Value, fd pref.FieldDescriptor) error { kind := fd.Kind() switch kind { case pref.BoolKind: e.WriteBool(val.Bool()) case pref.StringKind: s := val.String() if !e.opts.allowInvalidUTF8 && strs.EnforceUTF8(fd) && !utf8.ValidString(s) { return errors.InvalidUTF8(string(fd.FullName())) } e.WriteString(s) case pref.Int32Kind, pref.Int64Kind, pref.Sint32Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: e.WriteInt(val.Int()) case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: e.WriteUint(val.Uint()) case pref.FloatKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 32) case pref.DoubleKind: // Encoder.WriteFloat handles the special numbers NaN and infinites. e.WriteFloat(val.Float(), 64) case pref.BytesKind: e.WriteString(string(val.Bytes())) case pref.EnumKind: num := val.Enum() if desc := fd.Enum().Values().ByNumber(num); desc != nil { e.WriteLiteral(string(desc.Name())) } else { // Use numeric value if there is no enum description. e.WriteInt(int64(num)) } case pref.MessageKind, pref.GroupKind: return e.marshalMessage(val.Message(), true) default: panic(fmt.Sprintf("%v has unknown kind: %v", fd.FullName(), kind)) } return nil } // marshalList marshals the given protoreflect.List as multiple name-value fields. func (e encoder) marshalList(name string, list pref.List, fd pref.FieldDescriptor) error { size := list.Len() for i := 0; i < size; i++ { e.WriteName(name) if err := e.marshalSingular(list.Get(i), fd); err != nil { return err } } return nil } // marshalMap marshals the given protoreflect.Map as multiple name-value fields. func (e encoder) marshalMap(name string, mmap pref.Map, fd pref.FieldDescriptor) error { var err error order.RangeEntries(mmap, order.GenericKeyOrder, func(key pref.MapKey, val pref.Value) bool { e.WriteName(name) e.StartMessage() defer e.EndMessage() e.WriteName(string(genid.MapEntry_Key_field_name)) err = e.marshalSingular(key.Value(), fd.MapKey()) if err != nil { return false } e.WriteName(string(genid.MapEntry_Value_field_name)) err = e.marshalSingular(val, fd.MapValue()) if err != nil { return false } return true }) return err } // marshalUnknown parses the given []byte and marshals fields out. // This function assumes proper encoding in the given []byte. func (e encoder) marshalUnknown(b []byte) { const dec = 10 const hex = 16 for len(b) > 0 { num, wtype, n := protowire.ConsumeTag(b) b = b[n:] e.WriteName(strconv.FormatInt(int64(num), dec)) switch wtype { case protowire.VarintType: var v uint64 v, n = protowire.ConsumeVarint(b) e.WriteUint(v) case protowire.Fixed32Type: var v uint32 v, n = protowire.ConsumeFixed32(b) e.WriteLiteral("0x" + strconv.FormatUint(uint64(v), hex)) case protowire.Fixed64Type: var v uint64 v, n = protowire.ConsumeFixed64(b) e.WriteLiteral("0x" + strconv.FormatUint(v, hex)) case protowire.BytesType: var v []byte v, n = protowire.ConsumeBytes(b) e.WriteString(string(v)) case protowire.StartGroupType: e.StartMessage() var v []byte v, n = protowire.ConsumeGroup(num, b) e.marshalUnknown(v) e.EndMessage() default: panic(fmt.Sprintf("prototext: error parsing unknown field wire type: %v", wtype)) } b = b[n:] } } // marshalAny marshals the given google.protobuf.Any message in expanded form. // It returns true if it was able to marshal, else false. func (e encoder) marshalAny(any pref.Message) bool { // Construct the embedded message. fds := any.Descriptor().Fields() fdType := fds.ByNumber(genid.Any_TypeUrl_field_number) typeURL := any.Get(fdType).String() mt, err := e.opts.Resolver.FindMessageByURL(typeURL) if err != nil { return false } m := mt.New().Interface() // Unmarshal bytes into embedded message. fdValue := fds.ByNumber(genid.Any_Value_field_number) value := any.Get(fdValue) err = proto.UnmarshalOptions{ AllowPartial: true, Resolver: e.opts.Resolver, }.Unmarshal(value.Bytes(), m) if err != nil { return false } // Get current encoder position. If marshaling fails, reset encoder output // back to this position. pos := e.Snapshot() // Field name is the proto field name enclosed in []. e.WriteName("[" + typeURL + "]") err = e.marshalMessage(m.ProtoReflect(), true) if err != nil { e.Reset(pos) return false } return true } ================================================ FILE: vendor/google.golang.org/protobuf/encoding/protowire/wire.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protowire parses and formats the raw wire encoding. // See https://developers.google.com/protocol-buffers/docs/encoding. // // For marshaling and unmarshaling entire protobuf messages, // use the "google.golang.org/protobuf/proto" package instead. package protowire import ( "io" "math" "math/bits" "google.golang.org/protobuf/internal/errors" ) // Number represents the field number. type Number int32 const ( MinValidNumber Number = 1 FirstReservedNumber Number = 19000 LastReservedNumber Number = 19999 MaxValidNumber Number = 1<<29 - 1 ) // IsValid reports whether the field number is semantically valid. // // Note that while numbers within the reserved range are semantically invalid, // they are syntactically valid in the wire format. // Implementations may treat records with reserved field numbers as unknown. func (n Number) IsValid() bool { return MinValidNumber <= n && n < FirstReservedNumber || LastReservedNumber < n && n <= MaxValidNumber } // Type represents the wire type. type Type int8 const ( VarintType Type = 0 Fixed32Type Type = 5 Fixed64Type Type = 1 BytesType Type = 2 StartGroupType Type = 3 EndGroupType Type = 4 ) const ( _ = -iota errCodeTruncated errCodeFieldNumber errCodeOverflow errCodeReserved errCodeEndGroup ) var ( errFieldNumber = errors.New("invalid field number") errOverflow = errors.New("variable length integer overflow") errReserved = errors.New("cannot parse reserved wire type") errEndGroup = errors.New("mismatching end group marker") errParse = errors.New("parse error") ) // ParseError converts an error code into an error value. // This returns nil if n is a non-negative number. func ParseError(n int) error { if n >= 0 { return nil } switch n { case errCodeTruncated: return io.ErrUnexpectedEOF case errCodeFieldNumber: return errFieldNumber case errCodeOverflow: return errOverflow case errCodeReserved: return errReserved case errCodeEndGroup: return errEndGroup default: return errParse } } // ConsumeField parses an entire field record (both tag and value) and returns // the field number, the wire type, and the total length. // This returns a negative length upon an error (see ParseError). // // The total length includes the tag header and the end group marker (if the // field is a group). func ConsumeField(b []byte) (Number, Type, int) { num, typ, n := ConsumeTag(b) if n < 0 { return 0, 0, n // forward error code } m := ConsumeFieldValue(num, typ, b[n:]) if m < 0 { return 0, 0, m // forward error code } return num, typ, n + m } // ConsumeFieldValue parses a field value and returns its length. // This assumes that the field Number and wire Type have already been parsed. // This returns a negative length upon an error (see ParseError). // // When parsing a group, the length includes the end group marker and // the end group is verified to match the starting field number. func ConsumeFieldValue(num Number, typ Type, b []byte) (n int) { switch typ { case VarintType: _, n = ConsumeVarint(b) return n case Fixed32Type: _, n = ConsumeFixed32(b) return n case Fixed64Type: _, n = ConsumeFixed64(b) return n case BytesType: _, n = ConsumeBytes(b) return n case StartGroupType: n0 := len(b) for { num2, typ2, n := ConsumeTag(b) if n < 0 { return n // forward error code } b = b[n:] if typ2 == EndGroupType { if num != num2 { return errCodeEndGroup } return n0 - len(b) } n = ConsumeFieldValue(num2, typ2, b) if n < 0 { return n // forward error code } b = b[n:] } case EndGroupType: return errCodeEndGroup default: return errCodeReserved } } // AppendTag encodes num and typ as a varint-encoded tag and appends it to b. func AppendTag(b []byte, num Number, typ Type) []byte { return AppendVarint(b, EncodeTag(num, typ)) } // ConsumeTag parses b as a varint-encoded tag, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeTag(b []byte) (Number, Type, int) { v, n := ConsumeVarint(b) if n < 0 { return 0, 0, n // forward error code } num, typ := DecodeTag(v) if num < MinValidNumber { return 0, 0, errCodeFieldNumber } return num, typ, n } func SizeTag(num Number) int { return SizeVarint(EncodeTag(num, 0)) // wire type has no effect on size } // AppendVarint appends v to b as a varint-encoded uint64. func AppendVarint(b []byte, v uint64) []byte { switch { case v < 1<<7: b = append(b, byte(v)) case v < 1<<14: b = append(b, byte((v>>0)&0x7f|0x80), byte(v>>7)) case v < 1<<21: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte(v>>14)) case v < 1<<28: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte(v>>21)) case v < 1<<35: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte(v>>28)) case v < 1<<42: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte(v>>35)) case v < 1<<49: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte(v>>42)) case v < 1<<56: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte(v>>49)) case v < 1<<63: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte((v>>49)&0x7f|0x80), byte(v>>56)) default: b = append(b, byte((v>>0)&0x7f|0x80), byte((v>>7)&0x7f|0x80), byte((v>>14)&0x7f|0x80), byte((v>>21)&0x7f|0x80), byte((v>>28)&0x7f|0x80), byte((v>>35)&0x7f|0x80), byte((v>>42)&0x7f|0x80), byte((v>>49)&0x7f|0x80), byte((v>>56)&0x7f|0x80), 1) } return b } // ConsumeVarint parses b as a varint-encoded uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeVarint(b []byte) (v uint64, n int) { var y uint64 if len(b) <= 0 { return 0, errCodeTruncated } v = uint64(b[0]) if v < 0x80 { return v, 1 } v -= 0x80 if len(b) <= 1 { return 0, errCodeTruncated } y = uint64(b[1]) v += y << 7 if y < 0x80 { return v, 2 } v -= 0x80 << 7 if len(b) <= 2 { return 0, errCodeTruncated } y = uint64(b[2]) v += y << 14 if y < 0x80 { return v, 3 } v -= 0x80 << 14 if len(b) <= 3 { return 0, errCodeTruncated } y = uint64(b[3]) v += y << 21 if y < 0x80 { return v, 4 } v -= 0x80 << 21 if len(b) <= 4 { return 0, errCodeTruncated } y = uint64(b[4]) v += y << 28 if y < 0x80 { return v, 5 } v -= 0x80 << 28 if len(b) <= 5 { return 0, errCodeTruncated } y = uint64(b[5]) v += y << 35 if y < 0x80 { return v, 6 } v -= 0x80 << 35 if len(b) <= 6 { return 0, errCodeTruncated } y = uint64(b[6]) v += y << 42 if y < 0x80 { return v, 7 } v -= 0x80 << 42 if len(b) <= 7 { return 0, errCodeTruncated } y = uint64(b[7]) v += y << 49 if y < 0x80 { return v, 8 } v -= 0x80 << 49 if len(b) <= 8 { return 0, errCodeTruncated } y = uint64(b[8]) v += y << 56 if y < 0x80 { return v, 9 } v -= 0x80 << 56 if len(b) <= 9 { return 0, errCodeTruncated } y = uint64(b[9]) v += y << 63 if y < 2 { return v, 10 } return 0, errCodeOverflow } // SizeVarint returns the encoded size of a varint. // The size is guaranteed to be within 1 and 10, inclusive. func SizeVarint(v uint64) int { // This computes 1 + (bits.Len64(v)-1)/7. // 9/64 is a good enough approximation of 1/7 return int(9*uint32(bits.Len64(v))+64) / 64 } // AppendFixed32 appends v to b as a little-endian uint32. func AppendFixed32(b []byte, v uint32) []byte { return append(b, byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24)) } // ConsumeFixed32 parses b as a little-endian uint32, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeFixed32(b []byte) (v uint32, n int) { if len(b) < 4 { return 0, errCodeTruncated } v = uint32(b[0])<<0 | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 return v, 4 } // SizeFixed32 returns the encoded size of a fixed32; which is always 4. func SizeFixed32() int { return 4 } // AppendFixed64 appends v to b as a little-endian uint64. func AppendFixed64(b []byte, v uint64) []byte { return append(b, byte(v>>0), byte(v>>8), byte(v>>16), byte(v>>24), byte(v>>32), byte(v>>40), byte(v>>48), byte(v>>56)) } // ConsumeFixed64 parses b as a little-endian uint64, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeFixed64(b []byte) (v uint64, n int) { if len(b) < 8 { return 0, errCodeTruncated } v = uint64(b[0])<<0 | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 | uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56 return v, 8 } // SizeFixed64 returns the encoded size of a fixed64; which is always 8. func SizeFixed64() int { return 8 } // AppendBytes appends v to b as a length-prefixed bytes value. func AppendBytes(b []byte, v []byte) []byte { return append(AppendVarint(b, uint64(len(v))), v...) } // ConsumeBytes parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeBytes(b []byte) (v []byte, n int) { m, n := ConsumeVarint(b) if n < 0 { return nil, n // forward error code } if m > uint64(len(b[n:])) { return nil, errCodeTruncated } return b[n:][:m], n + int(m) } // SizeBytes returns the encoded size of a length-prefixed bytes value, // given only the length. func SizeBytes(n int) int { return SizeVarint(uint64(n)) + n } // AppendString appends v to b as a length-prefixed bytes value. func AppendString(b []byte, v string) []byte { return append(AppendVarint(b, uint64(len(v))), v...) } // ConsumeString parses b as a length-prefixed bytes value, reporting its length. // This returns a negative length upon an error (see ParseError). func ConsumeString(b []byte) (v string, n int) { bb, n := ConsumeBytes(b) return string(bb), n } // AppendGroup appends v to b as group value, with a trailing end group marker. // The value v must not contain the end marker. func AppendGroup(b []byte, num Number, v []byte) []byte { return AppendVarint(append(b, v...), EncodeTag(num, EndGroupType)) } // ConsumeGroup parses b as a group value until the trailing end group marker, // and verifies that the end marker matches the provided num. The value v // does not contain the end marker, while the length does contain the end marker. // This returns a negative length upon an error (see ParseError). func ConsumeGroup(num Number, b []byte) (v []byte, n int) { n = ConsumeFieldValue(num, StartGroupType, b) if n < 0 { return nil, n // forward error code } b = b[:n] // Truncate off end group marker, but need to handle denormalized varints. // Assuming end marker is never 0 (which is always the case since // EndGroupType is non-zero), we can truncate all trailing bytes where the // lower 7 bits are all zero (implying that the varint is denormalized). for len(b) > 0 && b[len(b)-1]&0x7f == 0 { b = b[:len(b)-1] } b = b[:len(b)-SizeTag(num)] return b, n } // SizeGroup returns the encoded size of a group, given only the length. func SizeGroup(num Number, n int) int { return n + SizeTag(num) } // DecodeTag decodes the field Number and wire Type from its unified form. // The Number is -1 if the decoded field number overflows int32. // Other than overflow, this does not check for field number validity. func DecodeTag(x uint64) (Number, Type) { // NOTE: MessageSet allows for larger field numbers than normal. if x>>3 > uint64(math.MaxInt32) { return -1, 0 } return Number(x >> 3), Type(x & 7) } // EncodeTag encodes the field Number and wire Type into its unified form. func EncodeTag(num Number, typ Type) uint64 { return uint64(num)<<3 | uint64(typ&7) } // DecodeZigZag decodes a zig-zag-encoded uint64 as an int64. // Input: {…, 5, 3, 1, 0, 2, 4, 6, …} // Output: {…, -3, -2, -1, 0, +1, +2, +3, …} func DecodeZigZag(x uint64) int64 { return int64(x>>1) ^ int64(x)<<63>>63 } // EncodeZigZag encodes an int64 as a zig-zag-encoded uint64. // Input: {…, -3, -2, -1, 0, +1, +2, +3, …} // Output: {…, 5, 3, 1, 0, 2, 4, 6, …} func EncodeZigZag(x int64) uint64 { return uint64(x<<1) ^ uint64(x>>63) } // DecodeBool decodes a uint64 as a bool. // Input: { 0, 1, 2, …} // Output: {false, true, true, …} func DecodeBool(x uint64) bool { return x != 0 } // EncodeBool encodes a bool as a uint64. // Input: {false, true} // Output: { 0, 1} func EncodeBool(x bool) uint64 { if x { return 1 } return 0 } ================================================ FILE: vendor/google.golang.org/protobuf/internal/descfmt/stringer.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package descfmt provides functionality to format descriptors. package descfmt import ( "fmt" "io" "reflect" "strconv" "strings" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) type list interface { Len() int pragma.DoNotImplement } func FormatList(s fmt.State, r rune, vs list) { io.WriteString(s, formatListOpt(vs, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) } func formatListOpt(vs list, isRoot, allowMulti bool) string { start, end := "[", "]" if isRoot { var name string switch vs.(type) { case pref.Names: name = "Names" case pref.FieldNumbers: name = "FieldNumbers" case pref.FieldRanges: name = "FieldRanges" case pref.EnumRanges: name = "EnumRanges" case pref.FileImports: name = "FileImports" case pref.Descriptor: name = reflect.ValueOf(vs).MethodByName("Get").Type().Out(0).Name() + "s" default: name = reflect.ValueOf(vs).Elem().Type().Name() } start, end = name+"{", "}" } var ss []string switch vs := vs.(type) { case pref.Names: for i := 0; i < vs.Len(); i++ { ss = append(ss, fmt.Sprint(vs.Get(i))) } return start + joinStrings(ss, false) + end case pref.FieldNumbers: for i := 0; i < vs.Len(); i++ { ss = append(ss, fmt.Sprint(vs.Get(i))) } return start + joinStrings(ss, false) + end case pref.FieldRanges: for i := 0; i < vs.Len(); i++ { r := vs.Get(i) if r[0]+1 == r[1] { ss = append(ss, fmt.Sprintf("%d", r[0])) } else { ss = append(ss, fmt.Sprintf("%d:%d", r[0], r[1])) // enum ranges are end exclusive } } return start + joinStrings(ss, false) + end case pref.EnumRanges: for i := 0; i < vs.Len(); i++ { r := vs.Get(i) if r[0] == r[1] { ss = append(ss, fmt.Sprintf("%d", r[0])) } else { ss = append(ss, fmt.Sprintf("%d:%d", r[0], int64(r[1])+1)) // enum ranges are end inclusive } } return start + joinStrings(ss, false) + end case pref.FileImports: for i := 0; i < vs.Len(); i++ { var rs records rs.Append(reflect.ValueOf(vs.Get(i)), "Path", "Package", "IsPublic", "IsWeak") ss = append(ss, "{"+rs.Join()+"}") } return start + joinStrings(ss, allowMulti) + end default: _, isEnumValue := vs.(pref.EnumValueDescriptors) for i := 0; i < vs.Len(); i++ { m := reflect.ValueOf(vs).MethodByName("Get") v := m.Call([]reflect.Value{reflect.ValueOf(i)})[0].Interface() ss = append(ss, formatDescOpt(v.(pref.Descriptor), false, allowMulti && !isEnumValue)) } return start + joinStrings(ss, allowMulti && isEnumValue) + end } } // descriptorAccessors is a list of accessors to print for each descriptor. // // Do not print all accessors since some contain redundant information, // while others are pointers that we do not want to follow since the descriptor // is actually a cyclic graph. // // Using a list allows us to print the accessors in a sensible order. var descriptorAccessors = map[reflect.Type][]string{ reflect.TypeOf((*pref.FileDescriptor)(nil)).Elem(): {"Path", "Package", "Imports", "Messages", "Enums", "Extensions", "Services"}, reflect.TypeOf((*pref.MessageDescriptor)(nil)).Elem(): {"IsMapEntry", "Fields", "Oneofs", "ReservedNames", "ReservedRanges", "RequiredNumbers", "ExtensionRanges", "Messages", "Enums", "Extensions"}, reflect.TypeOf((*pref.FieldDescriptor)(nil)).Elem(): {"Number", "Cardinality", "Kind", "HasJSONName", "JSONName", "HasPresence", "IsExtension", "IsPacked", "IsWeak", "IsList", "IsMap", "MapKey", "MapValue", "HasDefault", "Default", "ContainingOneof", "ContainingMessage", "Message", "Enum"}, reflect.TypeOf((*pref.OneofDescriptor)(nil)).Elem(): {"Fields"}, // not directly used; must keep in sync with formatDescOpt reflect.TypeOf((*pref.EnumDescriptor)(nil)).Elem(): {"Values", "ReservedNames", "ReservedRanges"}, reflect.TypeOf((*pref.EnumValueDescriptor)(nil)).Elem(): {"Number"}, reflect.TypeOf((*pref.ServiceDescriptor)(nil)).Elem(): {"Methods"}, reflect.TypeOf((*pref.MethodDescriptor)(nil)).Elem(): {"Input", "Output", "IsStreamingClient", "IsStreamingServer"}, } func FormatDesc(s fmt.State, r rune, t pref.Descriptor) { io.WriteString(s, formatDescOpt(t, true, r == 'v' && (s.Flag('+') || s.Flag('#')))) } func formatDescOpt(t pref.Descriptor, isRoot, allowMulti bool) string { rv := reflect.ValueOf(t) rt := rv.MethodByName("ProtoType").Type().In(0) start, end := "{", "}" if isRoot { start = rt.Name() + "{" } _, isFile := t.(pref.FileDescriptor) rs := records{allowMulti: allowMulti} if t.IsPlaceholder() { if isFile { rs.Append(rv, "Path", "Package", "IsPlaceholder") } else { rs.Append(rv, "FullName", "IsPlaceholder") } } else { switch { case isFile: rs.Append(rv, "Syntax") case isRoot: rs.Append(rv, "Syntax", "FullName") default: rs.Append(rv, "Name") } switch t := t.(type) { case pref.FieldDescriptor: for _, s := range descriptorAccessors[rt] { switch s { case "MapKey": if k := t.MapKey(); k != nil { rs.recs = append(rs.recs, [2]string{"MapKey", k.Kind().String()}) } case "MapValue": if v := t.MapValue(); v != nil { switch v.Kind() { case pref.EnumKind: rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Enum().FullName())}) case pref.MessageKind, pref.GroupKind: rs.recs = append(rs.recs, [2]string{"MapValue", string(v.Message().FullName())}) default: rs.recs = append(rs.recs, [2]string{"MapValue", v.Kind().String()}) } } case "ContainingOneof": if od := t.ContainingOneof(); od != nil { rs.recs = append(rs.recs, [2]string{"Oneof", string(od.Name())}) } case "ContainingMessage": if t.IsExtension() { rs.recs = append(rs.recs, [2]string{"Extendee", string(t.ContainingMessage().FullName())}) } case "Message": if !t.IsMap() { rs.Append(rv, s) } default: rs.Append(rv, s) } } case pref.OneofDescriptor: var ss []string fs := t.Fields() for i := 0; i < fs.Len(); i++ { ss = append(ss, string(fs.Get(i).Name())) } if len(ss) > 0 { rs.recs = append(rs.recs, [2]string{"Fields", "[" + joinStrings(ss, false) + "]"}) } default: rs.Append(rv, descriptorAccessors[rt]...) } if rv.MethodByName("GoType").IsValid() { rs.Append(rv, "GoType") } } return start + rs.Join() + end } type records struct { recs [][2]string allowMulti bool } func (rs *records) Append(v reflect.Value, accessors ...string) { for _, a := range accessors { var rv reflect.Value if m := v.MethodByName(a); m.IsValid() { rv = m.Call(nil)[0] } if v.Kind() == reflect.Struct && !rv.IsValid() { rv = v.FieldByName(a) } if !rv.IsValid() { panic(fmt.Sprintf("unknown accessor: %v.%s", v.Type(), a)) } if _, ok := rv.Interface().(pref.Value); ok { rv = rv.MethodByName("Interface").Call(nil)[0] if !rv.IsNil() { rv = rv.Elem() } } // Ignore zero values. var isZero bool switch rv.Kind() { case reflect.Interface, reflect.Slice: isZero = rv.IsNil() case reflect.Bool: isZero = rv.Bool() == false case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: isZero = rv.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: isZero = rv.Uint() == 0 case reflect.String: isZero = rv.String() == "" } if n, ok := rv.Interface().(list); ok { isZero = n.Len() == 0 } if isZero { continue } // Format the value. var s string v := rv.Interface() switch v := v.(type) { case list: s = formatListOpt(v, false, rs.allowMulti) case pref.FieldDescriptor, pref.OneofDescriptor, pref.EnumValueDescriptor, pref.MethodDescriptor: s = string(v.(pref.Descriptor).Name()) case pref.Descriptor: s = string(v.FullName()) case string: s = strconv.Quote(v) case []byte: s = fmt.Sprintf("%q", v) default: s = fmt.Sprint(v) } rs.recs = append(rs.recs, [2]string{a, s}) } } func (rs *records) Join() string { var ss []string // In single line mode, simply join all records with commas. if !rs.allowMulti { for _, r := range rs.recs { ss = append(ss, r[0]+formatColon(0)+r[1]) } return joinStrings(ss, false) } // In allowMulti line mode, align single line records for more readable output. var maxLen int flush := func(i int) { for _, r := range rs.recs[len(ss):i] { ss = append(ss, r[0]+formatColon(maxLen-len(r[0]))+r[1]) } maxLen = 0 } for i, r := range rs.recs { if isMulti := strings.Contains(r[1], "\n"); isMulti { flush(i) ss = append(ss, r[0]+formatColon(0)+strings.Join(strings.Split(r[1], "\n"), "\n\t")) } else if maxLen < len(r[0]) { maxLen = len(r[0]) } } flush(len(rs.recs)) return joinStrings(ss, true) } func formatColon(padding int) string { // Deliberately introduce instability into the debug output to // discourage users from performing string comparisons. // This provides us flexibility to change the output in the future. if detrand.Bool() { return ":" + strings.Repeat(" ", 1+padding) // use non-breaking spaces (U+00a0) } else { return ":" + strings.Repeat(" ", 1+padding) // use regular spaces (U+0020) } } func joinStrings(ss []string, isMulti bool) string { if len(ss) == 0 { return "" } if isMulti { return "\n\t" + strings.Join(ss, "\n\t") + "\n" } return strings.Join(ss, ", ") } ================================================ FILE: vendor/google.golang.org/protobuf/internal/descopts/options.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package descopts contains the nil pointers to concrete descriptor options. // // This package exists as a form of reverse dependency injection so that certain // packages (e.g., internal/filedesc and internal/filetype can avoid a direct // dependency on the descriptor proto package). package descopts import pref "google.golang.org/protobuf/reflect/protoreflect" // These variables are set by the init function in descriptor.pb.go via logic // in internal/filetype. In other words, so long as the descriptor proto package // is linked in, these variables will be populated. // // Each variable is populated with a nil pointer to the options struct. var ( File pref.ProtoMessage Enum pref.ProtoMessage EnumValue pref.ProtoMessage Message pref.ProtoMessage Field pref.ProtoMessage Oneof pref.ProtoMessage ExtensionRange pref.ProtoMessage Service pref.ProtoMessage Method pref.ProtoMessage ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/detrand/rand.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package detrand provides deterministically random functionality. // // The pseudo-randomness of these functions is seeded by the program binary // itself and guarantees that the output does not change within a program, // while ensuring that the output is unstable across different builds. package detrand import ( "encoding/binary" "hash/fnv" "os" ) // Disable disables detrand such that all functions returns the zero value. // This function is not concurrent-safe and must be called during program init. func Disable() { randSeed = 0 } // Bool returns a deterministically random boolean. func Bool() bool { return randSeed%2 == 1 } // Intn returns a deterministically random integer between 0 and n-1, inclusive. func Intn(n int) int { if n <= 0 { panic("must be positive") } return int(randSeed % uint64(n)) } // randSeed is a best-effort at an approximate hash of the Go binary. var randSeed = binaryHash() func binaryHash() uint64 { // Open the Go binary. s, err := os.Executable() if err != nil { return 0 } f, err := os.Open(s) if err != nil { return 0 } defer f.Close() // Hash the size and several samples of the Go binary. const numSamples = 8 var buf [64]byte h := fnv.New64() fi, err := f.Stat() if err != nil { return 0 } binary.LittleEndian.PutUint64(buf[:8], uint64(fi.Size())) h.Write(buf[:8]) for i := int64(0); i < numSamples; i++ { if _, err := f.ReadAt(buf[:], i*fi.Size()/numSamples); err != nil { return 0 } h.Write(buf[:]) } return h.Sum64() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/defval/default.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package defval marshals and unmarshals textual forms of default values. // // This package handles both the form historically used in Go struct field tags // and also the form used by google.protobuf.FieldDescriptorProto.default_value // since they differ in superficial ways. package defval import ( "fmt" "math" "strconv" ptext "google.golang.org/protobuf/internal/encoding/text" errors "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) // Format is the serialization format used to represent the default value. type Format int const ( _ Format = iota // Descriptor uses the serialization format that protoc uses with the // google.protobuf.FieldDescriptorProto.default_value field. Descriptor // GoTag uses the historical serialization format in Go struct field tags. GoTag ) // Unmarshal deserializes the default string s according to the given kind k. // When k is an enum, a list of enum value descriptors must be provided. func Unmarshal(s string, k pref.Kind, evs pref.EnumValueDescriptors, f Format) (pref.Value, pref.EnumValueDescriptor, error) { switch k { case pref.BoolKind: if f == GoTag { switch s { case "1": return pref.ValueOfBool(true), nil, nil case "0": return pref.ValueOfBool(false), nil, nil } } else { switch s { case "true": return pref.ValueOfBool(true), nil, nil case "false": return pref.ValueOfBool(false), nil, nil } } case pref.EnumKind: if f == GoTag { // Go tags use the numeric form of the enum value. if n, err := strconv.ParseInt(s, 10, 32); err == nil { if ev := evs.ByNumber(pref.EnumNumber(n)); ev != nil { return pref.ValueOfEnum(ev.Number()), ev, nil } } } else { // Descriptor default_value use the enum identifier. ev := evs.ByName(pref.Name(s)) if ev != nil { return pref.ValueOfEnum(ev.Number()), ev, nil } } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if v, err := strconv.ParseInt(s, 10, 32); err == nil { return pref.ValueOfInt32(int32(v)), nil, nil } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if v, err := strconv.ParseInt(s, 10, 64); err == nil { return pref.ValueOfInt64(int64(v)), nil, nil } case pref.Uint32Kind, pref.Fixed32Kind: if v, err := strconv.ParseUint(s, 10, 32); err == nil { return pref.ValueOfUint32(uint32(v)), nil, nil } case pref.Uint64Kind, pref.Fixed64Kind: if v, err := strconv.ParseUint(s, 10, 64); err == nil { return pref.ValueOfUint64(uint64(v)), nil, nil } case pref.FloatKind, pref.DoubleKind: var v float64 var err error switch s { case "-inf": v = math.Inf(-1) case "inf": v = math.Inf(+1) case "nan": v = math.NaN() default: v, err = strconv.ParseFloat(s, 64) } if err == nil { if k == pref.FloatKind { return pref.ValueOfFloat32(float32(v)), nil, nil } else { return pref.ValueOfFloat64(float64(v)), nil, nil } } case pref.StringKind: // String values are already unescaped and can be used as is. return pref.ValueOfString(s), nil, nil case pref.BytesKind: if b, ok := unmarshalBytes(s); ok { return pref.ValueOfBytes(b), nil, nil } } return pref.Value{}, nil, errors.New("could not parse value for %v: %q", k, s) } // Marshal serializes v as the default string according to the given kind k. // When specifying the Descriptor format for an enum kind, the associated // enum value descriptor must be provided. func Marshal(v pref.Value, ev pref.EnumValueDescriptor, k pref.Kind, f Format) (string, error) { switch k { case pref.BoolKind: if f == GoTag { if v.Bool() { return "1", nil } else { return "0", nil } } else { if v.Bool() { return "true", nil } else { return "false", nil } } case pref.EnumKind: if f == GoTag { return strconv.FormatInt(int64(v.Enum()), 10), nil } else { return string(ev.Name()), nil } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: return strconv.FormatInt(v.Int(), 10), nil case pref.Uint32Kind, pref.Fixed32Kind, pref.Uint64Kind, pref.Fixed64Kind: return strconv.FormatUint(v.Uint(), 10), nil case pref.FloatKind, pref.DoubleKind: f := v.Float() switch { case math.IsInf(f, -1): return "-inf", nil case math.IsInf(f, +1): return "inf", nil case math.IsNaN(f): return "nan", nil default: if k == pref.FloatKind { return strconv.FormatFloat(f, 'g', -1, 32), nil } else { return strconv.FormatFloat(f, 'g', -1, 64), nil } } case pref.StringKind: // String values are serialized as is without any escaping. return v.String(), nil case pref.BytesKind: if s, ok := marshalBytes(v.Bytes()); ok { return s, nil } } return "", errors.New("could not format value for %v: %v", k, v) } // unmarshalBytes deserializes bytes by applying C unescaping. func unmarshalBytes(s string) ([]byte, bool) { // Bytes values use the same escaping as the text format, // however they lack the surrounding double quotes. v, err := ptext.UnmarshalString(`"` + s + `"`) if err != nil { return nil, false } return []byte(v), true } // marshalBytes serializes bytes by using C escaping. // To match the exact output of protoc, this is identical to the // CEscape function in strutil.cc of the protoc source code. func marshalBytes(b []byte) (string, bool) { var s []byte for _, c := range b { switch c { case '\n': s = append(s, `\n`...) case '\r': s = append(s, `\r`...) case '\t': s = append(s, `\t`...) case '"': s = append(s, `\"`...) case '\'': s = append(s, `\'`...) case '\\': s = append(s, `\\`...) default: if printableASCII := c >= 0x20 && c <= 0x7e; printableASCII { s = append(s, c) } else { s = append(s, fmt.Sprintf(`\%03o`, c)...) } } } return string(s), true } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/json/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "bytes" "fmt" "io" "regexp" "unicode/utf8" "google.golang.org/protobuf/internal/errors" ) // call specifies which Decoder method was invoked. type call uint8 const ( readCall call = iota peekCall ) const unexpectedFmt = "unexpected token %s" // ErrUnexpectedEOF means that EOF was encountered in the middle of the input. var ErrUnexpectedEOF = errors.New("%v", io.ErrUnexpectedEOF) // Decoder is a token-based JSON decoder. type Decoder struct { // lastCall is last method called, either readCall or peekCall. // Initial value is readCall. lastCall call // lastToken contains the last read token. lastToken Token // lastErr contains the last read error. lastErr error // openStack is a stack containing ObjectOpen and ArrayOpen values. The // top of stack represents the object or the array the current value is // directly located in. openStack []Kind // orig is used in reporting line and column. orig []byte // in contains the unconsumed input. in []byte } // NewDecoder returns a Decoder to read the given []byte. func NewDecoder(b []byte) *Decoder { return &Decoder{orig: b, in: b} } // Peek looks ahead and returns the next token kind without advancing a read. func (d *Decoder) Peek() (Token, error) { defer func() { d.lastCall = peekCall }() if d.lastCall == readCall { d.lastToken, d.lastErr = d.Read() } return d.lastToken, d.lastErr } // Read returns the next JSON token. // It will return an error if there is no valid token. func (d *Decoder) Read() (Token, error) { const scalar = Null | Bool | Number | String defer func() { d.lastCall = readCall }() if d.lastCall == peekCall { return d.lastToken, d.lastErr } tok, err := d.parseNext() if err != nil { return Token{}, err } switch tok.kind { case EOF: if len(d.openStack) != 0 || d.lastToken.kind&scalar|ObjectClose|ArrayClose == 0 { return Token{}, ErrUnexpectedEOF } case Null: if !d.isValueNext() { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } case Bool, Number: if !d.isValueNext() { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } case String: if d.isValueNext() { break } // This string token should only be for a field name. if d.lastToken.kind&(ObjectOpen|comma) == 0 { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } if len(d.in) == 0 { return Token{}, ErrUnexpectedEOF } if c := d.in[0]; c != ':' { return Token{}, d.newSyntaxError(d.currPos(), `unexpected character %s, missing ":" after field name`, string(c)) } tok.kind = Name d.consume(1) case ObjectOpen, ArrayOpen: if !d.isValueNext() { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } d.openStack = append(d.openStack, tok.kind) case ObjectClose: if len(d.openStack) == 0 || d.lastToken.kind == comma || d.openStack[len(d.openStack)-1] != ObjectOpen { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } d.openStack = d.openStack[:len(d.openStack)-1] case ArrayClose: if len(d.openStack) == 0 || d.lastToken.kind == comma || d.openStack[len(d.openStack)-1] != ArrayOpen { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } d.openStack = d.openStack[:len(d.openStack)-1] case comma: if len(d.openStack) == 0 || d.lastToken.kind&(scalar|ObjectClose|ArrayClose) == 0 { return Token{}, d.newSyntaxError(tok.pos, unexpectedFmt, tok.RawString()) } } // Update d.lastToken only after validating token to be in the right sequence. d.lastToken = tok if d.lastToken.kind == comma { return d.Read() } return tok, nil } // Any sequence that looks like a non-delimiter (for error reporting). var errRegexp = regexp.MustCompile(`^([-+._a-zA-Z0-9]{1,32}|.)`) // parseNext parses for the next JSON token. It returns a Token object for // different types, except for Name. It does not handle whether the next token // is in a valid sequence or not. func (d *Decoder) parseNext() (Token, error) { // Trim leading spaces. d.consume(0) in := d.in if len(in) == 0 { return d.consumeToken(EOF, 0), nil } switch in[0] { case 'n': if n := matchWithDelim("null", in); n != 0 { return d.consumeToken(Null, n), nil } case 't': if n := matchWithDelim("true", in); n != 0 { return d.consumeBoolToken(true, n), nil } case 'f': if n := matchWithDelim("false", in); n != 0 { return d.consumeBoolToken(false, n), nil } case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': if n, ok := parseNumber(in); ok { return d.consumeToken(Number, n), nil } case '"': s, n, err := d.parseString(in) if err != nil { return Token{}, err } return d.consumeStringToken(s, n), nil case '{': return d.consumeToken(ObjectOpen, 1), nil case '}': return d.consumeToken(ObjectClose, 1), nil case '[': return d.consumeToken(ArrayOpen, 1), nil case ']': return d.consumeToken(ArrayClose, 1), nil case ',': return d.consumeToken(comma, 1), nil } return Token{}, d.newSyntaxError(d.currPos(), "invalid value %s", errRegexp.Find(in)) } // newSyntaxError returns an error with line and column information useful for // syntax errors. func (d *Decoder) newSyntaxError(pos int, f string, x ...interface{}) error { e := errors.New(f, x...) line, column := d.Position(pos) return errors.New("syntax error (line %d:%d): %v", line, column, e) } // Position returns line and column number of given index of the original input. // It will panic if index is out of range. func (d *Decoder) Position(idx int) (line int, column int) { b := d.orig[:idx] line = bytes.Count(b, []byte("\n")) + 1 if i := bytes.LastIndexByte(b, '\n'); i >= 0 { b = b[i+1:] } column = utf8.RuneCount(b) + 1 // ignore multi-rune characters return line, column } // currPos returns the current index position of d.in from d.orig. func (d *Decoder) currPos() int { return len(d.orig) - len(d.in) } // matchWithDelim matches s with the input b and verifies that the match // terminates with a delimiter of some form (e.g., r"[^-+_.a-zA-Z0-9]"). // As a special case, EOF is considered a delimiter. It returns the length of s // if there is a match, else 0. func matchWithDelim(s string, b []byte) int { if !bytes.HasPrefix(b, []byte(s)) { return 0 } n := len(s) if n < len(b) && isNotDelim(b[n]) { return 0 } return n } // isNotDelim returns true if given byte is a not delimiter character. func isNotDelim(c byte) bool { return (c == '-' || c == '+' || c == '.' || c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) } // consume consumes n bytes of input and any subsequent whitespace. func (d *Decoder) consume(n int) { d.in = d.in[n:] for len(d.in) > 0 { switch d.in[0] { case ' ', '\n', '\r', '\t': d.in = d.in[1:] default: return } } } // isValueNext returns true if next type should be a JSON value: Null, // Number, String or Bool. func (d *Decoder) isValueNext() bool { if len(d.openStack) == 0 { return d.lastToken.kind == 0 } start := d.openStack[len(d.openStack)-1] switch start { case ObjectOpen: return d.lastToken.kind&Name != 0 case ArrayOpen: return d.lastToken.kind&(ArrayOpen|comma) != 0 } panic(fmt.Sprintf( "unreachable logic in Decoder.isValueNext, lastToken.kind: %v, openStack: %v", d.lastToken.kind, start)) } // consumeToken constructs a Token for given Kind with raw value derived from // current d.in and given size, and consumes the given size-lenght of it. func (d *Decoder) consumeToken(kind Kind, size int) Token { tok := Token{ kind: kind, raw: d.in[:size], pos: len(d.orig) - len(d.in), } d.consume(size) return tok } // consumeBoolToken constructs a Token for a Bool kind with raw value derived from // current d.in and given size. func (d *Decoder) consumeBoolToken(b bool, size int) Token { tok := Token{ kind: Bool, raw: d.in[:size], pos: len(d.orig) - len(d.in), boo: b, } d.consume(size) return tok } // consumeStringToken constructs a Token for a String kind with raw value derived // from current d.in and given size. func (d *Decoder) consumeStringToken(s string, size int) Token { tok := Token{ kind: String, raw: d.in[:size], pos: len(d.orig) - len(d.in), str: s, } d.consume(size) return tok } // Clone returns a copy of the Decoder for use in reading ahead the next JSON // object, array or other values without affecting current Decoder. func (d *Decoder) Clone() *Decoder { ret := *d ret.openStack = append([]Kind(nil), ret.openStack...) return &ret } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/json/decode_number.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "bytes" "strconv" ) // parseNumber reads the given []byte for a valid JSON number. If it is valid, // it returns the number of bytes. Parsing logic follows the definition in // https://tools.ietf.org/html/rfc7159#section-6, and is based off // encoding/json.isValidNumber function. func parseNumber(input []byte) (int, bool) { var n int s := input if len(s) == 0 { return 0, false } // Optional - if s[0] == '-' { s = s[1:] n++ if len(s) == 0 { return 0, false } } // Digits switch { case s[0] == '0': s = s[1:] n++ case '1' <= s[0] && s[0] <= '9': s = s[1:] n++ for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } default: return 0, false } // . followed by 1 or more digits. if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { s = s[2:] n += 2 for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } } // e or E followed by an optional - or + and // 1 or more digits. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { s = s[1:] n++ if s[0] == '+' || s[0] == '-' { s = s[1:] n++ if len(s) == 0 { return 0, false } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } } // Check that next byte is a delimiter or it is at the end. if n < len(input) && isNotDelim(input[n]) { return 0, false } return n, true } // numberParts is the result of parsing out a valid JSON number. It contains // the parts of a number. The parts are used for integer conversion. type numberParts struct { neg bool intp []byte frac []byte exp []byte } // parseNumber constructs numberParts from given []byte. The logic here is // similar to consumeNumber above with the difference of having to construct // numberParts. The slice fields in numberParts are subslices of the input. func parseNumberParts(input []byte) (numberParts, bool) { var neg bool var intp []byte var frac []byte var exp []byte s := input if len(s) == 0 { return numberParts{}, false } // Optional - if s[0] == '-' { neg = true s = s[1:] if len(s) == 0 { return numberParts{}, false } } // Digits switch { case s[0] == '0': // Skip first 0 and no need to store. s = s[1:] case '1' <= s[0] && s[0] <= '9': intp = s n := 1 s = s[1:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } intp = intp[:n] default: return numberParts{}, false } // . followed by 1 or more digits. if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' { frac = s[1:] n := 1 s = s[2:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } frac = frac[:n] } // e or E followed by an optional - or + and // 1 or more digits. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { s = s[1:] exp = s n := 0 if s[0] == '+' || s[0] == '-' { s = s[1:] n++ if len(s) == 0 { return numberParts{}, false } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } exp = exp[:n] } return numberParts{ neg: neg, intp: intp, frac: bytes.TrimRight(frac, "0"), // Remove unnecessary 0s to the right. exp: exp, }, true } // normalizeToIntString returns an integer string in normal form without the // E-notation for given numberParts. It will return false if it is not an // integer or if the exponent exceeds than max/min int value. func normalizeToIntString(n numberParts) (string, bool) { intpSize := len(n.intp) fracSize := len(n.frac) if intpSize == 0 && fracSize == 0 { return "0", true } var exp int if len(n.exp) > 0 { i, err := strconv.ParseInt(string(n.exp), 10, 32) if err != nil { return "", false } exp = int(i) } var num []byte if exp >= 0 { // For positive E, shift fraction digits into integer part and also pad // with zeroes as needed. // If there are more digits in fraction than the E value, then the // number is not an integer. if fracSize > exp { return "", false } // Make sure resulting digits are within max value limit to avoid // unnecessarily constructing a large byte slice that may simply fail // later on. const maxDigits = 20 // Max uint64 value has 20 decimal digits. if intpSize+exp > maxDigits { return "", false } // Set cap to make a copy of integer part when appended. num = n.intp[:len(n.intp):len(n.intp)] num = append(num, n.frac...) for i := 0; i < exp-fracSize; i++ { num = append(num, '0') } } else { // For negative E, shift digits in integer part out. // If there are fractions, then the number is not an integer. if fracSize > 0 { return "", false } // index is where the decimal point will be after adjusting for negative // exponent. index := intpSize + exp if index < 0 { return "", false } num = n.intp // If any of the digits being shifted to the right of the decimal point // is non-zero, then the number is not an integer. for i := index; i < intpSize; i++ { if num[i] != '0' { return "", false } } num = num[:index] } if n.neg { return "-" + string(num), true } return string(num), true } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/json/decode_string.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "strconv" "unicode" "unicode/utf16" "unicode/utf8" "google.golang.org/protobuf/internal/strs" ) func (d *Decoder) parseString(in []byte) (string, int, error) { in0 := in if len(in) == 0 { return "", 0, ErrUnexpectedEOF } if in[0] != '"' { return "", 0, d.newSyntaxError(d.currPos(), "invalid character %q at start of string", in[0]) } in = in[1:] i := indexNeedEscapeInBytes(in) in, out := in[i:], in[:i:i] // set cap to prevent mutations for len(in) > 0 { switch r, n := utf8.DecodeRune(in); { case r == utf8.RuneError && n == 1: return "", 0, d.newSyntaxError(d.currPos(), "invalid UTF-8 in string") case r < ' ': return "", 0, d.newSyntaxError(d.currPos(), "invalid character %q in string", r) case r == '"': in = in[1:] n := len(in0) - len(in) return string(out), n, nil case r == '\\': if len(in) < 2 { return "", 0, ErrUnexpectedEOF } switch r := in[1]; r { case '"', '\\', '/': in, out = in[2:], append(out, r) case 'b': in, out = in[2:], append(out, '\b') case 'f': in, out = in[2:], append(out, '\f') case 'n': in, out = in[2:], append(out, '\n') case 'r': in, out = in[2:], append(out, '\r') case 't': in, out = in[2:], append(out, '\t') case 'u': if len(in) < 6 { return "", 0, ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:6]), 16, 16) if err != nil { return "", 0, d.newSyntaxError(d.currPos(), "invalid escape code %q in string", in[:6]) } in = in[6:] r := rune(v) if utf16.IsSurrogate(r) { if len(in) < 6 { return "", 0, ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:6]), 16, 16) r = utf16.DecodeRune(r, rune(v)) if in[0] != '\\' || in[1] != 'u' || r == unicode.ReplacementChar || err != nil { return "", 0, d.newSyntaxError(d.currPos(), "invalid escape code %q in string", in[:6]) } in = in[6:] } out = append(out, string(r)...) default: return "", 0, d.newSyntaxError(d.currPos(), "invalid escape code %q in string", in[:2]) } default: i := indexNeedEscapeInBytes(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } return "", 0, ErrUnexpectedEOF } // indexNeedEscapeInBytes returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInBytes(b []byte) int { return indexNeedEscapeInString(strs.UnsafeString(b)) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/json/decode_token.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "bytes" "fmt" "strconv" ) // Kind represents a token kind expressible in the JSON format. type Kind uint16 const ( Invalid Kind = (1 << iota) / 2 EOF Null Bool Number String Name ObjectOpen ObjectClose ArrayOpen ArrayClose // comma is only for parsing in between tokens and // does not need to be exported. comma ) func (k Kind) String() string { switch k { case EOF: return "eof" case Null: return "null" case Bool: return "bool" case Number: return "number" case String: return "string" case ObjectOpen: return "{" case ObjectClose: return "}" case Name: return "name" case ArrayOpen: return "[" case ArrayClose: return "]" case comma: return "," } return "" } // Token provides a parsed token kind and value. // // Values are provided by the difference accessor methods. The accessor methods // Name, Bool, and ParsedString will panic if called on the wrong kind. There // are different accessor methods for the Number kind for converting to the // appropriate Go numeric type and those methods have the ok return value. type Token struct { // Token kind. kind Kind // pos provides the position of the token in the original input. pos int // raw bytes of the serialized token. // This is a subslice into the original input. raw []byte // boo is parsed boolean value. boo bool // str is parsed string value. str string } // Kind returns the token kind. func (t Token) Kind() Kind { return t.kind } // RawString returns the read value in string. func (t Token) RawString() string { return string(t.raw) } // Pos returns the token position from the input. func (t Token) Pos() int { return t.pos } // Name returns the object name if token is Name, else it panics. func (t Token) Name() string { if t.kind == Name { return t.str } panic(fmt.Sprintf("Token is not a Name: %v", t.RawString())) } // Bool returns the bool value if token kind is Bool, else it panics. func (t Token) Bool() bool { if t.kind == Bool { return t.boo } panic(fmt.Sprintf("Token is not a Bool: %v", t.RawString())) } // ParsedString returns the string value for a JSON string token or the read // value in string if token is not a string. func (t Token) ParsedString() string { if t.kind == String { return t.str } panic(fmt.Sprintf("Token is not a String: %v", t.RawString())) } // Float returns the floating-point number if token kind is Number. // // The floating-point precision is specified by the bitSize parameter: 32 for // float32 or 64 for float64. If bitSize=32, the result still has type float64, // but it will be convertible to float32 without changing its value. It will // return false if the number exceeds the floating point limits for given // bitSize. func (t Token) Float(bitSize int) (float64, bool) { if t.kind != Number { return 0, false } f, err := strconv.ParseFloat(t.RawString(), bitSize) if err != nil { return 0, false } return f, true } // Int returns the signed integer number if token is Number. // // The given bitSize specifies the integer type that the result must fit into. // It returns false if the number is not an integer value or if the result // exceeds the limits for given bitSize. func (t Token) Int(bitSize int) (int64, bool) { s, ok := t.getIntStr() if !ok { return 0, false } n, err := strconv.ParseInt(s, 10, bitSize) if err != nil { return 0, false } return n, true } // Uint returns the signed integer number if token is Number. // // The given bitSize specifies the unsigned integer type that the result must // fit into. It returns false if the number is not an unsigned integer value // or if the result exceeds the limits for given bitSize. func (t Token) Uint(bitSize int) (uint64, bool) { s, ok := t.getIntStr() if !ok { return 0, false } n, err := strconv.ParseUint(s, 10, bitSize) if err != nil { return 0, false } return n, true } func (t Token) getIntStr() (string, bool) { if t.kind != Number { return "", false } parts, ok := parseNumberParts(t.raw) if !ok { return "", false } return normalizeToIntString(parts) } // TokenEquals returns true if given Tokens are equal, else false. func TokenEquals(x, y Token) bool { return x.kind == y.kind && x.pos == y.pos && bytes.Equal(x.raw, y.raw) && x.boo == y.boo && x.str == y.str } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/json/encode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package json import ( "math" "math/bits" "strconv" "strings" "unicode/utf8" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/errors" ) // kind represents an encoding type. type kind uint8 const ( _ kind = (1 << iota) / 2 name scalar objectOpen objectClose arrayOpen arrayClose ) // Encoder provides methods to write out JSON constructs and values. The user is // responsible for producing valid sequences of JSON constructs and values. type Encoder struct { indent string lastKind kind indents []byte out []byte } // NewEncoder returns an Encoder. // // If indent is a non-empty string, it causes every entry for an Array or Object // to be preceded by the indent and trailed by a newline. func NewEncoder(indent string) (*Encoder, error) { e := &Encoder{} if len(indent) > 0 { if strings.Trim(indent, " \t") != "" { return nil, errors.New("indent may only be composed of space or tab characters") } e.indent = indent } return e, nil } // Bytes returns the content of the written bytes. func (e *Encoder) Bytes() []byte { return e.out } // WriteNull writes out the null value. func (e *Encoder) WriteNull() { e.prepareNext(scalar) e.out = append(e.out, "null"...) } // WriteBool writes out the given boolean value. func (e *Encoder) WriteBool(b bool) { e.prepareNext(scalar) if b { e.out = append(e.out, "true"...) } else { e.out = append(e.out, "false"...) } } // WriteString writes out the given string in JSON string value. Returns error // if input string contains invalid UTF-8. func (e *Encoder) WriteString(s string) error { e.prepareNext(scalar) var err error if e.out, err = appendString(e.out, s); err != nil { return err } return nil } // Sentinel error used for indicating invalid UTF-8. var errInvalidUTF8 = errors.New("invalid UTF-8") func appendString(out []byte, in string) ([]byte, error) { out = append(out, '"') i := indexNeedEscapeInString(in) in, out = in[i:], append(out, in[:i]...) for len(in) > 0 { switch r, n := utf8.DecodeRuneInString(in); { case r == utf8.RuneError && n == 1: return out, errInvalidUTF8 case r < ' ' || r == '"' || r == '\\': out = append(out, '\\') switch r { case '"', '\\': out = append(out, byte(r)) case '\b': out = append(out, 'b') case '\f': out = append(out, 'f') case '\n': out = append(out, 'n') case '\r': out = append(out, 'r') case '\t': out = append(out, 't') default: out = append(out, 'u') out = append(out, "0000"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } in = in[n:] default: i := indexNeedEscapeInString(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } out = append(out, '"') return out, nil } // indexNeedEscapeInString returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInString(s string) int { for i, r := range s { if r < ' ' || r == '\\' || r == '"' || r == utf8.RuneError { return i } } return len(s) } // WriteFloat writes out the given float and bitSize in JSON number value. func (e *Encoder) WriteFloat(n float64, bitSize int) { e.prepareNext(scalar) e.out = appendFloat(e.out, n, bitSize) } // appendFloat formats given float in bitSize, and appends to the given []byte. func appendFloat(out []byte, n float64, bitSize int) []byte { switch { case math.IsNaN(n): return append(out, `"NaN"`...) case math.IsInf(n, +1): return append(out, `"Infinity"`...) case math.IsInf(n, -1): return append(out, `"-Infinity"`...) } // JSON number formatting logic based on encoding/json. // See floatEncoder.encode for reference. fmt := byte('f') if abs := math.Abs(n); abs != 0 { if bitSize == 64 && (abs < 1e-6 || abs >= 1e21) || bitSize == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { fmt = 'e' } } out = strconv.AppendFloat(out, n, fmt, -1, bitSize) if fmt == 'e' { n := len(out) if n >= 4 && out[n-4] == 'e' && out[n-3] == '-' && out[n-2] == '0' { out[n-2] = out[n-1] out = out[:n-1] } } return out } // WriteInt writes out the given signed integer in JSON number value. func (e *Encoder) WriteInt(n int64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatInt(n, 10)...) } // WriteUint writes out the given unsigned integer in JSON number value. func (e *Encoder) WriteUint(n uint64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatUint(n, 10)...) } // StartObject writes out the '{' symbol. func (e *Encoder) StartObject() { e.prepareNext(objectOpen) e.out = append(e.out, '{') } // EndObject writes out the '}' symbol. func (e *Encoder) EndObject() { e.prepareNext(objectClose) e.out = append(e.out, '}') } // WriteName writes out the given string in JSON string value and the name // separator ':'. Returns error if input string contains invalid UTF-8, which // should not be likely as protobuf field names should be valid. func (e *Encoder) WriteName(s string) error { e.prepareNext(name) var err error // Append to output regardless of error. e.out, err = appendString(e.out, s) e.out = append(e.out, ':') return err } // StartArray writes out the '[' symbol. func (e *Encoder) StartArray() { e.prepareNext(arrayOpen) e.out = append(e.out, '[') } // EndArray writes out the ']' symbol. func (e *Encoder) EndArray() { e.prepareNext(arrayClose) e.out = append(e.out, ']') } // prepareNext adds possible comma and indentation for the next value based // on last type and indent option. It also updates lastKind to next. func (e *Encoder) prepareNext(next kind) { defer func() { // Set lastKind to next. e.lastKind = next }() if len(e.indent) == 0 { // Need to add comma on the following condition. if e.lastKind&(scalar|objectClose|arrayClose) != 0 && next&(name|scalar|objectOpen|arrayOpen) != 0 { e.out = append(e.out, ',') // For single-line output, add a random extra space after each // comma to make output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } } return } switch { case e.lastKind&(objectOpen|arrayOpen) != 0: // If next type is NOT closing, add indent and newline. if next&(objectClose|arrayClose) == 0 { e.indents = append(e.indents, e.indent...) e.out = append(e.out, '\n') e.out = append(e.out, e.indents...) } case e.lastKind&(scalar|objectClose|arrayClose) != 0: switch { // If next type is either a value or name, add comma and newline. case next&(name|scalar|objectOpen|arrayOpen) != 0: e.out = append(e.out, ',', '\n') // If next type is a closing object or array, adjust indentation. case next&(objectClose|arrayClose) != 0: e.indents = e.indents[:len(e.indents)-len(e.indent)] e.out = append(e.out, '\n') } e.out = append(e.out, e.indents...) case e.lastKind&name != 0: e.out = append(e.out, ' ') // For multi-line output, add a random extra space after key: to make // output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/messageset/messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package messageset encodes and decodes the obsolete MessageSet wire format. package messageset import ( "math" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) // The MessageSet wire format is equivalent to a message defined as follows, // where each Item defines an extension field with a field number of 'type_id' // and content of 'message'. MessageSet extensions must be non-repeated message // fields. // // message MessageSet { // repeated group Item = 1 { // required int32 type_id = 2; // required string message = 3; // } // } const ( FieldItem = protowire.Number(1) FieldTypeID = protowire.Number(2) FieldMessage = protowire.Number(3) ) // ExtensionName is the field name for extensions of MessageSet. // // A valid MessageSet extension must be of the form: // message MyMessage { // extend proto2.bridge.MessageSet { // optional MyMessage message_set_extension = 1234; // } // ... // } const ExtensionName = "message_set_extension" // IsMessageSet returns whether the message uses the MessageSet wire format. func IsMessageSet(md pref.MessageDescriptor) bool { xmd, ok := md.(interface{ IsMessageSet() bool }) return ok && xmd.IsMessageSet() } // IsMessageSetExtension reports this field properly extends a MessageSet. func IsMessageSetExtension(fd pref.FieldDescriptor) bool { switch { case fd.Name() != ExtensionName: return false case !IsMessageSet(fd.ContainingMessage()): return false case fd.FullName().Parent() != fd.Message().FullName(): return false } return true } // SizeField returns the size of a MessageSet item field containing an extension // with the given field number, not counting the contents of the message subfield. func SizeField(num protowire.Number) int { return 2*protowire.SizeTag(FieldItem) + protowire.SizeTag(FieldTypeID) + protowire.SizeVarint(uint64(num)) } // Unmarshal parses a MessageSet. // // It calls fn with the type ID and value of each item in the MessageSet. // Unknown fields are discarded. // // If wantLen is true, the item values include the varint length prefix. // This is ugly, but simplifies the fast-path decoder in internal/impl. func Unmarshal(b []byte, wantLen bool, fn func(typeID protowire.Number, value []byte) error) error { for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return protowire.ParseError(n) } b = b[n:] if num != FieldItem || wtyp != protowire.StartGroupType { n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return protowire.ParseError(n) } b = b[n:] continue } typeID, value, n, err := ConsumeFieldValue(b, wantLen) if err != nil { return err } b = b[n:] if typeID == 0 { continue } if err := fn(typeID, value); err != nil { return err } } return nil } // ConsumeFieldValue parses b as a MessageSet item field value until and including // the trailing end group marker. It assumes the start group tag has already been parsed. // It returns the contents of the type_id and message subfields and the total // item length. // // If wantLen is true, the returned message value includes the length prefix. func ConsumeFieldValue(b []byte, wantLen bool) (typeid protowire.Number, message []byte, n int, err error) { ilen := len(b) for { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] switch { case num == FieldItem && wtyp == protowire.EndGroupType: if wantLen && len(message) == 0 { // The message field was missing, which should never happen. // Be prepared for this case anyway. message = protowire.AppendVarint(message, 0) } return typeid, message, ilen - len(b), nil case num == FieldTypeID && wtyp == protowire.VarintType: v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] if v < 1 || v > math.MaxInt32 { return 0, nil, 0, errors.New("invalid type_id in message set") } typeid = protowire.Number(v) case num == FieldMessage && wtyp == protowire.BytesType: m, n := protowire.ConsumeBytes(b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } if message == nil { if wantLen { message = b[:n:n] } else { message = m[:len(m):len(m)] } } else { // This case should never happen in practice, but handle it for // correctness: The MessageSet item contains multiple message // fields, which need to be merged. // // In the case where we're returning the length, this becomes // quite inefficient since we need to strip the length off // the existing data and reconstruct it with the combined length. if wantLen { _, nn := protowire.ConsumeVarint(message) m0 := message[nn:] message = nil message = protowire.AppendVarint(message, uint64(len(m0)+len(m))) message = append(message, m0...) message = append(message, m...) } else { message = append(message, m...) } } b = b[n:] default: // We have no place to put it, so we just ignore unknown fields. n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return 0, nil, 0, protowire.ParseError(n) } b = b[n:] } } } // AppendFieldStart appends the start of a MessageSet item field containing // an extension with the given number. The caller must add the message // subfield (including the tag). func AppendFieldStart(b []byte, num protowire.Number) []byte { b = protowire.AppendTag(b, FieldItem, protowire.StartGroupType) b = protowire.AppendTag(b, FieldTypeID, protowire.VarintType) b = protowire.AppendVarint(b, uint64(num)) return b } // AppendFieldEnd appends the trailing end group marker for a MessageSet item field. func AppendFieldEnd(b []byte) []byte { return protowire.AppendTag(b, FieldItem, protowire.EndGroupType) } // SizeUnknown returns the size of an unknown fields section in MessageSet format. // // See AppendUnknown. func SizeUnknown(unknown []byte) (size int) { for len(unknown) > 0 { num, typ, n := protowire.ConsumeTag(unknown) if n < 0 || typ != protowire.BytesType { return 0 } unknown = unknown[n:] _, n = protowire.ConsumeBytes(unknown) if n < 0 { return 0 } unknown = unknown[n:] size += SizeField(num) + protowire.SizeTag(FieldMessage) + n } return size } // AppendUnknown appends unknown fields to b in MessageSet format. // // For historic reasons, unresolved items in a MessageSet are stored in a // message's unknown fields section in non-MessageSet format. That is, an // unknown item with typeID T and value V appears in the unknown fields as // a field with number T and value V. // // This function converts the unknown fields back into MessageSet form. func AppendUnknown(b, unknown []byte) ([]byte, error) { for len(unknown) > 0 { num, typ, n := protowire.ConsumeTag(unknown) if n < 0 || typ != protowire.BytesType { return nil, errors.New("invalid data in message set unknown fields") } unknown = unknown[n:] _, n = protowire.ConsumeBytes(unknown) if n < 0 { return nil, errors.New("invalid data in message set unknown fields") } b = AppendFieldStart(b, num) b = protowire.AppendTag(b, FieldMessage, protowire.BytesType) b = append(b, unknown[:n]...) b = AppendFieldEnd(b) unknown = unknown[n:] } return b, nil } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package tag marshals and unmarshals the legacy struct tags as generated // by historical versions of protoc-gen-go. package tag import ( "reflect" "strconv" "strings" defval "google.golang.org/protobuf/internal/encoding/defval" fdesc "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) var byteType = reflect.TypeOf(byte(0)) // Unmarshal decodes the tag into a prototype.Field. // // The goType is needed to determine the original protoreflect.Kind since the // tag does not record sufficient information to determine that. // The type is the underlying field type (e.g., a repeated field may be // represented by []T, but the Go type passed in is just T). // A list of enum value descriptors must be provided for enum fields. // This does not populate the Enum or Message (except for weak message). // // This function is a best effort attempt; parsing errors are ignored. func Unmarshal(tag string, goType reflect.Type, evs pref.EnumValueDescriptors) pref.FieldDescriptor { f := new(fdesc.Field) f.L0.ParentFile = fdesc.SurrogateProto2 for len(tag) > 0 { i := strings.IndexByte(tag, ',') if i < 0 { i = len(tag) } switch s := tag[:i]; { case strings.HasPrefix(s, "name="): f.L0.FullName = pref.FullName(s[len("name="):]) case strings.Trim(s, "0123456789") == "": n, _ := strconv.ParseUint(s, 10, 32) f.L1.Number = pref.FieldNumber(n) case s == "opt": f.L1.Cardinality = pref.Optional case s == "req": f.L1.Cardinality = pref.Required case s == "rep": f.L1.Cardinality = pref.Repeated case s == "varint": switch goType.Kind() { case reflect.Bool: f.L1.Kind = pref.BoolKind case reflect.Int32: f.L1.Kind = pref.Int32Kind case reflect.Int64: f.L1.Kind = pref.Int64Kind case reflect.Uint32: f.L1.Kind = pref.Uint32Kind case reflect.Uint64: f.L1.Kind = pref.Uint64Kind } case s == "zigzag32": if goType.Kind() == reflect.Int32 { f.L1.Kind = pref.Sint32Kind } case s == "zigzag64": if goType.Kind() == reflect.Int64 { f.L1.Kind = pref.Sint64Kind } case s == "fixed32": switch goType.Kind() { case reflect.Int32: f.L1.Kind = pref.Sfixed32Kind case reflect.Uint32: f.L1.Kind = pref.Fixed32Kind case reflect.Float32: f.L1.Kind = pref.FloatKind } case s == "fixed64": switch goType.Kind() { case reflect.Int64: f.L1.Kind = pref.Sfixed64Kind case reflect.Uint64: f.L1.Kind = pref.Fixed64Kind case reflect.Float64: f.L1.Kind = pref.DoubleKind } case s == "bytes": switch { case goType.Kind() == reflect.String: f.L1.Kind = pref.StringKind case goType.Kind() == reflect.Slice && goType.Elem() == byteType: f.L1.Kind = pref.BytesKind default: f.L1.Kind = pref.MessageKind } case s == "group": f.L1.Kind = pref.GroupKind case strings.HasPrefix(s, "enum="): f.L1.Kind = pref.EnumKind case strings.HasPrefix(s, "json="): jsonName := s[len("json="):] if jsonName != strs.JSONCamelCase(string(f.L0.FullName.Name())) { f.L1.StringName.InitJSON(jsonName) } case s == "packed": f.L1.HasPacked = true f.L1.IsPacked = true case strings.HasPrefix(s, "weak="): f.L1.IsWeak = true f.L1.Message = fdesc.PlaceholderMessage(pref.FullName(s[len("weak="):])) case strings.HasPrefix(s, "def="): // The default tag is special in that everything afterwards is the // default regardless of the presence of commas. s, i = tag[len("def="):], len(tag) v, ev, _ := defval.Unmarshal(s, f.L1.Kind, evs, defval.GoTag) f.L1.Default = fdesc.DefaultValue(v, ev) case s == "proto3": f.L0.ParentFile = fdesc.SurrogateProto3 } tag = strings.TrimPrefix(tag[i:], ",") } // The generator uses the group message name instead of the field name. // We obtain the real field name by lowercasing the group name. if f.L1.Kind == pref.GroupKind { f.L0.FullName = pref.FullName(strings.ToLower(string(f.L0.FullName))) } return f } // Marshal encodes the protoreflect.FieldDescriptor as a tag. // // The enumName must be provided if the kind is an enum. // Historically, the formulation of the enum "name" was the proto package // dot-concatenated with the generated Go identifier for the enum type. // Depending on the context on how Marshal is called, there are different ways // through which that information is determined. As such it is the caller's // responsibility to provide a function to obtain that information. func Marshal(fd pref.FieldDescriptor, enumName string) string { var tag []string switch fd.Kind() { case pref.BoolKind, pref.EnumKind, pref.Int32Kind, pref.Uint32Kind, pref.Int64Kind, pref.Uint64Kind: tag = append(tag, "varint") case pref.Sint32Kind: tag = append(tag, "zigzag32") case pref.Sint64Kind: tag = append(tag, "zigzag64") case pref.Sfixed32Kind, pref.Fixed32Kind, pref.FloatKind: tag = append(tag, "fixed32") case pref.Sfixed64Kind, pref.Fixed64Kind, pref.DoubleKind: tag = append(tag, "fixed64") case pref.StringKind, pref.BytesKind, pref.MessageKind: tag = append(tag, "bytes") case pref.GroupKind: tag = append(tag, "group") } tag = append(tag, strconv.Itoa(int(fd.Number()))) switch fd.Cardinality() { case pref.Optional: tag = append(tag, "opt") case pref.Required: tag = append(tag, "req") case pref.Repeated: tag = append(tag, "rep") } if fd.IsPacked() { tag = append(tag, "packed") } name := string(fd.Name()) if fd.Kind() == pref.GroupKind { // The name of the FieldDescriptor for a group field is // lowercased. To find the original capitalization, we // look in the field's MessageType. name = string(fd.Message().Name()) } tag = append(tag, "name="+name) if jsonName := fd.JSONName(); jsonName != "" && jsonName != name && !fd.IsExtension() { // NOTE: The jsonName != name condition is suspect, but it preserve // the exact same semantics from the previous generator. tag = append(tag, "json="+jsonName) } if fd.IsWeak() { tag = append(tag, "weak="+string(fd.Message().FullName())) } // The previous implementation does not tag extension fields as proto3, // even when the field is defined in a proto3 file. Match that behavior // for consistency. if fd.Syntax() == pref.Proto3 && !fd.IsExtension() { tag = append(tag, "proto3") } if fd.Kind() == pref.EnumKind && enumName != "" { tag = append(tag, "enum="+enumName) } if fd.ContainingOneof() != nil { tag = append(tag, "oneof") } // This must appear last in the tag, since commas in strings aren't escaped. if fd.HasDefault() { def, _ := defval.Marshal(fd.Default(), fd.DefaultEnumValue(), fd.Kind(), defval.GoTag) tag = append(tag, "def="+def) } return strings.Join(tag, ",") } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "fmt" "io" "regexp" "strconv" "unicode/utf8" "google.golang.org/protobuf/internal/errors" ) // Decoder is a token-based textproto decoder. type Decoder struct { // lastCall is last method called, either readCall or peekCall. // Initial value is readCall. lastCall call // lastToken contains the last read token. lastToken Token // lastErr contains the last read error. lastErr error // openStack is a stack containing the byte characters for MessageOpen and // ListOpen kinds. The top of stack represents the message or the list that // the current token is nested in. An empty stack means the current token is // at the top level message. The characters '{' and '<' both represent the // MessageOpen kind. openStack []byte // orig is used in reporting line and column. orig []byte // in contains the unconsumed input. in []byte } // NewDecoder returns a Decoder to read the given []byte. func NewDecoder(b []byte) *Decoder { return &Decoder{orig: b, in: b} } // ErrUnexpectedEOF means that EOF was encountered in the middle of the input. var ErrUnexpectedEOF = errors.New("%v", io.ErrUnexpectedEOF) // call specifies which Decoder method was invoked. type call uint8 const ( readCall call = iota peekCall ) // Peek looks ahead and returns the next token and error without advancing a read. func (d *Decoder) Peek() (Token, error) { defer func() { d.lastCall = peekCall }() if d.lastCall == readCall { d.lastToken, d.lastErr = d.Read() } return d.lastToken, d.lastErr } // Read returns the next token. // It will return an error if there is no valid token. func (d *Decoder) Read() (Token, error) { defer func() { d.lastCall = readCall }() if d.lastCall == peekCall { return d.lastToken, d.lastErr } tok, err := d.parseNext(d.lastToken.kind) if err != nil { return Token{}, err } switch tok.kind { case comma, semicolon: tok, err = d.parseNext(tok.kind) if err != nil { return Token{}, err } } d.lastToken = tok return tok, nil } const ( mismatchedFmt = "mismatched close character %q" unexpectedFmt = "unexpected character %q" ) // parseNext parses the next Token based on given last kind. func (d *Decoder) parseNext(lastKind Kind) (Token, error) { // Trim leading spaces. d.consume(0) isEOF := false if len(d.in) == 0 { isEOF = true } switch lastKind { case EOF: return d.consumeToken(EOF, 0, 0), nil case bof: // Start of top level message. Next token can be EOF or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } return d.parseFieldName() case Name: // Next token can be MessageOpen, ListOpen or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil case '[': d.pushOpenStack(ch) return d.consumeToken(ListOpen, 1, 0), nil default: return d.parseScalar() } case Scalar: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch d.in[0] { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case ListOpen: // Next token can be ListClose or comma. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case ']': d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case ',': return d.consumeToken(comma, 1, 0), nil default: return Token{}, d.newSyntaxError(unexpectedFmt, ch) } } case MessageOpen: // Next token can be MessageClose or Name. if isEOF { return Token{}, ErrUnexpectedEOF } _, closeCh := d.currentOpenKind() switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) default: return d.parseFieldName() } case MessageClose: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch ch := d.in[0]; ch { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case ListOpen: // Next token can be ListClose or comma if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case ',': return d.consumeToken(comma, 1, 0), nil default: return Token{}, d.newSyntaxError(unexpectedFmt, ch) } } case ListOpen: // Next token can be ListClose, MessageStart or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case ']': d.popOpenStack() return d.consumeToken(ListClose, 1, 0), nil case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil default: return d.parseScalar() } case ListClose: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. // Next token can be EOF, comma, semicolon or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } switch ch := d.in[0]; ch { case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } case MessageOpen: // Next token can be MessageClose, comma, semicolon or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) case ',': return d.consumeToken(comma, 1, 0), nil case ';': return d.consumeToken(semicolon, 1, 0), nil default: return d.parseFieldName() } default: // It is not possible to have this case. Let it panic below. } case comma, semicolon: openKind, closeCh := d.currentOpenKind() switch openKind { case bof: // Top level message. Next token can be EOF or Name. if isEOF { return d.consumeToken(EOF, 0, 0), nil } return d.parseFieldName() case MessageOpen: // Next token can be MessageClose or Name. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case closeCh: d.popOpenStack() return d.consumeToken(MessageClose, 1, 0), nil case otherCloseChar[closeCh]: return Token{}, d.newSyntaxError(mismatchedFmt, ch) default: return d.parseFieldName() } case ListOpen: if lastKind == semicolon { // It is not be possible to have this case as logic here // should not have produced a semicolon Token when inside a // list. Let it panic below. break } // Next token can be MessageOpen or Scalar. if isEOF { return Token{}, ErrUnexpectedEOF } switch ch := d.in[0]; ch { case '{', '<': d.pushOpenStack(ch) return d.consumeToken(MessageOpen, 1, 0), nil default: return d.parseScalar() } } } line, column := d.Position(len(d.orig) - len(d.in)) panic(fmt.Sprintf("Decoder.parseNext: bug at handling line %d:%d with lastKind=%v", line, column, lastKind)) } var otherCloseChar = map[byte]byte{ '}': '>', '>': '}', } // currentOpenKind indicates whether current position is inside a message, list // or top-level message by returning MessageOpen, ListOpen or bof respectively. // If the returned kind is either a MessageOpen or ListOpen, it also returns the // corresponding closing character. func (d *Decoder) currentOpenKind() (Kind, byte) { if len(d.openStack) == 0 { return bof, 0 } openCh := d.openStack[len(d.openStack)-1] switch openCh { case '{': return MessageOpen, '}' case '<': return MessageOpen, '>' case '[': return ListOpen, ']' } panic(fmt.Sprintf("Decoder: openStack contains invalid byte %s", string(openCh))) } func (d *Decoder) pushOpenStack(ch byte) { d.openStack = append(d.openStack, ch) } func (d *Decoder) popOpenStack() { d.openStack = d.openStack[:len(d.openStack)-1] } // parseFieldName parses field name and separator. func (d *Decoder) parseFieldName() (tok Token, err error) { defer func() { if err == nil && d.tryConsumeChar(':') { tok.attrs |= hasSeparator } }() // Extension or Any type URL. if d.in[0] == '[' { return d.parseTypeName() } // Identifier. if size := parseIdent(d.in, false); size > 0 { return d.consumeToken(Name, size, uint8(IdentName)), nil } // Field number. Identify if input is a valid number that is not negative // and is decimal integer within 32-bit range. if num := parseNumber(d.in); num.size > 0 { if !num.neg && num.kind == numDec { if _, err := strconv.ParseInt(string(d.in[:num.size]), 10, 32); err == nil { return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil } } return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) } return Token{}, d.newSyntaxError("invalid field name: %s", errRegexp.Find(d.in)) } // parseTypeName parses Any type URL or extension field name. The name is // enclosed in [ and ] characters. The C++ parser does not handle many legal URL // strings. This implementation is more liberal and allows for the pattern // ^[-_a-zA-Z0-9]+([./][-_a-zA-Z0-9]+)*`). Whitespaces and comments are allowed // in between [ ], '.', '/' and the sub names. func (d *Decoder) parseTypeName() (Token, error) { startPos := len(d.orig) - len(d.in) // Use alias s to advance first in order to use d.in for error handling. // Caller already checks for [ as first character. s := consume(d.in[1:], 0) if len(s) == 0 { return Token{}, ErrUnexpectedEOF } var name []byte for len(s) > 0 && isTypeNameChar(s[0]) { name = append(name, s[0]) s = s[1:] } s = consume(s, 0) var closed bool for len(s) > 0 && !closed { switch { case s[0] == ']': s = s[1:] closed = true case s[0] == '/', s[0] == '.': if len(name) > 0 && (name[len(name)-1] == '/' || name[len(name)-1] == '.') { return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1]) } name = append(name, s[0]) s = s[1:] s = consume(s, 0) for len(s) > 0 && isTypeNameChar(s[0]) { name = append(name, s[0]) s = s[1:] } s = consume(s, 0) default: return Token{}, d.newSyntaxError( "invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)+1]) } } if !closed { return Token{}, ErrUnexpectedEOF } // First character cannot be '.'. Last character cannot be '.' or '/'. size := len(name) if size == 0 || name[0] == '.' || name[size-1] == '.' || name[size-1] == '/' { return Token{}, d.newSyntaxError("invalid type URL/extension field name: %s", d.orig[startPos:len(d.orig)-len(s)]) } d.in = s endPos := len(d.orig) - len(d.in) d.consume(0) return Token{ kind: Name, attrs: uint8(TypeName), pos: startPos, raw: d.orig[startPos:endPos], str: string(name), }, nil } func isTypeNameChar(b byte) bool { return (b == '-' || b == '_' || ('0' <= b && b <= '9') || ('a' <= b && b <= 'z') || ('A' <= b && b <= 'Z')) } func isWhiteSpace(b byte) bool { switch b { case ' ', '\n', '\r', '\t': return true default: return false } } // parseIdent parses an unquoted proto identifier and returns size. // If allowNeg is true, it allows '-' to be the first character in the // identifier. This is used when parsing literal values like -infinity, etc. // Regular expression matches an identifier: `^[_a-zA-Z][_a-zA-Z0-9]*` func parseIdent(input []byte, allowNeg bool) int { var size int s := input if len(s) == 0 { return 0 } if allowNeg && s[0] == '-' { s = s[1:] size++ if len(s) == 0 { return 0 } } switch { case s[0] == '_', 'a' <= s[0] && s[0] <= 'z', 'A' <= s[0] && s[0] <= 'Z': s = s[1:] size++ default: return 0 } for len(s) > 0 && (s[0] == '_' || 'a' <= s[0] && s[0] <= 'z' || 'A' <= s[0] && s[0] <= 'Z' || '0' <= s[0] && s[0] <= '9') { s = s[1:] size++ } if len(s) > 0 && !isDelim(s[0]) { return 0 } return size } // parseScalar parses for a string, literal or number value. func (d *Decoder) parseScalar() (Token, error) { if d.in[0] == '"' || d.in[0] == '\'' { return d.parseStringValue() } if tok, ok := d.parseLiteralValue(); ok { return tok, nil } if tok, ok := d.parseNumberValue(); ok { return tok, nil } return Token{}, d.newSyntaxError("invalid scalar value: %s", errRegexp.Find(d.in)) } // parseLiteralValue parses a literal value. A literal value is used for // bools, special floats and enums. This function simply identifies that the // field value is a literal. func (d *Decoder) parseLiteralValue() (Token, bool) { size := parseIdent(d.in, true) if size == 0 { return Token{}, false } return d.consumeToken(Scalar, size, literalValue), true } // consumeToken constructs a Token for given Kind from d.in and consumes given // size-length from it. func (d *Decoder) consumeToken(kind Kind, size int, attrs uint8) Token { // Important to compute raw and pos before consuming. tok := Token{ kind: kind, attrs: attrs, pos: len(d.orig) - len(d.in), raw: d.in[:size], } d.consume(size) return tok } // newSyntaxError returns a syntax error with line and column information for // current position. func (d *Decoder) newSyntaxError(f string, x ...interface{}) error { e := errors.New(f, x...) line, column := d.Position(len(d.orig) - len(d.in)) return errors.New("syntax error (line %d:%d): %v", line, column, e) } // Position returns line and column number of given index of the original input. // It will panic if index is out of range. func (d *Decoder) Position(idx int) (line int, column int) { b := d.orig[:idx] line = bytes.Count(b, []byte("\n")) + 1 if i := bytes.LastIndexByte(b, '\n'); i >= 0 { b = b[i+1:] } column = utf8.RuneCount(b) + 1 // ignore multi-rune characters return line, column } func (d *Decoder) tryConsumeChar(c byte) bool { if len(d.in) > 0 && d.in[0] == c { d.consume(1) return true } return false } // consume consumes n bytes of input and any subsequent whitespace or comments. func (d *Decoder) consume(n int) { d.in = consume(d.in, n) return } // consume consumes n bytes of input and any subsequent whitespace or comments. func consume(b []byte, n int) []byte { b = b[n:] for len(b) > 0 { switch b[0] { case ' ', '\n', '\r', '\t': b = b[1:] case '#': if i := bytes.IndexByte(b, '\n'); i >= 0 { b = b[i+len("\n"):] } else { b = nil } default: return b } } return b } // Any sequence that looks like a non-delimiter (for error reporting). var errRegexp = regexp.MustCompile(`^([-+._a-zA-Z0-9\/]+|.)`) // isDelim returns true if given byte is a delimiter character. func isDelim(c byte) bool { return !(c == '-' || c == '+' || c == '.' || c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9')) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text // parseNumberValue parses a number from the input and returns a Token object. func (d *Decoder) parseNumberValue() (Token, bool) { in := d.in num := parseNumber(in) if num.size == 0 { return Token{}, false } numAttrs := num.kind if num.neg { numAttrs |= isNegative } strSize := num.size last := num.size - 1 if num.kind == numFloat && (d.in[last] == 'f' || d.in[last] == 'F') { strSize = last } tok := Token{ kind: Scalar, attrs: numberValue, pos: len(d.orig) - len(d.in), raw: d.in[:num.size], str: string(d.in[:strSize]), numAttrs: numAttrs, } d.consume(num.size) return tok, true } const ( numDec uint8 = (1 << iota) / 2 numHex numOct numFloat ) // number is the result of parsing out a valid number from parseNumber. It // contains data for doing float or integer conversion via the strconv package // in conjunction with the input bytes. type number struct { kind uint8 neg bool size int } // parseNumber constructs a number object from given input. It allows for the // following patterns: // integer: ^-?([1-9][0-9]*|0[xX][0-9a-fA-F]+|0[0-7]*) // float: ^-?((0|[1-9][0-9]*)?([.][0-9]*)?([eE][+-]?[0-9]+)?[fF]?) // It also returns the number of parsed bytes for the given number, 0 if it is // not a number. func parseNumber(input []byte) number { kind := numDec var size int var neg bool s := input if len(s) == 0 { return number{} } // Optional - if s[0] == '-' { neg = true s = s[1:] size++ if len(s) == 0 { return number{} } } // C++ allows for whitespace and comments in between the negative sign and // the rest of the number. This logic currently does not but is consistent // with v1. switch { case s[0] == '0': if len(s) > 1 { switch { case s[1] == 'x' || s[1] == 'X': // Parse as hex number. kind = numHex n := 2 s = s[2:] for len(s) > 0 && (('0' <= s[0] && s[0] <= '9') || ('a' <= s[0] && s[0] <= 'f') || ('A' <= s[0] && s[0] <= 'F')) { s = s[1:] n++ } if n == 2 { return number{} } size += n case '0' <= s[1] && s[1] <= '7': // Parse as octal number. kind = numOct n := 2 s = s[2:] for len(s) > 0 && '0' <= s[0] && s[0] <= '7' { s = s[1:] n++ } size += n } if kind&(numHex|numOct) > 0 { if len(s) > 0 && !isDelim(s[0]) { return number{} } return number{kind: kind, neg: neg, size: size} } } s = s[1:] size++ case '1' <= s[0] && s[0] <= '9': n := 1 s = s[1:] for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n case s[0] == '.': // Set kind to numFloat to signify the intent to parse as float. And // that it needs to have other digits after '.'. kind = numFloat default: return number{} } // . followed by 0 or more digits. if len(s) > 0 && s[0] == '.' { n := 1 s = s[1:] // If decimal point was before any digits, it should be followed by // other digits. if len(s) == 0 && kind == numFloat { return number{} } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n kind = numFloat } // e or E followed by an optional - or + and 1 or more digits. if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') { kind = numFloat s = s[1:] n := 1 if s[0] == '+' || s[0] == '-' { s = s[1:] n++ if len(s) == 0 { return number{} } } for len(s) > 0 && '0' <= s[0] && s[0] <= '9' { s = s[1:] n++ } size += n } // Optional suffix f or F for floats. if len(s) > 0 && (s[0] == 'f' || s[0] == 'F') { kind = numFloat s = s[1:] size++ } // Check that next byte is a delimiter or it is at the end. if len(s) > 0 && !isDelim(s[0]) { return number{} } return number{kind: kind, neg: neg, size: size} } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/decode_string.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "strconv" "strings" "unicode" "unicode/utf16" "unicode/utf8" "google.golang.org/protobuf/internal/strs" ) // parseStringValue parses string field token. // This differs from parseString since the text format allows // multiple back-to-back string literals where they are semantically treated // as a single large string with all values concatenated. // // E.g., `"foo" "bar" "baz"` => "foobarbaz" func (d *Decoder) parseStringValue() (Token, error) { // Note that the ending quote is sufficient to unambiguously mark the end // of a string. Thus, the text grammar does not require intervening // whitespace or control characters in-between strings. // Thus, the following is valid: // `"foo"'bar'"baz"` => "foobarbaz" in0 := d.in var ss []string for len(d.in) > 0 && (d.in[0] == '"' || d.in[0] == '\'') { s, err := d.parseString() if err != nil { return Token{}, err } ss = append(ss, s) } // d.in already points to the end of the value at this point. return Token{ kind: Scalar, attrs: stringValue, pos: len(d.orig) - len(in0), raw: in0[:len(in0)-len(d.in)], str: strings.Join(ss, ""), }, nil } // parseString parses a string value enclosed in " or '. func (d *Decoder) parseString() (string, error) { in := d.in if len(in) == 0 { return "", ErrUnexpectedEOF } quote := in[0] in = in[1:] i := indexNeedEscapeInBytes(in) in, out := in[i:], in[:i:i] // set cap to prevent mutations for len(in) > 0 { switch r, n := utf8.DecodeRune(in); { case r == utf8.RuneError && n == 1: return "", d.newSyntaxError("invalid UTF-8 detected") case r == 0 || r == '\n': return "", d.newSyntaxError("invalid character %q in string", r) case r == rune(quote): in = in[1:] d.consume(len(d.in) - len(in)) return string(out), nil case r == '\\': if len(in) < 2 { return "", ErrUnexpectedEOF } switch r := in[1]; r { case '"', '\'', '\\', '?': in, out = in[2:], append(out, r) case 'a': in, out = in[2:], append(out, '\a') case 'b': in, out = in[2:], append(out, '\b') case 'n': in, out = in[2:], append(out, '\n') case 'r': in, out = in[2:], append(out, '\r') case 't': in, out = in[2:], append(out, '\t') case 'v': in, out = in[2:], append(out, '\v') case 'f': in, out = in[2:], append(out, '\f') case '0', '1', '2', '3', '4', '5', '6', '7': // One, two, or three octal characters. n := len(in[1:]) - len(bytes.TrimLeft(in[1:], "01234567")) if n > 3 { n = 3 } v, err := strconv.ParseUint(string(in[1:1+n]), 8, 8) if err != nil { return "", d.newSyntaxError("invalid octal escape code %q in string", in[:1+n]) } in, out = in[1+n:], append(out, byte(v)) case 'x': // One or two hexadecimal characters. n := len(in[2:]) - len(bytes.TrimLeft(in[2:], "0123456789abcdefABCDEF")) if n > 2 { n = 2 } v, err := strconv.ParseUint(string(in[2:2+n]), 16, 8) if err != nil { return "", d.newSyntaxError("invalid hex escape code %q in string", in[:2+n]) } in, out = in[2+n:], append(out, byte(v)) case 'u', 'U': // Four or eight hexadecimal characters n := 6 if r == 'U' { n = 10 } if len(in) < n { return "", ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:n]), 16, 32) if utf8.MaxRune < v || err != nil { return "", d.newSyntaxError("invalid Unicode escape code %q in string", in[:n]) } in = in[n:] r := rune(v) if utf16.IsSurrogate(r) { if len(in) < 6 { return "", ErrUnexpectedEOF } v, err := strconv.ParseUint(string(in[2:6]), 16, 16) r = utf16.DecodeRune(r, rune(v)) if in[0] != '\\' || in[1] != 'u' || r == unicode.ReplacementChar || err != nil { return "", d.newSyntaxError("invalid Unicode escape code %q in string", in[:6]) } in = in[6:] } out = append(out, string(r)...) default: return "", d.newSyntaxError("invalid escape code %q in string", in[:2]) } default: i := indexNeedEscapeInBytes(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } return "", ErrUnexpectedEOF } // indexNeedEscapeInString returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInBytes(b []byte) int { return indexNeedEscapeInString(strs.UnsafeString(b)) } // UnmarshalString returns an unescaped string given a textproto string value. // String value needs to contain single or double quotes. This is only used by // internal/encoding/defval package for unmarshaling bytes. func UnmarshalString(s string) (string, error) { d := NewDecoder([]byte(s)) return d.parseString() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/decode_token.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "bytes" "fmt" "math" "strconv" "strings" "google.golang.org/protobuf/internal/flags" ) // Kind represents a token kind expressible in the textproto format. type Kind uint8 // Kind values. const ( Invalid Kind = iota EOF Name // Name indicates the field name. Scalar // Scalar are scalar values, e.g. "string", 47, ENUM_LITERAL, true. MessageOpen MessageClose ListOpen ListClose // comma and semi-colon are only for parsing in between values and should not be exposed. comma semicolon // bof indicates beginning of file, which is the default token // kind at the beginning of parsing. bof = Invalid ) func (t Kind) String() string { switch t { case Invalid: return "" case EOF: return "eof" case Scalar: return "scalar" case Name: return "name" case MessageOpen: return "{" case MessageClose: return "}" case ListOpen: return "[" case ListClose: return "]" case comma: return "," case semicolon: return ";" default: return fmt.Sprintf("", uint8(t)) } } // NameKind represents different types of field names. type NameKind uint8 // NameKind values. const ( IdentName NameKind = iota + 1 TypeName FieldNumber ) func (t NameKind) String() string { switch t { case IdentName: return "IdentName" case TypeName: return "TypeName" case FieldNumber: return "FieldNumber" default: return fmt.Sprintf("", uint8(t)) } } // Bit mask in Token.attrs to indicate if a Name token is followed by the // separator char ':'. The field name separator char is optional for message // field or repeated message field, but required for all other types. Decoder // simply indicates whether a Name token is followed by separator or not. It is // up to the prototext package to validate. const hasSeparator = 1 << 7 // Scalar value types. const ( numberValue = iota + 1 stringValue literalValue ) // Bit mask in Token.numAttrs to indicate that the number is a negative. const isNegative = 1 << 7 // Token provides a parsed token kind and value. Values are provided by the // different accessor methods. type Token struct { // Kind of the Token object. kind Kind // attrs contains metadata for the following Kinds: // Name: hasSeparator bit and one of NameKind. // Scalar: one of numberValue, stringValue, literalValue. attrs uint8 // numAttrs contains metadata for numberValue: // - highest bit is whether negative or positive. // - lower bits indicate one of numDec, numHex, numOct, numFloat. numAttrs uint8 // pos provides the position of the token in the original input. pos int // raw bytes of the serialized token. // This is a subslice into the original input. raw []byte // str contains parsed string for the following: // - stringValue of Scalar kind // - numberValue of Scalar kind // - TypeName of Name kind str string } // Kind returns the token kind. func (t Token) Kind() Kind { return t.kind } // RawString returns the read value in string. func (t Token) RawString() string { return string(t.raw) } // Pos returns the token position from the input. func (t Token) Pos() int { return t.pos } // NameKind returns IdentName, TypeName or FieldNumber. // It panics if type is not Name. func (t Token) NameKind() NameKind { if t.kind == Name { return NameKind(t.attrs &^ hasSeparator) } panic(fmt.Sprintf("Token is not a Name type: %s", t.kind)) } // HasSeparator returns true if the field name is followed by the separator char // ':', else false. It panics if type is not Name. func (t Token) HasSeparator() bool { if t.kind == Name { return t.attrs&hasSeparator != 0 } panic(fmt.Sprintf("Token is not a Name type: %s", t.kind)) } // IdentName returns the value for IdentName type. func (t Token) IdentName() string { if t.kind == Name && t.attrs&uint8(IdentName) != 0 { return string(t.raw) } panic(fmt.Sprintf("Token is not an IdentName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // TypeName returns the value for TypeName type. func (t Token) TypeName() string { if t.kind == Name && t.attrs&uint8(TypeName) != 0 { return t.str } panic(fmt.Sprintf("Token is not a TypeName: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // FieldNumber returns the value for FieldNumber type. It returns a // non-negative int32 value. Caller will still need to validate for the correct // field number range. func (t Token) FieldNumber() int32 { if t.kind != Name || t.attrs&uint8(FieldNumber) == 0 { panic(fmt.Sprintf("Token is not a FieldNumber: %s:%s", t.kind, NameKind(t.attrs&^hasSeparator))) } // Following should not return an error as it had already been called right // before this Token was constructed. num, _ := strconv.ParseInt(string(t.raw), 10, 32) return int32(num) } // String returns the string value for a Scalar type. func (t Token) String() (string, bool) { if t.kind != Scalar || t.attrs != stringValue { return "", false } return t.str, true } // Enum returns the literal value for a Scalar type for use as enum literals. func (t Token) Enum() (string, bool) { if t.kind != Scalar || t.attrs != literalValue || (len(t.raw) > 0 && t.raw[0] == '-') { return "", false } return string(t.raw), true } // Bool returns the bool value for a Scalar type. func (t Token) Bool() (bool, bool) { if t.kind != Scalar { return false, false } switch t.attrs { case literalValue: if b, ok := boolLits[string(t.raw)]; ok { return b, true } case numberValue: // Unsigned integer representation of 0 or 1 is permitted: 00, 0x0, 01, // 0x1, etc. n, err := strconv.ParseUint(t.str, 0, 64) if err == nil { switch n { case 0: return false, true case 1: return true, true } } } return false, false } // These exact boolean literals are the ones supported in C++. var boolLits = map[string]bool{ "t": true, "true": true, "True": true, "f": false, "false": false, "False": false, } // Uint64 returns the uint64 value for a Scalar type. func (t Token) Uint64() (uint64, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 { return 0, false } n, err := strconv.ParseUint(t.str, 0, 64) if err != nil { return 0, false } return n, true } // Uint32 returns the uint32 value for a Scalar type. func (t Token) Uint32() (uint32, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&isNegative > 0 || t.numAttrs&numFloat > 0 { return 0, false } n, err := strconv.ParseUint(t.str, 0, 32) if err != nil { return 0, false } return uint32(n), true } // Int64 returns the int64 value for a Scalar type. func (t Token) Int64() (int64, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 { return 0, false } if n, err := strconv.ParseInt(t.str, 0, 64); err == nil { return n, true } // C++ accepts large positive hex numbers as negative values. // This feature is here for proto1 backwards compatibility purposes. if flags.ProtoLegacy && (t.numAttrs == numHex) { if n, err := strconv.ParseUint(t.str, 0, 64); err == nil { return int64(n), true } } return 0, false } // Int32 returns the int32 value for a Scalar type. func (t Token) Int32() (int32, bool) { if t.kind != Scalar || t.attrs != numberValue || t.numAttrs&numFloat > 0 { return 0, false } if n, err := strconv.ParseInt(t.str, 0, 32); err == nil { return int32(n), true } // C++ accepts large positive hex numbers as negative values. // This feature is here for proto1 backwards compatibility purposes. if flags.ProtoLegacy && (t.numAttrs == numHex) { if n, err := strconv.ParseUint(t.str, 0, 32); err == nil { return int32(n), true } } return 0, false } // Float64 returns the float64 value for a Scalar type. func (t Token) Float64() (float64, bool) { if t.kind != Scalar { return 0, false } switch t.attrs { case literalValue: if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok { return f, true } case numberValue: n, err := strconv.ParseFloat(t.str, 64) if err == nil { return n, true } nerr := err.(*strconv.NumError) if nerr.Err == strconv.ErrRange { return n, true } } return 0, false } // Float32 returns the float32 value for a Scalar type. func (t Token) Float32() (float32, bool) { if t.kind != Scalar { return 0, false } switch t.attrs { case literalValue: if f, ok := floatLits[strings.ToLower(string(t.raw))]; ok { return float32(f), true } case numberValue: n, err := strconv.ParseFloat(t.str, 64) if err == nil { // Overflows are treated as (-)infinity. return float32(n), true } nerr := err.(*strconv.NumError) if nerr.Err == strconv.ErrRange { return float32(n), true } } return 0, false } // These are the supported float literals which C++ permits case-insensitive // variants of these. var floatLits = map[string]float64{ "nan": math.NaN(), "inf": math.Inf(1), "infinity": math.Inf(1), "-inf": math.Inf(-1), "-infinity": math.Inf(-1), } // TokenEquals returns true if given Tokens are equal, else false. func TokenEquals(x, y Token) bool { return x.kind == y.kind && x.attrs == y.attrs && x.numAttrs == y.numAttrs && x.pos == y.pos && bytes.Equal(x.raw, y.raw) && x.str == y.str } ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/doc.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package text implements the text format for protocol buffers. // This package has no semantic understanding for protocol buffers and is only // a parser and composer for the format. // // There is no formal specification for the protobuf text format, as such the // C++ implementation (see google::protobuf::TextFormat) is the reference // implementation of the text format. // // This package is neither a superset nor a subset of the C++ implementation. // This implementation permits a more liberal grammar in some cases to be // backwards compatible with the historical Go implementation. // Future parsings unique to Go should not be added. // Some grammars allowed by the C++ implementation are deliberately // not implemented here because they are considered a bug by the protobuf team // and should not be replicated. // // The Go implementation should implement a sufficient amount of the C++ // grammar such that the default text serialization by C++ can be parsed by Go. // However, just because the C++ parser accepts some input does not mean that // the Go implementation should as well. // // The text format is almost a superset of JSON except: // * message keys are not quoted strings, but identifiers // * the top-level value must be a message without the delimiters package text ================================================ FILE: vendor/google.golang.org/protobuf/internal/encoding/text/encode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package text import ( "math" "math/bits" "strconv" "strings" "unicode/utf8" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/errors" ) // encType represents an encoding type. type encType uint8 const ( _ encType = (1 << iota) / 2 name scalar messageOpen messageClose ) // Encoder provides methods to write out textproto constructs and values. The user is // responsible for producing valid sequences of constructs and values. type Encoder struct { encoderState indent string delims [2]byte outputASCII bool } type encoderState struct { lastType encType indents []byte out []byte } // NewEncoder returns an Encoder. // // If indent is a non-empty string, it causes every entry in a List or Message // to be preceded by the indent and trailed by a newline. // // If delims is not the zero value, it controls the delimiter characters used // for messages (e.g., "{}" vs "<>"). // // If outputASCII is true, strings will be serialized in such a way that // multi-byte UTF-8 sequences are escaped. This property ensures that the // overall output is ASCII (as opposed to UTF-8). func NewEncoder(indent string, delims [2]byte, outputASCII bool) (*Encoder, error) { e := &Encoder{} if len(indent) > 0 { if strings.Trim(indent, " \t") != "" { return nil, errors.New("indent may only be composed of space and tab characters") } e.indent = indent } switch delims { case [2]byte{0, 0}: e.delims = [2]byte{'{', '}'} case [2]byte{'{', '}'}, [2]byte{'<', '>'}: e.delims = delims default: return nil, errors.New("delimiters may only be \"{}\" or \"<>\"") } e.outputASCII = outputASCII return e, nil } // Bytes returns the content of the written bytes. func (e *Encoder) Bytes() []byte { return e.out } // StartMessage writes out the '{' or '<' symbol. func (e *Encoder) StartMessage() { e.prepareNext(messageOpen) e.out = append(e.out, e.delims[0]) } // EndMessage writes out the '}' or '>' symbol. func (e *Encoder) EndMessage() { e.prepareNext(messageClose) e.out = append(e.out, e.delims[1]) } // WriteName writes out the field name and the separator ':'. func (e *Encoder) WriteName(s string) { e.prepareNext(name) e.out = append(e.out, s...) e.out = append(e.out, ':') } // WriteBool writes out the given boolean value. func (e *Encoder) WriteBool(b bool) { if b { e.WriteLiteral("true") } else { e.WriteLiteral("false") } } // WriteString writes out the given string value. func (e *Encoder) WriteString(s string) { e.prepareNext(scalar) e.out = appendString(e.out, s, e.outputASCII) } func appendString(out []byte, in string, outputASCII bool) []byte { out = append(out, '"') i := indexNeedEscapeInString(in) in, out = in[i:], append(out, in[:i]...) for len(in) > 0 { switch r, n := utf8.DecodeRuneInString(in); { case r == utf8.RuneError && n == 1: // We do not report invalid UTF-8 because strings in the text format // are used to represent both the proto string and bytes type. r = rune(in[0]) fallthrough case r < ' ' || r == '"' || r == '\\' || r == 0x7f: out = append(out, '\\') switch r { case '"', '\\': out = append(out, byte(r)) case '\n': out = append(out, 'n') case '\r': out = append(out, 'r') case '\t': out = append(out, 't') default: out = append(out, 'x') out = append(out, "00"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } in = in[n:] case r >= utf8.RuneSelf && (outputASCII || r <= 0x009f): out = append(out, '\\') if r <= math.MaxUint16 { out = append(out, 'u') out = append(out, "0000"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } else { out = append(out, 'U') out = append(out, "00000000"[1+(bits.Len32(uint32(r))-1)/4:]...) out = strconv.AppendUint(out, uint64(r), 16) } in = in[n:] default: i := indexNeedEscapeInString(in[n:]) in, out = in[n+i:], append(out, in[:n+i]...) } } out = append(out, '"') return out } // indexNeedEscapeInString returns the index of the character that needs // escaping. If no characters need escaping, this returns the input length. func indexNeedEscapeInString(s string) int { for i := 0; i < len(s); i++ { if c := s[i]; c < ' ' || c == '"' || c == '\'' || c == '\\' || c >= 0x7f { return i } } return len(s) } // WriteFloat writes out the given float value for given bitSize. func (e *Encoder) WriteFloat(n float64, bitSize int) { e.prepareNext(scalar) e.out = appendFloat(e.out, n, bitSize) } func appendFloat(out []byte, n float64, bitSize int) []byte { switch { case math.IsNaN(n): return append(out, "nan"...) case math.IsInf(n, +1): return append(out, "inf"...) case math.IsInf(n, -1): return append(out, "-inf"...) default: return strconv.AppendFloat(out, n, 'g', -1, bitSize) } } // WriteInt writes out the given signed integer value. func (e *Encoder) WriteInt(n int64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatInt(n, 10)...) } // WriteUint writes out the given unsigned integer value. func (e *Encoder) WriteUint(n uint64) { e.prepareNext(scalar) e.out = append(e.out, strconv.FormatUint(n, 10)...) } // WriteLiteral writes out the given string as a literal value without quotes. // This is used for writing enum literal strings. func (e *Encoder) WriteLiteral(s string) { e.prepareNext(scalar) e.out = append(e.out, s...) } // prepareNext adds possible space and indentation for the next value based // on last encType and indent option. It also updates e.lastType to next. func (e *Encoder) prepareNext(next encType) { defer func() { e.lastType = next }() // Single line. if len(e.indent) == 0 { // Add space after each field before the next one. if e.lastType&(scalar|messageClose) != 0 && next == name { e.out = append(e.out, ' ') // Add a random extra space to make output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } } return } // Multi-line. switch { case e.lastType == name: e.out = append(e.out, ' ') // Add a random extra space after name: to make output unstable. if detrand.Bool() { e.out = append(e.out, ' ') } case e.lastType == messageOpen && next != messageClose: e.indents = append(e.indents, e.indent...) e.out = append(e.out, '\n') e.out = append(e.out, e.indents...) case e.lastType&(scalar|messageClose) != 0: if next == messageClose { e.indents = e.indents[:len(e.indents)-len(e.indent)] } e.out = append(e.out, '\n') e.out = append(e.out, e.indents...) } } // Snapshot returns the current snapshot for use in Reset. func (e *Encoder) Snapshot() encoderState { return e.encoderState } // Reset resets the Encoder to the given encoderState from a Snapshot. func (e *Encoder) Reset(es encoderState) { e.encoderState = es } ================================================ FILE: vendor/google.golang.org/protobuf/internal/errors/errors.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package errors implements functions to manipulate errors. package errors import ( "errors" "fmt" "google.golang.org/protobuf/internal/detrand" ) // Error is a sentinel matching all errors produced by this package. var Error = errors.New("protobuf error") // New formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. func New(f string, x ...interface{}) error { return &prefixError{s: format(f, x...)} } type prefixError struct{ s string } var prefix = func() string { // Deliberately introduce instability into the error message string to // discourage users from performing error string comparisons. if detrand.Bool() { return "proto: " // use non-breaking spaces (U+00a0) } else { return "proto: " // use regular spaces (U+0020) } }() func (e *prefixError) Error() string { return prefix + e.s } func (e *prefixError) Unwrap() error { return Error } // Wrap returns an error that has a "proto" prefix, the formatted string described // by the format specifier and arguments, and a suffix of err. The error wraps err. func Wrap(err error, f string, x ...interface{}) error { return &wrapError{ s: format(f, x...), err: err, } } type wrapError struct { s string err error } func (e *wrapError) Error() string { return format("%v%v: %v", prefix, e.s, e.err) } func (e *wrapError) Unwrap() error { return e.err } func (e *wrapError) Is(target error) bool { return target == Error } func format(f string, x ...interface{}) string { // avoid "proto: " prefix when chaining for i := 0; i < len(x); i++ { switch e := x[i].(type) { case *prefixError: x[i] = e.s case *wrapError: x[i] = format("%v: %v", e.s, e.err) } } return fmt.Sprintf(f, x...) } func InvalidUTF8(name string) error { return New("field %v contains invalid UTF-8", name) } func RequiredNotSet(name string) error { return New("required field %v not set", name) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/errors/is_go112.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !go1.13 package errors import "reflect" // Is is a copy of Go 1.13's errors.Is for use with older Go versions. func Is(err, target error) bool { if target == nil { return err == target } isComparable := reflect.TypeOf(target).Comparable() for { if isComparable && err == target { return true } if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) { return true } if err = unwrap(err); err == nil { return false } } } func unwrap(err error) error { u, ok := err.(interface { Unwrap() error }) if !ok { return nil } return u.Unwrap() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/errors/is_go113.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.13 package errors import "errors" // Is is errors.Is. func Is(err, target error) bool { return errors.Is(err, target) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/build.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package filedesc provides functionality for constructing descriptors. // // The types in this package implement interfaces in the protoreflect package // related to protobuf descripriptors. package filedesc import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // Builder construct a protoreflect.FileDescriptor from the raw descriptor. type Builder struct { // GoPackagePath is the Go package path that is invoking this builder. GoPackagePath string // RawDescriptor is the wire-encoded bytes of FileDescriptorProto // and must be populated. RawDescriptor []byte // NumEnums is the total number of enums declared in the file. NumEnums int32 // NumMessages is the total number of messages declared in the file. // It includes the implicit message declarations for map entries. NumMessages int32 // NumExtensions is the total number of extensions declared in the file. NumExtensions int32 // NumServices is the total number of services declared in the file. NumServices int32 // TypeResolver resolves extension field types for descriptor options. // If nil, it uses protoregistry.GlobalTypes. TypeResolver interface { preg.ExtensionTypeResolver } // FileRegistry is use to lookup file, enum, and message dependencies. // Once constructed, the file descriptor is registered here. // If nil, it uses protoregistry.GlobalFiles. FileRegistry interface { FindFileByPath(string) (protoreflect.FileDescriptor, error) FindDescriptorByName(pref.FullName) (pref.Descriptor, error) RegisterFile(pref.FileDescriptor) error } } // resolverByIndex is an interface Builder.FileRegistry may implement. // If so, it permits looking up an enum or message dependency based on the // sub-list and element index into filetype.Builder.DependencyIndexes. type resolverByIndex interface { FindEnumByIndex(int32, int32, []Enum, []Message) pref.EnumDescriptor FindMessageByIndex(int32, int32, []Enum, []Message) pref.MessageDescriptor } // Indexes of each sub-list in filetype.Builder.DependencyIndexes. const ( listFieldDeps int32 = iota listExtTargets listExtDeps listMethInDeps listMethOutDeps ) // Out is the output of the Builder. type Out struct { File pref.FileDescriptor // Enums is all enum descriptors in "flattened ordering". Enums []Enum // Messages is all message descriptors in "flattened ordering". // It includes the implicit message declarations for map entries. Messages []Message // Extensions is all extension descriptors in "flattened ordering". Extensions []Extension // Service is all service descriptors in "flattened ordering". Services []Service } // Build constructs a FileDescriptor given the parameters set in Builder. // It assumes that the inputs are well-formed and panics if any inconsistencies // are encountered. // // If NumEnums+NumMessages+NumExtensions+NumServices is zero, // then Build automatically derives them from the raw descriptor. func (db Builder) Build() (out Out) { // Populate the counts if uninitialized. if db.NumEnums+db.NumMessages+db.NumExtensions+db.NumServices == 0 { db.unmarshalCounts(db.RawDescriptor, true) } // Initialize resolvers and registries if unpopulated. if db.TypeResolver == nil { db.TypeResolver = preg.GlobalTypes } if db.FileRegistry == nil { db.FileRegistry = preg.GlobalFiles } fd := newRawFile(db) out.File = fd out.Enums = fd.allEnums out.Messages = fd.allMessages out.Extensions = fd.allExtensions out.Services = fd.allServices if err := db.FileRegistry.RegisterFile(fd); err != nil { panic(err) } return out } // unmarshalCounts counts the number of enum, message, extension, and service // declarations in the raw message, which is either a FileDescriptorProto // or a MessageDescriptorProto depending on whether isFile is set. func (db *Builder) unmarshalCounts(b []byte, isFile bool) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] if isFile { switch num { case genid.FileDescriptorProto_EnumType_field_number: db.NumEnums++ case genid.FileDescriptorProto_MessageType_field_number: db.unmarshalCounts(v, false) db.NumMessages++ case genid.FileDescriptorProto_Extension_field_number: db.NumExtensions++ case genid.FileDescriptorProto_Service_field_number: db.NumServices++ } } else { switch num { case genid.DescriptorProto_EnumType_field_number: db.NumEnums++ case genid.DescriptorProto_NestedType_field_number: db.unmarshalCounts(v, false) db.NumMessages++ case genid.DescriptorProto_Extension_field_number: db.NumExtensions++ } } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/desc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "bytes" "fmt" "sync" "sync/atomic" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/encoding/defval" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // The types in this file may have a suffix: // • L0: Contains fields common to all descriptors (except File) and // must be initialized up front. // • L1: Contains fields specific to a descriptor and // must be initialized up front. // • L2: Contains fields that are lazily initialized when constructing // from the raw file descriptor. When constructing as a literal, the L2 // fields must be initialized up front. // // The types are exported so that packages like reflect/protodesc can // directly construct descriptors. type ( File struct { fileRaw L1 FileL1 once uint32 // atomically set if L2 is valid mu sync.Mutex // protects L2 L2 *FileL2 } FileL1 struct { Syntax pref.Syntax Path string Package pref.FullName Enums Enums Messages Messages Extensions Extensions Services Services } FileL2 struct { Options func() pref.ProtoMessage Imports FileImports Locations SourceLocations } ) func (fd *File) ParentFile() pref.FileDescriptor { return fd } func (fd *File) Parent() pref.Descriptor { return nil } func (fd *File) Index() int { return 0 } func (fd *File) Syntax() pref.Syntax { return fd.L1.Syntax } func (fd *File) Name() pref.Name { return fd.L1.Package.Name() } func (fd *File) FullName() pref.FullName { return fd.L1.Package } func (fd *File) IsPlaceholder() bool { return false } func (fd *File) Options() pref.ProtoMessage { if f := fd.lazyInit().Options; f != nil { return f() } return descopts.File } func (fd *File) Path() string { return fd.L1.Path } func (fd *File) Package() pref.FullName { return fd.L1.Package } func (fd *File) Imports() pref.FileImports { return &fd.lazyInit().Imports } func (fd *File) Enums() pref.EnumDescriptors { return &fd.L1.Enums } func (fd *File) Messages() pref.MessageDescriptors { return &fd.L1.Messages } func (fd *File) Extensions() pref.ExtensionDescriptors { return &fd.L1.Extensions } func (fd *File) Services() pref.ServiceDescriptors { return &fd.L1.Services } func (fd *File) SourceLocations() pref.SourceLocations { return &fd.lazyInit().Locations } func (fd *File) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) } func (fd *File) ProtoType(pref.FileDescriptor) {} func (fd *File) ProtoInternal(pragma.DoNotImplement) {} func (fd *File) lazyInit() *FileL2 { if atomic.LoadUint32(&fd.once) == 0 { fd.lazyInitOnce() } return fd.L2 } func (fd *File) lazyInitOnce() { fd.mu.Lock() if fd.L2 == nil { fd.lazyRawInit() // recursively initializes all L2 structures } atomic.StoreUint32(&fd.once, 1) fd.mu.Unlock() } // GoPackagePath is a pseudo-internal API for determining the Go package path // that this file descriptor is declared in. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (fd *File) GoPackagePath() string { return fd.builder.GoPackagePath } type ( Enum struct { Base L1 EnumL1 L2 *EnumL2 // protected by fileDesc.once } EnumL1 struct { eagerValues bool // controls whether EnumL2.Values is already populated } EnumL2 struct { Options func() pref.ProtoMessage Values EnumValues ReservedNames Names ReservedRanges EnumRanges } EnumValue struct { Base L1 EnumValueL1 } EnumValueL1 struct { Options func() pref.ProtoMessage Number pref.EnumNumber } ) func (ed *Enum) Options() pref.ProtoMessage { if f := ed.lazyInit().Options; f != nil { return f() } return descopts.Enum } func (ed *Enum) Values() pref.EnumValueDescriptors { if ed.L1.eagerValues { return &ed.L2.Values } return &ed.lazyInit().Values } func (ed *Enum) ReservedNames() pref.Names { return &ed.lazyInit().ReservedNames } func (ed *Enum) ReservedRanges() pref.EnumRanges { return &ed.lazyInit().ReservedRanges } func (ed *Enum) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) } func (ed *Enum) ProtoType(pref.EnumDescriptor) {} func (ed *Enum) lazyInit() *EnumL2 { ed.L0.ParentFile.lazyInit() // implicitly initializes L2 return ed.L2 } func (ed *EnumValue) Options() pref.ProtoMessage { if f := ed.L1.Options; f != nil { return f() } return descopts.EnumValue } func (ed *EnumValue) Number() pref.EnumNumber { return ed.L1.Number } func (ed *EnumValue) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, ed) } func (ed *EnumValue) ProtoType(pref.EnumValueDescriptor) {} type ( Message struct { Base L1 MessageL1 L2 *MessageL2 // protected by fileDesc.once } MessageL1 struct { Enums Enums Messages Messages Extensions Extensions IsMapEntry bool // promoted from google.protobuf.MessageOptions IsMessageSet bool // promoted from google.protobuf.MessageOptions } MessageL2 struct { Options func() pref.ProtoMessage Fields Fields Oneofs Oneofs ReservedNames Names ReservedRanges FieldRanges RequiredNumbers FieldNumbers // must be consistent with Fields.Cardinality ExtensionRanges FieldRanges ExtensionRangeOptions []func() pref.ProtoMessage // must be same length as ExtensionRanges } Field struct { Base L1 FieldL1 } FieldL1 struct { Options func() pref.ProtoMessage Number pref.FieldNumber Cardinality pref.Cardinality // must be consistent with Message.RequiredNumbers Kind pref.Kind StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsWeak bool // promoted from google.protobuf.FieldOptions HasPacked bool // promoted from google.protobuf.FieldOptions IsPacked bool // promoted from google.protobuf.FieldOptions HasEnforceUTF8 bool // promoted from google.protobuf.FieldOptions EnforceUTF8 bool // promoted from google.protobuf.FieldOptions Default defaultValue ContainingOneof pref.OneofDescriptor // must be consistent with Message.Oneofs.Fields Enum pref.EnumDescriptor Message pref.MessageDescriptor } Oneof struct { Base L1 OneofL1 } OneofL1 struct { Options func() pref.ProtoMessage Fields OneofFields // must be consistent with Message.Fields.ContainingOneof } ) func (md *Message) Options() pref.ProtoMessage { if f := md.lazyInit().Options; f != nil { return f() } return descopts.Message } func (md *Message) IsMapEntry() bool { return md.L1.IsMapEntry } func (md *Message) Fields() pref.FieldDescriptors { return &md.lazyInit().Fields } func (md *Message) Oneofs() pref.OneofDescriptors { return &md.lazyInit().Oneofs } func (md *Message) ReservedNames() pref.Names { return &md.lazyInit().ReservedNames } func (md *Message) ReservedRanges() pref.FieldRanges { return &md.lazyInit().ReservedRanges } func (md *Message) RequiredNumbers() pref.FieldNumbers { return &md.lazyInit().RequiredNumbers } func (md *Message) ExtensionRanges() pref.FieldRanges { return &md.lazyInit().ExtensionRanges } func (md *Message) ExtensionRangeOptions(i int) pref.ProtoMessage { if f := md.lazyInit().ExtensionRangeOptions[i]; f != nil { return f() } return descopts.ExtensionRange } func (md *Message) Enums() pref.EnumDescriptors { return &md.L1.Enums } func (md *Message) Messages() pref.MessageDescriptors { return &md.L1.Messages } func (md *Message) Extensions() pref.ExtensionDescriptors { return &md.L1.Extensions } func (md *Message) ProtoType(pref.MessageDescriptor) {} func (md *Message) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) } func (md *Message) lazyInit() *MessageL2 { md.L0.ParentFile.lazyInit() // implicitly initializes L2 return md.L2 } // IsMessageSet is a pseudo-internal API for checking whether a message // should serialize in the proto1 message format. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (md *Message) IsMessageSet() bool { return md.L1.IsMessageSet } func (fd *Field) Options() pref.ProtoMessage { if f := fd.L1.Options; f != nil { return f() } return descopts.Field } func (fd *Field) Number() pref.FieldNumber { return fd.L1.Number } func (fd *Field) Cardinality() pref.Cardinality { return fd.L1.Cardinality } func (fd *Field) Kind() pref.Kind { return fd.L1.Kind } func (fd *Field) HasJSONName() bool { return fd.L1.StringName.hasJSON } func (fd *Field) JSONName() string { return fd.L1.StringName.getJSON(fd) } func (fd *Field) TextName() string { return fd.L1.StringName.getText(fd) } func (fd *Field) HasPresence() bool { return fd.L1.Cardinality != pref.Repeated && (fd.L0.ParentFile.L1.Syntax == pref.Proto2 || fd.L1.Message != nil || fd.L1.ContainingOneof != nil) } func (fd *Field) HasOptionalKeyword() bool { return (fd.L0.ParentFile.L1.Syntax == pref.Proto2 && fd.L1.Cardinality == pref.Optional && fd.L1.ContainingOneof == nil) || fd.L1.IsProto3Optional } func (fd *Field) IsPacked() bool { if !fd.L1.HasPacked && fd.L0.ParentFile.L1.Syntax != pref.Proto2 && fd.L1.Cardinality == pref.Repeated { switch fd.L1.Kind { case pref.StringKind, pref.BytesKind, pref.MessageKind, pref.GroupKind: default: return true } } return fd.L1.IsPacked } func (fd *Field) IsExtension() bool { return false } func (fd *Field) IsWeak() bool { return fd.L1.IsWeak } func (fd *Field) IsList() bool { return fd.Cardinality() == pref.Repeated && !fd.IsMap() } func (fd *Field) IsMap() bool { return fd.Message() != nil && fd.Message().IsMapEntry() } func (fd *Field) MapKey() pref.FieldDescriptor { if !fd.IsMap() { return nil } return fd.Message().Fields().ByNumber(genid.MapEntry_Key_field_number) } func (fd *Field) MapValue() pref.FieldDescriptor { if !fd.IsMap() { return nil } return fd.Message().Fields().ByNumber(genid.MapEntry_Value_field_number) } func (fd *Field) HasDefault() bool { return fd.L1.Default.has } func (fd *Field) Default() pref.Value { return fd.L1.Default.get(fd) } func (fd *Field) DefaultEnumValue() pref.EnumValueDescriptor { return fd.L1.Default.enum } func (fd *Field) ContainingOneof() pref.OneofDescriptor { return fd.L1.ContainingOneof } func (fd *Field) ContainingMessage() pref.MessageDescriptor { return fd.L0.Parent.(pref.MessageDescriptor) } func (fd *Field) Enum() pref.EnumDescriptor { return fd.L1.Enum } func (fd *Field) Message() pref.MessageDescriptor { if fd.L1.IsWeak { if d, _ := protoregistry.GlobalFiles.FindDescriptorByName(fd.L1.Message.FullName()); d != nil { return d.(pref.MessageDescriptor) } } return fd.L1.Message } func (fd *Field) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, fd) } func (fd *Field) ProtoType(pref.FieldDescriptor) {} // EnforceUTF8 is a pseudo-internal API to determine whether to enforce UTF-8 // validation for the string field. This exists for Google-internal use only // since proto3 did not enforce UTF-8 validity prior to the open-source release. // If this method does not exist, the default is to enforce valid UTF-8. // // WARNING: This method is exempt from the compatibility promise and may be // removed in the future without warning. func (fd *Field) EnforceUTF8() bool { if fd.L1.HasEnforceUTF8 { return fd.L1.EnforceUTF8 } return fd.L0.ParentFile.L1.Syntax == pref.Proto3 } func (od *Oneof) IsSynthetic() bool { return od.L0.ParentFile.L1.Syntax == pref.Proto3 && len(od.L1.Fields.List) == 1 && od.L1.Fields.List[0].HasOptionalKeyword() } func (od *Oneof) Options() pref.ProtoMessage { if f := od.L1.Options; f != nil { return f() } return descopts.Oneof } func (od *Oneof) Fields() pref.FieldDescriptors { return &od.L1.Fields } func (od *Oneof) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, od) } func (od *Oneof) ProtoType(pref.OneofDescriptor) {} type ( Extension struct { Base L1 ExtensionL1 L2 *ExtensionL2 // protected by fileDesc.once } ExtensionL1 struct { Number pref.FieldNumber Extendee pref.MessageDescriptor Cardinality pref.Cardinality Kind pref.Kind } ExtensionL2 struct { Options func() pref.ProtoMessage StringName stringName IsProto3Optional bool // promoted from google.protobuf.FieldDescriptorProto IsPacked bool // promoted from google.protobuf.FieldOptions Default defaultValue Enum pref.EnumDescriptor Message pref.MessageDescriptor } ) func (xd *Extension) Options() pref.ProtoMessage { if f := xd.lazyInit().Options; f != nil { return f() } return descopts.Field } func (xd *Extension) Number() pref.FieldNumber { return xd.L1.Number } func (xd *Extension) Cardinality() pref.Cardinality { return xd.L1.Cardinality } func (xd *Extension) Kind() pref.Kind { return xd.L1.Kind } func (xd *Extension) HasJSONName() bool { return xd.lazyInit().StringName.hasJSON } func (xd *Extension) JSONName() string { return xd.lazyInit().StringName.getJSON(xd) } func (xd *Extension) TextName() string { return xd.lazyInit().StringName.getText(xd) } func (xd *Extension) HasPresence() bool { return xd.L1.Cardinality != pref.Repeated } func (xd *Extension) HasOptionalKeyword() bool { return (xd.L0.ParentFile.L1.Syntax == pref.Proto2 && xd.L1.Cardinality == pref.Optional) || xd.lazyInit().IsProto3Optional } func (xd *Extension) IsPacked() bool { return xd.lazyInit().IsPacked } func (xd *Extension) IsExtension() bool { return true } func (xd *Extension) IsWeak() bool { return false } func (xd *Extension) IsList() bool { return xd.Cardinality() == pref.Repeated } func (xd *Extension) IsMap() bool { return false } func (xd *Extension) MapKey() pref.FieldDescriptor { return nil } func (xd *Extension) MapValue() pref.FieldDescriptor { return nil } func (xd *Extension) HasDefault() bool { return xd.lazyInit().Default.has } func (xd *Extension) Default() pref.Value { return xd.lazyInit().Default.get(xd) } func (xd *Extension) DefaultEnumValue() pref.EnumValueDescriptor { return xd.lazyInit().Default.enum } func (xd *Extension) ContainingOneof() pref.OneofDescriptor { return nil } func (xd *Extension) ContainingMessage() pref.MessageDescriptor { return xd.L1.Extendee } func (xd *Extension) Enum() pref.EnumDescriptor { return xd.lazyInit().Enum } func (xd *Extension) Message() pref.MessageDescriptor { return xd.lazyInit().Message } func (xd *Extension) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, xd) } func (xd *Extension) ProtoType(pref.FieldDescriptor) {} func (xd *Extension) ProtoInternal(pragma.DoNotImplement) {} func (xd *Extension) lazyInit() *ExtensionL2 { xd.L0.ParentFile.lazyInit() // implicitly initializes L2 return xd.L2 } type ( Service struct { Base L1 ServiceL1 L2 *ServiceL2 // protected by fileDesc.once } ServiceL1 struct{} ServiceL2 struct { Options func() pref.ProtoMessage Methods Methods } Method struct { Base L1 MethodL1 } MethodL1 struct { Options func() pref.ProtoMessage Input pref.MessageDescriptor Output pref.MessageDescriptor IsStreamingClient bool IsStreamingServer bool } ) func (sd *Service) Options() pref.ProtoMessage { if f := sd.lazyInit().Options; f != nil { return f() } return descopts.Service } func (sd *Service) Methods() pref.MethodDescriptors { return &sd.lazyInit().Methods } func (sd *Service) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, sd) } func (sd *Service) ProtoType(pref.ServiceDescriptor) {} func (sd *Service) ProtoInternal(pragma.DoNotImplement) {} func (sd *Service) lazyInit() *ServiceL2 { sd.L0.ParentFile.lazyInit() // implicitly initializes L2 return sd.L2 } func (md *Method) Options() pref.ProtoMessage { if f := md.L1.Options; f != nil { return f() } return descopts.Method } func (md *Method) Input() pref.MessageDescriptor { return md.L1.Input } func (md *Method) Output() pref.MessageDescriptor { return md.L1.Output } func (md *Method) IsStreamingClient() bool { return md.L1.IsStreamingClient } func (md *Method) IsStreamingServer() bool { return md.L1.IsStreamingServer } func (md *Method) Format(s fmt.State, r rune) { descfmt.FormatDesc(s, r, md) } func (md *Method) ProtoType(pref.MethodDescriptor) {} func (md *Method) ProtoInternal(pragma.DoNotImplement) {} // Surrogate files are can be used to create standalone descriptors // where the syntax is only information derived from the parent file. var ( SurrogateProto2 = &File{L1: FileL1{Syntax: pref.Proto2}, L2: &FileL2{}} SurrogateProto3 = &File{L1: FileL1{Syntax: pref.Proto3}, L2: &FileL2{}} ) type ( Base struct { L0 BaseL0 } BaseL0 struct { FullName pref.FullName // must be populated ParentFile *File // must be populated Parent pref.Descriptor Index int } ) func (d *Base) Name() pref.Name { return d.L0.FullName.Name() } func (d *Base) FullName() pref.FullName { return d.L0.FullName } func (d *Base) ParentFile() pref.FileDescriptor { if d.L0.ParentFile == SurrogateProto2 || d.L0.ParentFile == SurrogateProto3 { return nil // surrogate files are not real parents } return d.L0.ParentFile } func (d *Base) Parent() pref.Descriptor { return d.L0.Parent } func (d *Base) Index() int { return d.L0.Index } func (d *Base) Syntax() pref.Syntax { return d.L0.ParentFile.Syntax() } func (d *Base) IsPlaceholder() bool { return false } func (d *Base) ProtoInternal(pragma.DoNotImplement) {} type stringName struct { hasJSON bool once sync.Once nameJSON string nameText string } // InitJSON initializes the name. It is exported for use by other internal packages. func (s *stringName) InitJSON(name string) { s.hasJSON = true s.nameJSON = name } func (s *stringName) lazyInit(fd pref.FieldDescriptor) *stringName { s.once.Do(func() { if fd.IsExtension() { // For extensions, JSON and text are formatted the same way. var name string if messageset.IsMessageSetExtension(fd) { name = string("[" + fd.FullName().Parent() + "]") } else { name = string("[" + fd.FullName() + "]") } s.nameJSON = name s.nameText = name } else { // Format the JSON name. if !s.hasJSON { s.nameJSON = strs.JSONCamelCase(string(fd.Name())) } // Format the text name. s.nameText = string(fd.Name()) if fd.Kind() == pref.GroupKind { s.nameText = string(fd.Message().Name()) } } }) return s } func (s *stringName) getJSON(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameJSON } func (s *stringName) getText(fd pref.FieldDescriptor) string { return s.lazyInit(fd).nameText } func DefaultValue(v pref.Value, ev pref.EnumValueDescriptor) defaultValue { dv := defaultValue{has: v.IsValid(), val: v, enum: ev} if b, ok := v.Interface().([]byte); ok { // Store a copy of the default bytes, so that we can detect // accidental mutations of the original value. dv.bytes = append([]byte(nil), b...) } return dv } func unmarshalDefault(b []byte, k pref.Kind, pf *File, ed pref.EnumDescriptor) defaultValue { var evs pref.EnumValueDescriptors if k == pref.EnumKind { // If the enum is declared within the same file, be careful not to // blindly call the Values method, lest we bind ourselves in a deadlock. if e, ok := ed.(*Enum); ok && e.L0.ParentFile == pf { evs = &e.L2.Values } else { evs = ed.Values() } // If we are unable to resolve the enum dependency, use a placeholder // enum value since we will not be able to parse the default value. if ed.IsPlaceholder() && pref.Name(b).IsValid() { v := pref.ValueOfEnum(0) ev := PlaceholderEnumValue(ed.FullName().Parent().Append(pref.Name(b))) return DefaultValue(v, ev) } } v, ev, err := defval.Unmarshal(string(b), k, evs, defval.Descriptor) if err != nil { panic(err) } return DefaultValue(v, ev) } type defaultValue struct { has bool val pref.Value enum pref.EnumValueDescriptor bytes []byte } func (dv *defaultValue) get(fd pref.FieldDescriptor) pref.Value { // Return the zero value as the default if unpopulated. if !dv.has { if fd.Cardinality() == pref.Repeated { return pref.Value{} } switch fd.Kind() { case pref.BoolKind: return pref.ValueOfBool(false) case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: return pref.ValueOfInt32(0) case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: return pref.ValueOfInt64(0) case pref.Uint32Kind, pref.Fixed32Kind: return pref.ValueOfUint32(0) case pref.Uint64Kind, pref.Fixed64Kind: return pref.ValueOfUint64(0) case pref.FloatKind: return pref.ValueOfFloat32(0) case pref.DoubleKind: return pref.ValueOfFloat64(0) case pref.StringKind: return pref.ValueOfString("") case pref.BytesKind: return pref.ValueOfBytes(nil) case pref.EnumKind: if evs := fd.Enum().Values(); evs.Len() > 0 { return pref.ValueOfEnum(evs.Get(0).Number()) } return pref.ValueOfEnum(0) } } if len(dv.bytes) > 0 && !bytes.Equal(dv.bytes, dv.val.Bytes()) { // TODO: Avoid panic if we're running with the race detector // and instead spawn a goroutine that periodically resets // this value back to the original to induce a race. panic(fmt.Sprintf("detected mutation on the default bytes for %v", fd.FullName())) } return dv.val } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) // fileRaw is a data struct used when initializing a file descriptor from // a raw FileDescriptorProto. type fileRaw struct { builder Builder allEnums []Enum allMessages []Message allExtensions []Extension allServices []Service } func newRawFile(db Builder) *File { fd := &File{fileRaw: fileRaw{builder: db}} fd.initDecls(db.NumEnums, db.NumMessages, db.NumExtensions, db.NumServices) fd.unmarshalSeed(db.RawDescriptor) // Extended message targets are eagerly resolved since registration // needs this information at program init time. for i := range fd.allExtensions { xd := &fd.allExtensions[i] xd.L1.Extendee = fd.resolveMessageDependency(xd.L1.Extendee, listExtTargets, int32(i)) } fd.checkDecls() return fd } // initDecls pre-allocates slices for the exact number of enums, messages // (including map entries), extensions, and services declared in the proto file. // This is done to avoid regrowing the slice, which would change the address // for any previously seen declaration. // // The alloc methods "allocates" slices by pulling from the capacity. func (fd *File) initDecls(numEnums, numMessages, numExtensions, numServices int32) { fd.allEnums = make([]Enum, 0, numEnums) fd.allMessages = make([]Message, 0, numMessages) fd.allExtensions = make([]Extension, 0, numExtensions) fd.allServices = make([]Service, 0, numServices) } func (fd *File) allocEnums(n int) []Enum { total := len(fd.allEnums) es := fd.allEnums[total : total+n] fd.allEnums = fd.allEnums[:total+n] return es } func (fd *File) allocMessages(n int) []Message { total := len(fd.allMessages) ms := fd.allMessages[total : total+n] fd.allMessages = fd.allMessages[:total+n] return ms } func (fd *File) allocExtensions(n int) []Extension { total := len(fd.allExtensions) xs := fd.allExtensions[total : total+n] fd.allExtensions = fd.allExtensions[:total+n] return xs } func (fd *File) allocServices(n int) []Service { total := len(fd.allServices) xs := fd.allServices[total : total+n] fd.allServices = fd.allServices[:total+n] return xs } // checkDecls performs a sanity check that the expected number of expected // declarations matches the number that were found in the descriptor proto. func (fd *File) checkDecls() { switch { case len(fd.allEnums) != cap(fd.allEnums): case len(fd.allMessages) != cap(fd.allMessages): case len(fd.allExtensions) != cap(fd.allExtensions): case len(fd.allServices) != cap(fd.allServices): default: return } panic("mismatching cardinality") } func (fd *File) unmarshalSeed(b []byte) { sb := getBuilder() defer putBuilder(sb) var prevField pref.FieldNumber var numEnums, numMessages, numExtensions, numServices int var posEnums, posMessages, posExtensions, posServices int b0 := b for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FileDescriptorProto_Syntax_field_number: switch string(v) { case "proto2": fd.L1.Syntax = pref.Proto2 case "proto3": fd.L1.Syntax = pref.Proto3 default: panic("invalid syntax") } case genid.FileDescriptorProto_Name_field_number: fd.L1.Path = sb.MakeString(v) case genid.FileDescriptorProto_Package_field_number: fd.L1.Package = pref.FullName(sb.MakeString(v)) case genid.FileDescriptorProto_EnumType_field_number: if prevField != genid.FileDescriptorProto_EnumType_field_number { if numEnums > 0 { panic("non-contiguous repeated field") } posEnums = len(b0) - len(b) - n - m } numEnums++ case genid.FileDescriptorProto_MessageType_field_number: if prevField != genid.FileDescriptorProto_MessageType_field_number { if numMessages > 0 { panic("non-contiguous repeated field") } posMessages = len(b0) - len(b) - n - m } numMessages++ case genid.FileDescriptorProto_Extension_field_number: if prevField != genid.FileDescriptorProto_Extension_field_number { if numExtensions > 0 { panic("non-contiguous repeated field") } posExtensions = len(b0) - len(b) - n - m } numExtensions++ case genid.FileDescriptorProto_Service_field_number: if prevField != genid.FileDescriptorProto_Service_field_number { if numServices > 0 { panic("non-contiguous repeated field") } posServices = len(b0) - len(b) - n - m } numServices++ } prevField = num default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] prevField = -1 // ignore known field numbers of unknown wire type } } // If syntax is missing, it is assumed to be proto2. if fd.L1.Syntax == 0 { fd.L1.Syntax = pref.Proto2 } // Must allocate all declarations before parsing each descriptor type // to ensure we handled all descriptors in "flattened ordering". if numEnums > 0 { fd.L1.Enums.List = fd.allocEnums(numEnums) } if numMessages > 0 { fd.L1.Messages.List = fd.allocMessages(numMessages) } if numExtensions > 0 { fd.L1.Extensions.List = fd.allocExtensions(numExtensions) } if numServices > 0 { fd.L1.Services.List = fd.allocServices(numServices) } if numEnums > 0 { b := b0[posEnums:] for i := range fd.L1.Enums.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numMessages > 0 { b := b0[posMessages:] for i := range fd.L1.Messages.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numExtensions > 0 { b := b0[posExtensions:] for i := range fd.L1.Extensions.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } if numServices > 0 { b := b0[posServices:] for i := range fd.L1.Services.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i) b = b[n+m:] } } } func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { ed.L0.ParentFile = pf ed.L0.Parent = pd ed.L0.Index = i var numValues int for b := b; len(b) > 0; { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Name_field_number: ed.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.EnumDescriptorProto_Value_field_number: numValues++ } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } // Only construct enum value descriptors for top-level enums since // they are needed for registration. if pd != pf { return } ed.L1.eagerValues = true ed.L2 = new(EnumL2) ed.L2.Values.List = make([]EnumValue, numValues) for i := 0; len(b) > 0; { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Value_field_number: ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i) i++ } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { md.L0.ParentFile = pf md.L0.Parent = pd md.L0.Index = i var prevField pref.FieldNumber var numEnums, numMessages, numExtensions int var posEnums, posMessages, posExtensions int b0 := b for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_Name_field_number: md.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.DescriptorProto_EnumType_field_number: if prevField != genid.DescriptorProto_EnumType_field_number { if numEnums > 0 { panic("non-contiguous repeated field") } posEnums = len(b0) - len(b) - n - m } numEnums++ case genid.DescriptorProto_NestedType_field_number: if prevField != genid.DescriptorProto_NestedType_field_number { if numMessages > 0 { panic("non-contiguous repeated field") } posMessages = len(b0) - len(b) - n - m } numMessages++ case genid.DescriptorProto_Extension_field_number: if prevField != genid.DescriptorProto_Extension_field_number { if numExtensions > 0 { panic("non-contiguous repeated field") } posExtensions = len(b0) - len(b) - n - m } numExtensions++ case genid.DescriptorProto_Options_field_number: md.unmarshalSeedOptions(v) } prevField = num default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] prevField = -1 // ignore known field numbers of unknown wire type } } // Must allocate all declarations before parsing each descriptor type // to ensure we handled all descriptors in "flattened ordering". if numEnums > 0 { md.L1.Enums.List = pf.allocEnums(numEnums) } if numMessages > 0 { md.L1.Messages.List = pf.allocMessages(numMessages) } if numExtensions > 0 { md.L1.Extensions.List = pf.allocExtensions(numExtensions) } if numEnums > 0 { b := b0[posEnums:] for i := range md.L1.Enums.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } if numMessages > 0 { b := b0[posMessages:] for i := range md.L1.Messages.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } if numExtensions > 0 { b := b0[posExtensions:] for i := range md.L1.Extensions.List { _, n := protowire.ConsumeVarint(b) v, m := protowire.ConsumeBytes(b[n:]) md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i) b = b[n+m:] } } } func (md *Message) unmarshalSeedOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MessageOptions_MapEntry_field_number: md.L1.IsMapEntry = protowire.DecodeBool(v) case genid.MessageOptions_MessageSetWireFormat_field_number: md.L1.IsMessageSet = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { xd.L0.ParentFile = pf xd.L0.Parent = pd xd.L0.Index = i for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Number_field_number: xd.L1.Number = pref.FieldNumber(v) case genid.FieldDescriptorProto_Label_field_number: xd.L1.Cardinality = pref.Cardinality(v) case genid.FieldDescriptorProto_Type_field_number: xd.L1.Kind = pref.Kind(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Name_field_number: xd.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.FieldDescriptorProto_Extendee_field_number: xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v)) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { sd.L0.ParentFile = pf sd.L0.Parent = pd sd.L0.Index = i for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.ServiceDescriptorProto_Name_field_number: sd.L0.FullName = appendFullName(sb, pd.FullName(), v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } var nameBuilderPool = sync.Pool{ New: func() interface{} { return new(strs.Builder) }, } func getBuilder() *strs.Builder { return nameBuilderPool.Get().(*strs.Builder) } func putBuilder(b *strs.Builder) { nameBuilderPool.Put(b) } // makeFullName converts b to a protoreflect.FullName, // where b must start with a leading dot. func makeFullName(sb *strs.Builder, b []byte) pref.FullName { if len(b) == 0 || b[0] != '.' { panic("name reference must be fully qualified") } return pref.FullName(sb.MakeString(b[1:])) } func appendFullName(sb *strs.Builder, prefix pref.FullName, suffix []byte) pref.FullName { return sb.AppendFullName(prefix, pref.Name(strs.UnsafeString(suffix))) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "reflect" "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" ) func (fd *File) lazyRawInit() { fd.unmarshalFull(fd.builder.RawDescriptor) fd.resolveMessages() fd.resolveExtensions() fd.resolveServices() } func (file *File) resolveMessages() { var depIdx int32 for i := range file.allMessages { md := &file.allMessages[i] // Resolve message field dependencies. for j := range md.L2.Fields.List { fd := &md.L2.Fields.List[j] // Weak fields are resolved upon actual use. if fd.L1.IsWeak { continue } // Resolve message field dependency. switch fd.L1.Kind { case pref.EnumKind: fd.L1.Enum = file.resolveEnumDependency(fd.L1.Enum, listFieldDeps, depIdx) depIdx++ case pref.MessageKind, pref.GroupKind: fd.L1.Message = file.resolveMessageDependency(fd.L1.Message, listFieldDeps, depIdx) depIdx++ } // Default is resolved here since it depends on Enum being resolved. if v := fd.L1.Default.val; v.IsValid() { fd.L1.Default = unmarshalDefault(v.Bytes(), fd.L1.Kind, file, fd.L1.Enum) } } } } func (file *File) resolveExtensions() { var depIdx int32 for i := range file.allExtensions { xd := &file.allExtensions[i] // Resolve extension field dependency. switch xd.L1.Kind { case pref.EnumKind: xd.L2.Enum = file.resolveEnumDependency(xd.L2.Enum, listExtDeps, depIdx) depIdx++ case pref.MessageKind, pref.GroupKind: xd.L2.Message = file.resolveMessageDependency(xd.L2.Message, listExtDeps, depIdx) depIdx++ } // Default is resolved here since it depends on Enum being resolved. if v := xd.L2.Default.val; v.IsValid() { xd.L2.Default = unmarshalDefault(v.Bytes(), xd.L1.Kind, file, xd.L2.Enum) } } } func (file *File) resolveServices() { var depIdx int32 for i := range file.allServices { sd := &file.allServices[i] // Resolve method dependencies. for j := range sd.L2.Methods.List { md := &sd.L2.Methods.List[j] md.L1.Input = file.resolveMessageDependency(md.L1.Input, listMethInDeps, depIdx) md.L1.Output = file.resolveMessageDependency(md.L1.Output, listMethOutDeps, depIdx) depIdx++ } } } func (file *File) resolveEnumDependency(ed pref.EnumDescriptor, i, j int32) pref.EnumDescriptor { r := file.builder.FileRegistry if r, ok := r.(resolverByIndex); ok { if ed2 := r.FindEnumByIndex(i, j, file.allEnums, file.allMessages); ed2 != nil { return ed2 } } for i := range file.allEnums { if ed2 := &file.allEnums[i]; ed2.L0.FullName == ed.FullName() { return ed2 } } if d, _ := r.FindDescriptorByName(ed.FullName()); d != nil { return d.(pref.EnumDescriptor) } return ed } func (file *File) resolveMessageDependency(md pref.MessageDescriptor, i, j int32) pref.MessageDescriptor { r := file.builder.FileRegistry if r, ok := r.(resolverByIndex); ok { if md2 := r.FindMessageByIndex(i, j, file.allEnums, file.allMessages); md2 != nil { return md2 } } for i := range file.allMessages { if md2 := &file.allMessages[i]; md2.L0.FullName == md.FullName() { return md2 } } if d, _ := r.FindDescriptorByName(md.FullName()); d != nil { return d.(pref.MessageDescriptor) } return md } func (fd *File) unmarshalFull(b []byte) { sb := getBuilder() defer putBuilder(sb) var enumIdx, messageIdx, extensionIdx, serviceIdx int var rawOptions []byte fd.L2 = new(FileL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FileDescriptorProto_PublicDependency_field_number: fd.L2.Imports[v].IsPublic = true case genid.FileDescriptorProto_WeakDependency_field_number: fd.L2.Imports[v].IsWeak = true } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FileDescriptorProto_Dependency_field_number: path := sb.MakeString(v) imp, _ := fd.builder.FileRegistry.FindFileByPath(path) if imp == nil { imp = PlaceholderFile(path) } fd.L2.Imports = append(fd.L2.Imports, pref.FileImport{FileDescriptor: imp}) case genid.FileDescriptorProto_EnumType_field_number: fd.L1.Enums.List[enumIdx].unmarshalFull(v, sb) enumIdx++ case genid.FileDescriptorProto_MessageType_field_number: fd.L1.Messages.List[messageIdx].unmarshalFull(v, sb) messageIdx++ case genid.FileDescriptorProto_Extension_field_number: fd.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) extensionIdx++ case genid.FileDescriptorProto_Service_field_number: fd.L1.Services.List[serviceIdx].unmarshalFull(v, sb) serviceIdx++ case genid.FileDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } fd.L2.Options = fd.builder.optionsUnmarshaler(&descopts.File, rawOptions) } func (ed *Enum) unmarshalFull(b []byte, sb *strs.Builder) { var rawValues [][]byte var rawOptions []byte if !ed.L1.eagerValues { ed.L2 = new(EnumL2) } for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumDescriptorProto_Value_field_number: rawValues = append(rawValues, v) case genid.EnumDescriptorProto_ReservedName_field_number: ed.L2.ReservedNames.List = append(ed.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) case genid.EnumDescriptorProto_ReservedRange_field_number: ed.L2.ReservedRanges.List = append(ed.L2.ReservedRanges.List, unmarshalEnumReservedRange(v)) case genid.EnumDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if !ed.L1.eagerValues && len(rawValues) > 0 { ed.L2.Values.List = make([]EnumValue, len(rawValues)) for i, b := range rawValues { ed.L2.Values.List[i].unmarshalFull(b, sb, ed.L0.ParentFile, ed, i) } } ed.L2.Options = ed.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Enum, rawOptions) } func unmarshalEnumReservedRange(b []byte) (r [2]pref.EnumNumber) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.EnumDescriptorProto_EnumReservedRange_Start_field_number: r[0] = pref.EnumNumber(v) case genid.EnumDescriptorProto_EnumReservedRange_End_field_number: r[1] = pref.EnumNumber(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r } func (vd *EnumValue) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { vd.L0.ParentFile = pf vd.L0.Parent = pd vd.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.EnumValueDescriptorProto_Number_field_number: vd.L1.Number = pref.EnumNumber(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.EnumValueDescriptorProto_Name_field_number: // NOTE: Enum values are in the same scope as the enum parent. vd.L0.FullName = appendFullName(sb, pd.Parent().FullName(), v) case genid.EnumValueDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } vd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.EnumValue, rawOptions) } func (md *Message) unmarshalFull(b []byte, sb *strs.Builder) { var rawFields, rawOneofs [][]byte var enumIdx, messageIdx, extensionIdx int var rawOptions []byte md.L2 = new(MessageL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_Field_field_number: rawFields = append(rawFields, v) case genid.DescriptorProto_OneofDecl_field_number: rawOneofs = append(rawOneofs, v) case genid.DescriptorProto_ReservedName_field_number: md.L2.ReservedNames.List = append(md.L2.ReservedNames.List, pref.Name(sb.MakeString(v))) case genid.DescriptorProto_ReservedRange_field_number: md.L2.ReservedRanges.List = append(md.L2.ReservedRanges.List, unmarshalMessageReservedRange(v)) case genid.DescriptorProto_ExtensionRange_field_number: r, rawOptions := unmarshalMessageExtensionRange(v) opts := md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.ExtensionRange, rawOptions) md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, r) md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, opts) case genid.DescriptorProto_EnumType_field_number: md.L1.Enums.List[enumIdx].unmarshalFull(v, sb) enumIdx++ case genid.DescriptorProto_NestedType_field_number: md.L1.Messages.List[messageIdx].unmarshalFull(v, sb) messageIdx++ case genid.DescriptorProto_Extension_field_number: md.L1.Extensions.List[extensionIdx].unmarshalFull(v, sb) extensionIdx++ case genid.DescriptorProto_Options_field_number: md.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if len(rawFields) > 0 || len(rawOneofs) > 0 { md.L2.Fields.List = make([]Field, len(rawFields)) md.L2.Oneofs.List = make([]Oneof, len(rawOneofs)) for i, b := range rawFields { fd := &md.L2.Fields.List[i] fd.unmarshalFull(b, sb, md.L0.ParentFile, md, i) if fd.L1.Cardinality == pref.Required { md.L2.RequiredNumbers.List = append(md.L2.RequiredNumbers.List, fd.L1.Number) } } for i, b := range rawOneofs { od := &md.L2.Oneofs.List[i] od.unmarshalFull(b, sb, md.L0.ParentFile, md, i) } } md.L2.Options = md.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Message, rawOptions) } func (md *Message) unmarshalOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MessageOptions_MapEntry_field_number: md.L1.IsMapEntry = protowire.DecodeBool(v) case genid.MessageOptions_MessageSetWireFormat_field_number: md.L1.IsMessageSet = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func unmarshalMessageReservedRange(b []byte) (r [2]pref.FieldNumber) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.DescriptorProto_ReservedRange_Start_field_number: r[0] = pref.FieldNumber(v) case genid.DescriptorProto_ReservedRange_End_field_number: r[1] = pref.FieldNumber(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r } func unmarshalMessageExtensionRange(b []byte) (r [2]pref.FieldNumber, rawOptions []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.DescriptorProto_ExtensionRange_Start_field_number: r[0] = pref.FieldNumber(v) case genid.DescriptorProto_ExtensionRange_End_field_number: r[1] = pref.FieldNumber(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.DescriptorProto_ExtensionRange_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } return r, rawOptions } func (fd *Field) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { fd.L0.ParentFile = pf fd.L0.Parent = pd fd.L0.Index = i var rawTypeName []byte var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Number_field_number: fd.L1.Number = pref.FieldNumber(v) case genid.FieldDescriptorProto_Label_field_number: fd.L1.Cardinality = pref.Cardinality(v) case genid.FieldDescriptorProto_Type_field_number: fd.L1.Kind = pref.Kind(v) case genid.FieldDescriptorProto_OneofIndex_field_number: // In Message.unmarshalFull, we allocate slices for both // the field and oneof descriptors before unmarshaling either // of them. This ensures pointers to slice elements are stable. od := &pd.(*Message).L2.Oneofs.List[v] od.L1.Fields.List = append(od.L1.Fields.List, fd) if fd.L1.ContainingOneof != nil { panic("oneof type already set") } fd.L1.ContainingOneof = od case genid.FieldDescriptorProto_Proto3Optional_field_number: fd.L1.IsProto3Optional = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Name_field_number: fd.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.FieldDescriptorProto_JsonName_field_number: fd.L1.StringName.InitJSON(sb.MakeString(v)) case genid.FieldDescriptorProto_DefaultValue_field_number: fd.L1.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveMessages case genid.FieldDescriptorProto_TypeName_field_number: rawTypeName = v case genid.FieldDescriptorProto_Options_field_number: fd.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if rawTypeName != nil { name := makeFullName(sb, rawTypeName) switch fd.L1.Kind { case pref.EnumKind: fd.L1.Enum = PlaceholderEnum(name) case pref.MessageKind, pref.GroupKind: fd.L1.Message = PlaceholderMessage(name) } } fd.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Field, rawOptions) } func (fd *Field) unmarshalOptions(b []byte) { const FieldOptions_EnforceUTF8 = 13 for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldOptions_Packed_field_number: fd.L1.HasPacked = true fd.L1.IsPacked = protowire.DecodeBool(v) case genid.FieldOptions_Weak_field_number: fd.L1.IsWeak = protowire.DecodeBool(v) case FieldOptions_EnforceUTF8: fd.L1.HasEnforceUTF8 = true fd.L1.EnforceUTF8 = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (od *Oneof) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { od.L0.ParentFile = pf od.L0.Parent = pd od.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.OneofDescriptorProto_Name_field_number: od.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.OneofDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } od.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Oneof, rawOptions) } func (xd *Extension) unmarshalFull(b []byte, sb *strs.Builder) { var rawTypeName []byte var rawOptions []byte xd.L2 = new(ExtensionL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldDescriptorProto_Proto3Optional_field_number: xd.L2.IsProto3Optional = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.FieldDescriptorProto_JsonName_field_number: xd.L2.StringName.InitJSON(sb.MakeString(v)) case genid.FieldDescriptorProto_DefaultValue_field_number: xd.L2.Default.val = pref.ValueOfBytes(v) // temporarily store as bytes; later resolved in resolveExtensions case genid.FieldDescriptorProto_TypeName_field_number: rawTypeName = v case genid.FieldDescriptorProto_Options_field_number: xd.unmarshalOptions(v) rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if rawTypeName != nil { name := makeFullName(sb, rawTypeName) switch xd.L1.Kind { case pref.EnumKind: xd.L2.Enum = PlaceholderEnum(name) case pref.MessageKind, pref.GroupKind: xd.L2.Message = PlaceholderMessage(name) } } xd.L2.Options = xd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Field, rawOptions) } func (xd *Extension) unmarshalOptions(b []byte) { for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.FieldOptions_Packed_field_number: xd.L2.IsPacked = protowire.DecodeBool(v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } } func (sd *Service) unmarshalFull(b []byte, sb *strs.Builder) { var rawMethods [][]byte var rawOptions []byte sd.L2 = new(ServiceL2) for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.ServiceDescriptorProto_Method_field_number: rawMethods = append(rawMethods, v) case genid.ServiceDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } if len(rawMethods) > 0 { sd.L2.Methods.List = make([]Method, len(rawMethods)) for i, b := range rawMethods { sd.L2.Methods.List[i].unmarshalFull(b, sb, sd.L0.ParentFile, sd, i) } } sd.L2.Options = sd.L0.ParentFile.builder.optionsUnmarshaler(&descopts.Service, rawOptions) } func (md *Method) unmarshalFull(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) { md.L0.ParentFile = pf md.L0.Parent = pd md.L0.Index = i var rawOptions []byte for len(b) > 0 { num, typ, n := protowire.ConsumeTag(b) b = b[n:] switch typ { case protowire.VarintType: v, m := protowire.ConsumeVarint(b) b = b[m:] switch num { case genid.MethodDescriptorProto_ClientStreaming_field_number: md.L1.IsStreamingClient = protowire.DecodeBool(v) case genid.MethodDescriptorProto_ServerStreaming_field_number: md.L1.IsStreamingServer = protowire.DecodeBool(v) } case protowire.BytesType: v, m := protowire.ConsumeBytes(b) b = b[m:] switch num { case genid.MethodDescriptorProto_Name_field_number: md.L0.FullName = appendFullName(sb, pd.FullName(), v) case genid.MethodDescriptorProto_InputType_field_number: md.L1.Input = PlaceholderMessage(makeFullName(sb, v)) case genid.MethodDescriptorProto_OutputType_field_number: md.L1.Output = PlaceholderMessage(makeFullName(sb, v)) case genid.MethodDescriptorProto_Options_field_number: rawOptions = appendOptions(rawOptions, v) } default: m := protowire.ConsumeFieldValue(num, typ, b) b = b[m:] } } md.L1.Options = pf.builder.optionsUnmarshaler(&descopts.Method, rawOptions) } // appendOptions appends src to dst, where the returned slice is never nil. // This is necessary to distinguish between empty and unpopulated options. func appendOptions(dst, src []byte) []byte { if dst == nil { dst = []byte{} } return append(dst, src...) } // optionsUnmarshaler constructs a lazy unmarshal function for an options message. // // The type of message to unmarshal to is passed as a pointer since the // vars in descopts may not yet be populated at the time this function is called. func (db *Builder) optionsUnmarshaler(p *pref.ProtoMessage, b []byte) func() pref.ProtoMessage { if b == nil { return nil } var opts pref.ProtoMessage var once sync.Once return func() pref.ProtoMessage { once.Do(func() { if *p == nil { panic("Descriptor.Options called without importing the descriptor package") } opts = reflect.New(reflect.TypeOf(*p).Elem()).Interface().(pref.ProtoMessage) if err := (proto.UnmarshalOptions{ AllowPartial: true, Resolver: db.TypeResolver, }).Unmarshal(b, opts); err != nil { panic(err) } }) return opts } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/desc_list.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "fmt" "math" "sort" "sync" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type FileImports []pref.FileImport func (p *FileImports) Len() int { return len(*p) } func (p *FileImports) Get(i int) pref.FileImport { return (*p)[i] } func (p *FileImports) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FileImports) ProtoInternal(pragma.DoNotImplement) {} type Names struct { List []pref.Name once sync.Once has map[pref.Name]int // protected by once } func (p *Names) Len() int { return len(p.List) } func (p *Names) Get(i int) pref.Name { return p.List[i] } func (p *Names) Has(s pref.Name) bool { return p.lazyInit().has[s] > 0 } func (p *Names) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Names) ProtoInternal(pragma.DoNotImplement) {} func (p *Names) lazyInit() *Names { p.once.Do(func() { if len(p.List) > 0 { p.has = make(map[pref.Name]int, len(p.List)) for _, s := range p.List { p.has[s] = p.has[s] + 1 } } }) return p } // CheckValid reports any errors with the set of names with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *Names) CheckValid() error { for s, n := range p.lazyInit().has { switch { case n > 1: return errors.New("duplicate name: %q", s) case false && !s.IsValid(): // NOTE: The C++ implementation does not validate the identifier. // See https://github.com/protocolbuffers/protobuf/issues/6335. return errors.New("invalid name: %q", s) } } return nil } type EnumRanges struct { List [][2]pref.EnumNumber // start inclusive; end inclusive once sync.Once sorted [][2]pref.EnumNumber // protected by once } func (p *EnumRanges) Len() int { return len(p.List) } func (p *EnumRanges) Get(i int) [2]pref.EnumNumber { return p.List[i] } func (p *EnumRanges) Has(n pref.EnumNumber) bool { for ls := p.lazyInit().sorted; len(ls) > 0; { i := len(ls) / 2 switch r := enumRange(ls[i]); { case n < r.Start(): ls = ls[:i] // search lower case n > r.End(): ls = ls[i+1:] // search upper default: return true } } return false } func (p *EnumRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *EnumRanges) ProtoInternal(pragma.DoNotImplement) {} func (p *EnumRanges) lazyInit() *EnumRanges { p.once.Do(func() { p.sorted = append(p.sorted, p.List...) sort.Slice(p.sorted, func(i, j int) bool { return p.sorted[i][0] < p.sorted[j][0] }) }) return p } // CheckValid reports any errors with the set of names with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *EnumRanges) CheckValid() error { var rp enumRange for i, r := range p.lazyInit().sorted { r := enumRange(r) switch { case !(r.Start() <= r.End()): return errors.New("invalid range: %v", r) case !(rp.End() < r.Start()) && i > 0: return errors.New("overlapping ranges: %v with %v", rp, r) } rp = r } return nil } type enumRange [2]protoreflect.EnumNumber func (r enumRange) Start() protoreflect.EnumNumber { return r[0] } // inclusive func (r enumRange) End() protoreflect.EnumNumber { return r[1] } // inclusive func (r enumRange) String() string { if r.Start() == r.End() { return fmt.Sprintf("%d", r.Start()) } return fmt.Sprintf("%d to %d", r.Start(), r.End()) } type FieldRanges struct { List [][2]pref.FieldNumber // start inclusive; end exclusive once sync.Once sorted [][2]pref.FieldNumber // protected by once } func (p *FieldRanges) Len() int { return len(p.List) } func (p *FieldRanges) Get(i int) [2]pref.FieldNumber { return p.List[i] } func (p *FieldRanges) Has(n pref.FieldNumber) bool { for ls := p.lazyInit().sorted; len(ls) > 0; { i := len(ls) / 2 switch r := fieldRange(ls[i]); { case n < r.Start(): ls = ls[:i] // search lower case n > r.End(): ls = ls[i+1:] // search upper default: return true } } return false } func (p *FieldRanges) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FieldRanges) ProtoInternal(pragma.DoNotImplement) {} func (p *FieldRanges) lazyInit() *FieldRanges { p.once.Do(func() { p.sorted = append(p.sorted, p.List...) sort.Slice(p.sorted, func(i, j int) bool { return p.sorted[i][0] < p.sorted[j][0] }) }) return p } // CheckValid reports any errors with the set of ranges with an error message // that completes the sentence: "ranges is invalid because it has ..." func (p *FieldRanges) CheckValid(isMessageSet bool) error { var rp fieldRange for i, r := range p.lazyInit().sorted { r := fieldRange(r) switch { case !isValidFieldNumber(r.Start(), isMessageSet): return errors.New("invalid field number: %d", r.Start()) case !isValidFieldNumber(r.End(), isMessageSet): return errors.New("invalid field number: %d", r.End()) case !(r.Start() <= r.End()): return errors.New("invalid range: %v", r) case !(rp.End() < r.Start()) && i > 0: return errors.New("overlapping ranges: %v with %v", rp, r) } rp = r } return nil } // isValidFieldNumber reports whether the field number is valid. // Unlike the FieldNumber.IsValid method, it allows ranges that cover the // reserved number range. func isValidFieldNumber(n protoreflect.FieldNumber, isMessageSet bool) bool { return protowire.MinValidNumber <= n && (n <= protowire.MaxValidNumber || isMessageSet) } // CheckOverlap reports an error if p and q overlap. func (p *FieldRanges) CheckOverlap(q *FieldRanges) error { rps := p.lazyInit().sorted rqs := q.lazyInit().sorted for pi, qi := 0, 0; pi < len(rps) && qi < len(rqs); { rp := fieldRange(rps[pi]) rq := fieldRange(rqs[qi]) if !(rp.End() < rq.Start() || rq.End() < rp.Start()) { return errors.New("overlapping ranges: %v with %v", rp, rq) } if rp.Start() < rq.Start() { pi++ } else { qi++ } } return nil } type fieldRange [2]protoreflect.FieldNumber func (r fieldRange) Start() protoreflect.FieldNumber { return r[0] } // inclusive func (r fieldRange) End() protoreflect.FieldNumber { return r[1] - 1 } // inclusive func (r fieldRange) String() string { if r.Start() == r.End() { return fmt.Sprintf("%d", r.Start()) } return fmt.Sprintf("%d to %d", r.Start(), r.End()) } type FieldNumbers struct { List []pref.FieldNumber once sync.Once has map[pref.FieldNumber]struct{} // protected by once } func (p *FieldNumbers) Len() int { return len(p.List) } func (p *FieldNumbers) Get(i int) pref.FieldNumber { return p.List[i] } func (p *FieldNumbers) Has(n pref.FieldNumber) bool { p.once.Do(func() { if len(p.List) > 0 { p.has = make(map[pref.FieldNumber]struct{}, len(p.List)) for _, n := range p.List { p.has[n] = struct{}{} } } }) _, ok := p.has[n] return ok } func (p *FieldNumbers) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *FieldNumbers) ProtoInternal(pragma.DoNotImplement) {} type OneofFields struct { List []pref.FieldDescriptor once sync.Once byName map[pref.Name]pref.FieldDescriptor // protected by once byJSON map[string]pref.FieldDescriptor // protected by once byText map[string]pref.FieldDescriptor // protected by once byNum map[pref.FieldNumber]pref.FieldDescriptor // protected by once } func (p *OneofFields) Len() int { return len(p.List) } func (p *OneofFields) Get(i int) pref.FieldDescriptor { return p.List[i] } func (p *OneofFields) ByName(s pref.Name) pref.FieldDescriptor { return p.lazyInit().byName[s] } func (p *OneofFields) ByJSONName(s string) pref.FieldDescriptor { return p.lazyInit().byJSON[s] } func (p *OneofFields) ByTextName(s string) pref.FieldDescriptor { return p.lazyInit().byText[s] } func (p *OneofFields) ByNumber(n pref.FieldNumber) pref.FieldDescriptor { return p.lazyInit().byNum[n] } func (p *OneofFields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *OneofFields) ProtoInternal(pragma.DoNotImplement) {} func (p *OneofFields) lazyInit() *OneofFields { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[pref.Name]pref.FieldDescriptor, len(p.List)) p.byJSON = make(map[string]pref.FieldDescriptor, len(p.List)) p.byText = make(map[string]pref.FieldDescriptor, len(p.List)) p.byNum = make(map[pref.FieldNumber]pref.FieldDescriptor, len(p.List)) for _, f := range p.List { // Field names and numbers are guaranteed to be unique. p.byName[f.Name()] = f p.byJSON[f.JSONName()] = f p.byText[f.TextName()] = f p.byNum[f.Number()] = f } } }) return p } type SourceLocations struct { // List is a list of SourceLocations. // The SourceLocation.Next field does not need to be populated // as it will be lazily populated upon first need. List []pref.SourceLocation // File is the parent file descriptor that these locations are relative to. // If non-nil, ByDescriptor verifies that the provided descriptor // is a child of this file descriptor. File pref.FileDescriptor once sync.Once byPath map[pathKey]int } func (p *SourceLocations) Len() int { return len(p.List) } func (p *SourceLocations) Get(i int) pref.SourceLocation { return p.lazyInit().List[i] } func (p *SourceLocations) byKey(k pathKey) pref.SourceLocation { if i, ok := p.lazyInit().byPath[k]; ok { return p.List[i] } return pref.SourceLocation{} } func (p *SourceLocations) ByPath(path pref.SourcePath) pref.SourceLocation { return p.byKey(newPathKey(path)) } func (p *SourceLocations) ByDescriptor(desc pref.Descriptor) pref.SourceLocation { if p.File != nil && desc != nil && p.File != desc.ParentFile() { return pref.SourceLocation{} // mismatching parent files } var pathArr [16]int32 path := pathArr[:0] for { switch desc.(type) { case pref.FileDescriptor: // Reverse the path since it was constructed in reverse. for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 { path[i], path[j] = path[j], path[i] } return p.byKey(newPathKey(path)) case pref.MessageDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_MessageType_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_NestedType_field_number)) default: return pref.SourceLocation{} } case pref.FieldDescriptor: isExtension := desc.(pref.FieldDescriptor).IsExtension() path = append(path, int32(desc.Index())) desc = desc.Parent() if isExtension { switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_Extension_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_Extension_field_number)) default: return pref.SourceLocation{} } } else { switch desc.(type) { case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_Field_field_number)) default: return pref.SourceLocation{} } } case pref.OneofDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_OneofDecl_field_number)) default: return pref.SourceLocation{} } case pref.EnumDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_EnumType_field_number)) case pref.MessageDescriptor: path = append(path, int32(genid.DescriptorProto_EnumType_field_number)) default: return pref.SourceLocation{} } case pref.EnumValueDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.EnumDescriptor: path = append(path, int32(genid.EnumDescriptorProto_Value_field_number)) default: return pref.SourceLocation{} } case pref.ServiceDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.FileDescriptor: path = append(path, int32(genid.FileDescriptorProto_Service_field_number)) default: return pref.SourceLocation{} } case pref.MethodDescriptor: path = append(path, int32(desc.Index())) desc = desc.Parent() switch desc.(type) { case pref.ServiceDescriptor: path = append(path, int32(genid.ServiceDescriptorProto_Method_field_number)) default: return pref.SourceLocation{} } default: return pref.SourceLocation{} } } } func (p *SourceLocations) lazyInit() *SourceLocations { p.once.Do(func() { if len(p.List) > 0 { // Collect all the indexes for a given path. pathIdxs := make(map[pathKey][]int, len(p.List)) for i, l := range p.List { k := newPathKey(l.Path) pathIdxs[k] = append(pathIdxs[k], i) } // Update the next index for all locations. p.byPath = make(map[pathKey]int, len(p.List)) for k, idxs := range pathIdxs { for i := 0; i < len(idxs)-1; i++ { p.List[idxs[i]].Next = idxs[i+1] } p.List[idxs[len(idxs)-1]].Next = 0 p.byPath[k] = idxs[0] // record the first location for this path } } }) return p } func (p *SourceLocations) ProtoInternal(pragma.DoNotImplement) {} // pathKey is a comparable representation of protoreflect.SourcePath. type pathKey struct { arr [16]uint8 // first n-1 path segments; last element is the length str string // used if the path does not fit in arr } func newPathKey(p pref.SourcePath) (k pathKey) { if len(p) < len(k.arr) { for i, ps := range p { if ps < 0 || math.MaxUint8 <= ps { return pathKey{str: p.String()} } k.arr[i] = uint8(ps) } k.arr[len(k.arr)-1] = uint8(len(p)) return k } return pathKey{str: p.String()} } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package filedesc import ( "fmt" "sync" "google.golang.org/protobuf/internal/descfmt" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" ) type Enums struct { List []Enum once sync.Once byName map[protoreflect.Name]*Enum // protected by once } func (p *Enums) Len() int { return len(p.List) } func (p *Enums) Get(i int) protoreflect.EnumDescriptor { return &p.List[i] } func (p *Enums) ByName(s protoreflect.Name) protoreflect.EnumDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Enums) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Enums) ProtoInternal(pragma.DoNotImplement) {} func (p *Enums) lazyInit() *Enums { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Enum, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type EnumValues struct { List []EnumValue once sync.Once byName map[protoreflect.Name]*EnumValue // protected by once byNum map[protoreflect.EnumNumber]*EnumValue // protected by once } func (p *EnumValues) Len() int { return len(p.List) } func (p *EnumValues) Get(i int) protoreflect.EnumValueDescriptor { return &p.List[i] } func (p *EnumValues) ByName(s protoreflect.Name) protoreflect.EnumValueDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *EnumValues) ByNumber(n protoreflect.EnumNumber) protoreflect.EnumValueDescriptor { if d := p.lazyInit().byNum[n]; d != nil { return d } return nil } func (p *EnumValues) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *EnumValues) ProtoInternal(pragma.DoNotImplement) {} func (p *EnumValues) lazyInit() *EnumValues { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*EnumValue, len(p.List)) p.byNum = make(map[protoreflect.EnumNumber]*EnumValue, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } if _, ok := p.byNum[d.Number()]; !ok { p.byNum[d.Number()] = d } } } }) return p } type Messages struct { List []Message once sync.Once byName map[protoreflect.Name]*Message // protected by once } func (p *Messages) Len() int { return len(p.List) } func (p *Messages) Get(i int) protoreflect.MessageDescriptor { return &p.List[i] } func (p *Messages) ByName(s protoreflect.Name) protoreflect.MessageDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Messages) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Messages) ProtoInternal(pragma.DoNotImplement) {} func (p *Messages) lazyInit() *Messages { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Message, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Fields struct { List []Field once sync.Once byName map[protoreflect.Name]*Field // protected by once byJSON map[string]*Field // protected by once byText map[string]*Field // protected by once byNum map[protoreflect.FieldNumber]*Field // protected by once } func (p *Fields) Len() int { return len(p.List) } func (p *Fields) Get(i int) protoreflect.FieldDescriptor { return &p.List[i] } func (p *Fields) ByName(s protoreflect.Name) protoreflect.FieldDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Fields) ByJSONName(s string) protoreflect.FieldDescriptor { if d := p.lazyInit().byJSON[s]; d != nil { return d } return nil } func (p *Fields) ByTextName(s string) protoreflect.FieldDescriptor { if d := p.lazyInit().byText[s]; d != nil { return d } return nil } func (p *Fields) ByNumber(n protoreflect.FieldNumber) protoreflect.FieldDescriptor { if d := p.lazyInit().byNum[n]; d != nil { return d } return nil } func (p *Fields) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Fields) ProtoInternal(pragma.DoNotImplement) {} func (p *Fields) lazyInit() *Fields { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Field, len(p.List)) p.byJSON = make(map[string]*Field, len(p.List)) p.byText = make(map[string]*Field, len(p.List)) p.byNum = make(map[protoreflect.FieldNumber]*Field, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } if _, ok := p.byJSON[d.JSONName()]; !ok { p.byJSON[d.JSONName()] = d } if _, ok := p.byText[d.TextName()]; !ok { p.byText[d.TextName()] = d } if _, ok := p.byNum[d.Number()]; !ok { p.byNum[d.Number()] = d } } } }) return p } type Oneofs struct { List []Oneof once sync.Once byName map[protoreflect.Name]*Oneof // protected by once } func (p *Oneofs) Len() int { return len(p.List) } func (p *Oneofs) Get(i int) protoreflect.OneofDescriptor { return &p.List[i] } func (p *Oneofs) ByName(s protoreflect.Name) protoreflect.OneofDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Oneofs) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Oneofs) ProtoInternal(pragma.DoNotImplement) {} func (p *Oneofs) lazyInit() *Oneofs { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Oneof, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Extensions struct { List []Extension once sync.Once byName map[protoreflect.Name]*Extension // protected by once } func (p *Extensions) Len() int { return len(p.List) } func (p *Extensions) Get(i int) protoreflect.ExtensionDescriptor { return &p.List[i] } func (p *Extensions) ByName(s protoreflect.Name) protoreflect.ExtensionDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Extensions) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Extensions) ProtoInternal(pragma.DoNotImplement) {} func (p *Extensions) lazyInit() *Extensions { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Extension, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Services struct { List []Service once sync.Once byName map[protoreflect.Name]*Service // protected by once } func (p *Services) Len() int { return len(p.List) } func (p *Services) Get(i int) protoreflect.ServiceDescriptor { return &p.List[i] } func (p *Services) ByName(s protoreflect.Name) protoreflect.ServiceDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Services) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Services) ProtoInternal(pragma.DoNotImplement) {} func (p *Services) lazyInit() *Services { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Service, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } type Methods struct { List []Method once sync.Once byName map[protoreflect.Name]*Method // protected by once } func (p *Methods) Len() int { return len(p.List) } func (p *Methods) Get(i int) protoreflect.MethodDescriptor { return &p.List[i] } func (p *Methods) ByName(s protoreflect.Name) protoreflect.MethodDescriptor { if d := p.lazyInit().byName[s]; d != nil { return d } return nil } func (p *Methods) Format(s fmt.State, r rune) { descfmt.FormatList(s, r, p) } func (p *Methods) ProtoInternal(pragma.DoNotImplement) {} func (p *Methods) lazyInit() *Methods { p.once.Do(func() { if len(p.List) > 0 { p.byName = make(map[protoreflect.Name]*Method, len(p.List)) for i := range p.List { d := &p.List[i] if _, ok := p.byName[d.Name()]; !ok { p.byName[d.Name()] = d } } } }) return p } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package filedesc import ( "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) var ( emptyNames = new(Names) emptyEnumRanges = new(EnumRanges) emptyFieldRanges = new(FieldRanges) emptyFieldNumbers = new(FieldNumbers) emptySourceLocations = new(SourceLocations) emptyFiles = new(FileImports) emptyMessages = new(Messages) emptyFields = new(Fields) emptyOneofs = new(Oneofs) emptyEnums = new(Enums) emptyEnumValues = new(EnumValues) emptyExtensions = new(Extensions) emptyServices = new(Services) ) // PlaceholderFile is a placeholder, representing only the file path. type PlaceholderFile string func (f PlaceholderFile) ParentFile() pref.FileDescriptor { return f } func (f PlaceholderFile) Parent() pref.Descriptor { return nil } func (f PlaceholderFile) Index() int { return 0 } func (f PlaceholderFile) Syntax() pref.Syntax { return 0 } func (f PlaceholderFile) Name() pref.Name { return "" } func (f PlaceholderFile) FullName() pref.FullName { return "" } func (f PlaceholderFile) IsPlaceholder() bool { return true } func (f PlaceholderFile) Options() pref.ProtoMessage { return descopts.File } func (f PlaceholderFile) Path() string { return string(f) } func (f PlaceholderFile) Package() pref.FullName { return "" } func (f PlaceholderFile) Imports() pref.FileImports { return emptyFiles } func (f PlaceholderFile) Messages() pref.MessageDescriptors { return emptyMessages } func (f PlaceholderFile) Enums() pref.EnumDescriptors { return emptyEnums } func (f PlaceholderFile) Extensions() pref.ExtensionDescriptors { return emptyExtensions } func (f PlaceholderFile) Services() pref.ServiceDescriptors { return emptyServices } func (f PlaceholderFile) SourceLocations() pref.SourceLocations { return emptySourceLocations } func (f PlaceholderFile) ProtoType(pref.FileDescriptor) { return } func (f PlaceholderFile) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderEnum is a placeholder, representing only the full name. type PlaceholderEnum pref.FullName func (e PlaceholderEnum) ParentFile() pref.FileDescriptor { return nil } func (e PlaceholderEnum) Parent() pref.Descriptor { return nil } func (e PlaceholderEnum) Index() int { return 0 } func (e PlaceholderEnum) Syntax() pref.Syntax { return 0 } func (e PlaceholderEnum) Name() pref.Name { return pref.FullName(e).Name() } func (e PlaceholderEnum) FullName() pref.FullName { return pref.FullName(e) } func (e PlaceholderEnum) IsPlaceholder() bool { return true } func (e PlaceholderEnum) Options() pref.ProtoMessage { return descopts.Enum } func (e PlaceholderEnum) Values() pref.EnumValueDescriptors { return emptyEnumValues } func (e PlaceholderEnum) ReservedNames() pref.Names { return emptyNames } func (e PlaceholderEnum) ReservedRanges() pref.EnumRanges { return emptyEnumRanges } func (e PlaceholderEnum) ProtoType(pref.EnumDescriptor) { return } func (e PlaceholderEnum) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderEnumValue is a placeholder, representing only the full name. type PlaceholderEnumValue pref.FullName func (e PlaceholderEnumValue) ParentFile() pref.FileDescriptor { return nil } func (e PlaceholderEnumValue) Parent() pref.Descriptor { return nil } func (e PlaceholderEnumValue) Index() int { return 0 } func (e PlaceholderEnumValue) Syntax() pref.Syntax { return 0 } func (e PlaceholderEnumValue) Name() pref.Name { return pref.FullName(e).Name() } func (e PlaceholderEnumValue) FullName() pref.FullName { return pref.FullName(e) } func (e PlaceholderEnumValue) IsPlaceholder() bool { return true } func (e PlaceholderEnumValue) Options() pref.ProtoMessage { return descopts.EnumValue } func (e PlaceholderEnumValue) Number() pref.EnumNumber { return 0 } func (e PlaceholderEnumValue) ProtoType(pref.EnumValueDescriptor) { return } func (e PlaceholderEnumValue) ProtoInternal(pragma.DoNotImplement) { return } // PlaceholderMessage is a placeholder, representing only the full name. type PlaceholderMessage pref.FullName func (m PlaceholderMessage) ParentFile() pref.FileDescriptor { return nil } func (m PlaceholderMessage) Parent() pref.Descriptor { return nil } func (m PlaceholderMessage) Index() int { return 0 } func (m PlaceholderMessage) Syntax() pref.Syntax { return 0 } func (m PlaceholderMessage) Name() pref.Name { return pref.FullName(m).Name() } func (m PlaceholderMessage) FullName() pref.FullName { return pref.FullName(m) } func (m PlaceholderMessage) IsPlaceholder() bool { return true } func (m PlaceholderMessage) Options() pref.ProtoMessage { return descopts.Message } func (m PlaceholderMessage) IsMapEntry() bool { return false } func (m PlaceholderMessage) Fields() pref.FieldDescriptors { return emptyFields } func (m PlaceholderMessage) Oneofs() pref.OneofDescriptors { return emptyOneofs } func (m PlaceholderMessage) ReservedNames() pref.Names { return emptyNames } func (m PlaceholderMessage) ReservedRanges() pref.FieldRanges { return emptyFieldRanges } func (m PlaceholderMessage) RequiredNumbers() pref.FieldNumbers { return emptyFieldNumbers } func (m PlaceholderMessage) ExtensionRanges() pref.FieldRanges { return emptyFieldRanges } func (m PlaceholderMessage) ExtensionRangeOptions(int) pref.ProtoMessage { panic("index out of range") } func (m PlaceholderMessage) Messages() pref.MessageDescriptors { return emptyMessages } func (m PlaceholderMessage) Enums() pref.EnumDescriptors { return emptyEnums } func (m PlaceholderMessage) Extensions() pref.ExtensionDescriptors { return emptyExtensions } func (m PlaceholderMessage) ProtoType(pref.MessageDescriptor) { return } func (m PlaceholderMessage) ProtoInternal(pragma.DoNotImplement) { return } ================================================ FILE: vendor/google.golang.org/protobuf/internal/filetype/build.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package filetype provides functionality for wrapping descriptors // with Go type information. package filetype import ( "reflect" "google.golang.org/protobuf/internal/descopts" fdesc "google.golang.org/protobuf/internal/filedesc" pimpl "google.golang.org/protobuf/internal/impl" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // Builder constructs type descriptors from a raw file descriptor // and associated Go types for each enum and message declaration. // // // Flattened Ordering // // The protobuf type system represents declarations as a tree. Certain nodes in // the tree require us to either associate it with a concrete Go type or to // resolve a dependency, which is information that must be provided separately // since it cannot be derived from the file descriptor alone. // // However, representing a tree as Go literals is difficult to simply do in a // space and time efficient way. Thus, we store them as a flattened list of // objects where the serialization order from the tree-based form is important. // // The "flattened ordering" is defined as a tree traversal of all enum, message, // extension, and service declarations using the following algorithm: // // def VisitFileDecls(fd): // for e in fd.Enums: yield e // for m in fd.Messages: yield m // for x in fd.Extensions: yield x // for s in fd.Services: yield s // for m in fd.Messages: yield from VisitMessageDecls(m) // // def VisitMessageDecls(md): // for e in md.Enums: yield e // for m in md.Messages: yield m // for x in md.Extensions: yield x // for m in md.Messages: yield from VisitMessageDecls(m) // // The traversal starts at the root file descriptor and yields each direct // declaration within each node before traversing into sub-declarations // that children themselves may have. type Builder struct { // File is the underlying file descriptor builder. File fdesc.Builder // GoTypes is a unique set of the Go types for all declarations and // dependencies. Each type is represented as a zero value of the Go type. // // Declarations are Go types generated for enums and messages directly // declared (not publicly imported) in the proto source file. // Messages for map entries are accounted for, but represented by nil. // Enum declarations in "flattened ordering" come first, followed by // message declarations in "flattened ordering". // // Dependencies are Go types for enums or messages referenced by // message fields (excluding weak fields), for parent extended messages of // extension fields, for enums or messages referenced by extension fields, // and for input and output messages referenced by service methods. // Dependencies must come after declarations, but the ordering of // dependencies themselves is unspecified. GoTypes []interface{} // DependencyIndexes is an ordered list of indexes into GoTypes for the // dependencies of messages, extensions, or services. // // There are 5 sub-lists in "flattened ordering" concatenated back-to-back: // 0. Message field dependencies: list of the enum or message type // referred to by every message field. // 1. Extension field targets: list of the extended parent message of // every extension. // 2. Extension field dependencies: list of the enum or message type // referred to by every extension field. // 3. Service method inputs: list of the input message type // referred to by every service method. // 4. Service method outputs: list of the output message type // referred to by every service method. // // The offset into DependencyIndexes for the start of each sub-list // is appended to the end in reverse order. DependencyIndexes []int32 // EnumInfos is a list of enum infos in "flattened ordering". EnumInfos []pimpl.EnumInfo // MessageInfos is a list of message infos in "flattened ordering". // If provided, the GoType and PBType for each element is populated. // // Requirement: len(MessageInfos) == len(Build.Messages) MessageInfos []pimpl.MessageInfo // ExtensionInfos is a list of extension infos in "flattened ordering". // Each element is initialized and registered with the protoregistry package. // // Requirement: len(LegacyExtensions) == len(Build.Extensions) ExtensionInfos []pimpl.ExtensionInfo // TypeRegistry is the registry to register each type descriptor. // If nil, it uses protoregistry.GlobalTypes. TypeRegistry interface { RegisterMessage(pref.MessageType) error RegisterEnum(pref.EnumType) error RegisterExtension(pref.ExtensionType) error } } // Out is the output of the builder. type Out struct { File pref.FileDescriptor } func (tb Builder) Build() (out Out) { // Replace the resolver with one that resolves dependencies by index, // which is faster and more reliable than relying on the global registry. if tb.File.FileRegistry == nil { tb.File.FileRegistry = preg.GlobalFiles } tb.File.FileRegistry = &resolverByIndex{ goTypes: tb.GoTypes, depIdxs: tb.DependencyIndexes, fileRegistry: tb.File.FileRegistry, } // Initialize registry if unpopulated. if tb.TypeRegistry == nil { tb.TypeRegistry = preg.GlobalTypes } fbOut := tb.File.Build() out.File = fbOut.File // Process enums. enumGoTypes := tb.GoTypes[:len(fbOut.Enums)] if len(tb.EnumInfos) != len(fbOut.Enums) { panic("mismatching enum lengths") } if len(fbOut.Enums) > 0 { for i := range fbOut.Enums { tb.EnumInfos[i] = pimpl.EnumInfo{ GoReflectType: reflect.TypeOf(enumGoTypes[i]), Desc: &fbOut.Enums[i], } // Register enum types. if err := tb.TypeRegistry.RegisterEnum(&tb.EnumInfos[i]); err != nil { panic(err) } } } // Process messages. messageGoTypes := tb.GoTypes[len(fbOut.Enums):][:len(fbOut.Messages)] if len(tb.MessageInfos) != len(fbOut.Messages) { panic("mismatching message lengths") } if len(fbOut.Messages) > 0 { for i := range fbOut.Messages { if messageGoTypes[i] == nil { continue // skip map entry } tb.MessageInfos[i].GoReflectType = reflect.TypeOf(messageGoTypes[i]) tb.MessageInfos[i].Desc = &fbOut.Messages[i] // Register message types. if err := tb.TypeRegistry.RegisterMessage(&tb.MessageInfos[i]); err != nil { panic(err) } } // As a special-case for descriptor.proto, // locally register concrete message type for the options. if out.File.Path() == "google/protobuf/descriptor.proto" && out.File.Package() == "google.protobuf" { for i := range fbOut.Messages { switch fbOut.Messages[i].Name() { case "FileOptions": descopts.File = messageGoTypes[i].(pref.ProtoMessage) case "EnumOptions": descopts.Enum = messageGoTypes[i].(pref.ProtoMessage) case "EnumValueOptions": descopts.EnumValue = messageGoTypes[i].(pref.ProtoMessage) case "MessageOptions": descopts.Message = messageGoTypes[i].(pref.ProtoMessage) case "FieldOptions": descopts.Field = messageGoTypes[i].(pref.ProtoMessage) case "OneofOptions": descopts.Oneof = messageGoTypes[i].(pref.ProtoMessage) case "ExtensionRangeOptions": descopts.ExtensionRange = messageGoTypes[i].(pref.ProtoMessage) case "ServiceOptions": descopts.Service = messageGoTypes[i].(pref.ProtoMessage) case "MethodOptions": descopts.Method = messageGoTypes[i].(pref.ProtoMessage) } } } } // Process extensions. if len(tb.ExtensionInfos) != len(fbOut.Extensions) { panic("mismatching extension lengths") } var depIdx int32 for i := range fbOut.Extensions { // For enum and message kinds, determine the referent Go type so // that we can construct their constructors. const listExtDeps = 2 var goType reflect.Type switch fbOut.Extensions[i].L1.Kind { case pref.EnumKind: j := depIdxs.Get(tb.DependencyIndexes, listExtDeps, depIdx) goType = reflect.TypeOf(tb.GoTypes[j]) depIdx++ case pref.MessageKind, pref.GroupKind: j := depIdxs.Get(tb.DependencyIndexes, listExtDeps, depIdx) goType = reflect.TypeOf(tb.GoTypes[j]) depIdx++ default: goType = goTypeForPBKind[fbOut.Extensions[i].L1.Kind] } if fbOut.Extensions[i].IsList() { goType = reflect.SliceOf(goType) } pimpl.InitExtensionInfo(&tb.ExtensionInfos[i], &fbOut.Extensions[i], goType) // Register extension types. if err := tb.TypeRegistry.RegisterExtension(&tb.ExtensionInfos[i]); err != nil { panic(err) } } return out } var goTypeForPBKind = map[pref.Kind]reflect.Type{ pref.BoolKind: reflect.TypeOf(bool(false)), pref.Int32Kind: reflect.TypeOf(int32(0)), pref.Sint32Kind: reflect.TypeOf(int32(0)), pref.Sfixed32Kind: reflect.TypeOf(int32(0)), pref.Int64Kind: reflect.TypeOf(int64(0)), pref.Sint64Kind: reflect.TypeOf(int64(0)), pref.Sfixed64Kind: reflect.TypeOf(int64(0)), pref.Uint32Kind: reflect.TypeOf(uint32(0)), pref.Fixed32Kind: reflect.TypeOf(uint32(0)), pref.Uint64Kind: reflect.TypeOf(uint64(0)), pref.Fixed64Kind: reflect.TypeOf(uint64(0)), pref.FloatKind: reflect.TypeOf(float32(0)), pref.DoubleKind: reflect.TypeOf(float64(0)), pref.StringKind: reflect.TypeOf(string("")), pref.BytesKind: reflect.TypeOf([]byte(nil)), } type depIdxs []int32 // Get retrieves the jth element of the ith sub-list. func (x depIdxs) Get(i, j int32) int32 { return x[x[int32(len(x))-i-1]+j] } type ( resolverByIndex struct { goTypes []interface{} depIdxs depIdxs fileRegistry } fileRegistry interface { FindFileByPath(string) (pref.FileDescriptor, error) FindDescriptorByName(pref.FullName) (pref.Descriptor, error) RegisterFile(pref.FileDescriptor) error } ) func (r *resolverByIndex) FindEnumByIndex(i, j int32, es []fdesc.Enum, ms []fdesc.Message) pref.EnumDescriptor { if depIdx := int(r.depIdxs.Get(i, j)); int(depIdx) < len(es)+len(ms) { return &es[depIdx] } else { return pimpl.Export{}.EnumDescriptorOf(r.goTypes[depIdx]) } } func (r *resolverByIndex) FindMessageByIndex(i, j int32, es []fdesc.Enum, ms []fdesc.Message) pref.MessageDescriptor { if depIdx := int(r.depIdxs.Get(i, j)); depIdx < len(es)+len(ms) { return &ms[depIdx-len(es)] } else { return pimpl.Export{}.MessageDescriptorOf(r.goTypes[depIdx]) } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/flags/flags.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package flags provides a set of flags controlled by build tags. package flags // ProtoLegacy specifies whether to enable support for legacy functionality // such as MessageSets, weak fields, and various other obscure behavior // that is necessary to maintain backwards compatibility with proto1 or // the pre-release variants of proto2 and proto3. // // This is disabled by default unless built with the "protolegacy" tag. // // WARNING: The compatibility agreement covers nothing provided by this flag. // As such, functionality may suddenly be removed or changed at our discretion. const ProtoLegacy = protoLegacy // LazyUnmarshalExtensions specifies whether to lazily unmarshal extensions. // // Lazy extension unmarshaling validates the contents of message-valued // extension fields at unmarshal time, but defers creating the message // structure until the extension is first accessed. const LazyUnmarshalExtensions = ProtoLegacy ================================================ FILE: vendor/google.golang.org/protobuf/internal/flags/proto_legacy_disable.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !protolegacy package flags const protoLegacy = false ================================================ FILE: vendor/google.golang.org/protobuf/internal/flags/proto_legacy_enable.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build protolegacy package flags const protoLegacy = true ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/any_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_any_proto = "google/protobuf/any.proto" // Names for google.protobuf.Any. const ( Any_message_name protoreflect.Name = "Any" Any_message_fullname protoreflect.FullName = "google.protobuf.Any" ) // Field names for google.protobuf.Any. const ( Any_TypeUrl_field_name protoreflect.Name = "type_url" Any_Value_field_name protoreflect.Name = "value" Any_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Any.type_url" Any_Value_field_fullname protoreflect.FullName = "google.protobuf.Any.value" ) // Field numbers for google.protobuf.Any. const ( Any_TypeUrl_field_number protoreflect.FieldNumber = 1 Any_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/api_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_api_proto = "google/protobuf/api.proto" // Names for google.protobuf.Api. const ( Api_message_name protoreflect.Name = "Api" Api_message_fullname protoreflect.FullName = "google.protobuf.Api" ) // Field names for google.protobuf.Api. const ( Api_Name_field_name protoreflect.Name = "name" Api_Methods_field_name protoreflect.Name = "methods" Api_Options_field_name protoreflect.Name = "options" Api_Version_field_name protoreflect.Name = "version" Api_SourceContext_field_name protoreflect.Name = "source_context" Api_Mixins_field_name protoreflect.Name = "mixins" Api_Syntax_field_name protoreflect.Name = "syntax" Api_Name_field_fullname protoreflect.FullName = "google.protobuf.Api.name" Api_Methods_field_fullname protoreflect.FullName = "google.protobuf.Api.methods" Api_Options_field_fullname protoreflect.FullName = "google.protobuf.Api.options" Api_Version_field_fullname protoreflect.FullName = "google.protobuf.Api.version" Api_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Api.source_context" Api_Mixins_field_fullname protoreflect.FullName = "google.protobuf.Api.mixins" Api_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Api.syntax" ) // Field numbers for google.protobuf.Api. const ( Api_Name_field_number protoreflect.FieldNumber = 1 Api_Methods_field_number protoreflect.FieldNumber = 2 Api_Options_field_number protoreflect.FieldNumber = 3 Api_Version_field_number protoreflect.FieldNumber = 4 Api_SourceContext_field_number protoreflect.FieldNumber = 5 Api_Mixins_field_number protoreflect.FieldNumber = 6 Api_Syntax_field_number protoreflect.FieldNumber = 7 ) // Names for google.protobuf.Method. const ( Method_message_name protoreflect.Name = "Method" Method_message_fullname protoreflect.FullName = "google.protobuf.Method" ) // Field names for google.protobuf.Method. const ( Method_Name_field_name protoreflect.Name = "name" Method_RequestTypeUrl_field_name protoreflect.Name = "request_type_url" Method_RequestStreaming_field_name protoreflect.Name = "request_streaming" Method_ResponseTypeUrl_field_name protoreflect.Name = "response_type_url" Method_ResponseStreaming_field_name protoreflect.Name = "response_streaming" Method_Options_field_name protoreflect.Name = "options" Method_Syntax_field_name protoreflect.Name = "syntax" Method_Name_field_fullname protoreflect.FullName = "google.protobuf.Method.name" Method_RequestTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.request_type_url" Method_RequestStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.request_streaming" Method_ResponseTypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Method.response_type_url" Method_ResponseStreaming_field_fullname protoreflect.FullName = "google.protobuf.Method.response_streaming" Method_Options_field_fullname protoreflect.FullName = "google.protobuf.Method.options" Method_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Method.syntax" ) // Field numbers for google.protobuf.Method. const ( Method_Name_field_number protoreflect.FieldNumber = 1 Method_RequestTypeUrl_field_number protoreflect.FieldNumber = 2 Method_RequestStreaming_field_number protoreflect.FieldNumber = 3 Method_ResponseTypeUrl_field_number protoreflect.FieldNumber = 4 Method_ResponseStreaming_field_number protoreflect.FieldNumber = 5 Method_Options_field_number protoreflect.FieldNumber = 6 Method_Syntax_field_number protoreflect.FieldNumber = 7 ) // Names for google.protobuf.Mixin. const ( Mixin_message_name protoreflect.Name = "Mixin" Mixin_message_fullname protoreflect.FullName = "google.protobuf.Mixin" ) // Field names for google.protobuf.Mixin. const ( Mixin_Name_field_name protoreflect.Name = "name" Mixin_Root_field_name protoreflect.Name = "root" Mixin_Name_field_fullname protoreflect.FullName = "google.protobuf.Mixin.name" Mixin_Root_field_fullname protoreflect.FullName = "google.protobuf.Mixin.root" ) // Field numbers for google.protobuf.Mixin. const ( Mixin_Name_field_number protoreflect.FieldNumber = 1 Mixin_Root_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_descriptor_proto = "google/protobuf/descriptor.proto" // Names for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_message_name protoreflect.Name = "FileDescriptorSet" FileDescriptorSet_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet" ) // Field names for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_File_field_name protoreflect.Name = "file" FileDescriptorSet_File_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorSet.file" ) // Field numbers for google.protobuf.FileDescriptorSet. const ( FileDescriptorSet_File_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_message_name protoreflect.Name = "FileDescriptorProto" FileDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto" ) // Field names for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_Name_field_name protoreflect.Name = "name" FileDescriptorProto_Package_field_name protoreflect.Name = "package" FileDescriptorProto_Dependency_field_name protoreflect.Name = "dependency" FileDescriptorProto_PublicDependency_field_name protoreflect.Name = "public_dependency" FileDescriptorProto_WeakDependency_field_name protoreflect.Name = "weak_dependency" FileDescriptorProto_MessageType_field_name protoreflect.Name = "message_type" FileDescriptorProto_EnumType_field_name protoreflect.Name = "enum_type" FileDescriptorProto_Service_field_name protoreflect.Name = "service" FileDescriptorProto_Extension_field_name protoreflect.Name = "extension" FileDescriptorProto_Options_field_name protoreflect.Name = "options" FileDescriptorProto_SourceCodeInfo_field_name protoreflect.Name = "source_code_info" FileDescriptorProto_Syntax_field_name protoreflect.Name = "syntax" FileDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.name" FileDescriptorProto_Package_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.package" FileDescriptorProto_Dependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.dependency" FileDescriptorProto_PublicDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.public_dependency" FileDescriptorProto_WeakDependency_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.weak_dependency" FileDescriptorProto_MessageType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.message_type" FileDescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.enum_type" FileDescriptorProto_Service_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.service" FileDescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.extension" FileDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.options" FileDescriptorProto_SourceCodeInfo_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.source_code_info" FileDescriptorProto_Syntax_field_fullname protoreflect.FullName = "google.protobuf.FileDescriptorProto.syntax" ) // Field numbers for google.protobuf.FileDescriptorProto. const ( FileDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 FileDescriptorProto_Package_field_number protoreflect.FieldNumber = 2 FileDescriptorProto_Dependency_field_number protoreflect.FieldNumber = 3 FileDescriptorProto_PublicDependency_field_number protoreflect.FieldNumber = 10 FileDescriptorProto_WeakDependency_field_number protoreflect.FieldNumber = 11 FileDescriptorProto_MessageType_field_number protoreflect.FieldNumber = 4 FileDescriptorProto_EnumType_field_number protoreflect.FieldNumber = 5 FileDescriptorProto_Service_field_number protoreflect.FieldNumber = 6 FileDescriptorProto_Extension_field_number protoreflect.FieldNumber = 7 FileDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FileDescriptorProto_SourceCodeInfo_field_number protoreflect.FieldNumber = 9 FileDescriptorProto_Syntax_field_number protoreflect.FieldNumber = 12 ) // Names for google.protobuf.DescriptorProto. const ( DescriptorProto_message_name protoreflect.Name = "DescriptorProto" DescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto" ) // Field names for google.protobuf.DescriptorProto. const ( DescriptorProto_Name_field_name protoreflect.Name = "name" DescriptorProto_Field_field_name protoreflect.Name = "field" DescriptorProto_Extension_field_name protoreflect.Name = "extension" DescriptorProto_NestedType_field_name protoreflect.Name = "nested_type" DescriptorProto_EnumType_field_name protoreflect.Name = "enum_type" DescriptorProto_ExtensionRange_field_name protoreflect.Name = "extension_range" DescriptorProto_OneofDecl_field_name protoreflect.Name = "oneof_decl" DescriptorProto_Options_field_name protoreflect.Name = "options" DescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range" DescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name" DescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.name" DescriptorProto_Field_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.field" DescriptorProto_Extension_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension" DescriptorProto_NestedType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.nested_type" DescriptorProto_EnumType_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.enum_type" DescriptorProto_ExtensionRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.extension_range" DescriptorProto_OneofDecl_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.oneof_decl" DescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.options" DescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_range" DescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.reserved_name" ) // Field numbers for google.protobuf.DescriptorProto. const ( DescriptorProto_Name_field_number protoreflect.FieldNumber = 1 DescriptorProto_Field_field_number protoreflect.FieldNumber = 2 DescriptorProto_Extension_field_number protoreflect.FieldNumber = 6 DescriptorProto_NestedType_field_number protoreflect.FieldNumber = 3 DescriptorProto_EnumType_field_number protoreflect.FieldNumber = 4 DescriptorProto_ExtensionRange_field_number protoreflect.FieldNumber = 5 DescriptorProto_OneofDecl_field_number protoreflect.FieldNumber = 8 DescriptorProto_Options_field_number protoreflect.FieldNumber = 7 DescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 9 DescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 10 ) // Names for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_message_name protoreflect.Name = "ExtensionRange" DescriptorProto_ExtensionRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange" ) // Field names for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_Start_field_name protoreflect.Name = "start" DescriptorProto_ExtensionRange_End_field_name protoreflect.Name = "end" DescriptorProto_ExtensionRange_Options_field_name protoreflect.Name = "options" DescriptorProto_ExtensionRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.start" DescriptorProto_ExtensionRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.end" DescriptorProto_ExtensionRange_Options_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ExtensionRange.options" ) // Field numbers for google.protobuf.DescriptorProto.ExtensionRange. const ( DescriptorProto_ExtensionRange_Start_field_number protoreflect.FieldNumber = 1 DescriptorProto_ExtensionRange_End_field_number protoreflect.FieldNumber = 2 DescriptorProto_ExtensionRange_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_message_name protoreflect.Name = "ReservedRange" DescriptorProto_ReservedRange_message_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange" ) // Field names for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_Start_field_name protoreflect.Name = "start" DescriptorProto_ReservedRange_End_field_name protoreflect.Name = "end" DescriptorProto_ReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.start" DescriptorProto_ReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.DescriptorProto.ReservedRange.end" ) // Field numbers for google.protobuf.DescriptorProto.ReservedRange. const ( DescriptorProto_ReservedRange_Start_field_number protoreflect.FieldNumber = 1 DescriptorProto_ReservedRange_End_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_message_name protoreflect.Name = "ExtensionRangeOptions" ExtensionRangeOptions_message_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions" ) // Field names for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ExtensionRangeOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ExtensionRangeOptions.uninterpreted_option" ) // Field numbers for google.protobuf.ExtensionRangeOptions. const ( ExtensionRangeOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_message_name protoreflect.Name = "FieldDescriptorProto" FieldDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto" ) // Field names for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_Name_field_name protoreflect.Name = "name" FieldDescriptorProto_Number_field_name protoreflect.Name = "number" FieldDescriptorProto_Label_field_name protoreflect.Name = "label" FieldDescriptorProto_Type_field_name protoreflect.Name = "type" FieldDescriptorProto_TypeName_field_name protoreflect.Name = "type_name" FieldDescriptorProto_Extendee_field_name protoreflect.Name = "extendee" FieldDescriptorProto_DefaultValue_field_name protoreflect.Name = "default_value" FieldDescriptorProto_OneofIndex_field_name protoreflect.Name = "oneof_index" FieldDescriptorProto_JsonName_field_name protoreflect.Name = "json_name" FieldDescriptorProto_Options_field_name protoreflect.Name = "options" FieldDescriptorProto_Proto3Optional_field_name protoreflect.Name = "proto3_optional" FieldDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.name" FieldDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.number" FieldDescriptorProto_Label_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.label" FieldDescriptorProto_Type_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type" FieldDescriptorProto_TypeName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.type_name" FieldDescriptorProto_Extendee_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.extendee" FieldDescriptorProto_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.default_value" FieldDescriptorProto_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.oneof_index" FieldDescriptorProto_JsonName_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.json_name" FieldDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.options" FieldDescriptorProto_Proto3Optional_field_fullname protoreflect.FullName = "google.protobuf.FieldDescriptorProto.proto3_optional" ) // Field numbers for google.protobuf.FieldDescriptorProto. const ( FieldDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 FieldDescriptorProto_Number_field_number protoreflect.FieldNumber = 3 FieldDescriptorProto_Label_field_number protoreflect.FieldNumber = 4 FieldDescriptorProto_Type_field_number protoreflect.FieldNumber = 5 FieldDescriptorProto_TypeName_field_number protoreflect.FieldNumber = 6 FieldDescriptorProto_Extendee_field_number protoreflect.FieldNumber = 2 FieldDescriptorProto_DefaultValue_field_number protoreflect.FieldNumber = 7 FieldDescriptorProto_OneofIndex_field_number protoreflect.FieldNumber = 9 FieldDescriptorProto_JsonName_field_number protoreflect.FieldNumber = 10 FieldDescriptorProto_Options_field_number protoreflect.FieldNumber = 8 FieldDescriptorProto_Proto3Optional_field_number protoreflect.FieldNumber = 17 ) // Full and short names for google.protobuf.FieldDescriptorProto.Type. const ( FieldDescriptorProto_Type_enum_fullname = "google.protobuf.FieldDescriptorProto.Type" FieldDescriptorProto_Type_enum_name = "Type" ) // Full and short names for google.protobuf.FieldDescriptorProto.Label. const ( FieldDescriptorProto_Label_enum_fullname = "google.protobuf.FieldDescriptorProto.Label" FieldDescriptorProto_Label_enum_name = "Label" ) // Names for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_message_name protoreflect.Name = "OneofDescriptorProto" OneofDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto" ) // Field names for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_Name_field_name protoreflect.Name = "name" OneofDescriptorProto_Options_field_name protoreflect.Name = "options" OneofDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.name" OneofDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.OneofDescriptorProto.options" ) // Field numbers for google.protobuf.OneofDescriptorProto. const ( OneofDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 OneofDescriptorProto_Options_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_message_name protoreflect.Name = "EnumDescriptorProto" EnumDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto" ) // Field names for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_Name_field_name protoreflect.Name = "name" EnumDescriptorProto_Value_field_name protoreflect.Name = "value" EnumDescriptorProto_Options_field_name protoreflect.Name = "options" EnumDescriptorProto_ReservedRange_field_name protoreflect.Name = "reserved_range" EnumDescriptorProto_ReservedName_field_name protoreflect.Name = "reserved_name" EnumDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.name" EnumDescriptorProto_Value_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.value" EnumDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.options" EnumDescriptorProto_ReservedRange_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_range" EnumDescriptorProto_ReservedName_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.reserved_name" ) // Field numbers for google.protobuf.EnumDescriptorProto. const ( EnumDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 EnumDescriptorProto_Value_field_number protoreflect.FieldNumber = 2 EnumDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 EnumDescriptorProto_ReservedRange_field_number protoreflect.FieldNumber = 4 EnumDescriptorProto_ReservedName_field_number protoreflect.FieldNumber = 5 ) // Names for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_message_name protoreflect.Name = "EnumReservedRange" EnumDescriptorProto_EnumReservedRange_message_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange" ) // Field names for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_Start_field_name protoreflect.Name = "start" EnumDescriptorProto_EnumReservedRange_End_field_name protoreflect.Name = "end" EnumDescriptorProto_EnumReservedRange_Start_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.start" EnumDescriptorProto_EnumReservedRange_End_field_fullname protoreflect.FullName = "google.protobuf.EnumDescriptorProto.EnumReservedRange.end" ) // Field numbers for google.protobuf.EnumDescriptorProto.EnumReservedRange. const ( EnumDescriptorProto_EnumReservedRange_Start_field_number protoreflect.FieldNumber = 1 EnumDescriptorProto_EnumReservedRange_End_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_message_name protoreflect.Name = "EnumValueDescriptorProto" EnumValueDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto" ) // Field names for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_Name_field_name protoreflect.Name = "name" EnumValueDescriptorProto_Number_field_name protoreflect.Name = "number" EnumValueDescriptorProto_Options_field_name protoreflect.Name = "options" EnumValueDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.name" EnumValueDescriptorProto_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.number" EnumValueDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValueDescriptorProto.options" ) // Field numbers for google.protobuf.EnumValueDescriptorProto. const ( EnumValueDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 EnumValueDescriptorProto_Number_field_number protoreflect.FieldNumber = 2 EnumValueDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_message_name protoreflect.Name = "ServiceDescriptorProto" ServiceDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto" ) // Field names for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_Name_field_name protoreflect.Name = "name" ServiceDescriptorProto_Method_field_name protoreflect.Name = "method" ServiceDescriptorProto_Options_field_name protoreflect.Name = "options" ServiceDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.name" ServiceDescriptorProto_Method_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.method" ServiceDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.ServiceDescriptorProto.options" ) // Field numbers for google.protobuf.ServiceDescriptorProto. const ( ServiceDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 ServiceDescriptorProto_Method_field_number protoreflect.FieldNumber = 2 ServiceDescriptorProto_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_message_name protoreflect.Name = "MethodDescriptorProto" MethodDescriptorProto_message_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto" ) // Field names for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_Name_field_name protoreflect.Name = "name" MethodDescriptorProto_InputType_field_name protoreflect.Name = "input_type" MethodDescriptorProto_OutputType_field_name protoreflect.Name = "output_type" MethodDescriptorProto_Options_field_name protoreflect.Name = "options" MethodDescriptorProto_ClientStreaming_field_name protoreflect.Name = "client_streaming" MethodDescriptorProto_ServerStreaming_field_name protoreflect.Name = "server_streaming" MethodDescriptorProto_Name_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.name" MethodDescriptorProto_InputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.input_type" MethodDescriptorProto_OutputType_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.output_type" MethodDescriptorProto_Options_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.options" MethodDescriptorProto_ClientStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.client_streaming" MethodDescriptorProto_ServerStreaming_field_fullname protoreflect.FullName = "google.protobuf.MethodDescriptorProto.server_streaming" ) // Field numbers for google.protobuf.MethodDescriptorProto. const ( MethodDescriptorProto_Name_field_number protoreflect.FieldNumber = 1 MethodDescriptorProto_InputType_field_number protoreflect.FieldNumber = 2 MethodDescriptorProto_OutputType_field_number protoreflect.FieldNumber = 3 MethodDescriptorProto_Options_field_number protoreflect.FieldNumber = 4 MethodDescriptorProto_ClientStreaming_field_number protoreflect.FieldNumber = 5 MethodDescriptorProto_ServerStreaming_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.FileOptions. const ( FileOptions_message_name protoreflect.Name = "FileOptions" FileOptions_message_fullname protoreflect.FullName = "google.protobuf.FileOptions" ) // Field names for google.protobuf.FileOptions. const ( FileOptions_JavaPackage_field_name protoreflect.Name = "java_package" FileOptions_JavaOuterClassname_field_name protoreflect.Name = "java_outer_classname" FileOptions_JavaMultipleFiles_field_name protoreflect.Name = "java_multiple_files" FileOptions_JavaGenerateEqualsAndHash_field_name protoreflect.Name = "java_generate_equals_and_hash" FileOptions_JavaStringCheckUtf8_field_name protoreflect.Name = "java_string_check_utf8" FileOptions_OptimizeFor_field_name protoreflect.Name = "optimize_for" FileOptions_GoPackage_field_name protoreflect.Name = "go_package" FileOptions_CcGenericServices_field_name protoreflect.Name = "cc_generic_services" FileOptions_JavaGenericServices_field_name protoreflect.Name = "java_generic_services" FileOptions_PyGenericServices_field_name protoreflect.Name = "py_generic_services" FileOptions_PhpGenericServices_field_name protoreflect.Name = "php_generic_services" FileOptions_Deprecated_field_name protoreflect.Name = "deprecated" FileOptions_CcEnableArenas_field_name protoreflect.Name = "cc_enable_arenas" FileOptions_ObjcClassPrefix_field_name protoreflect.Name = "objc_class_prefix" FileOptions_CsharpNamespace_field_name protoreflect.Name = "csharp_namespace" FileOptions_SwiftPrefix_field_name protoreflect.Name = "swift_prefix" FileOptions_PhpClassPrefix_field_name protoreflect.Name = "php_class_prefix" FileOptions_PhpNamespace_field_name protoreflect.Name = "php_namespace" FileOptions_PhpMetadataNamespace_field_name protoreflect.Name = "php_metadata_namespace" FileOptions_RubyPackage_field_name protoreflect.Name = "ruby_package" FileOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FileOptions_JavaPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_package" FileOptions_JavaOuterClassname_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_outer_classname" FileOptions_JavaMultipleFiles_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_multiple_files" FileOptions_JavaGenerateEqualsAndHash_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generate_equals_and_hash" FileOptions_JavaStringCheckUtf8_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_string_check_utf8" FileOptions_OptimizeFor_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.optimize_for" FileOptions_GoPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.go_package" FileOptions_CcGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_generic_services" FileOptions_JavaGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.java_generic_services" FileOptions_PyGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.py_generic_services" FileOptions_PhpGenericServices_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_generic_services" FileOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.deprecated" FileOptions_CcEnableArenas_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.cc_enable_arenas" FileOptions_ObjcClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.objc_class_prefix" FileOptions_CsharpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.csharp_namespace" FileOptions_SwiftPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.swift_prefix" FileOptions_PhpClassPrefix_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_class_prefix" FileOptions_PhpNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_namespace" FileOptions_PhpMetadataNamespace_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.php_metadata_namespace" FileOptions_RubyPackage_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.ruby_package" FileOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FileOptions.uninterpreted_option" ) // Field numbers for google.protobuf.FileOptions. const ( FileOptions_JavaPackage_field_number protoreflect.FieldNumber = 1 FileOptions_JavaOuterClassname_field_number protoreflect.FieldNumber = 8 FileOptions_JavaMultipleFiles_field_number protoreflect.FieldNumber = 10 FileOptions_JavaGenerateEqualsAndHash_field_number protoreflect.FieldNumber = 20 FileOptions_JavaStringCheckUtf8_field_number protoreflect.FieldNumber = 27 FileOptions_OptimizeFor_field_number protoreflect.FieldNumber = 9 FileOptions_GoPackage_field_number protoreflect.FieldNumber = 11 FileOptions_CcGenericServices_field_number protoreflect.FieldNumber = 16 FileOptions_JavaGenericServices_field_number protoreflect.FieldNumber = 17 FileOptions_PyGenericServices_field_number protoreflect.FieldNumber = 18 FileOptions_PhpGenericServices_field_number protoreflect.FieldNumber = 42 FileOptions_Deprecated_field_number protoreflect.FieldNumber = 23 FileOptions_CcEnableArenas_field_number protoreflect.FieldNumber = 31 FileOptions_ObjcClassPrefix_field_number protoreflect.FieldNumber = 36 FileOptions_CsharpNamespace_field_number protoreflect.FieldNumber = 37 FileOptions_SwiftPrefix_field_number protoreflect.FieldNumber = 39 FileOptions_PhpClassPrefix_field_number protoreflect.FieldNumber = 40 FileOptions_PhpNamespace_field_number protoreflect.FieldNumber = 41 FileOptions_PhpMetadataNamespace_field_number protoreflect.FieldNumber = 44 FileOptions_RubyPackage_field_number protoreflect.FieldNumber = 45 FileOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.FileOptions.OptimizeMode. const ( FileOptions_OptimizeMode_enum_fullname = "google.protobuf.FileOptions.OptimizeMode" FileOptions_OptimizeMode_enum_name = "OptimizeMode" ) // Names for google.protobuf.MessageOptions. const ( MessageOptions_message_name protoreflect.Name = "MessageOptions" MessageOptions_message_fullname protoreflect.FullName = "google.protobuf.MessageOptions" ) // Field names for google.protobuf.MessageOptions. const ( MessageOptions_MessageSetWireFormat_field_name protoreflect.Name = "message_set_wire_format" MessageOptions_NoStandardDescriptorAccessor_field_name protoreflect.Name = "no_standard_descriptor_accessor" MessageOptions_Deprecated_field_name protoreflect.Name = "deprecated" MessageOptions_MapEntry_field_name protoreflect.Name = "map_entry" MessageOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MessageOptions_MessageSetWireFormat_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.message_set_wire_format" MessageOptions_NoStandardDescriptorAccessor_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.no_standard_descriptor_accessor" MessageOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.deprecated" MessageOptions_MapEntry_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.map_entry" MessageOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MessageOptions.uninterpreted_option" ) // Field numbers for google.protobuf.MessageOptions. const ( MessageOptions_MessageSetWireFormat_field_number protoreflect.FieldNumber = 1 MessageOptions_NoStandardDescriptorAccessor_field_number protoreflect.FieldNumber = 2 MessageOptions_Deprecated_field_number protoreflect.FieldNumber = 3 MessageOptions_MapEntry_field_number protoreflect.FieldNumber = 7 MessageOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.FieldOptions. const ( FieldOptions_message_name protoreflect.Name = "FieldOptions" FieldOptions_message_fullname protoreflect.FullName = "google.protobuf.FieldOptions" ) // Field names for google.protobuf.FieldOptions. const ( FieldOptions_Ctype_field_name protoreflect.Name = "ctype" FieldOptions_Packed_field_name protoreflect.Name = "packed" FieldOptions_Jstype_field_name protoreflect.Name = "jstype" FieldOptions_Lazy_field_name protoreflect.Name = "lazy" FieldOptions_Deprecated_field_name protoreflect.Name = "deprecated" FieldOptions_Weak_field_name protoreflect.Name = "weak" FieldOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" FieldOptions_Ctype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.ctype" FieldOptions_Packed_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.packed" FieldOptions_Jstype_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.jstype" FieldOptions_Lazy_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.lazy" FieldOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.deprecated" FieldOptions_Weak_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.weak" FieldOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.FieldOptions.uninterpreted_option" ) // Field numbers for google.protobuf.FieldOptions. const ( FieldOptions_Ctype_field_number protoreflect.FieldNumber = 1 FieldOptions_Packed_field_number protoreflect.FieldNumber = 2 FieldOptions_Jstype_field_number protoreflect.FieldNumber = 6 FieldOptions_Lazy_field_number protoreflect.FieldNumber = 5 FieldOptions_Deprecated_field_number protoreflect.FieldNumber = 3 FieldOptions_Weak_field_number protoreflect.FieldNumber = 10 FieldOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.FieldOptions.CType. const ( FieldOptions_CType_enum_fullname = "google.protobuf.FieldOptions.CType" FieldOptions_CType_enum_name = "CType" ) // Full and short names for google.protobuf.FieldOptions.JSType. const ( FieldOptions_JSType_enum_fullname = "google.protobuf.FieldOptions.JSType" FieldOptions_JSType_enum_name = "JSType" ) // Names for google.protobuf.OneofOptions. const ( OneofOptions_message_name protoreflect.Name = "OneofOptions" OneofOptions_message_fullname protoreflect.FullName = "google.protobuf.OneofOptions" ) // Field names for google.protobuf.OneofOptions. const ( OneofOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" OneofOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.OneofOptions.uninterpreted_option" ) // Field numbers for google.protobuf.OneofOptions. const ( OneofOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.EnumOptions. const ( EnumOptions_message_name protoreflect.Name = "EnumOptions" EnumOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumOptions" ) // Field names for google.protobuf.EnumOptions. const ( EnumOptions_AllowAlias_field_name protoreflect.Name = "allow_alias" EnumOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumOptions_AllowAlias_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.allow_alias" EnumOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.deprecated" EnumOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumOptions.uninterpreted_option" ) // Field numbers for google.protobuf.EnumOptions. const ( EnumOptions_AllowAlias_field_number protoreflect.FieldNumber = 2 EnumOptions_Deprecated_field_number protoreflect.FieldNumber = 3 EnumOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.EnumValueOptions. const ( EnumValueOptions_message_name protoreflect.Name = "EnumValueOptions" EnumValueOptions_message_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions" ) // Field names for google.protobuf.EnumValueOptions. const ( EnumValueOptions_Deprecated_field_name protoreflect.Name = "deprecated" EnumValueOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" EnumValueOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.deprecated" EnumValueOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.EnumValueOptions.uninterpreted_option" ) // Field numbers for google.protobuf.EnumValueOptions. const ( EnumValueOptions_Deprecated_field_number protoreflect.FieldNumber = 1 EnumValueOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.ServiceOptions. const ( ServiceOptions_message_name protoreflect.Name = "ServiceOptions" ServiceOptions_message_fullname protoreflect.FullName = "google.protobuf.ServiceOptions" ) // Field names for google.protobuf.ServiceOptions. const ( ServiceOptions_Deprecated_field_name protoreflect.Name = "deprecated" ServiceOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" ServiceOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.deprecated" ServiceOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.ServiceOptions.uninterpreted_option" ) // Field numbers for google.protobuf.ServiceOptions. const ( ServiceOptions_Deprecated_field_number protoreflect.FieldNumber = 33 ServiceOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Names for google.protobuf.MethodOptions. const ( MethodOptions_message_name protoreflect.Name = "MethodOptions" MethodOptions_message_fullname protoreflect.FullName = "google.protobuf.MethodOptions" ) // Field names for google.protobuf.MethodOptions. const ( MethodOptions_Deprecated_field_name protoreflect.Name = "deprecated" MethodOptions_IdempotencyLevel_field_name protoreflect.Name = "idempotency_level" MethodOptions_UninterpretedOption_field_name protoreflect.Name = "uninterpreted_option" MethodOptions_Deprecated_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.deprecated" MethodOptions_IdempotencyLevel_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.idempotency_level" MethodOptions_UninterpretedOption_field_fullname protoreflect.FullName = "google.protobuf.MethodOptions.uninterpreted_option" ) // Field numbers for google.protobuf.MethodOptions. const ( MethodOptions_Deprecated_field_number protoreflect.FieldNumber = 33 MethodOptions_IdempotencyLevel_field_number protoreflect.FieldNumber = 34 MethodOptions_UninterpretedOption_field_number protoreflect.FieldNumber = 999 ) // Full and short names for google.protobuf.MethodOptions.IdempotencyLevel. const ( MethodOptions_IdempotencyLevel_enum_fullname = "google.protobuf.MethodOptions.IdempotencyLevel" MethodOptions_IdempotencyLevel_enum_name = "IdempotencyLevel" ) // Names for google.protobuf.UninterpretedOption. const ( UninterpretedOption_message_name protoreflect.Name = "UninterpretedOption" UninterpretedOption_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption" ) // Field names for google.protobuf.UninterpretedOption. const ( UninterpretedOption_Name_field_name protoreflect.Name = "name" UninterpretedOption_IdentifierValue_field_name protoreflect.Name = "identifier_value" UninterpretedOption_PositiveIntValue_field_name protoreflect.Name = "positive_int_value" UninterpretedOption_NegativeIntValue_field_name protoreflect.Name = "negative_int_value" UninterpretedOption_DoubleValue_field_name protoreflect.Name = "double_value" UninterpretedOption_StringValue_field_name protoreflect.Name = "string_value" UninterpretedOption_AggregateValue_field_name protoreflect.Name = "aggregate_value" UninterpretedOption_Name_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.name" UninterpretedOption_IdentifierValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.identifier_value" UninterpretedOption_PositiveIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.positive_int_value" UninterpretedOption_NegativeIntValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.negative_int_value" UninterpretedOption_DoubleValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.double_value" UninterpretedOption_StringValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.string_value" UninterpretedOption_AggregateValue_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.aggregate_value" ) // Field numbers for google.protobuf.UninterpretedOption. const ( UninterpretedOption_Name_field_number protoreflect.FieldNumber = 2 UninterpretedOption_IdentifierValue_field_number protoreflect.FieldNumber = 3 UninterpretedOption_PositiveIntValue_field_number protoreflect.FieldNumber = 4 UninterpretedOption_NegativeIntValue_field_number protoreflect.FieldNumber = 5 UninterpretedOption_DoubleValue_field_number protoreflect.FieldNumber = 6 UninterpretedOption_StringValue_field_number protoreflect.FieldNumber = 7 UninterpretedOption_AggregateValue_field_number protoreflect.FieldNumber = 8 ) // Names for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_message_name protoreflect.Name = "NamePart" UninterpretedOption_NamePart_message_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart" ) // Field names for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_NamePart_field_name protoreflect.Name = "name_part" UninterpretedOption_NamePart_IsExtension_field_name protoreflect.Name = "is_extension" UninterpretedOption_NamePart_NamePart_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.name_part" UninterpretedOption_NamePart_IsExtension_field_fullname protoreflect.FullName = "google.protobuf.UninterpretedOption.NamePart.is_extension" ) // Field numbers for google.protobuf.UninterpretedOption.NamePart. const ( UninterpretedOption_NamePart_NamePart_field_number protoreflect.FieldNumber = 1 UninterpretedOption_NamePart_IsExtension_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_message_name protoreflect.Name = "SourceCodeInfo" SourceCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo" ) // Field names for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_Location_field_name protoreflect.Name = "location" SourceCodeInfo_Location_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.location" ) // Field numbers for google.protobuf.SourceCodeInfo. const ( SourceCodeInfo_Location_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_message_name protoreflect.Name = "Location" SourceCodeInfo_Location_message_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location" ) // Field names for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_Path_field_name protoreflect.Name = "path" SourceCodeInfo_Location_Span_field_name protoreflect.Name = "span" SourceCodeInfo_Location_LeadingComments_field_name protoreflect.Name = "leading_comments" SourceCodeInfo_Location_TrailingComments_field_name protoreflect.Name = "trailing_comments" SourceCodeInfo_Location_LeadingDetachedComments_field_name protoreflect.Name = "leading_detached_comments" SourceCodeInfo_Location_Path_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.path" SourceCodeInfo_Location_Span_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.span" SourceCodeInfo_Location_LeadingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_comments" SourceCodeInfo_Location_TrailingComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.trailing_comments" SourceCodeInfo_Location_LeadingDetachedComments_field_fullname protoreflect.FullName = "google.protobuf.SourceCodeInfo.Location.leading_detached_comments" ) // Field numbers for google.protobuf.SourceCodeInfo.Location. const ( SourceCodeInfo_Location_Path_field_number protoreflect.FieldNumber = 1 SourceCodeInfo_Location_Span_field_number protoreflect.FieldNumber = 2 SourceCodeInfo_Location_LeadingComments_field_number protoreflect.FieldNumber = 3 SourceCodeInfo_Location_TrailingComments_field_number protoreflect.FieldNumber = 4 SourceCodeInfo_Location_LeadingDetachedComments_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_message_name protoreflect.Name = "GeneratedCodeInfo" GeneratedCodeInfo_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo" ) // Field names for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_Annotation_field_name protoreflect.Name = "annotation" GeneratedCodeInfo_Annotation_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.annotation" ) // Field numbers for google.protobuf.GeneratedCodeInfo. const ( GeneratedCodeInfo_Annotation_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_message_name protoreflect.Name = "Annotation" GeneratedCodeInfo_Annotation_message_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation" ) // Field names for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_Path_field_name protoreflect.Name = "path" GeneratedCodeInfo_Annotation_SourceFile_field_name protoreflect.Name = "source_file" GeneratedCodeInfo_Annotation_Begin_field_name protoreflect.Name = "begin" GeneratedCodeInfo_Annotation_End_field_name protoreflect.Name = "end" GeneratedCodeInfo_Annotation_Path_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.path" GeneratedCodeInfo_Annotation_SourceFile_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.source_file" GeneratedCodeInfo_Annotation_Begin_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.begin" GeneratedCodeInfo_Annotation_End_field_fullname protoreflect.FullName = "google.protobuf.GeneratedCodeInfo.Annotation.end" ) // Field numbers for google.protobuf.GeneratedCodeInfo.Annotation. const ( GeneratedCodeInfo_Annotation_Path_field_number protoreflect.FieldNumber = 1 GeneratedCodeInfo_Annotation_SourceFile_field_number protoreflect.FieldNumber = 2 GeneratedCodeInfo_Annotation_Begin_field_number protoreflect.FieldNumber = 3 GeneratedCodeInfo_Annotation_End_field_number protoreflect.FieldNumber = 4 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package genid contains constants for declarations in descriptor.proto // and the well-known types. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" const GoogleProtobuf_package protoreflect.FullName = "google.protobuf" ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/duration_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_duration_proto = "google/protobuf/duration.proto" // Names for google.protobuf.Duration. const ( Duration_message_name protoreflect.Name = "Duration" Duration_message_fullname protoreflect.FullName = "google.protobuf.Duration" ) // Field names for google.protobuf.Duration. const ( Duration_Seconds_field_name protoreflect.Name = "seconds" Duration_Nanos_field_name protoreflect.Name = "nanos" Duration_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Duration.seconds" Duration_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Duration.nanos" ) // Field numbers for google.protobuf.Duration. const ( Duration_Seconds_field_number protoreflect.FieldNumber = 1 Duration_Nanos_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/empty_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_empty_proto = "google/protobuf/empty.proto" // Names for google.protobuf.Empty. const ( Empty_message_name protoreflect.Name = "Empty" Empty_message_fullname protoreflect.FullName = "google.protobuf.Empty" ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/field_mask_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_field_mask_proto = "google/protobuf/field_mask.proto" // Names for google.protobuf.FieldMask. const ( FieldMask_message_name protoreflect.Name = "FieldMask" FieldMask_message_fullname protoreflect.FullName = "google.protobuf.FieldMask" ) // Field names for google.protobuf.FieldMask. const ( FieldMask_Paths_field_name protoreflect.Name = "paths" FieldMask_Paths_field_fullname protoreflect.FullName = "google.protobuf.FieldMask.paths" ) // Field numbers for google.protobuf.FieldMask. const ( FieldMask_Paths_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/goname.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid // Go names of implementation-specific struct fields in generated messages. const ( State_goname = "state" SizeCache_goname = "sizeCache" SizeCacheA_goname = "XXX_sizecache" WeakFields_goname = "weakFields" WeakFieldsA_goname = "XXX_weak" UnknownFields_goname = "unknownFields" UnknownFieldsA_goname = "XXX_unrecognized" ExtensionFields_goname = "extensionFields" ExtensionFieldsA_goname = "XXX_InternalExtensions" ExtensionFieldsB_goname = "XXX_extensions" WeakFieldPrefix_goname = "XXX_weak_" ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/map_entry.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" // Generic field names and numbers for synthetic map entry messages. const ( MapEntry_Key_field_name protoreflect.Name = "key" MapEntry_Value_field_name protoreflect.Name = "value" MapEntry_Key_field_number protoreflect.FieldNumber = 1 MapEntry_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/source_context_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_source_context_proto = "google/protobuf/source_context.proto" // Names for google.protobuf.SourceContext. const ( SourceContext_message_name protoreflect.Name = "SourceContext" SourceContext_message_fullname protoreflect.FullName = "google.protobuf.SourceContext" ) // Field names for google.protobuf.SourceContext. const ( SourceContext_FileName_field_name protoreflect.Name = "file_name" SourceContext_FileName_field_fullname protoreflect.FullName = "google.protobuf.SourceContext.file_name" ) // Field numbers for google.protobuf.SourceContext. const ( SourceContext_FileName_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/struct_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_struct_proto = "google/protobuf/struct.proto" // Full and short names for google.protobuf.NullValue. const ( NullValue_enum_fullname = "google.protobuf.NullValue" NullValue_enum_name = "NullValue" ) // Names for google.protobuf.Struct. const ( Struct_message_name protoreflect.Name = "Struct" Struct_message_fullname protoreflect.FullName = "google.protobuf.Struct" ) // Field names for google.protobuf.Struct. const ( Struct_Fields_field_name protoreflect.Name = "fields" Struct_Fields_field_fullname protoreflect.FullName = "google.protobuf.Struct.fields" ) // Field numbers for google.protobuf.Struct. const ( Struct_Fields_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_message_name protoreflect.Name = "FieldsEntry" Struct_FieldsEntry_message_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry" ) // Field names for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_Key_field_name protoreflect.Name = "key" Struct_FieldsEntry_Value_field_name protoreflect.Name = "value" Struct_FieldsEntry_Key_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.key" Struct_FieldsEntry_Value_field_fullname protoreflect.FullName = "google.protobuf.Struct.FieldsEntry.value" ) // Field numbers for google.protobuf.Struct.FieldsEntry. const ( Struct_FieldsEntry_Key_field_number protoreflect.FieldNumber = 1 Struct_FieldsEntry_Value_field_number protoreflect.FieldNumber = 2 ) // Names for google.protobuf.Value. const ( Value_message_name protoreflect.Name = "Value" Value_message_fullname protoreflect.FullName = "google.protobuf.Value" ) // Field names for google.protobuf.Value. const ( Value_NullValue_field_name protoreflect.Name = "null_value" Value_NumberValue_field_name protoreflect.Name = "number_value" Value_StringValue_field_name protoreflect.Name = "string_value" Value_BoolValue_field_name protoreflect.Name = "bool_value" Value_StructValue_field_name protoreflect.Name = "struct_value" Value_ListValue_field_name protoreflect.Name = "list_value" Value_NullValue_field_fullname protoreflect.FullName = "google.protobuf.Value.null_value" Value_NumberValue_field_fullname protoreflect.FullName = "google.protobuf.Value.number_value" Value_StringValue_field_fullname protoreflect.FullName = "google.protobuf.Value.string_value" Value_BoolValue_field_fullname protoreflect.FullName = "google.protobuf.Value.bool_value" Value_StructValue_field_fullname protoreflect.FullName = "google.protobuf.Value.struct_value" Value_ListValue_field_fullname protoreflect.FullName = "google.protobuf.Value.list_value" ) // Field numbers for google.protobuf.Value. const ( Value_NullValue_field_number protoreflect.FieldNumber = 1 Value_NumberValue_field_number protoreflect.FieldNumber = 2 Value_StringValue_field_number protoreflect.FieldNumber = 3 Value_BoolValue_field_number protoreflect.FieldNumber = 4 Value_StructValue_field_number protoreflect.FieldNumber = 5 Value_ListValue_field_number protoreflect.FieldNumber = 6 ) // Oneof names for google.protobuf.Value. const ( Value_Kind_oneof_name protoreflect.Name = "kind" Value_Kind_oneof_fullname protoreflect.FullName = "google.protobuf.Value.kind" ) // Names for google.protobuf.ListValue. const ( ListValue_message_name protoreflect.Name = "ListValue" ListValue_message_fullname protoreflect.FullName = "google.protobuf.ListValue" ) // Field names for google.protobuf.ListValue. const ( ListValue_Values_field_name protoreflect.Name = "values" ListValue_Values_field_fullname protoreflect.FullName = "google.protobuf.ListValue.values" ) // Field numbers for google.protobuf.ListValue. const ( ListValue_Values_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/timestamp_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_timestamp_proto = "google/protobuf/timestamp.proto" // Names for google.protobuf.Timestamp. const ( Timestamp_message_name protoreflect.Name = "Timestamp" Timestamp_message_fullname protoreflect.FullName = "google.protobuf.Timestamp" ) // Field names for google.protobuf.Timestamp. const ( Timestamp_Seconds_field_name protoreflect.Name = "seconds" Timestamp_Nanos_field_name protoreflect.Name = "nanos" Timestamp_Seconds_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.seconds" Timestamp_Nanos_field_fullname protoreflect.FullName = "google.protobuf.Timestamp.nanos" ) // Field numbers for google.protobuf.Timestamp. const ( Timestamp_Seconds_field_number protoreflect.FieldNumber = 1 Timestamp_Nanos_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/type_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_type_proto = "google/protobuf/type.proto" // Full and short names for google.protobuf.Syntax. const ( Syntax_enum_fullname = "google.protobuf.Syntax" Syntax_enum_name = "Syntax" ) // Names for google.protobuf.Type. const ( Type_message_name protoreflect.Name = "Type" Type_message_fullname protoreflect.FullName = "google.protobuf.Type" ) // Field names for google.protobuf.Type. const ( Type_Name_field_name protoreflect.Name = "name" Type_Fields_field_name protoreflect.Name = "fields" Type_Oneofs_field_name protoreflect.Name = "oneofs" Type_Options_field_name protoreflect.Name = "options" Type_SourceContext_field_name protoreflect.Name = "source_context" Type_Syntax_field_name protoreflect.Name = "syntax" Type_Name_field_fullname protoreflect.FullName = "google.protobuf.Type.name" Type_Fields_field_fullname protoreflect.FullName = "google.protobuf.Type.fields" Type_Oneofs_field_fullname protoreflect.FullName = "google.protobuf.Type.oneofs" Type_Options_field_fullname protoreflect.FullName = "google.protobuf.Type.options" Type_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Type.source_context" Type_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Type.syntax" ) // Field numbers for google.protobuf.Type. const ( Type_Name_field_number protoreflect.FieldNumber = 1 Type_Fields_field_number protoreflect.FieldNumber = 2 Type_Oneofs_field_number protoreflect.FieldNumber = 3 Type_Options_field_number protoreflect.FieldNumber = 4 Type_SourceContext_field_number protoreflect.FieldNumber = 5 Type_Syntax_field_number protoreflect.FieldNumber = 6 ) // Names for google.protobuf.Field. const ( Field_message_name protoreflect.Name = "Field" Field_message_fullname protoreflect.FullName = "google.protobuf.Field" ) // Field names for google.protobuf.Field. const ( Field_Kind_field_name protoreflect.Name = "kind" Field_Cardinality_field_name protoreflect.Name = "cardinality" Field_Number_field_name protoreflect.Name = "number" Field_Name_field_name protoreflect.Name = "name" Field_TypeUrl_field_name protoreflect.Name = "type_url" Field_OneofIndex_field_name protoreflect.Name = "oneof_index" Field_Packed_field_name protoreflect.Name = "packed" Field_Options_field_name protoreflect.Name = "options" Field_JsonName_field_name protoreflect.Name = "json_name" Field_DefaultValue_field_name protoreflect.Name = "default_value" Field_Kind_field_fullname protoreflect.FullName = "google.protobuf.Field.kind" Field_Cardinality_field_fullname protoreflect.FullName = "google.protobuf.Field.cardinality" Field_Number_field_fullname protoreflect.FullName = "google.protobuf.Field.number" Field_Name_field_fullname protoreflect.FullName = "google.protobuf.Field.name" Field_TypeUrl_field_fullname protoreflect.FullName = "google.protobuf.Field.type_url" Field_OneofIndex_field_fullname protoreflect.FullName = "google.protobuf.Field.oneof_index" Field_Packed_field_fullname protoreflect.FullName = "google.protobuf.Field.packed" Field_Options_field_fullname protoreflect.FullName = "google.protobuf.Field.options" Field_JsonName_field_fullname protoreflect.FullName = "google.protobuf.Field.json_name" Field_DefaultValue_field_fullname protoreflect.FullName = "google.protobuf.Field.default_value" ) // Field numbers for google.protobuf.Field. const ( Field_Kind_field_number protoreflect.FieldNumber = 1 Field_Cardinality_field_number protoreflect.FieldNumber = 2 Field_Number_field_number protoreflect.FieldNumber = 3 Field_Name_field_number protoreflect.FieldNumber = 4 Field_TypeUrl_field_number protoreflect.FieldNumber = 6 Field_OneofIndex_field_number protoreflect.FieldNumber = 7 Field_Packed_field_number protoreflect.FieldNumber = 8 Field_Options_field_number protoreflect.FieldNumber = 9 Field_JsonName_field_number protoreflect.FieldNumber = 10 Field_DefaultValue_field_number protoreflect.FieldNumber = 11 ) // Full and short names for google.protobuf.Field.Kind. const ( Field_Kind_enum_fullname = "google.protobuf.Field.Kind" Field_Kind_enum_name = "Kind" ) // Full and short names for google.protobuf.Field.Cardinality. const ( Field_Cardinality_enum_fullname = "google.protobuf.Field.Cardinality" Field_Cardinality_enum_name = "Cardinality" ) // Names for google.protobuf.Enum. const ( Enum_message_name protoreflect.Name = "Enum" Enum_message_fullname protoreflect.FullName = "google.protobuf.Enum" ) // Field names for google.protobuf.Enum. const ( Enum_Name_field_name protoreflect.Name = "name" Enum_Enumvalue_field_name protoreflect.Name = "enumvalue" Enum_Options_field_name protoreflect.Name = "options" Enum_SourceContext_field_name protoreflect.Name = "source_context" Enum_Syntax_field_name protoreflect.Name = "syntax" Enum_Name_field_fullname protoreflect.FullName = "google.protobuf.Enum.name" Enum_Enumvalue_field_fullname protoreflect.FullName = "google.protobuf.Enum.enumvalue" Enum_Options_field_fullname protoreflect.FullName = "google.protobuf.Enum.options" Enum_SourceContext_field_fullname protoreflect.FullName = "google.protobuf.Enum.source_context" Enum_Syntax_field_fullname protoreflect.FullName = "google.protobuf.Enum.syntax" ) // Field numbers for google.protobuf.Enum. const ( Enum_Name_field_number protoreflect.FieldNumber = 1 Enum_Enumvalue_field_number protoreflect.FieldNumber = 2 Enum_Options_field_number protoreflect.FieldNumber = 3 Enum_SourceContext_field_number protoreflect.FieldNumber = 4 Enum_Syntax_field_number protoreflect.FieldNumber = 5 ) // Names for google.protobuf.EnumValue. const ( EnumValue_message_name protoreflect.Name = "EnumValue" EnumValue_message_fullname protoreflect.FullName = "google.protobuf.EnumValue" ) // Field names for google.protobuf.EnumValue. const ( EnumValue_Name_field_name protoreflect.Name = "name" EnumValue_Number_field_name protoreflect.Name = "number" EnumValue_Options_field_name protoreflect.Name = "options" EnumValue_Name_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.name" EnumValue_Number_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.number" EnumValue_Options_field_fullname protoreflect.FullName = "google.protobuf.EnumValue.options" ) // Field numbers for google.protobuf.EnumValue. const ( EnumValue_Name_field_number protoreflect.FieldNumber = 1 EnumValue_Number_field_number protoreflect.FieldNumber = 2 EnumValue_Options_field_number protoreflect.FieldNumber = 3 ) // Names for google.protobuf.Option. const ( Option_message_name protoreflect.Name = "Option" Option_message_fullname protoreflect.FullName = "google.protobuf.Option" ) // Field names for google.protobuf.Option. const ( Option_Name_field_name protoreflect.Name = "name" Option_Value_field_name protoreflect.Name = "value" Option_Name_field_fullname protoreflect.FullName = "google.protobuf.Option.name" Option_Value_field_fullname protoreflect.FullName = "google.protobuf.Option.value" ) // Field numbers for google.protobuf.Option. const ( Option_Name_field_number protoreflect.FieldNumber = 1 Option_Value_field_number protoreflect.FieldNumber = 2 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/wrappers.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package genid import protoreflect "google.golang.org/protobuf/reflect/protoreflect" // Generic field name and number for messages in wrappers.proto. const ( WrapperValue_Value_field_name protoreflect.Name = "value" WrapperValue_Value_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/genid/wrappers_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package genid import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" ) const File_google_protobuf_wrappers_proto = "google/protobuf/wrappers.proto" // Names for google.protobuf.DoubleValue. const ( DoubleValue_message_name protoreflect.Name = "DoubleValue" DoubleValue_message_fullname protoreflect.FullName = "google.protobuf.DoubleValue" ) // Field names for google.protobuf.DoubleValue. const ( DoubleValue_Value_field_name protoreflect.Name = "value" DoubleValue_Value_field_fullname protoreflect.FullName = "google.protobuf.DoubleValue.value" ) // Field numbers for google.protobuf.DoubleValue. const ( DoubleValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.FloatValue. const ( FloatValue_message_name protoreflect.Name = "FloatValue" FloatValue_message_fullname protoreflect.FullName = "google.protobuf.FloatValue" ) // Field names for google.protobuf.FloatValue. const ( FloatValue_Value_field_name protoreflect.Name = "value" FloatValue_Value_field_fullname protoreflect.FullName = "google.protobuf.FloatValue.value" ) // Field numbers for google.protobuf.FloatValue. const ( FloatValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Int64Value. const ( Int64Value_message_name protoreflect.Name = "Int64Value" Int64Value_message_fullname protoreflect.FullName = "google.protobuf.Int64Value" ) // Field names for google.protobuf.Int64Value. const ( Int64Value_Value_field_name protoreflect.Name = "value" Int64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int64Value.value" ) // Field numbers for google.protobuf.Int64Value. const ( Int64Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.UInt64Value. const ( UInt64Value_message_name protoreflect.Name = "UInt64Value" UInt64Value_message_fullname protoreflect.FullName = "google.protobuf.UInt64Value" ) // Field names for google.protobuf.UInt64Value. const ( UInt64Value_Value_field_name protoreflect.Name = "value" UInt64Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt64Value.value" ) // Field numbers for google.protobuf.UInt64Value. const ( UInt64Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.Int32Value. const ( Int32Value_message_name protoreflect.Name = "Int32Value" Int32Value_message_fullname protoreflect.FullName = "google.protobuf.Int32Value" ) // Field names for google.protobuf.Int32Value. const ( Int32Value_Value_field_name protoreflect.Name = "value" Int32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.Int32Value.value" ) // Field numbers for google.protobuf.Int32Value. const ( Int32Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.UInt32Value. const ( UInt32Value_message_name protoreflect.Name = "UInt32Value" UInt32Value_message_fullname protoreflect.FullName = "google.protobuf.UInt32Value" ) // Field names for google.protobuf.UInt32Value. const ( UInt32Value_Value_field_name protoreflect.Name = "value" UInt32Value_Value_field_fullname protoreflect.FullName = "google.protobuf.UInt32Value.value" ) // Field numbers for google.protobuf.UInt32Value. const ( UInt32Value_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.BoolValue. const ( BoolValue_message_name protoreflect.Name = "BoolValue" BoolValue_message_fullname protoreflect.FullName = "google.protobuf.BoolValue" ) // Field names for google.protobuf.BoolValue. const ( BoolValue_Value_field_name protoreflect.Name = "value" BoolValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BoolValue.value" ) // Field numbers for google.protobuf.BoolValue. const ( BoolValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.StringValue. const ( StringValue_message_name protoreflect.Name = "StringValue" StringValue_message_fullname protoreflect.FullName = "google.protobuf.StringValue" ) // Field names for google.protobuf.StringValue. const ( StringValue_Value_field_name protoreflect.Name = "value" StringValue_Value_field_fullname protoreflect.FullName = "google.protobuf.StringValue.value" ) // Field numbers for google.protobuf.StringValue. const ( StringValue_Value_field_number protoreflect.FieldNumber = 1 ) // Names for google.protobuf.BytesValue. const ( BytesValue_message_name protoreflect.Name = "BytesValue" BytesValue_message_fullname protoreflect.FullName = "google.protobuf.BytesValue" ) // Field names for google.protobuf.BytesValue. const ( BytesValue_Value_field_name protoreflect.Name = "value" BytesValue_Value_field_fullname protoreflect.FullName = "google.protobuf.BytesValue.value" ) // Field numbers for google.protobuf.BytesValue. const ( BytesValue_Value_field_number protoreflect.FieldNumber = 1 ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/api_export.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strconv" "google.golang.org/protobuf/encoding/prototext" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // Export is a zero-length named type that exists only to export a set of // functions that we do not want to appear in godoc. type Export struct{} // NewError formats a string according to the format specifier and arguments and // returns an error that has a "proto" prefix. func (Export) NewError(f string, x ...interface{}) error { return errors.New(f, x...) } // enum is any enum type generated by protoc-gen-go // and must be a named int32 type. type enum = interface{} // EnumOf returns the protoreflect.Enum interface over e. // It returns nil if e is nil. func (Export) EnumOf(e enum) pref.Enum { switch e := e.(type) { case nil: return nil case pref.Enum: return e default: return legacyWrapEnum(reflect.ValueOf(e)) } } // EnumDescriptorOf returns the protoreflect.EnumDescriptor for e. // It returns nil if e is nil. func (Export) EnumDescriptorOf(e enum) pref.EnumDescriptor { switch e := e.(type) { case nil: return nil case pref.Enum: return e.Descriptor() default: return LegacyLoadEnumDesc(reflect.TypeOf(e)) } } // EnumTypeOf returns the protoreflect.EnumType for e. // It returns nil if e is nil. func (Export) EnumTypeOf(e enum) pref.EnumType { switch e := e.(type) { case nil: return nil case pref.Enum: return e.Type() default: return legacyLoadEnumType(reflect.TypeOf(e)) } } // EnumStringOf returns the enum value as a string, either as the name if // the number is resolvable, or the number formatted as a string. func (Export) EnumStringOf(ed pref.EnumDescriptor, n pref.EnumNumber) string { ev := ed.Values().ByNumber(n) if ev != nil { return string(ev.Name()) } return strconv.Itoa(int(n)) } // message is any message type generated by protoc-gen-go // and must be a pointer to a named struct type. type message = interface{} // legacyMessageWrapper wraps a v2 message as a v1 message. type legacyMessageWrapper struct{ m pref.ProtoMessage } func (m legacyMessageWrapper) Reset() { proto.Reset(m.m) } func (m legacyMessageWrapper) String() string { return Export{}.MessageStringOf(m.m) } func (m legacyMessageWrapper) ProtoMessage() {} // ProtoMessageV1Of converts either a v1 or v2 message to a v1 message. // It returns nil if m is nil. func (Export) ProtoMessageV1Of(m message) piface.MessageV1 { switch mv := m.(type) { case nil: return nil case piface.MessageV1: return mv case unwrapper: return Export{}.ProtoMessageV1Of(mv.protoUnwrap()) case pref.ProtoMessage: return legacyMessageWrapper{mv} default: panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) } } func (Export) protoMessageV2Of(m message) pref.ProtoMessage { switch mv := m.(type) { case nil: return nil case pref.ProtoMessage: return mv case legacyMessageWrapper: return mv.m case piface.MessageV1: return nil default: panic(fmt.Sprintf("message %T is neither a v1 or v2 Message", m)) } } // ProtoMessageV2Of converts either a v1 or v2 message to a v2 message. // It returns nil if m is nil. func (Export) ProtoMessageV2Of(m message) pref.ProtoMessage { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv } return legacyWrapMessage(reflect.ValueOf(m)).Interface() } // MessageOf returns the protoreflect.Message interface over m. // It returns nil if m is nil. func (Export) MessageOf(m message) pref.Message { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect() } return legacyWrapMessage(reflect.ValueOf(m)) } // MessageDescriptorOf returns the protoreflect.MessageDescriptor for m. // It returns nil if m is nil. func (Export) MessageDescriptorOf(m message) pref.MessageDescriptor { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Descriptor() } return LegacyLoadMessageDesc(reflect.TypeOf(m)) } // MessageTypeOf returns the protoreflect.MessageType for m. // It returns nil if m is nil. func (Export) MessageTypeOf(m message) pref.MessageType { if m == nil { return nil } if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Type() } return legacyLoadMessageType(reflect.TypeOf(m), "") } // MessageStringOf returns the message value as a string, // which is the message serialized in the protobuf text format. func (Export) MessageStringOf(m pref.ProtoMessage) string { return prototext.MarshalOptions{Multiline: false}.Format(m) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/checkinit.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sync" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) func (mi *MessageInfo) checkInitialized(in piface.CheckInitializedInput) (piface.CheckInitializedOutput, error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } return piface.CheckInitializedOutput{}, mi.checkInitializedPointer(p) } func (mi *MessageInfo) checkInitializedPointer(p pointer) error { mi.init() if !mi.needsInitCheck { return nil } if p.IsNil() { for _, f := range mi.orderedCoderFields { if f.isRequired { return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName())) } } return nil } if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() if err := mi.isInitExtensions(e); err != nil { return err } } for _, f := range mi.orderedCoderFields { if !f.isRequired && f.funcs.isInit == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { if f.isRequired { return errors.RequiredNotSet(string(mi.Desc.Fields().ByNumber(f.num).FullName())) } continue } if f.funcs.isInit == nil { continue } if err := f.funcs.isInit(fptr, f); err != nil { return err } } return nil } func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error { if ext == nil { return nil } for _, x := range *ext { ei := getExtensionFieldInfo(x.Type()) if ei.funcs.isInit == nil { continue } v := x.Value() if !v.IsValid() { continue } if err := ei.funcs.isInit(v); err != nil { return err } } return nil } var ( needsInitCheckMu sync.Mutex needsInitCheckMap sync.Map ) // needsInitCheck reports whether a message needs to be checked for partial initialization. // // It returns true if the message transitively includes any required or extension fields. func needsInitCheck(md pref.MessageDescriptor) bool { if v, ok := needsInitCheckMap.Load(md); ok { if has, ok := v.(bool); ok { return has } } needsInitCheckMu.Lock() defer needsInitCheckMu.Unlock() return needsInitCheckLocked(md) } func needsInitCheckLocked(md pref.MessageDescriptor) (has bool) { if v, ok := needsInitCheckMap.Load(md); ok { // If has is true, we've previously determined that this message // needs init checks. // // If has is false, we've previously determined that it can never // be uninitialized. // // If has is not a bool, we've just encountered a cycle in the // message graph. In this case, it is safe to return false: If // the message does have required fields, we'll detect them later // in the graph traversal. has, ok := v.(bool) return ok && has } needsInitCheckMap.Store(md, struct{}{}) // avoid cycles while descending into this message defer func() { needsInitCheckMap.Store(md, has) }() if md.RequiredNumbers().Len() > 0 { return true } if md.ExtensionRanges().Len() > 0 { return true } for i := 0; i < md.Fields().Len(); i++ { fd := md.Fields().Get(i) // Map keys are never messages, so just consider the map value. if fd.IsMap() { fd = fd.MapValue() } fmd := fd.Message() if fmd != nil && needsInitCheckLocked(fmd) { return true } } return false } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sync" "sync/atomic" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" ) type extensionFieldInfo struct { wiretag uint64 tagsize int unmarshalNeedsValue bool funcs valueCoderFuncs validation validationInfo } var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo func getExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { if xi, ok := xt.(*ExtensionInfo); ok { xi.lazyInit() return xi.info } return legacyLoadExtensionFieldInfo(xt) } // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt. func legacyLoadExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo { if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok { return xi.(*extensionFieldInfo) } e := makeExtensionFieldInfo(xt.TypeDescriptor()) if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok { return e.(*extensionFieldInfo) } return e } func makeExtensionFieldInfo(xd pref.ExtensionDescriptor) *extensionFieldInfo { var wiretag uint64 if !xd.IsPacked() { wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()]) } else { wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType) } e := &extensionFieldInfo{ wiretag: wiretag, tagsize: protowire.SizeVarint(wiretag), funcs: encoderFuncsForValue(xd), } // Does the unmarshal function need a value passed to it? // This is true for composite types, where we pass in a message, list, or map to fill in, // and for enums, where we pass in a prototype value to specify the concrete enum type. switch xd.Kind() { case pref.MessageKind, pref.GroupKind, pref.EnumKind: e.unmarshalNeedsValue = true default: if xd.Cardinality() == pref.Repeated { e.unmarshalNeedsValue = true } } return e } type lazyExtensionValue struct { atomicOnce uint32 // atomically set if value is valid mu sync.Mutex xi *extensionFieldInfo value pref.Value b []byte fn func() pref.Value } type ExtensionField struct { typ pref.ExtensionType // value is either the value of GetValue, // or a *lazyExtensionValue that then returns the value of GetValue. value pref.Value lazy *lazyExtensionValue } func (f *ExtensionField) appendLazyBytes(xt pref.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) { if f.lazy == nil { f.lazy = &lazyExtensionValue{xi: xi} } f.typ = xt f.lazy.xi = xi f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp) f.lazy.b = append(f.lazy.b, b...) } func (f *ExtensionField) canLazy(xt pref.ExtensionType) bool { if f.typ == nil { return true } if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { return true } return false } func (f *ExtensionField) lazyInit() { f.lazy.mu.Lock() defer f.lazy.mu.Unlock() if atomic.LoadUint32(&f.lazy.atomicOnce) == 1 { return } if f.lazy.xi != nil { b := f.lazy.b val := f.typ.New() for len(b) > 0 { var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { panic(errors.New("bad tag in lazy extension decoding")) } b = b[n:] } num := protowire.Number(tag >> 3) wtyp := protowire.Type(tag & 7) var out unmarshalOutput var err error val, out, err = f.lazy.xi.funcs.unmarshal(b, val, num, wtyp, lazyUnmarshalOptions) if err != nil { panic(errors.New("decode failure in lazy extension decoding: %v", err)) } b = b[out.n:] } f.lazy.value = val } else { f.lazy.value = f.lazy.fn() } f.lazy.xi = nil f.lazy.fn = nil f.lazy.b = nil atomic.StoreUint32(&f.lazy.atomicOnce, 1) } // Set sets the type and value of the extension field. // This must not be called concurrently. func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) { f.typ = t f.value = v f.lazy = nil } // SetLazy sets the type and a value that is to be lazily evaluated upon first use. // This must not be called concurrently. func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) { f.typ = t f.lazy = &lazyExtensionValue{fn: fn} } // Value returns the value of the extension field. // This may be called concurrently. func (f *ExtensionField) Value() pref.Value { if f.lazy != nil { if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 { f.lazyInit() } return f.lazy.value } return f.value } // Type returns the type of the extension field. // This may be called concurrently. func (f ExtensionField) Type() pref.ExtensionType { return f.typ } // IsSet returns whether the extension field is set. // This may be called concurrently. func (f ExtensionField) IsSet() bool { return f.typ != nil } // IsLazy reports whether a field is lazily encoded. // It is exported for testing. func IsLazy(m pref.Message, fd pref.FieldDescriptor) bool { var mi *MessageInfo var p pointer switch m := m.(type) { case *messageState: mi = m.messageInfo() p = m.pointer() case *messageReflectWrapper: mi = m.messageInfo() p = m.pointer() default: return false } xd, ok := fd.(pref.ExtensionTypeDescriptor) if !ok { return false } xt := xd.Type() ext := mi.extensionMap(p) if ext == nil { return false } f, ok := (*ext)[int32(fd.Number())] if !ok { return false } return f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_field.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "sync" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) type errInvalidUTF8 struct{} func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" } func (errInvalidUTF8) InvalidUTF8() bool { return true } func (errInvalidUTF8) Unwrap() error { return errors.Error } // initOneofFieldCoders initializes the fast-path functions for the fields in a oneof. // // For size, marshal, and isInit operations, functions are set only on the first field // in the oneof. The functions are called when the oneof is non-nil, and will dispatch // to the appropriate field-specific function as necessary. // // The unmarshal function is set on each field individually as usual. func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) { fs := si.oneofsByName[od.Name()] ft := fs.Type oneofFields := make(map[reflect.Type]*coderFieldInfo) needIsInit := false fields := od.Fields() for i, lim := 0, fields.Len(); i < lim; i++ { fd := od.Fields().Get(i) num := fd.Number() // Make a copy of the original coderFieldInfo for use in unmarshaling. // // oneofFields[oneofType].funcs.marshal is the field-specific marshal function. // // mi.coderFields[num].marshal is set on only the first field in the oneof, // and dispatches to the field-specific marshaler in oneofFields. cf := *mi.coderFields[num] ot := si.oneofWrappersByNumber[num] cf.ft = ot.Field(0).Type cf.mi, cf.funcs = fieldCoder(fd, cf.ft) oneofFields[ot] = &cf if cf.funcs.isInit != nil { needIsInit = true } mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { var vw reflect.Value // pointer to wrapper type vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot { vw = vi.Elem() } else { vw = reflect.New(ot) } out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts) if err != nil { return out, err } vi.Set(vw) return out, nil } } getInfo := func(p pointer) (pointer, *coderFieldInfo) { v := p.AsValueOf(ft).Elem() if v.IsNil() { return pointer{}, nil } v = v.Elem() // interface -> *struct if v.IsNil() { return pointer{}, nil } return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()] } first := mi.coderFields[od.Fields().Get(0).Number()] first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int { p, info := getInfo(p) if info == nil || info.funcs.size == nil { return 0 } return info.funcs.size(p, info, opts) } first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) { p, info := getInfo(p) if info == nil || info.funcs.marshal == nil { return b, nil } return info.funcs.marshal(b, p, info, opts) } first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) { srcp, srcinfo := getInfo(src) if srcinfo == nil || srcinfo.funcs.merge == nil { return } dstp, dstinfo := getInfo(dst) if dstinfo != srcinfo { dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type())) dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset) } srcinfo.funcs.merge(dstp, srcp, srcinfo, opts) } if needIsInit { first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error { p, info := getInfo(p) if info == nil || info.funcs.isInit == nil { return nil } return info.funcs.isInit(p, info) } } } func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs { var once sync.Once var messageType pref.MessageType lazyInit := func() { once.Do(func() { messageName := fd.Message().FullName() messageType, _ = preg.GlobalTypes.FindMessageByName(messageName) }) } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m, ok := p.WeakFields().get(f.num) if !ok { return 0 } lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } return sizeMessage(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m, ok := p.WeakFields().get(f.num) if !ok { return b, nil } lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } return appendMessage(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { fs := p.WeakFields() m, ok := fs.get(f.num) if !ok { lazyInit() if messageType == nil { return unmarshalOutput{}, errUnknown } m = messageType.New().Interface() fs.set(f.num, m) } return consumeMessage(b, m, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m, ok := p.WeakFields().get(f.num) if !ok { return nil } return proto.CheckInitialized(m) }, merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { sm, ok := src.WeakFields().get(f.num) if !ok { return } dm, ok := dst.WeakFields().get(f.num) if !ok { lazyInit() if messageType == nil { panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) } dm = messageType.New().Interface() dst.WeakFields().set(f.num, dm) } opts.Merge(dm, sm) }, } } func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeMessageInfo, marshal: appendMessageInfo, unmarshal: consumeMessageInfo, merge: mergeMessage, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageInfo } return funcs } else { return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m := asMessage(p.AsValueOf(ft).Elem()) return sizeMessage(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m := asMessage(p.AsValueOf(ft).Elem()) return appendMessage(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft).Elem() if mp.IsNil() { mp.Set(reflect.New(ft.Elem())) } return consumeMessage(b, asMessage(mp), wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m := asMessage(p.AsValueOf(ft).Elem()) return proto.CheckInitialized(m) }, merge: mergeMessage, } } } func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize } func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts))) return f.mi.marshalAppendPointer(b, p.Elem(), opts) } func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if p.Elem().IsNil() { p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts) if err != nil { return out, err } out.n = n out.initialized = o.initialized return out, nil } func isInitMessageInfo(p pointer, f *coderFieldInfo) error { return f.mi.checkInitializedPointer(p.Elem()) } func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int { return protowire.SizeBytes(proto.Size(m)) + tagsize } func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(proto.Size(m))) return opts.Options().MarshalAppend(b, m) } func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: m.ProtoReflect(), }) if err != nil { return out, err } out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int { m := v.Message().Interface() return sizeMessage(m, tagsize, opts) } func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { m := v.Message().Interface() return appendMessage(b, m, wiretag, opts) } func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { m := v.Message().Interface() out, err := consumeMessage(b, m, wtyp, opts) return v, out, err } func isInitMessageValue(v pref.Value) error { m := v.Message().Interface() return proto.CheckInitialized(m) } var coderMessageValue = valueCoderFuncs{ size: sizeMessageValue, marshal: appendMessageValue, unmarshal: consumeMessageValue, isInit: isInitMessageValue, merge: mergeMessageValue, } func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int { m := v.Message().Interface() return sizeGroup(m, tagsize, opts) } func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { m := v.Message().Interface() return appendGroup(b, m, wiretag, opts) } func consumeGroupValue(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { m := v.Message().Interface() out, err := consumeGroup(b, m, num, wtyp, opts) return v, out, err } var coderGroupValue = valueCoderFuncs{ size: sizeGroupValue, marshal: appendGroupValue, unmarshal: consumeGroupValue, isInit: isInitMessageValue, merge: mergeMessageValue, } func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { num := fd.Number() if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeGroupType, marshal: appendGroupType, unmarshal: consumeGroupType, merge: mergeMessage, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageInfo } return funcs } else { return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { m := asMessage(p.AsValueOf(ft).Elem()) return sizeGroup(m, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { m := asMessage(p.AsValueOf(ft).Elem()) return appendGroup(b, m, f.wiretag, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft).Elem() if mp.IsNil() { mp.Set(reflect.New(ft.Elem())) } return consumeGroup(b, asMessage(mp), num, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { m := asMessage(p.AsValueOf(ft).Elem()) return proto.CheckInitialized(m) }, merge: mergeMessage, } } } func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int { return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts) } func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, f.wiretag) // start group b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts) b = protowire.AppendVarint(b, f.wiretag+1) // end group return b, err } func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } if p.Elem().IsNil() { p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts) } func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int { return 2*tagsize + proto.Size(m) } func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) // start group b, err := opts.Options().MarshalAppend(b, m) b = protowire.AppendVarint(b, wiretag+1) // end group return b, err } func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return out, errDecode } o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: m.ProtoReflect(), }) if err != nil { return out, err } out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeMessageSliceInfo, marshal: appendMessageSliceInfo, unmarshal: consumeMessageSliceInfo, merge: mergeMessageSlice, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageSliceInfo } return funcs } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeMessageSlice(p, ft, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendMessageSlice(b, p, f.wiretag, ft, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { return consumeMessageSlice(b, p, ft, wtyp, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { return isInitMessageSlice(p, ft) }, merge: mergeMessageSlice, } } func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize } return n } func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) siz := f.mi.sizePointer(v, opts) b = protowire.AppendVarint(b, uint64(siz)) b, err = f.mi.marshalAppendPointer(b, v, opts) if err != nil { return b, err } } return b, nil } func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } m := reflect.New(f.mi.GoReflectType.Elem()).Interface() mp := pointerOfIface(m) o, err := f.mi.unmarshalPointer(v, mp, 0, opts) if err != nil { return out, err } p.AppendPointerSlice(mp) out.n = n out.initialized = o.initialized return out, nil } func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error { s := p.PointerSlice() for _, v := range s { if err := f.mi.checkInitializedPointer(v); err != nil { return err } } return nil } func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) n += protowire.SizeBytes(proto.Size(m)) + tagsize } return n } func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) b = protowire.AppendVarint(b, wiretag) siz := proto.Size(m) b = protowire.AppendVarint(b, uint64(siz)) b, err = opts.Options().MarshalAppend(b, m) if err != nil { return b, err } } return b, nil } func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } mp := reflect.New(goType.Elem()) o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: asMessage(mp).ProtoReflect(), }) if err != nil { return out, err } p.AppendPointerSlice(pointerOfValue(mp)) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func isInitMessageSlice(p pointer, goType reflect.Type) error { s := p.PointerSlice() for _, v := range s { m := asMessage(v.AsValueOf(goType.Elem())) if err := proto.CheckInitialized(m); err != nil { return err } } return nil } // Slices of messages func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() n += protowire.SizeBytes(proto.Size(m)) + tagsize } return n } func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() mopts := opts.Options() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() b = protowire.AppendVarint(b, wiretag) siz := proto.Size(m) b = protowire.AppendVarint(b, uint64(siz)) var err error b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } } return b, nil } func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return pref.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return pref.Value{}, out, errDecode } m := list.NewElement() o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: v, Message: m.Message(), }) if err != nil { return pref.Value{}, out, err } list.Append(m) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return listv, out, nil } func isInitMessageSliceValue(listv pref.Value) error { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() if err := proto.CheckInitialized(m); err != nil { return err } } return nil } var coderMessageSliceValue = valueCoderFuncs{ size: sizeMessageSliceValue, marshal: appendMessageSliceValue, unmarshal: consumeMessageSliceValue, isInit: isInitMessageSliceValue, merge: mergeMessageListValue, } func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { list := listv.List() n := 0 for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() n += 2*tagsize + proto.Size(m) } return n } func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() mopts := opts.Options() for i, llen := 0, list.Len(); i < llen; i++ { m := list.Get(i).Message().Interface() b = protowire.AppendVarint(b, wiretag) // start group var err error b, err = mopts.MarshalAppend(b, m) if err != nil { return b, err } b = protowire.AppendVarint(b, wiretag+1) // end group } return b, nil } func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.StartGroupType { return pref.Value{}, out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return pref.Value{}, out, errDecode } m := list.NewElement() o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: m.Message(), }) if err != nil { return pref.Value{}, out, err } list.Append(m) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return listv, out, nil } var coderGroupSliceValue = valueCoderFuncs{ size: sizeGroupSliceValue, marshal: appendGroupSliceValue, unmarshal: consumeGroupSliceValue, isInit: isInitMessageSliceValue, merge: mergeMessageListValue, } func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { num := fd.Number() if mi := getMessageInfo(ft); mi != nil { funcs := pointerCoderFuncs{ size: sizeGroupSliceInfo, marshal: appendGroupSliceInfo, unmarshal: consumeGroupSliceInfo, merge: mergeMessageSlice, } if needsInitCheck(mi.Desc) { funcs.isInit = isInitMessageSliceInfo } return funcs } return pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeGroupSlice(p, ft, f.tagsize, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendGroupSlice(b, p, f.wiretag, ft, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { return consumeGroupSlice(b, p, num, wtyp, ft, opts) }, isInit: func(p pointer, f *coderFieldInfo) error { return isInitMessageSlice(p, ft) }, merge: mergeMessageSlice, } } func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { m := asMessage(v.AsValueOf(messageType.Elem())) n += 2*tagsize + proto.Size(m) } return n } func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { m := asMessage(v.AsValueOf(messageType.Elem())) b = protowire.AppendVarint(b, wiretag) // start group b, err = opts.Options().MarshalAppend(b, m) if err != nil { return b, err } b = protowire.AppendVarint(b, wiretag+1) // end group } return b, nil } func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.StartGroupType { return out, errUnknown } b, n := protowire.ConsumeGroup(num, b) if n < 0 { return out, errDecode } mp := reflect.New(goType.Elem()) o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ Buf: b, Message: asMessage(mp).ProtoReflect(), }) if err != nil { return out, err } p.AppendPointerSlice(pointerOfValue(mp)) out.n = n out.initialized = o.Flags&piface.UnmarshalInitialized != 0 return out, nil } func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { s := p.PointerSlice() n := 0 for _, v := range s { n += 2*f.tagsize + f.mi.sizePointer(v, opts) } return n } func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.PointerSlice() var err error for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) // start group b, err = f.mi.marshalAppendPointer(b, v, opts) if err != nil { return b, err } b = protowire.AppendVarint(b, f.wiretag+1) // end group } return b, nil } func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { if wtyp != protowire.StartGroupType { return unmarshalOutput{}, errUnknown } m := reflect.New(f.mi.GoReflectType.Elem()).Interface() mp := pointerOfIface(m) out, err := f.mi.unmarshalPointer(b, mp, f.num, opts) if err != nil { return out, err } p.AppendPointerSlice(mp) return out, nil } func asMessage(v reflect.Value) pref.ProtoMessage { if m, ok := v.Interface().(pref.ProtoMessage); ok { return m } return legacyWrapMessage(v).Interface() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/reflect/protoreflect" ) // sizeBool returns the size of wire encoding a bool pointer as a Bool. func sizeBool(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bool() return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBool wire encodes a bool pointer as a Bool. func appendBool(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bool() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } // consumeBool wire decodes a bool pointer as a Bool. func consumeBool(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Bool() = protowire.DecodeBool(v) out.n = n return out, nil } var coderBool = pointerCoderFuncs{ size: sizeBool, marshal: appendBool, unmarshal: consumeBool, merge: mergeBool, } // sizeBoolNoZero returns the size of wire encoding a bool pointer as a Bool. // The zero value is not encoded. func sizeBoolNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bool() if v == false { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBoolNoZero wire encodes a bool pointer as a Bool. // The zero value is not encoded. func appendBoolNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bool() if v == false { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } var coderBoolNoZero = pointerCoderFuncs{ size: sizeBoolNoZero, marshal: appendBoolNoZero, unmarshal: consumeBool, merge: mergeBoolNoZero, } // sizeBoolPtr returns the size of wire encoding a *bool pointer as a Bool. // It panics if the pointer is nil. func sizeBoolPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.BoolPtr() return f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } // appendBoolPtr wire encodes a *bool pointer as a Bool. // It panics if the pointer is nil. func appendBoolPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.BoolPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) return b, nil } // consumeBoolPtr wire decodes a *bool pointer as a Bool. func consumeBoolPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.BoolPtr() if *vp == nil { *vp = new(bool) } **vp = protowire.DecodeBool(v) out.n = n return out, nil } var coderBoolPtr = pointerCoderFuncs{ size: sizeBoolPtr, marshal: appendBoolPtr, unmarshal: consumeBoolPtr, merge: mergeBoolPtr, } // sizeBoolSlice returns the size of wire encoding a []bool pointer as a repeated Bool. func sizeBoolSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BoolSlice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeBool(v)) } return size } // appendBoolSlice encodes a []bool pointer as a repeated Bool. func appendBoolSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BoolSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v)) } return b, nil } // consumeBoolSlice wire decodes a []bool pointer as a repeated Bool. func consumeBoolSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.BoolSlice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, protowire.DecodeBool(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, protowire.DecodeBool(v)) out.n = n return out, nil } var coderBoolSlice = pointerCoderFuncs{ size: sizeBoolSlice, marshal: appendBoolSlice, unmarshal: consumeBoolSlice, merge: mergeBoolSlice, } // sizeBoolPackedSlice returns the size of wire encoding a []bool pointer as a packed repeated Bool. func sizeBoolPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BoolSlice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeBool(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendBoolPackedSlice encodes a []bool pointer as a packed repeated Bool. func appendBoolPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BoolSlice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeBool(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeBool(v)) } return b, nil } var coderBoolPackedSlice = pointerCoderFuncs{ size: sizeBoolPackedSlice, marshal: appendBoolPackedSlice, unmarshal: consumeBoolSlice, merge: mergeBoolSlice, } // sizeBoolValue returns the size of wire encoding a bool value as a Bool. func sizeBoolValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } // appendBoolValue encodes a bool value as a Bool. func appendBoolValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) return b, nil } // consumeBoolValue decodes a bool value as a Bool. func consumeBoolValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfBool(protowire.DecodeBool(v)), out, nil } var coderBoolValue = valueCoderFuncs{ size: sizeBoolValue, marshal: appendBoolValue, unmarshal: consumeBoolValue, merge: mergeScalarValue, } // sizeBoolSliceValue returns the size of wire encoding a []bool value as a repeated Bool. func sizeBoolSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } return size } // appendBoolSliceValue encodes a []bool value as a repeated Bool. func appendBoolSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) } return b, nil } // consumeBoolSliceValue wire decodes a []bool value as a repeated Bool. func consumeBoolSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) out.n = n return listv, out, nil } var coderBoolSliceValue = valueCoderFuncs{ size: sizeBoolSliceValue, marshal: appendBoolSliceValue, unmarshal: consumeBoolSliceValue, merge: mergeListValue, } // sizeBoolPackedSliceValue returns the size of wire encoding a []bool value as a packed repeated Bool. func sizeBoolPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } return tagsize + protowire.SizeBytes(n) } // appendBoolPackedSliceValue encodes a []bool value as a packed repeated Bool. func appendBoolPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeBool(v.Bool())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) } return b, nil } var coderBoolPackedSliceValue = valueCoderFuncs{ size: sizeBoolPackedSliceValue, marshal: appendBoolPackedSliceValue, unmarshal: consumeBoolSliceValue, merge: mergeListValue, } // sizeEnumValue returns the size of wire encoding a value as a Enum. func sizeEnumValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(v.Enum())) } // appendEnumValue encodes a value as a Enum. func appendEnumValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Enum())) return b, nil } // consumeEnumValue decodes a value as a Enum. func consumeEnumValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), out, nil } var coderEnumValue = valueCoderFuncs{ size: sizeEnumValue, marshal: appendEnumValue, unmarshal: consumeEnumValue, merge: mergeScalarValue, } // sizeEnumSliceValue returns the size of wire encoding a [] value as a repeated Enum. func sizeEnumSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(v.Enum())) } return size } // appendEnumSliceValue encodes a [] value as a repeated Enum. func appendEnumSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Enum())) } return b, nil } // consumeEnumSliceValue wire decodes a [] value as a repeated Enum. func consumeEnumSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) out.n = n return listv, out, nil } var coderEnumSliceValue = valueCoderFuncs{ size: sizeEnumSliceValue, marshal: appendEnumSliceValue, unmarshal: consumeEnumSliceValue, merge: mergeListValue, } // sizeEnumPackedSliceValue returns the size of wire encoding a [] value as a packed repeated Enum. func sizeEnumPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Enum())) } return tagsize + protowire.SizeBytes(n) } // appendEnumPackedSliceValue encodes a [] value as a packed repeated Enum. func appendEnumPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Enum())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(v.Enum())) } return b, nil } var coderEnumPackedSliceValue = valueCoderFuncs{ size: sizeEnumPackedSliceValue, marshal: appendEnumPackedSliceValue, unmarshal: consumeEnumSliceValue, merge: mergeListValue, } // sizeInt32 returns the size of wire encoding a int32 pointer as a Int32. func sizeInt32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32 wire encodes a int32 pointer as a Int32. func appendInt32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt32 wire decodes a int32 pointer as a Int32. func consumeInt32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int32() = int32(v) out.n = n return out, nil } var coderInt32 = pointerCoderFuncs{ size: sizeInt32, marshal: appendInt32, unmarshal: consumeInt32, merge: mergeInt32, } // sizeInt32NoZero returns the size of wire encoding a int32 pointer as a Int32. // The zero value is not encoded. func sizeInt32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32NoZero wire encodes a int32 pointer as a Int32. // The zero value is not encoded. func appendInt32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderInt32NoZero = pointerCoderFuncs{ size: sizeInt32NoZero, marshal: appendInt32NoZero, unmarshal: consumeInt32, merge: mergeInt32NoZero, } // sizeInt32Ptr returns the size of wire encoding a *int32 pointer as a Int32. // It panics if the pointer is nil. func sizeInt32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int32Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt32Ptr wire encodes a *int32 pointer as a Int32. // It panics if the pointer is nil. func appendInt32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt32Ptr wire decodes a *int32 pointer as a Int32. func consumeInt32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(v) out.n = n return out, nil } var coderInt32Ptr = pointerCoderFuncs{ size: sizeInt32Ptr, marshal: appendInt32Ptr, unmarshal: consumeInt32Ptr, merge: mergeInt32Ptr, } // sizeInt32Slice returns the size of wire encoding a []int32 pointer as a repeated Int32. func sizeInt32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendInt32Slice encodes a []int32 pointer as a repeated Int32. func appendInt32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeInt32Slice wire decodes a []int32 pointer as a repeated Int32. func consumeInt32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int32(v)) out.n = n return out, nil } var coderInt32Slice = pointerCoderFuncs{ size: sizeInt32Slice, marshal: appendInt32Slice, unmarshal: consumeInt32Slice, merge: mergeInt32Slice, } // sizeInt32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Int32. func sizeInt32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendInt32PackedSlice encodes a []int32 pointer as a packed repeated Int32. func appendInt32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderInt32PackedSlice = pointerCoderFuncs{ size: sizeInt32PackedSlice, marshal: appendInt32PackedSlice, unmarshal: consumeInt32Slice, merge: mergeInt32Slice, } // sizeInt32Value returns the size of wire encoding a int32 value as a Int32. func sizeInt32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(int32(v.Int()))) } // appendInt32Value encodes a int32 value as a Int32. func appendInt32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) return b, nil } // consumeInt32Value decodes a int32 value as a Int32. func consumeInt32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(v)), out, nil } var coderInt32Value = valueCoderFuncs{ size: sizeInt32Value, marshal: appendInt32Value, unmarshal: consumeInt32Value, merge: mergeScalarValue, } // sizeInt32SliceValue returns the size of wire encoding a []int32 value as a repeated Int32. func sizeInt32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(int32(v.Int()))) } return size } // appendInt32SliceValue encodes a []int32 value as a repeated Int32. func appendInt32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) } return b, nil } // consumeInt32SliceValue wire decodes a []int32 value as a repeated Int32. func consumeInt32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) out.n = n return listv, out, nil } var coderInt32SliceValue = valueCoderFuncs{ size: sizeInt32SliceValue, marshal: appendInt32SliceValue, unmarshal: consumeInt32SliceValue, merge: mergeListValue, } // sizeInt32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Int32. func sizeInt32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(int32(v.Int()))) } return tagsize + protowire.SizeBytes(n) } // appendInt32PackedSliceValue encodes a []int32 value as a packed repeated Int32. func appendInt32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(int32(v.Int()))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(int32(v.Int()))) } return b, nil } var coderInt32PackedSliceValue = valueCoderFuncs{ size: sizeInt32PackedSliceValue, marshal: appendInt32PackedSliceValue, unmarshal: consumeInt32SliceValue, merge: mergeListValue, } // sizeSint32 returns the size of wire encoding a int32 pointer as a Sint32. func sizeSint32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32 wire encodes a int32 pointer as a Sint32. func appendSint32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } // consumeSint32 wire decodes a int32 pointer as a Sint32. func consumeSint32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int32() = int32(protowire.DecodeZigZag(v & math.MaxUint32)) out.n = n return out, nil } var coderSint32 = pointerCoderFuncs{ size: sizeSint32, marshal: appendSint32, unmarshal: consumeSint32, merge: mergeInt32, } // sizeSint32NoZero returns the size of wire encoding a int32 pointer as a Sint32. // The zero value is not encoded. func sizeSint32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32NoZero wire encodes a int32 pointer as a Sint32. // The zero value is not encoded. func appendSint32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } var coderSint32NoZero = pointerCoderFuncs{ size: sizeSint32NoZero, marshal: appendSint32NoZero, unmarshal: consumeSint32, merge: mergeInt32NoZero, } // sizeSint32Ptr returns the size of wire encoding a *int32 pointer as a Sint32. // It panics if the pointer is nil. func sizeSint32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int32Ptr() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } // appendSint32Ptr wire encodes a *int32 pointer as a Sint32. // It panics if the pointer is nil. func appendSint32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) return b, nil } // consumeSint32Ptr wire decodes a *int32 pointer as a Sint32. func consumeSint32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(protowire.DecodeZigZag(v & math.MaxUint32)) out.n = n return out, nil } var coderSint32Ptr = pointerCoderFuncs{ size: sizeSint32Ptr, marshal: appendSint32Ptr, unmarshal: consumeSint32Ptr, merge: mergeInt32Ptr, } // sizeSint32Slice returns the size of wire encoding a []int32 pointer as a repeated Sint32. func sizeSint32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } return size } // appendSint32Slice encodes a []int32 pointer as a repeated Sint32. func appendSint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) } return b, nil } // consumeSint32Slice wire decodes a []int32 pointer as a repeated Sint32. func consumeSint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int32(protowire.DecodeZigZag(v&math.MaxUint32))) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int32(protowire.DecodeZigZag(v&math.MaxUint32))) out.n = n return out, nil } var coderSint32Slice = pointerCoderFuncs{ size: sizeSint32Slice, marshal: appendSint32Slice, unmarshal: consumeSint32Slice, merge: mergeInt32Slice, } // sizeSint32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sint32. func sizeSint32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } return f.tagsize + protowire.SizeBytes(n) } // appendSint32PackedSlice encodes a []int32 pointer as a packed repeated Sint32. func appendSint32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(int64(v))) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(v))) } return b, nil } var coderSint32PackedSlice = pointerCoderFuncs{ size: sizeSint32PackedSlice, marshal: appendSint32PackedSlice, unmarshal: consumeSint32Slice, merge: mergeInt32Slice, } // sizeSint32Value returns the size of wire encoding a int32 value as a Sint32. func sizeSint32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } // appendSint32Value encodes a int32 value as a Sint32. func appendSint32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) return b, nil } // consumeSint32Value decodes a int32 value as a Sint32. func consumeSint32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), out, nil } var coderSint32Value = valueCoderFuncs{ size: sizeSint32Value, marshal: appendSint32Value, unmarshal: consumeSint32Value, merge: mergeScalarValue, } // sizeSint32SliceValue returns the size of wire encoding a []int32 value as a repeated Sint32. func sizeSint32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } return size } // appendSint32SliceValue encodes a []int32 value as a repeated Sint32. func appendSint32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) } return b, nil } // consumeSint32SliceValue wire decodes a []int32 value as a repeated Sint32. func consumeSint32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) out.n = n return listv, out, nil } var coderSint32SliceValue = valueCoderFuncs{ size: sizeSint32SliceValue, marshal: appendSint32SliceValue, unmarshal: consumeSint32SliceValue, merge: mergeListValue, } // sizeSint32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Sint32. func sizeSint32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } return tagsize + protowire.SizeBytes(n) } // appendSint32PackedSliceValue encodes a []int32 value as a packed repeated Sint32. func appendSint32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) } return b, nil } var coderSint32PackedSliceValue = valueCoderFuncs{ size: sizeSint32PackedSliceValue, marshal: appendSint32PackedSliceValue, unmarshal: consumeSint32SliceValue, merge: mergeListValue, } // sizeUint32 returns the size of wire encoding a uint32 pointer as a Uint32. func sizeUint32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32 wire encodes a uint32 pointer as a Uint32. func appendUint32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeUint32 wire decodes a uint32 pointer as a Uint32. func consumeUint32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Uint32() = uint32(v) out.n = n return out, nil } var coderUint32 = pointerCoderFuncs{ size: sizeUint32, marshal: appendUint32, unmarshal: consumeUint32, merge: mergeUint32, } // sizeUint32NoZero returns the size of wire encoding a uint32 pointer as a Uint32. // The zero value is not encoded. func sizeUint32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32NoZero wire encodes a uint32 pointer as a Uint32. // The zero value is not encoded. func appendUint32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderUint32NoZero = pointerCoderFuncs{ size: sizeUint32NoZero, marshal: appendUint32NoZero, unmarshal: consumeUint32, merge: mergeUint32NoZero, } // sizeUint32Ptr returns the size of wire encoding a *uint32 pointer as a Uint32. // It panics if the pointer is nil. func sizeUint32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Uint32Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendUint32Ptr wire encodes a *uint32 pointer as a Uint32. // It panics if the pointer is nil. func appendUint32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeUint32Ptr wire decodes a *uint32 pointer as a Uint32. func consumeUint32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Uint32Ptr() if *vp == nil { *vp = new(uint32) } **vp = uint32(v) out.n = n return out, nil } var coderUint32Ptr = pointerCoderFuncs{ size: sizeUint32Ptr, marshal: appendUint32Ptr, unmarshal: consumeUint32Ptr, merge: mergeUint32Ptr, } // sizeUint32Slice returns the size of wire encoding a []uint32 pointer as a repeated Uint32. func sizeUint32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendUint32Slice encodes a []uint32 pointer as a repeated Uint32. func appendUint32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeUint32Slice wire decodes a []uint32 pointer as a repeated Uint32. func consumeUint32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, uint32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, uint32(v)) out.n = n return out, nil } var coderUint32Slice = pointerCoderFuncs{ size: sizeUint32Slice, marshal: appendUint32Slice, unmarshal: consumeUint32Slice, merge: mergeUint32Slice, } // sizeUint32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Uint32. func sizeUint32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendUint32PackedSlice encodes a []uint32 pointer as a packed repeated Uint32. func appendUint32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderUint32PackedSlice = pointerCoderFuncs{ size: sizeUint32PackedSlice, marshal: appendUint32PackedSlice, unmarshal: consumeUint32Slice, merge: mergeUint32Slice, } // sizeUint32Value returns the size of wire encoding a uint32 value as a Uint32. func sizeUint32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(uint32(v.Uint()))) } // appendUint32Value encodes a uint32 value as a Uint32. func appendUint32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) return b, nil } // consumeUint32Value decodes a uint32 value as a Uint32. func consumeUint32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint32(uint32(v)), out, nil } var coderUint32Value = valueCoderFuncs{ size: sizeUint32Value, marshal: appendUint32Value, unmarshal: consumeUint32Value, merge: mergeScalarValue, } // sizeUint32SliceValue returns the size of wire encoding a []uint32 value as a repeated Uint32. func sizeUint32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(uint32(v.Uint()))) } return size } // appendUint32SliceValue encodes a []uint32 value as a repeated Uint32. func appendUint32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) } return b, nil } // consumeUint32SliceValue wire decodes a []uint32 value as a repeated Uint32. func consumeUint32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) out.n = n return listv, out, nil } var coderUint32SliceValue = valueCoderFuncs{ size: sizeUint32SliceValue, marshal: appendUint32SliceValue, unmarshal: consumeUint32SliceValue, merge: mergeListValue, } // sizeUint32PackedSliceValue returns the size of wire encoding a []uint32 value as a packed repeated Uint32. func sizeUint32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(uint32(v.Uint()))) } return tagsize + protowire.SizeBytes(n) } // appendUint32PackedSliceValue encodes a []uint32 value as a packed repeated Uint32. func appendUint32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(uint32(v.Uint()))) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) } return b, nil } var coderUint32PackedSliceValue = valueCoderFuncs{ size: sizeUint32PackedSliceValue, marshal: appendUint32PackedSliceValue, unmarshal: consumeUint32SliceValue, merge: mergeListValue, } // sizeInt64 returns the size of wire encoding a int64 pointer as a Int64. func sizeInt64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64 wire encodes a int64 pointer as a Int64. func appendInt64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt64 wire decodes a int64 pointer as a Int64. func consumeInt64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int64() = int64(v) out.n = n return out, nil } var coderInt64 = pointerCoderFuncs{ size: sizeInt64, marshal: appendInt64, unmarshal: consumeInt64, merge: mergeInt64, } // sizeInt64NoZero returns the size of wire encoding a int64 pointer as a Int64. // The zero value is not encoded. func sizeInt64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64NoZero wire encodes a int64 pointer as a Int64. // The zero value is not encoded. func appendInt64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } var coderInt64NoZero = pointerCoderFuncs{ size: sizeInt64NoZero, marshal: appendInt64NoZero, unmarshal: consumeInt64, merge: mergeInt64NoZero, } // sizeInt64Ptr returns the size of wire encoding a *int64 pointer as a Int64. // It panics if the pointer is nil. func sizeInt64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int64Ptr() return f.tagsize + protowire.SizeVarint(uint64(v)) } // appendInt64Ptr wire encodes a *int64 pointer as a Int64. // It panics if the pointer is nil. func appendInt64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } // consumeInt64Ptr wire decodes a *int64 pointer as a Int64. func consumeInt64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = int64(v) out.n = n return out, nil } var coderInt64Ptr = pointerCoderFuncs{ size: sizeInt64Ptr, marshal: appendInt64Ptr, unmarshal: consumeInt64Ptr, merge: mergeInt64Ptr, } // sizeInt64Slice returns the size of wire encoding a []int64 pointer as a repeated Int64. func sizeInt64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(uint64(v)) } return size } // appendInt64Slice encodes a []int64 pointer as a repeated Int64. func appendInt64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) } return b, nil } // consumeInt64Slice wire decodes a []int64 pointer as a repeated Int64. func consumeInt64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, int64(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, int64(v)) out.n = n return out, nil } var coderInt64Slice = pointerCoderFuncs{ size: sizeInt64Slice, marshal: appendInt64Slice, unmarshal: consumeInt64Slice, merge: mergeInt64Slice, } // sizeInt64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Int64. func sizeInt64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendInt64PackedSlice encodes a []int64 pointer as a packed repeated Int64. func appendInt64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(uint64(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, uint64(v)) } return b, nil } var coderInt64PackedSlice = pointerCoderFuncs{ size: sizeInt64PackedSlice, marshal: appendInt64PackedSlice, unmarshal: consumeInt64Slice, merge: mergeInt64Slice, } // sizeInt64Value returns the size of wire encoding a int64 value as a Int64. func sizeInt64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(uint64(v.Int())) } // appendInt64Value encodes a int64 value as a Int64. func appendInt64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Int())) return b, nil } // consumeInt64Value decodes a int64 value as a Int64. func consumeInt64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(int64(v)), out, nil } var coderInt64Value = valueCoderFuncs{ size: sizeInt64Value, marshal: appendInt64Value, unmarshal: consumeInt64Value, merge: mergeScalarValue, } // sizeInt64SliceValue returns the size of wire encoding a []int64 value as a repeated Int64. func sizeInt64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(uint64(v.Int())) } return size } // appendInt64SliceValue encodes a []int64 value as a repeated Int64. func appendInt64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, uint64(v.Int())) } return b, nil } // consumeInt64SliceValue wire decodes a []int64 value as a repeated Int64. func consumeInt64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) out.n = n return listv, out, nil } var coderInt64SliceValue = valueCoderFuncs{ size: sizeInt64SliceValue, marshal: appendInt64SliceValue, unmarshal: consumeInt64SliceValue, merge: mergeListValue, } // sizeInt64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Int64. func sizeInt64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Int())) } return tagsize + protowire.SizeBytes(n) } // appendInt64PackedSliceValue encodes a []int64 value as a packed repeated Int64. func appendInt64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(uint64(v.Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, uint64(v.Int())) } return b, nil } var coderInt64PackedSliceValue = valueCoderFuncs{ size: sizeInt64PackedSliceValue, marshal: appendInt64PackedSliceValue, unmarshal: consumeInt64SliceValue, merge: mergeListValue, } // sizeSint64 returns the size of wire encoding a int64 pointer as a Sint64. func sizeSint64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64 wire encodes a int64 pointer as a Sint64. func appendSint64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } // consumeSint64 wire decodes a int64 pointer as a Sint64. func consumeSint64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Int64() = protowire.DecodeZigZag(v) out.n = n return out, nil } var coderSint64 = pointerCoderFuncs{ size: sizeSint64, marshal: appendSint64, unmarshal: consumeSint64, merge: mergeInt64, } // sizeSint64NoZero returns the size of wire encoding a int64 pointer as a Sint64. // The zero value is not encoded. func sizeSint64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64NoZero wire encodes a int64 pointer as a Sint64. // The zero value is not encoded. func appendSint64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } var coderSint64NoZero = pointerCoderFuncs{ size: sizeSint64NoZero, marshal: appendSint64NoZero, unmarshal: consumeSint64, merge: mergeInt64NoZero, } // sizeSint64Ptr returns the size of wire encoding a *int64 pointer as a Sint64. // It panics if the pointer is nil. func sizeSint64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Int64Ptr() return f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } // appendSint64Ptr wire encodes a *int64 pointer as a Sint64. // It panics if the pointer is nil. func appendSint64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) return b, nil } // consumeSint64Ptr wire decodes a *int64 pointer as a Sint64. func consumeSint64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = protowire.DecodeZigZag(v) out.n = n return out, nil } var coderSint64Ptr = pointerCoderFuncs{ size: sizeSint64Ptr, marshal: appendSint64Ptr, unmarshal: consumeSint64Ptr, merge: mergeInt64Ptr, } // sizeSint64Slice returns the size of wire encoding a []int64 pointer as a repeated Sint64. func sizeSint64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v)) } return size } // appendSint64Slice encodes a []int64 pointer as a repeated Sint64. func appendSint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) } return b, nil } // consumeSint64Slice wire decodes a []int64 pointer as a repeated Sint64. func consumeSint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, protowire.DecodeZigZag(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, protowire.DecodeZigZag(v)) out.n = n return out, nil } var coderSint64Slice = pointerCoderFuncs{ size: sizeSint64Slice, marshal: appendSint64Slice, unmarshal: consumeSint64Slice, merge: mergeInt64Slice, } // sizeSint64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sint64. func sizeSint64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(v)) } return f.tagsize + protowire.SizeBytes(n) } // appendSint64PackedSlice encodes a []int64 pointer as a packed repeated Sint64. func appendSint64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(protowire.EncodeZigZag(v)) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, protowire.EncodeZigZag(v)) } return b, nil } var coderSint64PackedSlice = pointerCoderFuncs{ size: sizeSint64PackedSlice, marshal: appendSint64PackedSlice, unmarshal: consumeSint64Slice, merge: mergeInt64Slice, } // sizeSint64Value returns the size of wire encoding a int64 value as a Sint64. func sizeSint64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } // appendSint64Value encodes a int64 value as a Sint64. func appendSint64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) return b, nil } // consumeSint64Value decodes a int64 value as a Sint64. func consumeSint64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), out, nil } var coderSint64Value = valueCoderFuncs{ size: sizeSint64Value, marshal: appendSint64Value, unmarshal: consumeSint64Value, merge: mergeScalarValue, } // sizeSint64SliceValue returns the size of wire encoding a []int64 value as a repeated Sint64. func sizeSint64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } return size } // appendSint64SliceValue encodes a []int64 value as a repeated Sint64. func appendSint64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) } return b, nil } // consumeSint64SliceValue wire decodes a []int64 value as a repeated Sint64. func consumeSint64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) out.n = n return listv, out, nil } var coderSint64SliceValue = valueCoderFuncs{ size: sizeSint64SliceValue, marshal: appendSint64SliceValue, unmarshal: consumeSint64SliceValue, merge: mergeListValue, } // sizeSint64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Sint64. func sizeSint64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } return tagsize + protowire.SizeBytes(n) } // appendSint64PackedSliceValue encodes a []int64 value as a packed repeated Sint64. func appendSint64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) } return b, nil } var coderSint64PackedSliceValue = valueCoderFuncs{ size: sizeSint64PackedSliceValue, marshal: appendSint64PackedSliceValue, unmarshal: consumeSint64SliceValue, merge: mergeListValue, } // sizeUint64 returns the size of wire encoding a uint64 pointer as a Uint64. func sizeUint64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() return f.tagsize + protowire.SizeVarint(v) } // appendUint64 wire encodes a uint64 pointer as a Uint64. func appendUint64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } // consumeUint64 wire decodes a uint64 pointer as a Uint64. func consumeUint64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *p.Uint64() = v out.n = n return out, nil } var coderUint64 = pointerCoderFuncs{ size: sizeUint64, marshal: appendUint64, unmarshal: consumeUint64, merge: mergeUint64, } // sizeUint64NoZero returns the size of wire encoding a uint64 pointer as a Uint64. // The zero value is not encoded. func sizeUint64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() if v == 0 { return 0 } return f.tagsize + protowire.SizeVarint(v) } // appendUint64NoZero wire encodes a uint64 pointer as a Uint64. // The zero value is not encoded. func appendUint64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } var coderUint64NoZero = pointerCoderFuncs{ size: sizeUint64NoZero, marshal: appendUint64NoZero, unmarshal: consumeUint64, merge: mergeUint64NoZero, } // sizeUint64Ptr returns the size of wire encoding a *uint64 pointer as a Uint64. // It panics if the pointer is nil. func sizeUint64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.Uint64Ptr() return f.tagsize + protowire.SizeVarint(v) } // appendUint64Ptr wire encodes a *uint64 pointer as a Uint64. // It panics if the pointer is nil. func appendUint64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) return b, nil } // consumeUint64Ptr wire decodes a *uint64 pointer as a Uint64. func consumeUint64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } vp := p.Uint64Ptr() if *vp == nil { *vp = new(uint64) } **vp = v out.n = n return out, nil } var coderUint64Ptr = pointerCoderFuncs{ size: sizeUint64Ptr, marshal: appendUint64Ptr, unmarshal: consumeUint64Ptr, merge: mergeUint64Ptr, } // sizeUint64Slice returns the size of wire encoding a []uint64 pointer as a repeated Uint64. func sizeUint64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() for _, v := range s { size += f.tagsize + protowire.SizeVarint(v) } return size } // appendUint64Slice encodes a []uint64 pointer as a repeated Uint64. func appendUint64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, v) } return b, nil } // consumeUint64Slice wire decodes a []uint64 pointer as a repeated Uint64. func consumeUint64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderUint64Slice = pointerCoderFuncs{ size: sizeUint64Slice, marshal: appendUint64Slice, unmarshal: consumeUint64Slice, merge: mergeUint64Slice, } // sizeUint64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Uint64. func sizeUint64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() if len(s) == 0 { return 0 } n := 0 for _, v := range s { n += protowire.SizeVarint(v) } return f.tagsize + protowire.SizeBytes(n) } // appendUint64PackedSlice encodes a []uint64 pointer as a packed repeated Uint64. func appendUint64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for _, v := range s { n += protowire.SizeVarint(v) } b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendVarint(b, v) } return b, nil } var coderUint64PackedSlice = pointerCoderFuncs{ size: sizeUint64PackedSlice, marshal: appendUint64PackedSlice, unmarshal: consumeUint64Slice, merge: mergeUint64Slice, } // sizeUint64Value returns the size of wire encoding a uint64 value as a Uint64. func sizeUint64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeVarint(v.Uint()) } // appendUint64Value encodes a uint64 value as a Uint64. func appendUint64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, v.Uint()) return b, nil } // consumeUint64Value decodes a uint64 value as a Uint64. func consumeUint64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint64(v), out, nil } var coderUint64Value = valueCoderFuncs{ size: sizeUint64Value, marshal: appendUint64Value, unmarshal: consumeUint64Value, merge: mergeScalarValue, } // sizeUint64SliceValue returns the size of wire encoding a []uint64 value as a repeated Uint64. func sizeUint64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeVarint(v.Uint()) } return size } // appendUint64SliceValue encodes a []uint64 value as a repeated Uint64. func appendUint64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendVarint(b, v.Uint()) } return b, nil } // consumeUint64SliceValue wire decodes a []uint64 value as a repeated Uint64. func consumeUint64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.VarintType { return protoreflect.Value{}, out, errUnknown } var v uint64 var n int if len(b) >= 1 && b[0] < 0x80 { v = uint64(b[0]) n = 1 } else if len(b) >= 2 && b[1] < 128 { v = uint64(b[0]&0x7f) + uint64(b[1])<<7 n = 2 } else { v, n = protowire.ConsumeVarint(b) } if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) out.n = n return listv, out, nil } var coderUint64SliceValue = valueCoderFuncs{ size: sizeUint64SliceValue, marshal: appendUint64SliceValue, unmarshal: consumeUint64SliceValue, merge: mergeListValue, } // sizeUint64PackedSliceValue returns the size of wire encoding a []uint64 value as a packed repeated Uint64. func sizeUint64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := 0 for i, llen := 0, llen; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(v.Uint()) } return tagsize + protowire.SizeBytes(n) } // appendUint64PackedSliceValue encodes a []uint64 value as a packed repeated Uint64. func appendUint64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := 0 for i := 0; i < llen; i++ { v := list.Get(i) n += protowire.SizeVarint(v.Uint()) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, v.Uint()) } return b, nil } var coderUint64PackedSliceValue = valueCoderFuncs{ size: sizeUint64PackedSliceValue, marshal: appendUint64PackedSliceValue, unmarshal: consumeUint64SliceValue, merge: mergeListValue, } // sizeSfixed32 returns the size of wire encoding a int32 pointer as a Sfixed32. func sizeSfixed32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendSfixed32 wire encodes a int32 pointer as a Sfixed32. func appendSfixed32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } // consumeSfixed32 wire decodes a int32 pointer as a Sfixed32. func consumeSfixed32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Int32() = int32(v) out.n = n return out, nil } var coderSfixed32 = pointerCoderFuncs{ size: sizeSfixed32, marshal: appendSfixed32, unmarshal: consumeSfixed32, merge: mergeInt32, } // sizeSfixed32NoZero returns the size of wire encoding a int32 pointer as a Sfixed32. // The zero value is not encoded. func sizeSfixed32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int32() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendSfixed32NoZero wire encodes a int32 pointer as a Sfixed32. // The zero value is not encoded. func appendSfixed32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } var coderSfixed32NoZero = pointerCoderFuncs{ size: sizeSfixed32NoZero, marshal: appendSfixed32NoZero, unmarshal: consumeSfixed32, merge: mergeInt32NoZero, } // sizeSfixed32Ptr returns the size of wire encoding a *int32 pointer as a Sfixed32. // It panics if the pointer is nil. func sizeSfixed32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendSfixed32Ptr wire encodes a *int32 pointer as a Sfixed32. // It panics if the pointer is nil. func appendSfixed32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) return b, nil } // consumeSfixed32Ptr wire decodes a *int32 pointer as a Sfixed32. func consumeSfixed32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Int32Ptr() if *vp == nil { *vp = new(int32) } **vp = int32(v) out.n = n return out, nil } var coderSfixed32Ptr = pointerCoderFuncs{ size: sizeSfixed32Ptr, marshal: appendSfixed32Ptr, unmarshal: consumeSfixed32Ptr, merge: mergeInt32Ptr, } // sizeSfixed32Slice returns the size of wire encoding a []int32 pointer as a repeated Sfixed32. func sizeSfixed32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendSfixed32Slice encodes a []int32 pointer as a repeated Sfixed32. func appendSfixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, uint32(v)) } return b, nil } // consumeSfixed32Slice wire decodes a []int32 pointer as a repeated Sfixed32. func consumeSfixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, int32(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, int32(v)) out.n = n return out, nil } var coderSfixed32Slice = pointerCoderFuncs{ size: sizeSfixed32Slice, marshal: appendSfixed32Slice, unmarshal: consumeSfixed32Slice, merge: mergeInt32Slice, } // sizeSfixed32PackedSlice returns the size of wire encoding a []int32 pointer as a packed repeated Sfixed32. func sizeSfixed32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendSfixed32PackedSlice encodes a []int32 pointer as a packed repeated Sfixed32. func appendSfixed32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, uint32(v)) } return b, nil } var coderSfixed32PackedSlice = pointerCoderFuncs{ size: sizeSfixed32PackedSlice, marshal: appendSfixed32PackedSlice, unmarshal: consumeSfixed32Slice, merge: mergeInt32Slice, } // sizeSfixed32Value returns the size of wire encoding a int32 value as a Sfixed32. func sizeSfixed32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendSfixed32Value encodes a int32 value as a Sfixed32. func appendSfixed32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Int())) return b, nil } // consumeSfixed32Value decodes a int32 value as a Sfixed32. func consumeSfixed32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt32(int32(v)), out, nil } var coderSfixed32Value = valueCoderFuncs{ size: sizeSfixed32Value, marshal: appendSfixed32Value, unmarshal: consumeSfixed32Value, merge: mergeScalarValue, } // sizeSfixed32SliceValue returns the size of wire encoding a []int32 value as a repeated Sfixed32. func sizeSfixed32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendSfixed32SliceValue encodes a []int32 value as a repeated Sfixed32. func appendSfixed32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Int())) } return b, nil } // consumeSfixed32SliceValue wire decodes a []int32 value as a repeated Sfixed32. func consumeSfixed32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) out.n = n return listv, out, nil } var coderSfixed32SliceValue = valueCoderFuncs{ size: sizeSfixed32SliceValue, marshal: appendSfixed32SliceValue, unmarshal: consumeSfixed32SliceValue, merge: mergeListValue, } // sizeSfixed32PackedSliceValue returns the size of wire encoding a []int32 value as a packed repeated Sfixed32. func sizeSfixed32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendSfixed32PackedSliceValue encodes a []int32 value as a packed repeated Sfixed32. func appendSfixed32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, uint32(v.Int())) } return b, nil } var coderSfixed32PackedSliceValue = valueCoderFuncs{ size: sizeSfixed32PackedSliceValue, marshal: appendSfixed32PackedSliceValue, unmarshal: consumeSfixed32SliceValue, merge: mergeListValue, } // sizeFixed32 returns the size of wire encoding a uint32 pointer as a Fixed32. func sizeFixed32(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFixed32 wire encodes a uint32 pointer as a Fixed32. func appendFixed32(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } // consumeFixed32 wire decodes a uint32 pointer as a Fixed32. func consumeFixed32(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Uint32() = v out.n = n return out, nil } var coderFixed32 = pointerCoderFuncs{ size: sizeFixed32, marshal: appendFixed32, unmarshal: consumeFixed32, merge: mergeUint32, } // sizeFixed32NoZero returns the size of wire encoding a uint32 pointer as a Fixed32. // The zero value is not encoded. func sizeFixed32NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint32() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendFixed32NoZero wire encodes a uint32 pointer as a Fixed32. // The zero value is not encoded. func appendFixed32NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint32() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } var coderFixed32NoZero = pointerCoderFuncs{ size: sizeFixed32NoZero, marshal: appendFixed32NoZero, unmarshal: consumeFixed32, merge: mergeUint32NoZero, } // sizeFixed32Ptr returns the size of wire encoding a *uint32 pointer as a Fixed32. // It panics if the pointer is nil. func sizeFixed32Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFixed32Ptr wire encodes a *uint32 pointer as a Fixed32. // It panics if the pointer is nil. func appendFixed32Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) return b, nil } // consumeFixed32Ptr wire decodes a *uint32 pointer as a Fixed32. func consumeFixed32Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Uint32Ptr() if *vp == nil { *vp = new(uint32) } **vp = v out.n = n return out, nil } var coderFixed32Ptr = pointerCoderFuncs{ size: sizeFixed32Ptr, marshal: appendFixed32Ptr, unmarshal: consumeFixed32Ptr, merge: mergeUint32Ptr, } // sizeFixed32Slice returns the size of wire encoding a []uint32 pointer as a repeated Fixed32. func sizeFixed32Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendFixed32Slice encodes a []uint32 pointer as a repeated Fixed32. func appendFixed32Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, v) } return b, nil } // consumeFixed32Slice wire decodes a []uint32 pointer as a repeated Fixed32. func consumeFixed32Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderFixed32Slice = pointerCoderFuncs{ size: sizeFixed32Slice, marshal: appendFixed32Slice, unmarshal: consumeFixed32Slice, merge: mergeUint32Slice, } // sizeFixed32PackedSlice returns the size of wire encoding a []uint32 pointer as a packed repeated Fixed32. func sizeFixed32PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendFixed32PackedSlice encodes a []uint32 pointer as a packed repeated Fixed32. func appendFixed32PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, v) } return b, nil } var coderFixed32PackedSlice = pointerCoderFuncs{ size: sizeFixed32PackedSlice, marshal: appendFixed32PackedSlice, unmarshal: consumeFixed32Slice, merge: mergeUint32Slice, } // sizeFixed32Value returns the size of wire encoding a uint32 value as a Fixed32. func sizeFixed32Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendFixed32Value encodes a uint32 value as a Fixed32. func appendFixed32Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Uint())) return b, nil } // consumeFixed32Value decodes a uint32 value as a Fixed32. func consumeFixed32Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint32(uint32(v)), out, nil } var coderFixed32Value = valueCoderFuncs{ size: sizeFixed32Value, marshal: appendFixed32Value, unmarshal: consumeFixed32Value, merge: mergeScalarValue, } // sizeFixed32SliceValue returns the size of wire encoding a []uint32 value as a repeated Fixed32. func sizeFixed32SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendFixed32SliceValue encodes a []uint32 value as a repeated Fixed32. func appendFixed32SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, uint32(v.Uint())) } return b, nil } // consumeFixed32SliceValue wire decodes a []uint32 value as a repeated Fixed32. func consumeFixed32SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) out.n = n return listv, out, nil } var coderFixed32SliceValue = valueCoderFuncs{ size: sizeFixed32SliceValue, marshal: appendFixed32SliceValue, unmarshal: consumeFixed32SliceValue, merge: mergeListValue, } // sizeFixed32PackedSliceValue returns the size of wire encoding a []uint32 value as a packed repeated Fixed32. func sizeFixed32PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendFixed32PackedSliceValue encodes a []uint32 value as a packed repeated Fixed32. func appendFixed32PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, uint32(v.Uint())) } return b, nil } var coderFixed32PackedSliceValue = valueCoderFuncs{ size: sizeFixed32PackedSliceValue, marshal: appendFixed32PackedSliceValue, unmarshal: consumeFixed32SliceValue, merge: mergeListValue, } // sizeFloat returns the size of wire encoding a float32 pointer as a Float. func sizeFloat(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFloat wire encodes a float32 pointer as a Float. func appendFloat(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float32() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } // consumeFloat wire decodes a float32 pointer as a Float. func consumeFloat(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *p.Float32() = math.Float32frombits(v) out.n = n return out, nil } var coderFloat = pointerCoderFuncs{ size: sizeFloat, marshal: appendFloat, unmarshal: consumeFloat, merge: mergeFloat32, } // sizeFloatNoZero returns the size of wire encoding a float32 pointer as a Float. // The zero value is not encoded. func sizeFloatNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Float32() if v == 0 && !math.Signbit(float64(v)) { return 0 } return f.tagsize + protowire.SizeFixed32() } // appendFloatNoZero wire encodes a float32 pointer as a Float. // The zero value is not encoded. func appendFloatNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float32() if v == 0 && !math.Signbit(float64(v)) { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } var coderFloatNoZero = pointerCoderFuncs{ size: sizeFloatNoZero, marshal: appendFloatNoZero, unmarshal: consumeFloat, merge: mergeFloat32NoZero, } // sizeFloatPtr returns the size of wire encoding a *float32 pointer as a Float. // It panics if the pointer is nil. func sizeFloatPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed32() } // appendFloatPtr wire encodes a *float32 pointer as a Float. // It panics if the pointer is nil. func appendFloatPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Float32Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) return b, nil } // consumeFloatPtr wire decodes a *float32 pointer as a Float. func consumeFloatPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } vp := p.Float32Ptr() if *vp == nil { *vp = new(float32) } **vp = math.Float32frombits(v) out.n = n return out, nil } var coderFloatPtr = pointerCoderFuncs{ size: sizeFloatPtr, marshal: appendFloatPtr, unmarshal: consumeFloatPtr, merge: mergeFloat32Ptr, } // sizeFloatSlice returns the size of wire encoding a []float32 pointer as a repeated Float. func sizeFloatSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float32Slice() size = len(s) * (f.tagsize + protowire.SizeFixed32()) return size } // appendFloatSlice encodes a []float32 pointer as a repeated Float. func appendFloatSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float32Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed32(b, math.Float32bits(v)) } return b, nil } // consumeFloatSlice wire decodes a []float32 pointer as a repeated Float. func consumeFloatSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Float32Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } s = append(s, math.Float32frombits(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed32Type { return out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return out, errDecode } *sp = append(*sp, math.Float32frombits(v)) out.n = n return out, nil } var coderFloatSlice = pointerCoderFuncs{ size: sizeFloatSlice, marshal: appendFloatSlice, unmarshal: consumeFloatSlice, merge: mergeFloat32Slice, } // sizeFloatPackedSlice returns the size of wire encoding a []float32 pointer as a packed repeated Float. func sizeFloatPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float32Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed32() return f.tagsize + protowire.SizeBytes(n) } // appendFloatPackedSlice encodes a []float32 pointer as a packed repeated Float. func appendFloatPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float32Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed32(b, math.Float32bits(v)) } return b, nil } var coderFloatPackedSlice = pointerCoderFuncs{ size: sizeFloatPackedSlice, marshal: appendFloatPackedSlice, unmarshal: consumeFloatSlice, merge: mergeFloat32Slice, } // sizeFloatValue returns the size of wire encoding a float32 value as a Float. func sizeFloatValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed32() } // appendFloatValue encodes a float32 value as a Float. func appendFloatValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) return b, nil } // consumeFloatValue decodes a float32 value as a Float. func consumeFloatValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), out, nil } var coderFloatValue = valueCoderFuncs{ size: sizeFloatValue, marshal: appendFloatValue, unmarshal: consumeFloatValue, merge: mergeScalarValue, } // sizeFloatSliceValue returns the size of wire encoding a []float32 value as a repeated Float. func sizeFloatSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed32()) return size } // appendFloatSliceValue encodes a []float32 value as a repeated Float. func appendFloatSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) } return b, nil } // consumeFloatSliceValue wire decodes a []float32 value as a repeated Float. func consumeFloatSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed32Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) out.n = n return listv, out, nil } var coderFloatSliceValue = valueCoderFuncs{ size: sizeFloatSliceValue, marshal: appendFloatSliceValue, unmarshal: consumeFloatSliceValue, merge: mergeListValue, } // sizeFloatPackedSliceValue returns the size of wire encoding a []float32 value as a packed repeated Float. func sizeFloatPackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed32() return tagsize + protowire.SizeBytes(n) } // appendFloatPackedSliceValue encodes a []float32 value as a packed repeated Float. func appendFloatPackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed32() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) } return b, nil } var coderFloatPackedSliceValue = valueCoderFuncs{ size: sizeFloatPackedSliceValue, marshal: appendFloatPackedSliceValue, unmarshal: consumeFloatSliceValue, merge: mergeListValue, } // sizeSfixed64 returns the size of wire encoding a int64 pointer as a Sfixed64. func sizeSfixed64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendSfixed64 wire encodes a int64 pointer as a Sfixed64. func appendSfixed64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } // consumeSfixed64 wire decodes a int64 pointer as a Sfixed64. func consumeSfixed64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Int64() = int64(v) out.n = n return out, nil } var coderSfixed64 = pointerCoderFuncs{ size: sizeSfixed64, marshal: appendSfixed64, unmarshal: consumeSfixed64, merge: mergeInt64, } // sizeSfixed64NoZero returns the size of wire encoding a int64 pointer as a Sfixed64. // The zero value is not encoded. func sizeSfixed64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Int64() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendSfixed64NoZero wire encodes a int64 pointer as a Sfixed64. // The zero value is not encoded. func appendSfixed64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Int64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } var coderSfixed64NoZero = pointerCoderFuncs{ size: sizeSfixed64NoZero, marshal: appendSfixed64NoZero, unmarshal: consumeSfixed64, merge: mergeInt64NoZero, } // sizeSfixed64Ptr returns the size of wire encoding a *int64 pointer as a Sfixed64. // It panics if the pointer is nil. func sizeSfixed64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendSfixed64Ptr wire encodes a *int64 pointer as a Sfixed64. // It panics if the pointer is nil. func appendSfixed64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Int64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) return b, nil } // consumeSfixed64Ptr wire decodes a *int64 pointer as a Sfixed64. func consumeSfixed64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Int64Ptr() if *vp == nil { *vp = new(int64) } **vp = int64(v) out.n = n return out, nil } var coderSfixed64Ptr = pointerCoderFuncs{ size: sizeSfixed64Ptr, marshal: appendSfixed64Ptr, unmarshal: consumeSfixed64Ptr, merge: mergeInt64Ptr, } // sizeSfixed64Slice returns the size of wire encoding a []int64 pointer as a repeated Sfixed64. func sizeSfixed64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendSfixed64Slice encodes a []int64 pointer as a repeated Sfixed64. func appendSfixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, uint64(v)) } return b, nil } // consumeSfixed64Slice wire decodes a []int64 pointer as a repeated Sfixed64. func consumeSfixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Int64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, int64(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, int64(v)) out.n = n return out, nil } var coderSfixed64Slice = pointerCoderFuncs{ size: sizeSfixed64Slice, marshal: appendSfixed64Slice, unmarshal: consumeSfixed64Slice, merge: mergeInt64Slice, } // sizeSfixed64PackedSlice returns the size of wire encoding a []int64 pointer as a packed repeated Sfixed64. func sizeSfixed64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Int64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendSfixed64PackedSlice encodes a []int64 pointer as a packed repeated Sfixed64. func appendSfixed64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Int64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, uint64(v)) } return b, nil } var coderSfixed64PackedSlice = pointerCoderFuncs{ size: sizeSfixed64PackedSlice, marshal: appendSfixed64PackedSlice, unmarshal: consumeSfixed64Slice, merge: mergeInt64Slice, } // sizeSfixed64Value returns the size of wire encoding a int64 value as a Sfixed64. func sizeSfixed64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendSfixed64Value encodes a int64 value as a Sfixed64. func appendSfixed64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, uint64(v.Int())) return b, nil } // consumeSfixed64Value decodes a int64 value as a Sfixed64. func consumeSfixed64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfInt64(int64(v)), out, nil } var coderSfixed64Value = valueCoderFuncs{ size: sizeSfixed64Value, marshal: appendSfixed64Value, unmarshal: consumeSfixed64Value, merge: mergeScalarValue, } // sizeSfixed64SliceValue returns the size of wire encoding a []int64 value as a repeated Sfixed64. func sizeSfixed64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendSfixed64SliceValue encodes a []int64 value as a repeated Sfixed64. func appendSfixed64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, uint64(v.Int())) } return b, nil } // consumeSfixed64SliceValue wire decodes a []int64 value as a repeated Sfixed64. func consumeSfixed64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) out.n = n return listv, out, nil } var coderSfixed64SliceValue = valueCoderFuncs{ size: sizeSfixed64SliceValue, marshal: appendSfixed64SliceValue, unmarshal: consumeSfixed64SliceValue, merge: mergeListValue, } // sizeSfixed64PackedSliceValue returns the size of wire encoding a []int64 value as a packed repeated Sfixed64. func sizeSfixed64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendSfixed64PackedSliceValue encodes a []int64 value as a packed repeated Sfixed64. func appendSfixed64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, uint64(v.Int())) } return b, nil } var coderSfixed64PackedSliceValue = valueCoderFuncs{ size: sizeSfixed64PackedSliceValue, marshal: appendSfixed64PackedSliceValue, unmarshal: consumeSfixed64SliceValue, merge: mergeListValue, } // sizeFixed64 returns the size of wire encoding a uint64 pointer as a Fixed64. func sizeFixed64(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendFixed64 wire encodes a uint64 pointer as a Fixed64. func appendFixed64(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } // consumeFixed64 wire decodes a uint64 pointer as a Fixed64. func consumeFixed64(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Uint64() = v out.n = n return out, nil } var coderFixed64 = pointerCoderFuncs{ size: sizeFixed64, marshal: appendFixed64, unmarshal: consumeFixed64, merge: mergeUint64, } // sizeFixed64NoZero returns the size of wire encoding a uint64 pointer as a Fixed64. // The zero value is not encoded. func sizeFixed64NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Uint64() if v == 0 { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendFixed64NoZero wire encodes a uint64 pointer as a Fixed64. // The zero value is not encoded. func appendFixed64NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Uint64() if v == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } var coderFixed64NoZero = pointerCoderFuncs{ size: sizeFixed64NoZero, marshal: appendFixed64NoZero, unmarshal: consumeFixed64, merge: mergeUint64NoZero, } // sizeFixed64Ptr returns the size of wire encoding a *uint64 pointer as a Fixed64. // It panics if the pointer is nil. func sizeFixed64Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendFixed64Ptr wire encodes a *uint64 pointer as a Fixed64. // It panics if the pointer is nil. func appendFixed64Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Uint64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) return b, nil } // consumeFixed64Ptr wire decodes a *uint64 pointer as a Fixed64. func consumeFixed64Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Uint64Ptr() if *vp == nil { *vp = new(uint64) } **vp = v out.n = n return out, nil } var coderFixed64Ptr = pointerCoderFuncs{ size: sizeFixed64Ptr, marshal: appendFixed64Ptr, unmarshal: consumeFixed64Ptr, merge: mergeUint64Ptr, } // sizeFixed64Slice returns the size of wire encoding a []uint64 pointer as a repeated Fixed64. func sizeFixed64Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendFixed64Slice encodes a []uint64 pointer as a repeated Fixed64. func appendFixed64Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, v) } return b, nil } // consumeFixed64Slice wire decodes a []uint64 pointer as a repeated Fixed64. func consumeFixed64Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Uint64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, v) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, v) out.n = n return out, nil } var coderFixed64Slice = pointerCoderFuncs{ size: sizeFixed64Slice, marshal: appendFixed64Slice, unmarshal: consumeFixed64Slice, merge: mergeUint64Slice, } // sizeFixed64PackedSlice returns the size of wire encoding a []uint64 pointer as a packed repeated Fixed64. func sizeFixed64PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Uint64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendFixed64PackedSlice encodes a []uint64 pointer as a packed repeated Fixed64. func appendFixed64PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Uint64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, v) } return b, nil } var coderFixed64PackedSlice = pointerCoderFuncs{ size: sizeFixed64PackedSlice, marshal: appendFixed64PackedSlice, unmarshal: consumeFixed64Slice, merge: mergeUint64Slice, } // sizeFixed64Value returns the size of wire encoding a uint64 value as a Fixed64. func sizeFixed64Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendFixed64Value encodes a uint64 value as a Fixed64. func appendFixed64Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, v.Uint()) return b, nil } // consumeFixed64Value decodes a uint64 value as a Fixed64. func consumeFixed64Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfUint64(v), out, nil } var coderFixed64Value = valueCoderFuncs{ size: sizeFixed64Value, marshal: appendFixed64Value, unmarshal: consumeFixed64Value, merge: mergeScalarValue, } // sizeFixed64SliceValue returns the size of wire encoding a []uint64 value as a repeated Fixed64. func sizeFixed64SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendFixed64SliceValue encodes a []uint64 value as a repeated Fixed64. func appendFixed64SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, v.Uint()) } return b, nil } // consumeFixed64SliceValue wire decodes a []uint64 value as a repeated Fixed64. func consumeFixed64SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfUint64(v)) out.n = n return listv, out, nil } var coderFixed64SliceValue = valueCoderFuncs{ size: sizeFixed64SliceValue, marshal: appendFixed64SliceValue, unmarshal: consumeFixed64SliceValue, merge: mergeListValue, } // sizeFixed64PackedSliceValue returns the size of wire encoding a []uint64 value as a packed repeated Fixed64. func sizeFixed64PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendFixed64PackedSliceValue encodes a []uint64 value as a packed repeated Fixed64. func appendFixed64PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, v.Uint()) } return b, nil } var coderFixed64PackedSliceValue = valueCoderFuncs{ size: sizeFixed64PackedSliceValue, marshal: appendFixed64PackedSliceValue, unmarshal: consumeFixed64SliceValue, merge: mergeListValue, } // sizeDouble returns the size of wire encoding a float64 pointer as a Double. func sizeDouble(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendDouble wire encodes a float64 pointer as a Double. func appendDouble(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float64() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } // consumeDouble wire decodes a float64 pointer as a Double. func consumeDouble(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *p.Float64() = math.Float64frombits(v) out.n = n return out, nil } var coderDouble = pointerCoderFuncs{ size: sizeDouble, marshal: appendDouble, unmarshal: consumeDouble, merge: mergeFloat64, } // sizeDoubleNoZero returns the size of wire encoding a float64 pointer as a Double. // The zero value is not encoded. func sizeDoubleNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Float64() if v == 0 && !math.Signbit(float64(v)) { return 0 } return f.tagsize + protowire.SizeFixed64() } // appendDoubleNoZero wire encodes a float64 pointer as a Double. // The zero value is not encoded. func appendDoubleNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Float64() if v == 0 && !math.Signbit(float64(v)) { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } var coderDoubleNoZero = pointerCoderFuncs{ size: sizeDoubleNoZero, marshal: appendDoubleNoZero, unmarshal: consumeDouble, merge: mergeFloat64NoZero, } // sizeDoublePtr returns the size of wire encoding a *float64 pointer as a Double. // It panics if the pointer is nil. func sizeDoublePtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return f.tagsize + protowire.SizeFixed64() } // appendDoublePtr wire encodes a *float64 pointer as a Double. // It panics if the pointer is nil. func appendDoublePtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.Float64Ptr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) return b, nil } // consumeDoublePtr wire decodes a *float64 pointer as a Double. func consumeDoublePtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } vp := p.Float64Ptr() if *vp == nil { *vp = new(float64) } **vp = math.Float64frombits(v) out.n = n return out, nil } var coderDoublePtr = pointerCoderFuncs{ size: sizeDoublePtr, marshal: appendDoublePtr, unmarshal: consumeDoublePtr, merge: mergeFloat64Ptr, } // sizeDoubleSlice returns the size of wire encoding a []float64 pointer as a repeated Double. func sizeDoubleSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float64Slice() size = len(s) * (f.tagsize + protowire.SizeFixed64()) return size } // appendDoubleSlice encodes a []float64 pointer as a repeated Double. func appendDoubleSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float64Slice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v)) } return b, nil } // consumeDoubleSlice wire decodes a []float64 pointer as a repeated Double. func consumeDoubleSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.Float64Slice() if wtyp == protowire.BytesType { s := *sp b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } s = append(s, math.Float64frombits(v)) b = b[n:] } *sp = s out.n = n return out, nil } if wtyp != protowire.Fixed64Type { return out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return out, errDecode } *sp = append(*sp, math.Float64frombits(v)) out.n = n return out, nil } var coderDoubleSlice = pointerCoderFuncs{ size: sizeDoubleSlice, marshal: appendDoubleSlice, unmarshal: consumeDoubleSlice, merge: mergeFloat64Slice, } // sizeDoublePackedSlice returns the size of wire encoding a []float64 pointer as a packed repeated Double. func sizeDoublePackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.Float64Slice() if len(s) == 0 { return 0 } n := len(s) * protowire.SizeFixed64() return f.tagsize + protowire.SizeBytes(n) } // appendDoublePackedSlice encodes a []float64 pointer as a packed repeated Double. func appendDoublePackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.Float64Slice() if len(s) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := len(s) * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for _, v := range s { b = protowire.AppendFixed64(b, math.Float64bits(v)) } return b, nil } var coderDoublePackedSlice = pointerCoderFuncs{ size: sizeDoublePackedSlice, marshal: appendDoublePackedSlice, unmarshal: consumeDoubleSlice, merge: mergeFloat64Slice, } // sizeDoubleValue returns the size of wire encoding a float64 value as a Double. func sizeDoubleValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeFixed64() } // appendDoubleValue encodes a float64 value as a Double. func appendDoubleValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) return b, nil } // consumeDoubleValue decodes a float64 value as a Double. func consumeDoubleValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfFloat64(math.Float64frombits(v)), out, nil } var coderDoubleValue = valueCoderFuncs{ size: sizeDoubleValue, marshal: appendDoubleValue, unmarshal: consumeDoubleValue, merge: mergeScalarValue, } // sizeDoubleSliceValue returns the size of wire encoding a []float64 value as a repeated Double. func sizeDoubleSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() size = list.Len() * (tagsize + protowire.SizeFixed64()) return size } // appendDoubleSliceValue encodes a []float64 value as a repeated Double. func appendDoubleSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) } return b, nil } // consumeDoubleSliceValue wire decodes a []float64 value as a repeated Double. func consumeDoubleSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) b = b[n:] } out.n = n return listv, out, nil } if wtyp != protowire.Fixed64Type { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) out.n = n return listv, out, nil } var coderDoubleSliceValue = valueCoderFuncs{ size: sizeDoubleSliceValue, marshal: appendDoubleSliceValue, unmarshal: consumeDoubleSliceValue, merge: mergeListValue, } // sizeDoublePackedSliceValue returns the size of wire encoding a []float64 value as a packed repeated Double. func sizeDoublePackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() llen := list.Len() if llen == 0 { return 0 } n := llen * protowire.SizeFixed64() return tagsize + protowire.SizeBytes(n) } // appendDoublePackedSliceValue encodes a []float64 value as a packed repeated Double. func appendDoublePackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() llen := list.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, wiretag) n := llen * protowire.SizeFixed64() b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { v := list.Get(i) b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) } return b, nil } var coderDoublePackedSliceValue = valueCoderFuncs{ size: sizeDoublePackedSliceValue, marshal: appendDoublePackedSliceValue, unmarshal: consumeDoubleSliceValue, merge: mergeListValue, } // sizeString returns the size of wire encoding a string pointer as a String. func sizeString(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.String() return f.tagsize + protowire.SizeBytes(len(v)) } // appendString wire encodes a string pointer as a String. func appendString(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } // consumeString wire decodes a string pointer as a String. func consumeString(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.String() = string(v) out.n = n return out, nil } var coderString = pointerCoderFuncs{ size: sizeString, marshal: appendString, unmarshal: consumeString, merge: mergeString, } // appendStringValidateUTF8 wire encodes a string pointer as a String. func appendStringValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } // consumeStringValidateUTF8 wire decodes a string pointer as a String. func consumeStringValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.String() = string(v) out.n = n return out, nil } var coderStringValidateUTF8 = pointerCoderFuncs{ size: sizeString, marshal: appendStringValidateUTF8, unmarshal: consumeStringValidateUTF8, merge: mergeString, } // sizeStringNoZero returns the size of wire encoding a string pointer as a String. // The zero value is not encoded. func sizeStringNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.String() if len(v) == 0 { return 0 } return f.tagsize + protowire.SizeBytes(len(v)) } // appendStringNoZero wire encodes a string pointer as a String. // The zero value is not encoded. func appendStringNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } var coderStringNoZero = pointerCoderFuncs{ size: sizeStringNoZero, marshal: appendStringNoZero, unmarshal: consumeString, merge: mergeStringNoZero, } // appendStringNoZeroValidateUTF8 wire encodes a string pointer as a String. // The zero value is not encoded. func appendStringNoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.String() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } var coderStringNoZeroValidateUTF8 = pointerCoderFuncs{ size: sizeStringNoZero, marshal: appendStringNoZeroValidateUTF8, unmarshal: consumeStringValidateUTF8, merge: mergeStringNoZero, } // sizeStringPtr returns the size of wire encoding a *string pointer as a String. // It panics if the pointer is nil. func sizeStringPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := **p.StringPtr() return f.tagsize + protowire.SizeBytes(len(v)) } // appendStringPtr wire encodes a *string pointer as a String. // It panics if the pointer is nil. func appendStringPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.StringPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) return b, nil } // consumeStringPtr wire decodes a *string pointer as a String. func consumeStringPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } vp := p.StringPtr() if *vp == nil { *vp = new(string) } **vp = string(v) out.n = n return out, nil } var coderStringPtr = pointerCoderFuncs{ size: sizeStringPtr, marshal: appendStringPtr, unmarshal: consumeStringPtr, merge: mergeStringPtr, } // appendStringPtrValidateUTF8 wire encodes a *string pointer as a String. // It panics if the pointer is nil. func appendStringPtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := **p.StringPtr() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } return b, nil } // consumeStringPtrValidateUTF8 wire decodes a *string pointer as a String. func consumeStringPtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } vp := p.StringPtr() if *vp == nil { *vp = new(string) } **vp = string(v) out.n = n return out, nil } var coderStringPtrValidateUTF8 = pointerCoderFuncs{ size: sizeStringPtr, marshal: appendStringPtrValidateUTF8, unmarshal: consumeStringPtrValidateUTF8, merge: mergeStringPtr, } // sizeStringSlice returns the size of wire encoding a []string pointer as a repeated String. func sizeStringSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.StringSlice() for _, v := range s { size += f.tagsize + protowire.SizeBytes(len(v)) } return size } // appendStringSlice encodes a []string pointer as a repeated String. func appendStringSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.StringSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) } return b, nil } // consumeStringSlice wire decodes a []string pointer as a repeated String. func consumeStringSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.StringSlice() if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *sp = append(*sp, string(v)) out.n = n return out, nil } var coderStringSlice = pointerCoderFuncs{ size: sizeStringSlice, marshal: appendStringSlice, unmarshal: consumeStringSlice, merge: mergeStringSlice, } // appendStringSliceValidateUTF8 encodes a []string pointer as a repeated String. func appendStringSliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.StringSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendString(b, v) if !utf8.ValidString(v) { return b, errInvalidUTF8{} } } return b, nil } // consumeStringSliceValidateUTF8 wire decodes a []string pointer as a repeated String. func consumeStringSliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } sp := p.StringSlice() *sp = append(*sp, string(v)) out.n = n return out, nil } var coderStringSliceValidateUTF8 = pointerCoderFuncs{ size: sizeStringSlice, marshal: appendStringSliceValidateUTF8, unmarshal: consumeStringSliceValidateUTF8, merge: mergeStringSlice, } // sizeStringValue returns the size of wire encoding a string value as a String. func sizeStringValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeBytes(len(v.String())) } // appendStringValue encodes a string value as a String. func appendStringValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) return b, nil } // consumeStringValue decodes a string value as a String. func consumeStringValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfString(string(v)), out, nil } var coderStringValue = valueCoderFuncs{ size: sizeStringValue, marshal: appendStringValue, unmarshal: consumeStringValue, merge: mergeScalarValue, } // appendStringValueValidateUTF8 encodes a string value as a String. func appendStringValueValidateUTF8(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) if !utf8.ValidString(v.String()) { return b, errInvalidUTF8{} } return b, nil } // consumeStringValueValidateUTF8 decodes a string value as a String. func consumeStringValueValidateUTF8(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } if !utf8.Valid(v) { return protoreflect.Value{}, out, errInvalidUTF8{} } out.n = n return protoreflect.ValueOfString(string(v)), out, nil } var coderStringValueValidateUTF8 = valueCoderFuncs{ size: sizeStringValue, marshal: appendStringValueValidateUTF8, unmarshal: consumeStringValueValidateUTF8, merge: mergeScalarValue, } // sizeStringSliceValue returns the size of wire encoding a []string value as a repeated String. func sizeStringSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeBytes(len(v.String())) } return size } // appendStringSliceValue encodes a []string value as a repeated String. func appendStringSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendString(b, v.String()) } return b, nil } // consumeStringSliceValue wire decodes a []string value as a repeated String. func consumeStringSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfString(string(v))) out.n = n return listv, out, nil } var coderStringSliceValue = valueCoderFuncs{ size: sizeStringSliceValue, marshal: appendStringSliceValue, unmarshal: consumeStringSliceValue, merge: mergeListValue, } // sizeBytes returns the size of wire encoding a []byte pointer as a Bytes. func sizeBytes(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bytes() return f.tagsize + protowire.SizeBytes(len(v)) } // appendBytes wire encodes a []byte pointer as a Bytes. func appendBytes(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) return b, nil } // consumeBytes wire decodes a []byte pointer as a Bytes. func consumeBytes(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.Bytes() = append(emptyBuf[:], v...) out.n = n return out, nil } var coderBytes = pointerCoderFuncs{ size: sizeBytes, marshal: appendBytes, unmarshal: consumeBytes, merge: mergeBytes, } // appendBytesValidateUTF8 wire encodes a []byte pointer as a Bytes. func appendBytesValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } return b, nil } // consumeBytesValidateUTF8 wire decodes a []byte pointer as a Bytes. func consumeBytesValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.Bytes() = append(emptyBuf[:], v...) out.n = n return out, nil } var coderBytesValidateUTF8 = pointerCoderFuncs{ size: sizeBytes, marshal: appendBytesValidateUTF8, unmarshal: consumeBytesValidateUTF8, merge: mergeBytes, } // sizeBytesNoZero returns the size of wire encoding a []byte pointer as a Bytes. // The zero value is not encoded. func sizeBytesNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { v := *p.Bytes() if len(v) == 0 { return 0 } return f.tagsize + protowire.SizeBytes(len(v)) } // appendBytesNoZero wire encodes a []byte pointer as a Bytes. // The zero value is not encoded. func appendBytesNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) return b, nil } // consumeBytesNoZero wire decodes a []byte pointer as a Bytes. // The zero value is not decoded. func consumeBytesNoZero(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *p.Bytes() = append(([]byte)(nil), v...) out.n = n return out, nil } var coderBytesNoZero = pointerCoderFuncs{ size: sizeBytesNoZero, marshal: appendBytesNoZero, unmarshal: consumeBytesNoZero, merge: mergeBytesNoZero, } // appendBytesNoZeroValidateUTF8 wire encodes a []byte pointer as a Bytes. // The zero value is not encoded. func appendBytesNoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := *p.Bytes() if len(v) == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } return b, nil } // consumeBytesNoZeroValidateUTF8 wire decodes a []byte pointer as a Bytes. func consumeBytesNoZeroValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } *p.Bytes() = append(([]byte)(nil), v...) out.n = n return out, nil } var coderBytesNoZeroValidateUTF8 = pointerCoderFuncs{ size: sizeBytesNoZero, marshal: appendBytesNoZeroValidateUTF8, unmarshal: consumeBytesNoZeroValidateUTF8, merge: mergeBytesNoZero, } // sizeBytesSlice returns the size of wire encoding a [][]byte pointer as a repeated Bytes. func sizeBytesSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := *p.BytesSlice() for _, v := range s { size += f.tagsize + protowire.SizeBytes(len(v)) } return size } // appendBytesSlice encodes a [][]byte pointer as a repeated Bytes. func appendBytesSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BytesSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) } return b, nil } // consumeBytesSlice wire decodes a [][]byte pointer as a repeated Bytes. func consumeBytesSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { sp := p.BytesSlice() if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } *sp = append(*sp, append(emptyBuf[:], v...)) out.n = n return out, nil } var coderBytesSlice = pointerCoderFuncs{ size: sizeBytesSlice, marshal: appendBytesSlice, unmarshal: consumeBytesSlice, merge: mergeBytesSlice, } // appendBytesSliceValidateUTF8 encodes a [][]byte pointer as a repeated Bytes. func appendBytesSliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := *p.BytesSlice() for _, v := range s { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendBytes(b, v) if !utf8.Valid(v) { return b, errInvalidUTF8{} } } return b, nil } // consumeBytesSliceValidateUTF8 wire decodes a [][]byte pointer as a repeated Bytes. func consumeBytesSliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } if !utf8.Valid(v) { return out, errInvalidUTF8{} } sp := p.BytesSlice() *sp = append(*sp, append(emptyBuf[:], v...)) out.n = n return out, nil } var coderBytesSliceValidateUTF8 = pointerCoderFuncs{ size: sizeBytesSlice, marshal: appendBytesSliceValidateUTF8, unmarshal: consumeBytesSliceValidateUTF8, merge: mergeBytesSlice, } // sizeBytesValue returns the size of wire encoding a []byte value as a Bytes. func sizeBytesValue(v protoreflect.Value, tagsize int, opts marshalOptions) int { return tagsize + protowire.SizeBytes(len(v.Bytes())) } // appendBytesValue encodes a []byte value as a Bytes. func appendBytesValue(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { b = protowire.AppendVarint(b, wiretag) b = protowire.AppendBytes(b, v.Bytes()) return b, nil } // consumeBytesValue decodes a []byte value as a Bytes. func consumeBytesValue(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } out.n = n return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), out, nil } var coderBytesValue = valueCoderFuncs{ size: sizeBytesValue, marshal: appendBytesValue, unmarshal: consumeBytesValue, merge: mergeBytesValue, } // sizeBytesSliceValue returns the size of wire encoding a [][]byte value as a repeated Bytes. func sizeBytesSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) size += tagsize + protowire.SizeBytes(len(v.Bytes())) } return size } // appendBytesSliceValue encodes a [][]byte value as a repeated Bytes. func appendBytesSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { list := listv.List() for i, llen := 0, list.Len(); i < llen; i++ { v := list.Get(i) b = protowire.AppendVarint(b, wiretag) b = protowire.AppendBytes(b, v.Bytes()) } return b, nil } // consumeBytesSliceValue wire decodes a [][]byte value as a repeated Bytes. func consumeBytesSliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { list := listv.List() if wtyp != protowire.BytesType { return protoreflect.Value{}, out, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return protoreflect.Value{}, out, errDecode } list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...))) out.n = n return listv, out, nil } var coderBytesSliceValue = valueCoderFuncs{ size: sizeBytesSliceValue, marshal: appendBytesSliceValue, unmarshal: consumeBytesSliceValue, merge: mergeBytesListValue, } // We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices. var emptyBuf [0]byte var wireTypes = map[protoreflect.Kind]protowire.Type{ protoreflect.BoolKind: protowire.VarintType, protoreflect.EnumKind: protowire.VarintType, protoreflect.Int32Kind: protowire.VarintType, protoreflect.Sint32Kind: protowire.VarintType, protoreflect.Uint32Kind: protowire.VarintType, protoreflect.Int64Kind: protowire.VarintType, protoreflect.Sint64Kind: protowire.VarintType, protoreflect.Uint64Kind: protowire.VarintType, protoreflect.Sfixed32Kind: protowire.Fixed32Type, protoreflect.Fixed32Kind: protowire.Fixed32Type, protoreflect.FloatKind: protowire.Fixed32Type, protoreflect.Sfixed64Kind: protowire.Fixed64Type, protoreflect.Fixed64Kind: protowire.Fixed64Type, protoreflect.DoubleKind: protowire.Fixed64Type, protoreflect.StringKind: protowire.BytesType, protoreflect.BytesKind: protowire.BytesType, protoreflect.MessageKind: protowire.BytesType, protoreflect.GroupKind: protowire.StartGroupType, } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_map.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/genid" pref "google.golang.org/protobuf/reflect/protoreflect" ) type mapInfo struct { goType reflect.Type keyWiretag uint64 valWiretag uint64 keyFuncs valueCoderFuncs valFuncs valueCoderFuncs keyZero pref.Value keyKind pref.Kind conv *mapConverter } func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) { // TODO: Consider generating specialized map coders. keyField := fd.MapKey() valField := fd.MapValue() keyWiretag := protowire.EncodeTag(1, wireTypes[keyField.Kind()]) valWiretag := protowire.EncodeTag(2, wireTypes[valField.Kind()]) keyFuncs := encoderFuncsForValue(keyField) valFuncs := encoderFuncsForValue(valField) conv := newMapConverter(ft, fd) mapi := &mapInfo{ goType: ft, keyWiretag: keyWiretag, valWiretag: valWiretag, keyFuncs: keyFuncs, valFuncs: valFuncs, keyZero: keyField.Default(), keyKind: keyField.Kind(), conv: conv, } if valField.Kind() == pref.MessageKind { valueMessage = getMessageInfo(ft.Elem()) } funcs = pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts) }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts) }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { mp := p.AsValueOf(ft) if mp.Elem().IsNil() { mp.Elem().Set(reflect.MakeMap(mapi.goType)) } if f.mi == nil { return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts) } else { return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts) } }, } switch valField.Kind() { case pref.MessageKind: funcs.merge = mergeMapOfMessage case pref.BytesKind: funcs.merge = mergeMapOfBytes default: funcs.merge = mergeMap } if valFuncs.isInit != nil { funcs.isInit = func(p pointer, f *coderFieldInfo) error { return isInitMap(p.AsValueOf(ft).Elem(), mapi, f) } } return valueMessage, funcs } const ( mapKeyTagSize = 1 // field 1, tag size 1. mapValTagSize = 1 // field 2, tag size 2. ) func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int { if mapv.Len() == 0 { return 0 } n := 0 iter := mapRange(mapv) for iter.Next() { key := mapi.conv.keyConv.PBValueOf(iter.Key()).MapKey() keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) var valSize int value := mapi.conv.valConv.PBValueOf(iter.Value()) if f.mi == nil { valSize = mapi.valFuncs.size(value, mapValTagSize, opts) } else { p := pointerOfValue(iter.Value()) valSize += mapValTagSize valSize += protowire.SizeBytes(f.mi.sizePointer(p, opts)) } n += f.tagsize + protowire.SizeBytes(keySize+valSize) } return n } func consumeMap(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var ( key = mapi.keyZero val = mapi.conv.valConv.New() ) for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return out, errDecode } if num > protowire.MaxValidNumber { return out, errDecode } b = b[n:] err := errUnknown switch num { case genid.MapEntry_Key_field_number: var v pref.Value var o unmarshalOutput v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts) if err != nil { break } key = v n = o.n case genid.MapEntry_Value_field_number: var v pref.Value var o unmarshalOutput v, o, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts) if err != nil { break } val = v n = o.n } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } } else if err != nil { return out, err } b = b[n:] } mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), mapi.conv.valConv.GoValueOf(val)) out.n = n return out, nil } func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp protowire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.BytesType { return out, errUnknown } b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var ( key = mapi.keyZero val = reflect.New(f.mi.GoReflectType.Elem()) ) for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return out, errDecode } if num > protowire.MaxValidNumber { return out, errDecode } b = b[n:] err := errUnknown switch num { case 1: var v pref.Value var o unmarshalOutput v, o, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts) if err != nil { break } key = v n = o.n case 2: if wtyp != protowire.BytesType { break } var v []byte v, n = protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } var o unmarshalOutput o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts) if o.initialized { // Consider this map item initialized so long as we see // an initialized value. out.initialized = true } } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } } else if err != nil { return out, err } b = b[n:] } mapv.SetMapIndex(mapi.conv.keyConv.GoValueOf(key), val) out.n = n return out, nil } func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if f.mi == nil { key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey() val := mapi.conv.valConv.PBValueOf(valrv) size := 0 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) size += mapi.valFuncs.size(val, mapValTagSize, opts) b = protowire.AppendVarint(b, uint64(size)) b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts) if err != nil { return nil, err } return mapi.valFuncs.marshal(b, val, mapi.valWiretag, opts) } else { key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey() val := pointerOfValue(valrv) valSize := f.mi.sizePointer(val, opts) size := 0 size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts) size += mapValTagSize + protowire.SizeBytes(valSize) b = protowire.AppendVarint(b, uint64(size)) b, err := mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts) if err != nil { return nil, err } b = protowire.AppendVarint(b, mapi.valWiretag) b = protowire.AppendVarint(b, uint64(valSize)) return f.mi.marshalAppendPointer(b, val, opts) } } func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if mapv.Len() == 0 { return b, nil } if opts.Deterministic() { return appendMapDeterministic(b, mapv, mapi, f, opts) } iter := mapRange(mapv) for iter.Next() { var err error b = protowire.AppendVarint(b, f.wiretag) b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts) if err != nil { return b, err } } return b, nil } func appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { keys := mapv.MapKeys() sort.Slice(keys, func(i, j int) bool { switch keys[i].Kind() { case reflect.Bool: return !keys[i].Bool() && keys[j].Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return keys[i].Int() < keys[j].Int() case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return keys[i].Uint() < keys[j].Uint() case reflect.Float32, reflect.Float64: return keys[i].Float() < keys[j].Float() case reflect.String: return keys[i].String() < keys[j].String() default: panic("invalid kind: " + keys[i].Kind().String()) } }) for _, key := range keys { var err error b = protowire.AppendVarint(b, f.wiretag) b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts) if err != nil { return b, err } } return b, nil } func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error { if mi := f.mi; mi != nil { mi.init() if !mi.needsInitCheck { return nil } iter := mapRange(mapv) for iter.Next() { val := pointerOfValue(iter.Value()) if err := mi.checkInitializedPointer(val); err != nil { return err } } } else { iter := mapRange(mapv) for iter.Next() { val := mapi.conv.valConv.PBValueOf(iter.Value()) if err := mapi.valFuncs.isInit(val); err != nil { return err } } } return nil } func mergeMap(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { dstm.SetMapIndex(iter.Key(), iter.Value()) } } func mergeMapOfBytes(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { dstm.SetMapIndex(iter.Key(), reflect.ValueOf(append(emptyBuf[:], iter.Value().Bytes()...))) } } func mergeMapOfMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { dstm := dst.AsValueOf(f.ft).Elem() srcm := src.AsValueOf(f.ft).Elem() if srcm.Len() == 0 { return } if dstm.IsNil() { dstm.Set(reflect.MakeMap(f.ft)) } iter := mapRange(srcm) for iter.Next() { val := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { f.mi.mergePointer(pointerOfValue(val), pointerOfValue(iter.Value()), opts) } else { opts.Merge(asMessage(val), asMessage(iter.Value())) } dstm.SetMapIndex(iter.Key(), val) } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !go1.12 package impl import "reflect" type mapIter struct { v reflect.Value keys []reflect.Value } // mapRange provides a less-efficient equivalent to // the Go 1.12 reflect.Value.MapRange method. func mapRange(v reflect.Value) *mapIter { return &mapIter{v: v} } func (i *mapIter) Next() bool { if i.keys == nil { i.keys = i.v.MapKeys() } else { i.keys = i.keys[1:] } return len(i.keys) > 0 } func (i *mapIter) Key() reflect.Value { return i.keys[0] } func (i *mapIter) Value() reflect.Value { return i.v.MapIndex(i.keys[0]) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build go1.12 package impl import "reflect" func mapRange(v reflect.Value) *reflect.MapIter { return v.MapRange() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_message.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/order" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // coderMessageInfo contains per-message information used by the fast-path functions. // This is a different type from MessageInfo to keep MessageInfo as general-purpose as // possible. type coderMessageInfo struct { methods piface.Methods orderedCoderFields []*coderFieldInfo denseCoderFields []*coderFieldInfo coderFields map[protowire.Number]*coderFieldInfo sizecacheOffset offset unknownOffset offset unknownPtrKind bool extensionOffset offset needsInitCheck bool isMessageSet bool numRequiredFields uint8 } type coderFieldInfo struct { funcs pointerCoderFuncs // fast-path per-field functions mi *MessageInfo // field's message ft reflect.Type validation validationInfo // information used by message validation num pref.FieldNumber // field number offset offset // struct field offset wiretag uint64 // field tag (number + wire type) tagsize int // size of the varint-encoded tag isPointer bool // true if IsNil may be called on the struct field isRequired bool // true if field is required } func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) { mi.sizecacheOffset = invalidOffset mi.unknownOffset = invalidOffset mi.extensionOffset = invalidOffset if si.sizecacheOffset.IsValid() && si.sizecacheType == sizecacheType { mi.sizecacheOffset = si.sizecacheOffset } if si.unknownOffset.IsValid() && (si.unknownType == unknownFieldsAType || si.unknownType == unknownFieldsBType) { mi.unknownOffset = si.unknownOffset mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr } if si.extensionOffset.IsValid() && si.extensionType == extensionFieldsType { mi.extensionOffset = si.extensionOffset } mi.coderFields = make(map[protowire.Number]*coderFieldInfo) fields := mi.Desc.Fields() preallocFields := make([]coderFieldInfo, fields.Len()) for i := 0; i < fields.Len(); i++ { fd := fields.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } ft := fs.Type var wiretag uint64 if !fd.IsPacked() { wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()]) } else { wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType) } var fieldOffset offset var funcs pointerCoderFuncs var childMessage *MessageInfo switch { case ft == nil: // This never occurs for generated message types. // It implies that a hand-crafted type has missing Go fields // for specific protobuf message fields. funcs = pointerCoderFuncs{ size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { return 0 }, marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return nil, nil }, unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { panic("missing Go struct field for " + string(fd.FullName())) }, isInit: func(p pointer, f *coderFieldInfo) error { panic("missing Go struct field for " + string(fd.FullName())) }, merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { panic("missing Go struct field for " + string(fd.FullName())) }, } case isOneof: fieldOffset = offsetOf(fs, mi.Exporter) case fd.IsWeak(): fieldOffset = si.weakOffset funcs = makeWeakMessageFieldCoder(fd) default: fieldOffset = offsetOf(fs, mi.Exporter) childMessage, funcs = fieldCoder(fd, ft) } cf := &preallocFields[i] *cf = coderFieldInfo{ num: fd.Number(), offset: fieldOffset, wiretag: wiretag, ft: ft, tagsize: protowire.SizeVarint(wiretag), funcs: funcs, mi: childMessage, validation: newFieldValidationInfo(mi, si, fd, ft), isPointer: fd.Cardinality() == pref.Repeated || fd.HasPresence(), isRequired: fd.Cardinality() == pref.Required, } mi.orderedCoderFields = append(mi.orderedCoderFields, cf) mi.coderFields[cf.num] = cf } for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ { if od := oneofs.Get(i); !od.IsSynthetic() { mi.initOneofFieldCoders(od, si) } } if messageset.IsMessageSet(mi.Desc) { if !mi.extensionOffset.IsValid() { panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName())) } if !mi.unknownOffset.IsValid() { panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName())) } mi.isMessageSet = true } sort.Slice(mi.orderedCoderFields, func(i, j int) bool { return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num }) var maxDense pref.FieldNumber for _, cf := range mi.orderedCoderFields { if cf.num >= 16 && cf.num >= 2*maxDense { break } maxDense = cf.num } mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1) for _, cf := range mi.orderedCoderFields { if int(cf.num) >= len(mi.denseCoderFields) { break } mi.denseCoderFields[cf.num] = cf } // To preserve compatibility with historic wire output, marshal oneofs last. if mi.Desc.Oneofs().Len() > 0 { sort.Slice(mi.orderedCoderFields, func(i, j int) bool { fi := fields.ByNumber(mi.orderedCoderFields[i].num) fj := fields.ByNumber(mi.orderedCoderFields[j].num) return order.LegacyFieldOrder(fi, fj) }) } mi.needsInitCheck = needsInitCheck(mi.Desc) if mi.methods.Marshal == nil && mi.methods.Size == nil { mi.methods.Flags |= piface.SupportMarshalDeterministic mi.methods.Marshal = mi.marshal mi.methods.Size = mi.size } if mi.methods.Unmarshal == nil { mi.methods.Flags |= piface.SupportUnmarshalDiscardUnknown mi.methods.Unmarshal = mi.unmarshal } if mi.methods.CheckInitialized == nil { mi.methods.CheckInitialized = mi.checkInitialized } if mi.methods.Merge == nil { mi.methods.Merge = mi.merge } } // getUnknownBytes returns a *[]byte for the unknown fields. // It is the caller's responsibility to check whether the pointer is nil. // This function is specially designed to be inlineable. func (mi *MessageInfo) getUnknownBytes(p pointer) *[]byte { if mi.unknownPtrKind { return *p.Apply(mi.unknownOffset).BytesPtr() } else { return p.Apply(mi.unknownOffset).Bytes() } } // mutableUnknownBytes returns a *[]byte for the unknown fields. // The returned pointer is guaranteed to not be nil. func (mi *MessageInfo) mutableUnknownBytes(p pointer) *[]byte { if mi.unknownPtrKind { bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { *bp = new([]byte) } return *bp } else { return p.Apply(mi.unknownOffset).Bytes() } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "sort" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" ) func sizeMessageSet(mi *MessageInfo, p pointer, opts marshalOptions) (size int) { if !flags.ProtoLegacy { return 0 } ext := *p.Apply(mi.extensionOffset).Extensions() for _, x := range ext { xi := getExtensionFieldInfo(x.Type()) if xi.funcs.size == nil { continue } num, _ := protowire.DecodeTag(xi.wiretag) size += messageset.SizeField(num) size += xi.funcs.size(x.Value(), protowire.SizeTag(messageset.FieldMessage), opts) } if u := mi.getUnknownBytes(p); u != nil { size += messageset.SizeUnknown(*u) } return size } func marshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts marshalOptions) ([]byte, error) { if !flags.ProtoLegacy { return b, errors.New("no support for message_set_wire_format") } ext := *p.Apply(mi.extensionOffset).Extensions() switch len(ext) { case 0: case 1: // Fast-path for one extension: Don't bother sorting the keys. for _, x := range ext { var err error b, err = marshalMessageSetField(mi, b, x, opts) if err != nil { return b, err } } default: // Sort the keys to provide a deterministic encoding. // Not sure this is required, but the old code does it. keys := make([]int, 0, len(ext)) for k := range ext { keys = append(keys, int(k)) } sort.Ints(keys) for _, k := range keys { var err error b, err = marshalMessageSetField(mi, b, ext[int32(k)], opts) if err != nil { return b, err } } } if u := mi.getUnknownBytes(p); u != nil { var err error b, err = messageset.AppendUnknown(b, *u) if err != nil { return b, err } } return b, nil } func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts marshalOptions) ([]byte, error) { xi := getExtensionFieldInfo(x.Type()) num, _ := protowire.DecodeTag(xi.wiretag) b = messageset.AppendFieldStart(b, num) b, err := xi.funcs.marshal(b, x.Value(), protowire.EncodeTag(messageset.FieldMessage, protowire.BytesType), opts) if err != nil { return b, err } b = messageset.AppendFieldEnd(b) return b, nil } func unmarshalMessageSet(mi *MessageInfo, b []byte, p pointer, opts unmarshalOptions) (out unmarshalOutput, err error) { if !flags.ProtoLegacy { return out, errors.New("no support for message_set_wire_format") } ep := p.Apply(mi.extensionOffset).Extensions() if *ep == nil { *ep = make(map[int32]ExtensionField) } ext := *ep initialized := true err = messageset.Unmarshal(b, true, func(num protowire.Number, v []byte) error { o, err := mi.unmarshalExtension(v, num, protowire.BytesType, ext, opts) if err == errUnknown { u := mi.mutableUnknownBytes(p) *u = protowire.AppendTag(*u, num, protowire.BytesType) *u = append(*u, v...) return nil } if !o.initialized { initialized = false } return err }) out.n = len(b) out.initialized = initialized return out, err } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package impl import ( "reflect" "google.golang.org/protobuf/encoding/protowire" ) func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) { v := p.v.Elem().Int() return f.tagsize + protowire.SizeVarint(uint64(v)) } func appendEnum(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { v := p.v.Elem().Int() b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(v)) return b, nil } func consumeEnum(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } p.v.Elem().SetInt(int64(v)) out.n = n return out, nil } func mergeEnum(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { dst.v.Elem().Set(src.v.Elem()) } var coderEnum = pointerCoderFuncs{ size: sizeEnum, marshal: appendEnum, unmarshal: consumeEnum, merge: mergeEnum, } func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { if p.v.Elem().Int() == 0 { return 0 } return sizeEnum(p, f, opts) } func appendEnumNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { if p.v.Elem().Int() == 0 { return b, nil } return appendEnum(b, p, f, opts) } func mergeEnumNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { if src.v.Elem().Int() != 0 { dst.v.Elem().Set(src.v.Elem()) } } var coderEnumNoZero = pointerCoderFuncs{ size: sizeEnumNoZero, marshal: appendEnumNoZero, unmarshal: consumeEnum, merge: mergeEnumNoZero, } func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { return sizeEnum(pointer{p.v.Elem()}, f, opts) } func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { return appendEnum(b, pointer{p.v.Elem()}, f, opts) } func consumeEnumPtr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { if wtyp != protowire.VarintType { return out, errUnknown } if p.v.Elem().IsNil() { p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem())) } return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts) } func mergeEnumPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { if !src.v.Elem().IsNil() { v := reflect.New(dst.v.Type().Elem().Elem()) v.Elem().Set(src.v.Elem().Elem()) dst.v.Elem().Set(v) } } var coderEnumPtr = pointerCoderFuncs{ size: sizeEnumPtr, marshal: appendEnumPtr, unmarshal: consumeEnumPtr, merge: mergeEnumPtr, } func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := p.v.Elem() for i, llen := 0, s.Len(); i < llen; i++ { size += protowire.SizeVarint(uint64(s.Index(i).Int())) + f.tagsize } return size } func appendEnumSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.v.Elem() for i, llen := 0, s.Len(); i < llen; i++ { b = protowire.AppendVarint(b, f.wiretag) b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) } return b, nil } func consumeEnumSlice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { s := p.v.Elem() if wtyp == protowire.BytesType { b, n := protowire.ConsumeBytes(b) if n < 0 { return out, errDecode } for len(b) > 0 { v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } rv := reflect.New(s.Type().Elem()).Elem() rv.SetInt(int64(v)) s.Set(reflect.Append(s, rv)) b = b[n:] } out.n = n return out, nil } if wtyp != protowire.VarintType { return out, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } rv := reflect.New(s.Type().Elem()).Elem() rv.SetInt(int64(v)) s.Set(reflect.Append(s, rv)) out.n = n return out, nil } func mergeEnumSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { dst.v.Elem().Set(reflect.AppendSlice(dst.v.Elem(), src.v.Elem())) } var coderEnumSlice = pointerCoderFuncs{ size: sizeEnumSlice, marshal: appendEnumSlice, unmarshal: consumeEnumSlice, merge: mergeEnumSlice, } func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { s := p.v.Elem() llen := s.Len() if llen == 0 { return 0 } n := 0 for i := 0; i < llen; i++ { n += protowire.SizeVarint(uint64(s.Index(i).Int())) } return f.tagsize + protowire.SizeBytes(n) } func appendEnumPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { s := p.v.Elem() llen := s.Len() if llen == 0 { return b, nil } b = protowire.AppendVarint(b, f.wiretag) n := 0 for i := 0; i < llen; i++ { n += protowire.SizeVarint(uint64(s.Index(i).Int())) } b = protowire.AppendVarint(b, uint64(n)) for i := 0; i < llen; i++ { b = protowire.AppendVarint(b, uint64(s.Index(i).Int())) } return b, nil } var coderEnumPackedSlice = pointerCoderFuncs{ size: sizeEnumPackedSlice, marshal: appendEnumPackedSlice, unmarshal: consumeEnumSlice, merge: mergeEnumSlice, } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_tables.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" ) // pointerCoderFuncs is a set of pointer encoding functions. type pointerCoderFuncs struct { mi *MessageInfo size func(p pointer, f *coderFieldInfo, opts marshalOptions) int marshal func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) unmarshal func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) isInit func(p pointer, f *coderFieldInfo) error merge func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) } // valueCoderFuncs is a set of protoreflect.Value encoding functions. type valueCoderFuncs struct { size func(v pref.Value, tagsize int, opts marshalOptions) int marshal func(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) unmarshal func(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) isInit func(v pref.Value) error merge func(dst, src pref.Value, opts mergeOptions) pref.Value } // fieldCoder returns pointer functions for a field, used for operating on // struct fields. func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointerCoderFuncs) { switch { case fd.IsMap(): return encoderFuncsForMap(fd, ft) case fd.Cardinality() == pref.Repeated && !fd.IsPacked(): // Repeated fields (not packed). if ft.Kind() != reflect.Slice { break } ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolSlice } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumSlice } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32Slice } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32Slice } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32Slice } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64Slice } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64Slice } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64Slice } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32Slice } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32Slice } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatSlice } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64Slice } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64Slice } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoubleSlice } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringSliceValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringSlice } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesSliceValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesSlice } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringSlice } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesSlice } case pref.MessageKind: return getMessageInfo(ft), makeMessageSliceFieldCoder(fd, ft) case pref.GroupKind: return getMessageInfo(ft), makeGroupSliceFieldCoder(fd, ft) } case fd.Cardinality() == pref.Repeated && fd.IsPacked(): // Packed repeated fields. // // Only repeated fields of primitive numeric types // (Varint, Fixed32, or Fixed64 wire type) can be packed. if ft.Kind() != reflect.Slice { break } ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolPackedSlice } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumPackedSlice } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32PackedSlice } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32PackedSlice } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32PackedSlice } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64PackedSlice } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64PackedSlice } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64PackedSlice } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32PackedSlice } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32PackedSlice } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatPackedSlice } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64PackedSlice } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64PackedSlice } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoublePackedSlice } } case fd.Kind() == pref.MessageKind: return getMessageInfo(ft), makeMessageFieldCoder(fd, ft) case fd.Kind() == pref.GroupKind: return getMessageInfo(ft), makeGroupFieldCoder(fd, ft) case fd.Syntax() == pref.Proto3 && fd.ContainingOneof() == nil: // Populated oneof fields always encode even if set to the zero value, // which normally are not encoded in proto3. switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolNoZero } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumNoZero } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32NoZero } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32NoZero } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32NoZero } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64NoZero } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64NoZero } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64NoZero } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32NoZero } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32NoZero } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatNoZero } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64NoZero } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64NoZero } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoubleNoZero } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringNoZeroValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringNoZero } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesNoZeroValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesNoZero } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringNoZero } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytesNoZero } } case ft.Kind() == reflect.Ptr: ft := ft.Elem() switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBoolPtr } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnumPtr } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32Ptr } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32Ptr } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32Ptr } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64Ptr } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64Ptr } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64Ptr } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32Ptr } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32Ptr } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloatPtr } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64Ptr } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64Ptr } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDoublePtr } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringPtrValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderStringPtr } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderStringPtr } } default: switch fd.Kind() { case pref.BoolKind: if ft.Kind() == reflect.Bool { return nil, coderBool } case pref.EnumKind: if ft.Kind() == reflect.Int32 { return nil, coderEnum } case pref.Int32Kind: if ft.Kind() == reflect.Int32 { return nil, coderInt32 } case pref.Sint32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSint32 } case pref.Uint32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderUint32 } case pref.Int64Kind: if ft.Kind() == reflect.Int64 { return nil, coderInt64 } case pref.Sint64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSint64 } case pref.Uint64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderUint64 } case pref.Sfixed32Kind: if ft.Kind() == reflect.Int32 { return nil, coderSfixed32 } case pref.Fixed32Kind: if ft.Kind() == reflect.Uint32 { return nil, coderFixed32 } case pref.FloatKind: if ft.Kind() == reflect.Float32 { return nil, coderFloat } case pref.Sfixed64Kind: if ft.Kind() == reflect.Int64 { return nil, coderSfixed64 } case pref.Fixed64Kind: if ft.Kind() == reflect.Uint64 { return nil, coderFixed64 } case pref.DoubleKind: if ft.Kind() == reflect.Float64 { return nil, coderDouble } case pref.StringKind: if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) { return nil, coderStringValidateUTF8 } if ft.Kind() == reflect.String { return nil, coderString } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) { return nil, coderBytesValidateUTF8 } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytes } case pref.BytesKind: if ft.Kind() == reflect.String { return nil, coderString } if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 { return nil, coderBytes } } } panic(fmt.Sprintf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft)) } // encoderFuncsForValue returns value functions for a field, used for // extension values and map encoding. func encoderFuncsForValue(fd pref.FieldDescriptor) valueCoderFuncs { switch { case fd.Cardinality() == pref.Repeated && !fd.IsPacked(): switch fd.Kind() { case pref.BoolKind: return coderBoolSliceValue case pref.EnumKind: return coderEnumSliceValue case pref.Int32Kind: return coderInt32SliceValue case pref.Sint32Kind: return coderSint32SliceValue case pref.Uint32Kind: return coderUint32SliceValue case pref.Int64Kind: return coderInt64SliceValue case pref.Sint64Kind: return coderSint64SliceValue case pref.Uint64Kind: return coderUint64SliceValue case pref.Sfixed32Kind: return coderSfixed32SliceValue case pref.Fixed32Kind: return coderFixed32SliceValue case pref.FloatKind: return coderFloatSliceValue case pref.Sfixed64Kind: return coderSfixed64SliceValue case pref.Fixed64Kind: return coderFixed64SliceValue case pref.DoubleKind: return coderDoubleSliceValue case pref.StringKind: // We don't have a UTF-8 validating coder for repeated string fields. // Value coders are used for extensions and maps. // Extensions are never proto3, and maps never contain lists. return coderStringSliceValue case pref.BytesKind: return coderBytesSliceValue case pref.MessageKind: return coderMessageSliceValue case pref.GroupKind: return coderGroupSliceValue } case fd.Cardinality() == pref.Repeated && fd.IsPacked(): switch fd.Kind() { case pref.BoolKind: return coderBoolPackedSliceValue case pref.EnumKind: return coderEnumPackedSliceValue case pref.Int32Kind: return coderInt32PackedSliceValue case pref.Sint32Kind: return coderSint32PackedSliceValue case pref.Uint32Kind: return coderUint32PackedSliceValue case pref.Int64Kind: return coderInt64PackedSliceValue case pref.Sint64Kind: return coderSint64PackedSliceValue case pref.Uint64Kind: return coderUint64PackedSliceValue case pref.Sfixed32Kind: return coderSfixed32PackedSliceValue case pref.Fixed32Kind: return coderFixed32PackedSliceValue case pref.FloatKind: return coderFloatPackedSliceValue case pref.Sfixed64Kind: return coderSfixed64PackedSliceValue case pref.Fixed64Kind: return coderFixed64PackedSliceValue case pref.DoubleKind: return coderDoublePackedSliceValue } default: switch fd.Kind() { default: case pref.BoolKind: return coderBoolValue case pref.EnumKind: return coderEnumValue case pref.Int32Kind: return coderInt32Value case pref.Sint32Kind: return coderSint32Value case pref.Uint32Kind: return coderUint32Value case pref.Int64Kind: return coderInt64Value case pref.Sint64Kind: return coderSint64Value case pref.Uint64Kind: return coderUint64Value case pref.Sfixed32Kind: return coderSfixed32Value case pref.Fixed32Kind: return coderFixed32Value case pref.FloatKind: return coderFloatValue case pref.Sfixed64Kind: return coderSfixed64Value case pref.Fixed64Kind: return coderFixed64Value case pref.DoubleKind: return coderDoubleValue case pref.StringKind: if strs.EnforceUTF8(fd) { return coderStringValueValidateUTF8 } return coderStringValue case pref.BytesKind: return coderBytesValue case pref.MessageKind: return coderMessageValue case pref.GroupKind: return coderGroupValue } } panic(fmt.Sprintf("invalid field: no encoder for %v %v %v", fd.FullName(), fd.Cardinality(), fd.Kind())) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package impl // When using unsafe pointers, we can just treat enum values as int32s. var ( coderEnumNoZero = coderInt32NoZero coderEnum = coderInt32 coderEnumPtr = coderInt32Ptr coderEnumSlice = coderInt32Slice coderEnumPackedSlice = coderInt32PackedSlice ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/convert.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) // unwrapper unwraps the value to the underlying value. // This is implemented by List and Map. type unwrapper interface { protoUnwrap() interface{} } // A Converter coverts to/from Go reflect.Value types and protobuf protoreflect.Value types. type Converter interface { // PBValueOf converts a reflect.Value to a protoreflect.Value. PBValueOf(reflect.Value) pref.Value // GoValueOf converts a protoreflect.Value to a reflect.Value. GoValueOf(pref.Value) reflect.Value // IsValidPB returns whether a protoreflect.Value is compatible with this type. IsValidPB(pref.Value) bool // IsValidGo returns whether a reflect.Value is compatible with this type. IsValidGo(reflect.Value) bool // New returns a new field value. // For scalars, it returns the default value of the field. // For composite types, it returns a new mutable value. New() pref.Value // Zero returns a new field value. // For scalars, it returns the default value of the field. // For composite types, it returns an immutable, empty value. Zero() pref.Value } // NewConverter matches a Go type with a protobuf field and returns a Converter // that converts between the two. Enums must be a named int32 kind that // implements protoreflect.Enum, and messages must be pointer to a named // struct type that implements protoreflect.ProtoMessage. // // This matcher deliberately supports a wider range of Go types than what // protoc-gen-go historically generated to be able to automatically wrap some // v1 messages generated by other forks of protoc-gen-go. func NewConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { switch { case fd.IsList(): return newListConverter(t, fd) case fd.IsMap(): return newMapConverter(t, fd) default: return newSingularConverter(t, fd) } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } var ( boolType = reflect.TypeOf(bool(false)) int32Type = reflect.TypeOf(int32(0)) int64Type = reflect.TypeOf(int64(0)) uint32Type = reflect.TypeOf(uint32(0)) uint64Type = reflect.TypeOf(uint64(0)) float32Type = reflect.TypeOf(float32(0)) float64Type = reflect.TypeOf(float64(0)) stringType = reflect.TypeOf(string("")) bytesType = reflect.TypeOf([]byte(nil)) byteType = reflect.TypeOf(byte(0)) ) var ( boolZero = pref.ValueOfBool(false) int32Zero = pref.ValueOfInt32(0) int64Zero = pref.ValueOfInt64(0) uint32Zero = pref.ValueOfUint32(0) uint64Zero = pref.ValueOfUint64(0) float32Zero = pref.ValueOfFloat32(0) float64Zero = pref.ValueOfFloat64(0) stringZero = pref.ValueOfString("") bytesZero = pref.ValueOfBytes(nil) ) func newSingularConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { defVal := func(fd pref.FieldDescriptor, zero pref.Value) pref.Value { if fd.Cardinality() == pref.Repeated { // Default isn't defined for repeated fields. return zero } return fd.Default() } switch fd.Kind() { case pref.BoolKind: if t.Kind() == reflect.Bool { return &boolConverter{t, defVal(fd, boolZero)} } case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: if t.Kind() == reflect.Int32 { return &int32Converter{t, defVal(fd, int32Zero)} } case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: if t.Kind() == reflect.Int64 { return &int64Converter{t, defVal(fd, int64Zero)} } case pref.Uint32Kind, pref.Fixed32Kind: if t.Kind() == reflect.Uint32 { return &uint32Converter{t, defVal(fd, uint32Zero)} } case pref.Uint64Kind, pref.Fixed64Kind: if t.Kind() == reflect.Uint64 { return &uint64Converter{t, defVal(fd, uint64Zero)} } case pref.FloatKind: if t.Kind() == reflect.Float32 { return &float32Converter{t, defVal(fd, float32Zero)} } case pref.DoubleKind: if t.Kind() == reflect.Float64 { return &float64Converter{t, defVal(fd, float64Zero)} } case pref.StringKind: if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) { return &stringConverter{t, defVal(fd, stringZero)} } case pref.BytesKind: if t.Kind() == reflect.String || (t.Kind() == reflect.Slice && t.Elem() == byteType) { return &bytesConverter{t, defVal(fd, bytesZero)} } case pref.EnumKind: // Handle enums, which must be a named int32 type. if t.Kind() == reflect.Int32 { return newEnumConverter(t, fd) } case pref.MessageKind, pref.GroupKind: return newMessageConverter(t) } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } type boolConverter struct { goType reflect.Type def pref.Value } func (c *boolConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfBool(v.Bool()) } func (c *boolConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Bool()).Convert(c.goType) } func (c *boolConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(bool) return ok } func (c *boolConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *boolConverter) New() pref.Value { return c.def } func (c *boolConverter) Zero() pref.Value { return c.def } type int32Converter struct { goType reflect.Type def pref.Value } func (c *int32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfInt32(int32(v.Int())) } func (c *int32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(int32(v.Int())).Convert(c.goType) } func (c *int32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(int32) return ok } func (c *int32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *int32Converter) New() pref.Value { return c.def } func (c *int32Converter) Zero() pref.Value { return c.def } type int64Converter struct { goType reflect.Type def pref.Value } func (c *int64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfInt64(int64(v.Int())) } func (c *int64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(int64(v.Int())).Convert(c.goType) } func (c *int64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(int64) return ok } func (c *int64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *int64Converter) New() pref.Value { return c.def } func (c *int64Converter) Zero() pref.Value { return c.def } type uint32Converter struct { goType reflect.Type def pref.Value } func (c *uint32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfUint32(uint32(v.Uint())) } func (c *uint32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(uint32(v.Uint())).Convert(c.goType) } func (c *uint32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(uint32) return ok } func (c *uint32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *uint32Converter) New() pref.Value { return c.def } func (c *uint32Converter) Zero() pref.Value { return c.def } type uint64Converter struct { goType reflect.Type def pref.Value } func (c *uint64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfUint64(uint64(v.Uint())) } func (c *uint64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(uint64(v.Uint())).Convert(c.goType) } func (c *uint64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(uint64) return ok } func (c *uint64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *uint64Converter) New() pref.Value { return c.def } func (c *uint64Converter) Zero() pref.Value { return c.def } type float32Converter struct { goType reflect.Type def pref.Value } func (c *float32Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfFloat32(float32(v.Float())) } func (c *float32Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(float32(v.Float())).Convert(c.goType) } func (c *float32Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(float32) return ok } func (c *float32Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *float32Converter) New() pref.Value { return c.def } func (c *float32Converter) Zero() pref.Value { return c.def } type float64Converter struct { goType reflect.Type def pref.Value } func (c *float64Converter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfFloat64(float64(v.Float())) } func (c *float64Converter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(float64(v.Float())).Convert(c.goType) } func (c *float64Converter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(float64) return ok } func (c *float64Converter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *float64Converter) New() pref.Value { return c.def } func (c *float64Converter) Zero() pref.Value { return c.def } type stringConverter struct { goType reflect.Type def pref.Value } func (c *stringConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfString(v.Convert(stringType).String()) } func (c *stringConverter) GoValueOf(v pref.Value) reflect.Value { // pref.Value.String never panics, so we go through an interface // conversion here to check the type. s := v.Interface().(string) if c.goType.Kind() == reflect.Slice && s == "" { return reflect.Zero(c.goType) // ensure empty string is []byte(nil) } return reflect.ValueOf(s).Convert(c.goType) } func (c *stringConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(string) return ok } func (c *stringConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *stringConverter) New() pref.Value { return c.def } func (c *stringConverter) Zero() pref.Value { return c.def } type bytesConverter struct { goType reflect.Type def pref.Value } func (c *bytesConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } if c.goType.Kind() == reflect.String && v.Len() == 0 { return pref.ValueOfBytes(nil) // ensure empty string is []byte(nil) } return pref.ValueOfBytes(v.Convert(bytesType).Bytes()) } func (c *bytesConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Bytes()).Convert(c.goType) } func (c *bytesConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().([]byte) return ok } func (c *bytesConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *bytesConverter) New() pref.Value { return c.def } func (c *bytesConverter) Zero() pref.Value { return c.def } type enumConverter struct { goType reflect.Type def pref.Value } func newEnumConverter(goType reflect.Type, fd pref.FieldDescriptor) Converter { var def pref.Value if fd.Cardinality() == pref.Repeated { def = pref.ValueOfEnum(fd.Enum().Values().Get(0).Number()) } else { def = fd.Default() } return &enumConverter{goType, def} } func (c *enumConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfEnum(pref.EnumNumber(v.Int())) } func (c *enumConverter) GoValueOf(v pref.Value) reflect.Value { return reflect.ValueOf(v.Enum()).Convert(c.goType) } func (c *enumConverter) IsValidPB(v pref.Value) bool { _, ok := v.Interface().(pref.EnumNumber) return ok } func (c *enumConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *enumConverter) New() pref.Value { return c.def } func (c *enumConverter) Zero() pref.Value { return c.def } type messageConverter struct { goType reflect.Type } func newMessageConverter(goType reflect.Type) Converter { return &messageConverter{goType} } func (c *messageConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } if c.isNonPointer() { if v.CanAddr() { v = v.Addr() // T => *T } else { v = reflect.Zero(reflect.PtrTo(v.Type())) } } if m, ok := v.Interface().(pref.ProtoMessage); ok { return pref.ValueOfMessage(m.ProtoReflect()) } return pref.ValueOfMessage(legacyWrapMessage(v)) } func (c *messageConverter) GoValueOf(v pref.Value) reflect.Value { m := v.Message() var rv reflect.Value if u, ok := m.(unwrapper); ok { rv = reflect.ValueOf(u.protoUnwrap()) } else { rv = reflect.ValueOf(m.Interface()) } if c.isNonPointer() { if rv.Type() != reflect.PtrTo(c.goType) { panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), reflect.PtrTo(c.goType))) } if !rv.IsNil() { rv = rv.Elem() // *T => T } else { rv = reflect.Zero(rv.Type().Elem()) } } if rv.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", rv.Type(), c.goType)) } return rv } func (c *messageConverter) IsValidPB(v pref.Value) bool { m := v.Message() var rv reflect.Value if u, ok := m.(unwrapper); ok { rv = reflect.ValueOf(u.protoUnwrap()) } else { rv = reflect.ValueOf(m.Interface()) } if c.isNonPointer() { return rv.Type() == reflect.PtrTo(c.goType) } return rv.Type() == c.goType } func (c *messageConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *messageConverter) New() pref.Value { if c.isNonPointer() { return c.PBValueOf(reflect.New(c.goType).Elem()) } return c.PBValueOf(reflect.New(c.goType.Elem())) } func (c *messageConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } // isNonPointer reports whether the type is a non-pointer type. // This never occurs for generated message types. func (c *messageConverter) isNonPointer() bool { return c.goType.Kind() != reflect.Ptr } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/convert_list.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) func newListConverter(t reflect.Type, fd pref.FieldDescriptor) Converter { switch { case t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Slice: return &listPtrConverter{t, newSingularConverter(t.Elem().Elem(), fd)} case t.Kind() == reflect.Slice: return &listConverter{t, newSingularConverter(t.Elem(), fd)} } panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } type listConverter struct { goType reflect.Type // []T c Converter } func (c *listConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } pv := reflect.New(c.goType) pv.Elem().Set(v) return pref.ValueOfList(&listReflect{pv, c.c}) } func (c *listConverter) GoValueOf(v pref.Value) reflect.Value { rv := v.List().(*listReflect).v if rv.IsNil() { return reflect.Zero(c.goType) } return rv.Elem() } func (c *listConverter) IsValidPB(v pref.Value) bool { list, ok := v.Interface().(*listReflect) if !ok { return false } return list.v.Type().Elem() == c.goType } func (c *listConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *listConverter) New() pref.Value { return pref.ValueOfList(&listReflect{reflect.New(c.goType), c.c}) } func (c *listConverter) Zero() pref.Value { return pref.ValueOfList(&listReflect{reflect.Zero(reflect.PtrTo(c.goType)), c.c}) } type listPtrConverter struct { goType reflect.Type // *[]T c Converter } func (c *listPtrConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfList(&listReflect{v, c.c}) } func (c *listPtrConverter) GoValueOf(v pref.Value) reflect.Value { return v.List().(*listReflect).v } func (c *listPtrConverter) IsValidPB(v pref.Value) bool { list, ok := v.Interface().(*listReflect) if !ok { return false } return list.v.Type() == c.goType } func (c *listPtrConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *listPtrConverter) New() pref.Value { return c.PBValueOf(reflect.New(c.goType.Elem())) } func (c *listPtrConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } type listReflect struct { v reflect.Value // *[]T conv Converter } func (ls *listReflect) Len() int { if ls.v.IsNil() { return 0 } return ls.v.Elem().Len() } func (ls *listReflect) Get(i int) pref.Value { return ls.conv.PBValueOf(ls.v.Elem().Index(i)) } func (ls *listReflect) Set(i int, v pref.Value) { ls.v.Elem().Index(i).Set(ls.conv.GoValueOf(v)) } func (ls *listReflect) Append(v pref.Value) { ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(v))) } func (ls *listReflect) AppendMutable() pref.Value { if _, ok := ls.conv.(*messageConverter); !ok { panic("invalid AppendMutable on list with non-message type") } v := ls.NewElement() ls.Append(v) return v } func (ls *listReflect) Truncate(i int) { ls.v.Elem().Set(ls.v.Elem().Slice(0, i)) } func (ls *listReflect) NewElement() pref.Value { return ls.conv.New() } func (ls *listReflect) IsValid() bool { return !ls.v.IsNil() } func (ls *listReflect) protoUnwrap() interface{} { return ls.v.Interface() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/convert_map.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type mapConverter struct { goType reflect.Type // map[K]V keyConv, valConv Converter } func newMapConverter(t reflect.Type, fd pref.FieldDescriptor) *mapConverter { if t.Kind() != reflect.Map { panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName())) } return &mapConverter{ goType: t, keyConv: newSingularConverter(t.Key(), fd.MapKey()), valConv: newSingularConverter(t.Elem(), fd.MapValue()), } } func (c *mapConverter) PBValueOf(v reflect.Value) pref.Value { if v.Type() != c.goType { panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType)) } return pref.ValueOfMap(&mapReflect{v, c.keyConv, c.valConv}) } func (c *mapConverter) GoValueOf(v pref.Value) reflect.Value { return v.Map().(*mapReflect).v } func (c *mapConverter) IsValidPB(v pref.Value) bool { mapv, ok := v.Interface().(*mapReflect) if !ok { return false } return mapv.v.Type() == c.goType } func (c *mapConverter) IsValidGo(v reflect.Value) bool { return v.IsValid() && v.Type() == c.goType } func (c *mapConverter) New() pref.Value { return c.PBValueOf(reflect.MakeMap(c.goType)) } func (c *mapConverter) Zero() pref.Value { return c.PBValueOf(reflect.Zero(c.goType)) } type mapReflect struct { v reflect.Value // map[K]V keyConv Converter valConv Converter } func (ms *mapReflect) Len() int { return ms.v.Len() } func (ms *mapReflect) Has(k pref.MapKey) bool { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.v.MapIndex(rk) return rv.IsValid() } func (ms *mapReflect) Get(k pref.MapKey) pref.Value { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.v.MapIndex(rk) if !rv.IsValid() { return pref.Value{} } return ms.valConv.PBValueOf(rv) } func (ms *mapReflect) Set(k pref.MapKey, v pref.Value) { rk := ms.keyConv.GoValueOf(k.Value()) rv := ms.valConv.GoValueOf(v) ms.v.SetMapIndex(rk, rv) } func (ms *mapReflect) Clear(k pref.MapKey) { rk := ms.keyConv.GoValueOf(k.Value()) ms.v.SetMapIndex(rk, reflect.Value{}) } func (ms *mapReflect) Mutable(k pref.MapKey) pref.Value { if _, ok := ms.valConv.(*messageConverter); !ok { panic("invalid Mutable on map with non-message value type") } v := ms.Get(k) if !v.IsValid() { v = ms.NewValue() ms.Set(k, v) } return v } func (ms *mapReflect) Range(f func(pref.MapKey, pref.Value) bool) { iter := mapRange(ms.v) for iter.Next() { k := ms.keyConv.PBValueOf(iter.Key()).MapKey() v := ms.valConv.PBValueOf(iter.Value()) if !f(k, v) { return } } } func (ms *mapReflect) NewValue() pref.Value { return ms.valConv.New() } func (ms *mapReflect) IsValid() bool { return !ms.v.IsNil() } func (ms *mapReflect) protoUnwrap() interface{} { return ms.v.Interface() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/decode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "math/bits" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface" ) var errDecode = errors.New("cannot parse invalid wire-format data") type unmarshalOptions struct { flags protoiface.UnmarshalInputFlags resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } func (o unmarshalOptions) Options() proto.UnmarshalOptions { return proto.UnmarshalOptions{ Merge: true, AllowPartial: true, DiscardUnknown: o.DiscardUnknown(), Resolver: o.resolver, } } func (o unmarshalOptions) DiscardUnknown() bool { return o.flags&piface.UnmarshalDiscardUnknown != 0 } func (o unmarshalOptions) IsDefault() bool { return o.flags == 0 && o.resolver == preg.GlobalTypes } var lazyUnmarshalOptions = unmarshalOptions{ resolver: preg.GlobalTypes, } type unmarshalOutput struct { n int // number of bytes consumed initialized bool } // unmarshal is protoreflect.Methods.Unmarshal. func (mi *MessageInfo) unmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions{ flags: in.Flags, resolver: in.Resolver, }) var flags piface.UnmarshalOutputFlags if out.initialized { flags |= piface.UnmarshalInitialized } return piface.UnmarshalOutput{ Flags: flags, }, err } // errUnknown is returned during unmarshaling to indicate a parse error that // should result in a field being placed in the unknown fields section (for example, // when the wire type doesn't match) as opposed to the entire unmarshal operation // failing (for example, when a field extends past the available input). // // This is a sentinel error which should never be visible to the user. var errUnknown = errors.New("unknown") func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) { mi.init() if flags.ProtoLegacy && mi.isMessageSet { return unmarshalMessageSet(mi, b, p, opts) } initialized := true var requiredMask uint64 var exts *map[int32]ExtensionField start := len(b) for len(b) > 0 { // Parse the tag (field number and wire type). var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { return out, errDecode } b = b[n:] } var num protowire.Number if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) { return out, errDecode } else { num = protowire.Number(n) } wtyp := protowire.Type(tag & 7) if wtyp == protowire.EndGroupType { if num != groupTag { return out, errDecode } groupTag = 0 break } var f *coderFieldInfo if int(num) < len(mi.denseCoderFields) { f = mi.denseCoderFields[num] } else { f = mi.coderFields[num] } var n int err := errUnknown switch { case f != nil: if f.funcs.unmarshal == nil { break } var o unmarshalOutput o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, f, opts) n = o.n if err != nil { break } requiredMask |= f.validation.requiredBit if f.funcs.isInit != nil && !o.initialized { initialized = false } default: // Possible extension. if exts == nil && mi.extensionOffset.IsValid() { exts = p.Apply(mi.extensionOffset).Extensions() if *exts == nil { *exts = make(map[int32]ExtensionField) } } if exts == nil { break } var o unmarshalOutput o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts) if err != nil { break } n = o.n if !o.initialized { initialized = false } } if err != nil { if err != errUnknown { return out, err } n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, errDecode } if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() { u := mi.mutableUnknownBytes(p) *u = protowire.AppendTag(*u, num, wtyp) *u = append(*u, b[:n]...) } } b = b[n:] } if groupTag != 0 { return out, errDecode } if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) { initialized = false } if initialized { out.initialized = true } out.n = start - len(b) return out, nil } func (mi *MessageInfo) unmarshalExtension(b []byte, num protowire.Number, wtyp protowire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (out unmarshalOutput, err error) { x := exts[int32(num)] xt := x.Type() if xt == nil { var err error xt, err = opts.resolver.FindExtensionByNumber(mi.Desc.FullName(), num) if err != nil { if err == preg.NotFound { return out, errUnknown } return out, errors.New("%v: unable to resolve extension %v: %v", mi.Desc.FullName(), num, err) } } xi := getExtensionFieldInfo(xt) if xi.funcs.unmarshal == nil { return out, errUnknown } if flags.LazyUnmarshalExtensions { if opts.IsDefault() && x.canLazy(xt) { out, valid := skipExtension(b, xi, num, wtyp, opts) switch valid { case ValidationValid: if out.initialized { x.appendLazyBytes(xt, xi, num, wtyp, b[:out.n]) exts[int32(num)] = x return out, nil } case ValidationInvalid: return out, errDecode case ValidationUnknown: } } } ival := x.Value() if !ival.IsValid() && xi.unmarshalNeedsValue { // Create a new message, list, or map value to fill in. // For enums, create a prototype value to let the unmarshal func know the // concrete type. ival = xt.New() } v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts) if err != nil { return out, err } if xi.funcs.isInit == nil { out.initialized = true } x.Set(xt, v) exts[int32(num)] = x return out, nil } func skipExtension(b []byte, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, _ ValidationStatus) { if xi.validation.mi == nil { return out, ValidationUnknown } xi.validation.mi.init() switch xi.validation.typ { case validationTypeMessage: if wtyp != protowire.BytesType { return out, ValidationUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return out, ValidationUnknown } out, st := xi.validation.mi.validate(v, 0, opts) out.n = n return out, st case validationTypeGroup: if wtyp != protowire.StartGroupType { return out, ValidationUnknown } out, st := xi.validation.mi.validate(b, num, opts) return out, st default: return out, ValidationUnknown } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/encode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "math" "sort" "sync/atomic" "google.golang.org/protobuf/internal/flags" proto "google.golang.org/protobuf/proto" piface "google.golang.org/protobuf/runtime/protoiface" ) type marshalOptions struct { flags piface.MarshalInputFlags } func (o marshalOptions) Options() proto.MarshalOptions { return proto.MarshalOptions{ AllowPartial: true, Deterministic: o.Deterministic(), UseCachedSize: o.UseCachedSize(), } } func (o marshalOptions) Deterministic() bool { return o.flags&piface.MarshalDeterministic != 0 } func (o marshalOptions) UseCachedSize() bool { return o.flags&piface.MarshalUseCachedSize != 0 } // size is protoreflect.Methods.Size. func (mi *MessageInfo) size(in piface.SizeInput) piface.SizeOutput { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } size := mi.sizePointer(p, marshalOptions{ flags: in.Flags, }) return piface.SizeOutput{Size: size} } func (mi *MessageInfo) sizePointer(p pointer, opts marshalOptions) (size int) { mi.init() if p.IsNil() { return 0 } if opts.UseCachedSize() && mi.sizecacheOffset.IsValid() { if size := atomic.LoadInt32(p.Apply(mi.sizecacheOffset).Int32()); size >= 0 { return int(size) } } return mi.sizePointerSlow(p, opts) } func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int) { if flags.ProtoLegacy && mi.isMessageSet { size = sizeMessageSet(mi, p, opts) if mi.sizecacheOffset.IsValid() { atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) } return size } if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() size += mi.sizeExtensions(e, opts) } for _, f := range mi.orderedCoderFields { if f.funcs.size == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { continue } size += f.funcs.size(fptr, f, opts) } if mi.unknownOffset.IsValid() { if u := mi.getUnknownBytes(p); u != nil { size += len(*u) } } if mi.sizecacheOffset.IsValid() { if size > math.MaxInt32 { // The size is too large for the int32 sizecache field. // We will need to recompute the size when encoding; // unfortunately expensive, but better than invalid output. atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), -1) } else { atomic.StoreInt32(p.Apply(mi.sizecacheOffset).Int32(), int32(size)) } } return size } // marshal is protoreflect.Methods.Marshal. func (mi *MessageInfo) marshal(in piface.MarshalInput) (out piface.MarshalOutput, err error) { var p pointer if ms, ok := in.Message.(*messageState); ok { p = ms.pointer() } else { p = in.Message.(*messageReflectWrapper).pointer() } b, err := mi.marshalAppendPointer(in.Buf, p, marshalOptions{ flags: in.Flags, }) return piface.MarshalOutput{Buf: b}, err } func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOptions) ([]byte, error) { mi.init() if p.IsNil() { return b, nil } if flags.ProtoLegacy && mi.isMessageSet { return marshalMessageSet(mi, b, p, opts) } var err error // The old marshaler encodes extensions at beginning. if mi.extensionOffset.IsValid() { e := p.Apply(mi.extensionOffset).Extensions() // TODO: Special handling for MessageSet? b, err = mi.appendExtensions(b, e, opts) if err != nil { return b, err } } for _, f := range mi.orderedCoderFields { if f.funcs.marshal == nil { continue } fptr := p.Apply(f.offset) if f.isPointer && fptr.Elem().IsNil() { continue } b, err = f.funcs.marshal(b, fptr, f, opts) if err != nil { return b, err } } if mi.unknownOffset.IsValid() && !mi.isMessageSet { if u := mi.getUnknownBytes(p); u != nil { b = append(b, (*u)...) } } return b, nil } func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marshalOptions) (n int) { if ext == nil { return 0 } for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) if xi.funcs.size == nil { continue } n += xi.funcs.size(x.Value(), xi.tagsize, opts) } return n } func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField, opts marshalOptions) ([]byte, error) { if ext == nil { return b, nil } switch len(*ext) { case 0: return b, nil case 1: // Fast-path for one extension: Don't bother sorting the keys. var err error for _, x := range *ext { xi := getExtensionFieldInfo(x.Type()) b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) } return b, err default: // Sort the keys to provide a deterministic encoding. // Not sure this is required, but the old code does it. keys := make([]int, 0, len(*ext)) for k := range *ext { keys = append(keys, int(k)) } sort.Ints(keys) var err error for _, k := range keys { x := (*ext)[int32(k)] xi := getExtensionFieldInfo(x.Type()) b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts) if err != nil { return b, err } } return b, nil } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/enum.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) type EnumInfo struct { GoReflectType reflect.Type // int32 kind Desc pref.EnumDescriptor } func (t *EnumInfo) New(n pref.EnumNumber) pref.Enum { return reflect.ValueOf(n).Convert(t.GoReflectType).Interface().(pref.Enum) } func (t *EnumInfo) Descriptor() pref.EnumDescriptor { return t.Desc } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "sync" "sync/atomic" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // ExtensionInfo implements ExtensionType. // // This type contains a number of exported fields for legacy compatibility. // The only non-deprecated use of this type is through the methods of the // ExtensionType interface. type ExtensionInfo struct { // An ExtensionInfo may exist in several stages of initialization. // // extensionInfoUninitialized: Some or all of the legacy exported // fields may be set, but none of the unexported fields have been // initialized. This is the starting state for an ExtensionInfo // in legacy generated code. // // extensionInfoDescInit: The desc field is set, but other unexported fields // may not be initialized. Legacy exported fields may or may not be set. // This is the starting state for an ExtensionInfo in newly generated code. // // extensionInfoFullInit: The ExtensionInfo is fully initialized. // This state is only entered after lazy initialization is complete. init uint32 mu sync.Mutex goType reflect.Type desc extensionTypeDescriptor conv Converter info *extensionFieldInfo // for fast-path method implementations // ExtendedType is a typed nil-pointer to the parent message type that // is being extended. It is possible for this to be unpopulated in v2 // since the message may no longer implement the MessageV1 interface. // // Deprecated: Use the ExtendedType method instead. ExtendedType piface.MessageV1 // ExtensionType is the zero value of the extension type. // // For historical reasons, reflect.TypeOf(ExtensionType) and the // type returned by InterfaceOf may not be identical. // // Deprecated: Use InterfaceOf(xt.Zero()) instead. ExtensionType interface{} // Field is the field number of the extension. // // Deprecated: Use the Descriptor().Number method instead. Field int32 // Name is the fully qualified name of extension. // // Deprecated: Use the Descriptor().FullName method instead. Name string // Tag is the protobuf struct tag used in the v1 API. // // Deprecated: Do not use. Tag string // Filename is the proto filename in which the extension is defined. // // Deprecated: Use Descriptor().ParentFile().Path() instead. Filename string } // Stages of initialization: See the ExtensionInfo.init field. const ( extensionInfoUninitialized = 0 extensionInfoDescInit = 1 extensionInfoFullInit = 2 ) func InitExtensionInfo(xi *ExtensionInfo, xd pref.ExtensionDescriptor, goType reflect.Type) { xi.goType = goType xi.desc = extensionTypeDescriptor{xd, xi} xi.init = extensionInfoDescInit } func (xi *ExtensionInfo) New() pref.Value { return xi.lazyInit().New() } func (xi *ExtensionInfo) Zero() pref.Value { return xi.lazyInit().Zero() } func (xi *ExtensionInfo) ValueOf(v interface{}) pref.Value { return xi.lazyInit().PBValueOf(reflect.ValueOf(v)) } func (xi *ExtensionInfo) InterfaceOf(v pref.Value) interface{} { return xi.lazyInit().GoValueOf(v).Interface() } func (xi *ExtensionInfo) IsValidValue(v pref.Value) bool { return xi.lazyInit().IsValidPB(v) } func (xi *ExtensionInfo) IsValidInterface(v interface{}) bool { return xi.lazyInit().IsValidGo(reflect.ValueOf(v)) } func (xi *ExtensionInfo) TypeDescriptor() pref.ExtensionTypeDescriptor { if atomic.LoadUint32(&xi.init) < extensionInfoDescInit { xi.lazyInitSlow() } return &xi.desc } func (xi *ExtensionInfo) lazyInit() Converter { if atomic.LoadUint32(&xi.init) < extensionInfoFullInit { xi.lazyInitSlow() } return xi.conv } func (xi *ExtensionInfo) lazyInitSlow() { xi.mu.Lock() defer xi.mu.Unlock() if xi.init == extensionInfoFullInit { return } defer atomic.StoreUint32(&xi.init, extensionInfoFullInit) if xi.desc.ExtensionDescriptor == nil { xi.initFromLegacy() } if !xi.desc.ExtensionDescriptor.IsPlaceholder() { if xi.ExtensionType == nil { xi.initToLegacy() } xi.conv = NewConverter(xi.goType, xi.desc.ExtensionDescriptor) xi.info = makeExtensionFieldInfo(xi.desc.ExtensionDescriptor) xi.info.validation = newValidationInfo(xi.desc.ExtensionDescriptor, xi.goType) } } type extensionTypeDescriptor struct { pref.ExtensionDescriptor xi *ExtensionInfo } func (xtd *extensionTypeDescriptor) Type() pref.ExtensionType { return xtd.xi } func (xtd *extensionTypeDescriptor) Descriptor() pref.ExtensionDescriptor { return xtd.ExtensionDescriptor } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strings" "sync" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" ) // legacyEnumName returns the name of enums used in legacy code. // It is neither the protobuf full name nor the qualified Go name, // but rather an odd hybrid of both. func legacyEnumName(ed pref.EnumDescriptor) string { var protoPkg string enumName := string(ed.FullName()) if fd := ed.ParentFile(); fd != nil { protoPkg = string(fd.Package()) enumName = strings.TrimPrefix(enumName, protoPkg+".") } if protoPkg == "" { return strs.GoCamelCase(enumName) } return protoPkg + "." + strs.GoCamelCase(enumName) } // legacyWrapEnum wraps v as a protoreflect.Enum, // where v must be a int32 kind and not implement the v2 API already. func legacyWrapEnum(v reflect.Value) pref.Enum { et := legacyLoadEnumType(v.Type()) return et.New(pref.EnumNumber(v.Int())) } var legacyEnumTypeCache sync.Map // map[reflect.Type]protoreflect.EnumType // legacyLoadEnumType dynamically loads a protoreflect.EnumType for t, // where t must be an int32 kind and not implement the v2 API already. func legacyLoadEnumType(t reflect.Type) pref.EnumType { // Fast-path: check if a EnumType is cached for this concrete type. if et, ok := legacyEnumTypeCache.Load(t); ok { return et.(pref.EnumType) } // Slow-path: derive enum descriptor and initialize EnumType. var et pref.EnumType ed := LegacyLoadEnumDesc(t) et = &legacyEnumType{ desc: ed, goType: t, } if et, ok := legacyEnumTypeCache.LoadOrStore(t, et); ok { return et.(pref.EnumType) } return et } type legacyEnumType struct { desc pref.EnumDescriptor goType reflect.Type m sync.Map // map[protoreflect.EnumNumber]proto.Enum } func (t *legacyEnumType) New(n pref.EnumNumber) pref.Enum { if e, ok := t.m.Load(n); ok { return e.(pref.Enum) } e := &legacyEnumWrapper{num: n, pbTyp: t, goTyp: t.goType} t.m.Store(n, e) return e } func (t *legacyEnumType) Descriptor() pref.EnumDescriptor { return t.desc } type legacyEnumWrapper struct { num pref.EnumNumber pbTyp pref.EnumType goTyp reflect.Type } func (e *legacyEnumWrapper) Descriptor() pref.EnumDescriptor { return e.pbTyp.Descriptor() } func (e *legacyEnumWrapper) Type() pref.EnumType { return e.pbTyp } func (e *legacyEnumWrapper) Number() pref.EnumNumber { return e.num } func (e *legacyEnumWrapper) ProtoReflect() pref.Enum { return e } func (e *legacyEnumWrapper) protoUnwrap() interface{} { v := reflect.New(e.goTyp).Elem() v.SetInt(int64(e.num)) return v.Interface() } var ( _ pref.Enum = (*legacyEnumWrapper)(nil) _ unwrapper = (*legacyEnumWrapper)(nil) ) var legacyEnumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor // LegacyLoadEnumDesc returns an EnumDescriptor derived from the Go type, // which must be an int32 kind and not implement the v2 API already. // // This is exported for testing purposes. func LegacyLoadEnumDesc(t reflect.Type) pref.EnumDescriptor { // Fast-path: check if an EnumDescriptor is cached for this concrete type. if ed, ok := legacyEnumDescCache.Load(t); ok { return ed.(pref.EnumDescriptor) } // Slow-path: initialize EnumDescriptor from the raw descriptor. ev := reflect.Zero(t).Interface() if _, ok := ev.(pref.Enum); ok { panic(fmt.Sprintf("%v already implements proto.Enum", t)) } edV1, ok := ev.(enumV1) if !ok { return aberrantLoadEnumDesc(t) } b, idxs := edV1.EnumDescriptor() var ed pref.EnumDescriptor if len(idxs) == 1 { ed = legacyLoadFileDesc(b).Enums().Get(idxs[0]) } else { md := legacyLoadFileDesc(b).Messages().Get(idxs[0]) for _, i := range idxs[1 : len(idxs)-1] { md = md.Messages().Get(i) } ed = md.Enums().Get(idxs[len(idxs)-1]) } if ed, ok := legacyEnumDescCache.LoadOrStore(t, ed); ok { return ed.(protoreflect.EnumDescriptor) } return ed } var aberrantEnumDescCache sync.Map // map[reflect.Type]protoreflect.EnumDescriptor // aberrantLoadEnumDesc returns an EnumDescriptor derived from the Go type, // which must not implement protoreflect.Enum or enumV1. // // If the type does not implement enumV1, then there is no reliable // way to derive the original protobuf type information. // We are unable to use the global enum registry since it is // unfortunately keyed by the protobuf full name, which we also do not know. // Thus, this produces some bogus enum descriptor based on the Go type name. func aberrantLoadEnumDesc(t reflect.Type) pref.EnumDescriptor { // Fast-path: check if an EnumDescriptor is cached for this concrete type. if ed, ok := aberrantEnumDescCache.Load(t); ok { return ed.(pref.EnumDescriptor) } // Slow-path: construct a bogus, but unique EnumDescriptor. ed := &filedesc.Enum{L2: new(filedesc.EnumL2)} ed.L0.FullName = AberrantDeriveFullName(t) // e.g., github_com.user.repo.MyEnum ed.L0.ParentFile = filedesc.SurrogateProto3 ed.L2.Values.List = append(ed.L2.Values.List, filedesc.EnumValue{}) // TODO: Use the presence of a UnmarshalJSON method to determine proto2? vd := &ed.L2.Values.List[0] vd.L0.FullName = ed.L0.FullName + "_UNKNOWN" // e.g., github_com.user.repo.MyEnum_UNKNOWN vd.L0.ParentFile = ed.L0.ParentFile vd.L0.Parent = ed // TODO: We could use the String method to obtain some enum value names by // starting at 0 and print the enum until it produces invalid identifiers. // An exhaustive query is clearly impractical, but can be best-effort. if ed, ok := aberrantEnumDescCache.LoadOrStore(t, ed); ok { return ed.(pref.EnumDescriptor) } return ed } // AberrantDeriveFullName derives a fully qualified protobuf name for the given Go type // The provided name is not guaranteed to be stable nor universally unique. // It should be sufficiently unique within a program. // // This is exported for testing purposes. func AberrantDeriveFullName(t reflect.Type) pref.FullName { sanitize := func(r rune) rune { switch { case r == '/': return '.' case 'a' <= r && r <= 'z', 'A' <= r && r <= 'Z', '0' <= r && r <= '9': return r default: return '_' } } prefix := strings.Map(sanitize, t.PkgPath()) suffix := strings.Map(sanitize, t.Name()) if suffix == "" { suffix = fmt.Sprintf("UnknownX%X", reflect.ValueOf(t).Pointer()) } ss := append(strings.Split(prefix, "."), suffix) for i, s := range ss { if s == "" || ('0' <= s[0] && s[0] <= '9') { ss[i] = "x" + s } } return pref.FullName(strings.Join(ss, ".")) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/legacy_export.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "encoding/binary" "encoding/json" "hash/crc32" "math" "reflect" "google.golang.org/protobuf/internal/errors" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) // These functions exist to support exported APIs in generated protobufs. // While these are deprecated, they cannot be removed for compatibility reasons. // LegacyEnumName returns the name of enums used in legacy code. func (Export) LegacyEnumName(ed pref.EnumDescriptor) string { return legacyEnumName(ed) } // LegacyMessageTypeOf returns the protoreflect.MessageType for m, // with name used as the message name if necessary. func (Export) LegacyMessageTypeOf(m piface.MessageV1, name pref.FullName) pref.MessageType { if mv := (Export{}).protoMessageV2Of(m); mv != nil { return mv.ProtoReflect().Type() } return legacyLoadMessageType(reflect.TypeOf(m), name) } // UnmarshalJSONEnum unmarshals an enum from a JSON-encoded input. // The input can either be a string representing the enum value by name, // or a number representing the enum number itself. func (Export) UnmarshalJSONEnum(ed pref.EnumDescriptor, b []byte) (pref.EnumNumber, error) { if b[0] == '"' { var name pref.Name if err := json.Unmarshal(b, &name); err != nil { return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) } ev := ed.Values().ByName(name) if ev == nil { return 0, errors.New("invalid value for enum %v: %s", ed.FullName(), name) } return ev.Number(), nil } else { var num pref.EnumNumber if err := json.Unmarshal(b, &num); err != nil { return 0, errors.New("invalid input for enum %v: %s", ed.FullName(), b) } return num, nil } } // CompressGZIP compresses the input as a GZIP-encoded file. // The current implementation does no compression. func (Export) CompressGZIP(in []byte) (out []byte) { // RFC 1952, section 2.3.1. var gzipHeader = [10]byte{0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff} // RFC 1951, section 3.2.4. var blockHeader [5]byte const maxBlockSize = math.MaxUint16 numBlocks := 1 + len(in)/maxBlockSize // RFC 1952, section 2.3.1. var gzipFooter [8]byte binary.LittleEndian.PutUint32(gzipFooter[0:4], crc32.ChecksumIEEE(in)) binary.LittleEndian.PutUint32(gzipFooter[4:8], uint32(len(in))) // Encode the input without compression using raw DEFLATE blocks. out = make([]byte, 0, len(gzipHeader)+len(blockHeader)*numBlocks+len(in)+len(gzipFooter)) out = append(out, gzipHeader[:]...) for blockHeader[0] == 0 { blockSize := maxBlockSize if blockSize > len(in) { blockHeader[0] = 0x01 // final bit per RFC 1951, section 3.2.3. blockSize = len(in) } binary.LittleEndian.PutUint16(blockHeader[1:3], uint16(blockSize)^0x0000) binary.LittleEndian.PutUint16(blockHeader[3:5], uint16(blockSize)^0xffff) out = append(out, blockHeader[:]...) out = append(out, in[:blockSize]...) in = in[blockSize:] } out = append(out, gzipFooter[:]...) return out } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "reflect" "google.golang.org/protobuf/internal/descopts" "google.golang.org/protobuf/internal/encoding/messageset" ptag "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) func (xi *ExtensionInfo) initToLegacy() { xd := xi.desc var parent piface.MessageV1 messageName := xd.ContainingMessage().FullName() if mt, _ := preg.GlobalTypes.FindMessageByName(messageName); mt != nil { // Create a new parent message and unwrap it if possible. mv := mt.New().Interface() t := reflect.TypeOf(mv) if mv, ok := mv.(unwrapper); ok { t = reflect.TypeOf(mv.protoUnwrap()) } // Check whether the message implements the legacy v1 Message interface. mz := reflect.Zero(t).Interface() if mz, ok := mz.(piface.MessageV1); ok { parent = mz } } // Determine the v1 extension type, which is unfortunately not the same as // the v2 ExtensionType.GoType. extType := xi.goType switch extType.Kind() { case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: extType = reflect.PtrTo(extType) // T -> *T for singular scalar fields } // Reconstruct the legacy enum full name. var enumName string if xd.Kind() == pref.EnumKind { enumName = legacyEnumName(xd.Enum()) } // Derive the proto file that the extension was declared within. var filename string if fd := xd.ParentFile(); fd != nil { filename = fd.Path() } // For MessageSet extensions, the name used is the parent message. name := xd.FullName() if messageset.IsMessageSetExtension(xd) { name = name.Parent() } xi.ExtendedType = parent xi.ExtensionType = reflect.Zero(extType).Interface() xi.Field = int32(xd.Number()) xi.Name = string(name) xi.Tag = ptag.Marshal(xd, enumName) xi.Filename = filename } // initFromLegacy initializes an ExtensionInfo from // the contents of the deprecated exported fields of the type. func (xi *ExtensionInfo) initFromLegacy() { // The v1 API returns "type incomplete" descriptors where only the // field number is specified. In such a case, use a placeholder. if xi.ExtendedType == nil || xi.ExtensionType == nil { xd := placeholderExtension{ name: pref.FullName(xi.Name), number: pref.FieldNumber(xi.Field), } xi.desc = extensionTypeDescriptor{xd, xi} return } // Resolve enum or message dependencies. var ed pref.EnumDescriptor var md pref.MessageDescriptor t := reflect.TypeOf(xi.ExtensionType) isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 if isOptional || isRepeated { t = t.Elem() } switch v := reflect.Zero(t).Interface().(type) { case pref.Enum: ed = v.Descriptor() case enumV1: ed = LegacyLoadEnumDesc(t) case pref.ProtoMessage: md = v.ProtoReflect().Descriptor() case messageV1: md = LegacyLoadMessageDesc(t) } // Derive basic field information from the struct tag. var evs pref.EnumValueDescriptors if ed != nil { evs = ed.Values() } fd := ptag.Unmarshal(xi.Tag, t, evs).(*filedesc.Field) // Construct a v2 ExtensionType. xd := &filedesc.Extension{L2: new(filedesc.ExtensionL2)} xd.L0.ParentFile = filedesc.SurrogateProto2 xd.L0.FullName = pref.FullName(xi.Name) xd.L1.Number = pref.FieldNumber(xi.Field) xd.L1.Cardinality = fd.L1.Cardinality xd.L1.Kind = fd.L1.Kind xd.L2.IsPacked = fd.L1.IsPacked xd.L2.Default = fd.L1.Default xd.L1.Extendee = Export{}.MessageDescriptorOf(xi.ExtendedType) xd.L2.Enum = ed xd.L2.Message = md // Derive real extension field name for MessageSets. if messageset.IsMessageSet(xd.L1.Extendee) && md.FullName() == xd.L0.FullName { xd.L0.FullName = xd.L0.FullName.Append(messageset.ExtensionName) } tt := reflect.TypeOf(xi.ExtensionType) if isOptional { tt = tt.Elem() } xi.goType = tt xi.desc = extensionTypeDescriptor{xd, xi} } type placeholderExtension struct { name pref.FullName number pref.FieldNumber } func (x placeholderExtension) ParentFile() pref.FileDescriptor { return nil } func (x placeholderExtension) Parent() pref.Descriptor { return nil } func (x placeholderExtension) Index() int { return 0 } func (x placeholderExtension) Syntax() pref.Syntax { return 0 } func (x placeholderExtension) Name() pref.Name { return x.name.Name() } func (x placeholderExtension) FullName() pref.FullName { return x.name } func (x placeholderExtension) IsPlaceholder() bool { return true } func (x placeholderExtension) Options() pref.ProtoMessage { return descopts.Field } func (x placeholderExtension) Number() pref.FieldNumber { return x.number } func (x placeholderExtension) Cardinality() pref.Cardinality { return 0 } func (x placeholderExtension) Kind() pref.Kind { return 0 } func (x placeholderExtension) HasJSONName() bool { return false } func (x placeholderExtension) JSONName() string { return "[" + string(x.name) + "]" } func (x placeholderExtension) TextName() string { return "[" + string(x.name) + "]" } func (x placeholderExtension) HasPresence() bool { return false } func (x placeholderExtension) HasOptionalKeyword() bool { return false } func (x placeholderExtension) IsExtension() bool { return true } func (x placeholderExtension) IsWeak() bool { return false } func (x placeholderExtension) IsPacked() bool { return false } func (x placeholderExtension) IsList() bool { return false } func (x placeholderExtension) IsMap() bool { return false } func (x placeholderExtension) MapKey() pref.FieldDescriptor { return nil } func (x placeholderExtension) MapValue() pref.FieldDescriptor { return nil } func (x placeholderExtension) HasDefault() bool { return false } func (x placeholderExtension) Default() pref.Value { return pref.Value{} } func (x placeholderExtension) DefaultEnumValue() pref.EnumValueDescriptor { return nil } func (x placeholderExtension) ContainingOneof() pref.OneofDescriptor { return nil } func (x placeholderExtension) ContainingMessage() pref.MessageDescriptor { return nil } func (x placeholderExtension) Enum() pref.EnumDescriptor { return nil } func (x placeholderExtension) Message() pref.MessageDescriptor { return nil } func (x placeholderExtension) ProtoType(pref.FieldDescriptor) { return } func (x placeholderExtension) ProtoInternal(pragma.DoNotImplement) { return } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/legacy_file.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "bytes" "compress/gzip" "io/ioutil" "sync" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // Every enum and message type generated by protoc-gen-go since commit 2fc053c5 // on February 25th, 2016 has had a method to get the raw descriptor. // Types that were not generated by protoc-gen-go or were generated prior // to that version are not supported. // // The []byte returned is the encoded form of a FileDescriptorProto message // compressed using GZIP. The []int is the path from the top-level file // to the specific message or enum declaration. type ( enumV1 interface { EnumDescriptor() ([]byte, []int) } messageV1 interface { Descriptor() ([]byte, []int) } ) var legacyFileDescCache sync.Map // map[*byte]protoreflect.FileDescriptor // legacyLoadFileDesc unmarshals b as a compressed FileDescriptorProto message. // // This assumes that b is immutable and that b does not refer to part of a // concatenated series of GZIP files (which would require shenanigans that // rely on the concatenation properties of both protobufs and GZIP). // File descriptors generated by protoc-gen-go do not rely on that property. func legacyLoadFileDesc(b []byte) protoreflect.FileDescriptor { // Fast-path: check whether we already have a cached file descriptor. if fd, ok := legacyFileDescCache.Load(&b[0]); ok { return fd.(protoreflect.FileDescriptor) } // Slow-path: decompress and unmarshal the file descriptor proto. zr, err := gzip.NewReader(bytes.NewReader(b)) if err != nil { panic(err) } b2, err := ioutil.ReadAll(zr) if err != nil { panic(err) } fd := filedesc.Builder{ RawDescriptor: b2, FileRegistry: resolverOnly{protoregistry.GlobalFiles}, // do not register back to global registry }.Build().File if fd, ok := legacyFileDescCache.LoadOrStore(&b[0], fd); ok { return fd.(protoreflect.FileDescriptor) } return fd } type resolverOnly struct { reg *protoregistry.Files } func (r resolverOnly) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { return r.reg.FindFileByPath(path) } func (r resolverOnly) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { return r.reg.FindDescriptorByName(name) } func (resolverOnly) RegisterFile(protoreflect.FileDescriptor) error { return nil } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/legacy_message.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strings" "sync" "google.golang.org/protobuf/internal/descopts" ptag "google.golang.org/protobuf/internal/encoding/tag" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" piface "google.golang.org/protobuf/runtime/protoiface" ) // legacyWrapMessage wraps v as a protoreflect.Message, // where v must be a *struct kind and not implement the v2 API already. func legacyWrapMessage(v reflect.Value) pref.Message { t := v.Type() if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return aberrantMessage{v: v} } mt := legacyLoadMessageInfo(t, "") return mt.MessageOf(v.Interface()) } // legacyLoadMessageType dynamically loads a protoreflect.Type for t, // where t must be not implement the v2 API already. // The provided name is used if it cannot be determined from the message. func legacyLoadMessageType(t reflect.Type, name pref.FullName) protoreflect.MessageType { if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return aberrantMessageType{t} } return legacyLoadMessageInfo(t, name) } var legacyMessageTypeCache sync.Map // map[reflect.Type]*MessageInfo // legacyLoadMessageInfo dynamically loads a *MessageInfo for t, // where t must be a *struct kind and not implement the v2 API already. // The provided name is used if it cannot be determined from the message. func legacyLoadMessageInfo(t reflect.Type, name pref.FullName) *MessageInfo { // Fast-path: check if a MessageInfo is cached for this concrete type. if mt, ok := legacyMessageTypeCache.Load(t); ok { return mt.(*MessageInfo) } // Slow-path: derive message descriptor and initialize MessageInfo. mi := &MessageInfo{ Desc: legacyLoadMessageDesc(t, name), GoReflectType: t, } var hasMarshal, hasUnmarshal bool v := reflect.Zero(t).Interface() if _, hasMarshal = v.(legacyMarshaler); hasMarshal { mi.methods.Marshal = legacyMarshal // We have no way to tell whether the type's Marshal method // supports deterministic serialization or not, but this // preserves the v1 implementation's behavior of always // calling Marshal methods when present. mi.methods.Flags |= piface.SupportMarshalDeterministic } if _, hasUnmarshal = v.(legacyUnmarshaler); hasUnmarshal { mi.methods.Unmarshal = legacyUnmarshal } if _, hasMerge := v.(legacyMerger); hasMerge || (hasMarshal && hasUnmarshal) { mi.methods.Merge = legacyMerge } if mi, ok := legacyMessageTypeCache.LoadOrStore(t, mi); ok { return mi.(*MessageInfo) } return mi } var legacyMessageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor // LegacyLoadMessageDesc returns an MessageDescriptor derived from the Go type, // which should be a *struct kind and must not implement the v2 API already. // // This is exported for testing purposes. func LegacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor { return legacyLoadMessageDesc(t, "") } func legacyLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { // Fast-path: check if a MessageDescriptor is cached for this concrete type. if mi, ok := legacyMessageDescCache.Load(t); ok { return mi.(pref.MessageDescriptor) } // Slow-path: initialize MessageDescriptor from the raw descriptor. mv := reflect.Zero(t).Interface() if _, ok := mv.(pref.ProtoMessage); ok { panic(fmt.Sprintf("%v already implements proto.Message", t)) } mdV1, ok := mv.(messageV1) if !ok { return aberrantLoadMessageDesc(t, name) } // If this is a dynamic message type where there isn't a 1-1 mapping between // Go and protobuf types, calling the Descriptor method on the zero value of // the message type isn't likely to work. If it panics, swallow the panic and // continue as if the Descriptor method wasn't present. b, idxs := func() ([]byte, []int) { defer func() { recover() }() return mdV1.Descriptor() }() if b == nil { return aberrantLoadMessageDesc(t, name) } // If the Go type has no fields, then this might be a proto3 empty message // from before the size cache was added. If there are any fields, check to // see that at least one of them looks like something we generated. if t.Elem().Kind() == reflect.Struct { if nfield := t.Elem().NumField(); nfield > 0 { hasProtoField := false for i := 0; i < nfield; i++ { f := t.Elem().Field(i) if f.Tag.Get("protobuf") != "" || f.Tag.Get("protobuf_oneof") != "" || strings.HasPrefix(f.Name, "XXX_") { hasProtoField = true break } } if !hasProtoField { return aberrantLoadMessageDesc(t, name) } } } md := legacyLoadFileDesc(b).Messages().Get(idxs[0]) for _, i := range idxs[1:] { md = md.Messages().Get(i) } if name != "" && md.FullName() != name { panic(fmt.Sprintf("mismatching message name: got %v, want %v", md.FullName(), name)) } if md, ok := legacyMessageDescCache.LoadOrStore(t, md); ok { return md.(protoreflect.MessageDescriptor) } return md } var ( aberrantMessageDescLock sync.Mutex aberrantMessageDescCache map[reflect.Type]protoreflect.MessageDescriptor ) // aberrantLoadMessageDesc returns an MessageDescriptor derived from the Go type, // which must not implement protoreflect.ProtoMessage or messageV1. // // This is a best-effort derivation of the message descriptor using the protobuf // tags on the struct fields. func aberrantLoadMessageDesc(t reflect.Type, name pref.FullName) pref.MessageDescriptor { aberrantMessageDescLock.Lock() defer aberrantMessageDescLock.Unlock() if aberrantMessageDescCache == nil { aberrantMessageDescCache = make(map[reflect.Type]protoreflect.MessageDescriptor) } return aberrantLoadMessageDescReentrant(t, name) } func aberrantLoadMessageDescReentrant(t reflect.Type, name pref.FullName) pref.MessageDescriptor { // Fast-path: check if an MessageDescriptor is cached for this concrete type. if md, ok := aberrantMessageDescCache[t]; ok { return md } // Slow-path: construct a descriptor from the Go struct type (best-effort). // Cache the MessageDescriptor early on so that we can resolve internal // cyclic references. md := &filedesc.Message{L2: new(filedesc.MessageL2)} md.L0.FullName = aberrantDeriveMessageName(t, name) md.L0.ParentFile = filedesc.SurrogateProto2 aberrantMessageDescCache[t] = md if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct { return md } // Try to determine if the message is using proto3 by checking scalars. for i := 0; i < t.Elem().NumField(); i++ { f := t.Elem().Field(i) if tag := f.Tag.Get("protobuf"); tag != "" { switch f.Type.Kind() { case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String: md.L0.ParentFile = filedesc.SurrogateProto3 } for _, s := range strings.Split(tag, ",") { if s == "proto3" { md.L0.ParentFile = filedesc.SurrogateProto3 } } } } // Obtain a list of oneof wrapper types. var oneofWrappers []reflect.Type for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { if fn, ok := t.MethodByName(method); ok { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { if vs, ok := v.Interface().([]interface{}); ok { for _, v := range vs { oneofWrappers = append(oneofWrappers, reflect.TypeOf(v)) } } } } } // Obtain a list of the extension ranges. if fn, ok := t.MethodByName("ExtensionRangeArray"); ok { vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0] for i := 0; i < vs.Len(); i++ { v := vs.Index(i) md.L2.ExtensionRanges.List = append(md.L2.ExtensionRanges.List, [2]pref.FieldNumber{ pref.FieldNumber(v.FieldByName("Start").Int()), pref.FieldNumber(v.FieldByName("End").Int() + 1), }) md.L2.ExtensionRangeOptions = append(md.L2.ExtensionRangeOptions, nil) } } // Derive the message fields by inspecting the struct fields. for i := 0; i < t.Elem().NumField(); i++ { f := t.Elem().Field(i) if tag := f.Tag.Get("protobuf"); tag != "" { tagKey := f.Tag.Get("protobuf_key") tagVal := f.Tag.Get("protobuf_val") aberrantAppendField(md, f.Type, tag, tagKey, tagVal) } if tag := f.Tag.Get("protobuf_oneof"); tag != "" { n := len(md.L2.Oneofs.List) md.L2.Oneofs.List = append(md.L2.Oneofs.List, filedesc.Oneof{}) od := &md.L2.Oneofs.List[n] od.L0.FullName = md.FullName().Append(pref.Name(tag)) od.L0.ParentFile = md.L0.ParentFile od.L0.Parent = md od.L0.Index = n for _, t := range oneofWrappers { if t.Implements(f.Type) { f := t.Elem().Field(0) if tag := f.Tag.Get("protobuf"); tag != "" { aberrantAppendField(md, f.Type, tag, "", "") fd := &md.L2.Fields.List[len(md.L2.Fields.List)-1] fd.L1.ContainingOneof = od od.L1.Fields.List = append(od.L1.Fields.List, fd) } } } } } return md } func aberrantDeriveMessageName(t reflect.Type, name pref.FullName) pref.FullName { if name.IsValid() { return name } func() { defer func() { recover() }() // swallow possible nil panics if m, ok := reflect.Zero(t).Interface().(interface{ XXX_MessageName() string }); ok { name = pref.FullName(m.XXX_MessageName()) } }() if name.IsValid() { return name } if t.Kind() == reflect.Ptr { t = t.Elem() } return AberrantDeriveFullName(t) } func aberrantAppendField(md *filedesc.Message, goType reflect.Type, tag, tagKey, tagVal string) { t := goType isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8 if isOptional || isRepeated { t = t.Elem() } fd := ptag.Unmarshal(tag, t, placeholderEnumValues{}).(*filedesc.Field) // Append field descriptor to the message. n := len(md.L2.Fields.List) md.L2.Fields.List = append(md.L2.Fields.List, *fd) fd = &md.L2.Fields.List[n] fd.L0.FullName = md.FullName().Append(fd.Name()) fd.L0.ParentFile = md.L0.ParentFile fd.L0.Parent = md fd.L0.Index = n if fd.L1.IsWeak || fd.L1.HasPacked { fd.L1.Options = func() pref.ProtoMessage { opts := descopts.Field.ProtoReflect().New() if fd.L1.IsWeak { opts.Set(opts.Descriptor().Fields().ByName("weak"), protoreflect.ValueOfBool(true)) } if fd.L1.HasPacked { opts.Set(opts.Descriptor().Fields().ByName("packed"), protoreflect.ValueOfBool(fd.L1.IsPacked)) } return opts.Interface() } } // Populate Enum and Message. if fd.Enum() == nil && fd.Kind() == pref.EnumKind { switch v := reflect.Zero(t).Interface().(type) { case pref.Enum: fd.L1.Enum = v.Descriptor() default: fd.L1.Enum = LegacyLoadEnumDesc(t) } } if fd.Message() == nil && (fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind) { switch v := reflect.Zero(t).Interface().(type) { case pref.ProtoMessage: fd.L1.Message = v.ProtoReflect().Descriptor() case messageV1: fd.L1.Message = LegacyLoadMessageDesc(t) default: if t.Kind() == reflect.Map { n := len(md.L1.Messages.List) md.L1.Messages.List = append(md.L1.Messages.List, filedesc.Message{L2: new(filedesc.MessageL2)}) md2 := &md.L1.Messages.List[n] md2.L0.FullName = md.FullName().Append(pref.Name(strs.MapEntryName(string(fd.Name())))) md2.L0.ParentFile = md.L0.ParentFile md2.L0.Parent = md md2.L0.Index = n md2.L1.IsMapEntry = true md2.L2.Options = func() pref.ProtoMessage { opts := descopts.Message.ProtoReflect().New() opts.Set(opts.Descriptor().Fields().ByName("map_entry"), protoreflect.ValueOfBool(true)) return opts.Interface() } aberrantAppendField(md2, t.Key(), tagKey, "", "") aberrantAppendField(md2, t.Elem(), tagVal, "", "") fd.L1.Message = md2 break } fd.L1.Message = aberrantLoadMessageDescReentrant(t, "") } } } type placeholderEnumValues struct { protoreflect.EnumValueDescriptors } func (placeholderEnumValues) ByNumber(n pref.EnumNumber) pref.EnumValueDescriptor { return filedesc.PlaceholderEnumValue(pref.FullName(fmt.Sprintf("UNKNOWN_%d", n))) } // legacyMarshaler is the proto.Marshaler interface superseded by protoiface.Methoder. type legacyMarshaler interface { Marshal() ([]byte, error) } // legacyUnmarshaler is the proto.Unmarshaler interface superseded by protoiface.Methoder. type legacyUnmarshaler interface { Unmarshal([]byte) error } // legacyMerger is the proto.Merger interface superseded by protoiface.Methoder. type legacyMerger interface { Merge(protoiface.MessageV1) } var aberrantProtoMethods = &piface.Methods{ Marshal: legacyMarshal, Unmarshal: legacyUnmarshal, Merge: legacyMerge, // We have no way to tell whether the type's Marshal method // supports deterministic serialization or not, but this // preserves the v1 implementation's behavior of always // calling Marshal methods when present. Flags: piface.SupportMarshalDeterministic, } func legacyMarshal(in piface.MarshalInput) (piface.MarshalOutput, error) { v := in.Message.(unwrapper).protoUnwrap() marshaler, ok := v.(legacyMarshaler) if !ok { return piface.MarshalOutput{}, errors.New("%T does not implement Marshal", v) } out, err := marshaler.Marshal() if in.Buf != nil { out = append(in.Buf, out...) } return piface.MarshalOutput{ Buf: out, }, err } func legacyUnmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) { v := in.Message.(unwrapper).protoUnwrap() unmarshaler, ok := v.(legacyUnmarshaler) if !ok { return piface.UnmarshalOutput{}, errors.New("%T does not implement Unmarshal", v) } return piface.UnmarshalOutput{}, unmarshaler.Unmarshal(in.Buf) } func legacyMerge(in piface.MergeInput) piface.MergeOutput { // Check whether this supports the legacy merger. dstv := in.Destination.(unwrapper).protoUnwrap() merger, ok := dstv.(legacyMerger) if ok { merger.Merge(Export{}.ProtoMessageV1Of(in.Source)) return piface.MergeOutput{Flags: piface.MergeComplete} } // If legacy merger is unavailable, implement merge in terms of // a marshal and unmarshal operation. srcv := in.Source.(unwrapper).protoUnwrap() marshaler, ok := srcv.(legacyMarshaler) if !ok { return piface.MergeOutput{} } dstv = in.Destination.(unwrapper).protoUnwrap() unmarshaler, ok := dstv.(legacyUnmarshaler) if !ok { return piface.MergeOutput{} } b, err := marshaler.Marshal() if err != nil { return piface.MergeOutput{} } err = unmarshaler.Unmarshal(b) if err != nil { return piface.MergeOutput{} } return piface.MergeOutput{Flags: piface.MergeComplete} } // aberrantMessageType implements MessageType for all types other than pointer-to-struct. type aberrantMessageType struct { t reflect.Type } func (mt aberrantMessageType) New() pref.Message { if mt.t.Kind() == reflect.Ptr { return aberrantMessage{reflect.New(mt.t.Elem())} } return aberrantMessage{reflect.Zero(mt.t)} } func (mt aberrantMessageType) Zero() pref.Message { return aberrantMessage{reflect.Zero(mt.t)} } func (mt aberrantMessageType) GoType() reflect.Type { return mt.t } func (mt aberrantMessageType) Descriptor() pref.MessageDescriptor { return LegacyLoadMessageDesc(mt.t) } // aberrantMessage implements Message for all types other than pointer-to-struct. // // When the underlying type implements legacyMarshaler or legacyUnmarshaler, // the aberrant Message can be marshaled or unmarshaled. Otherwise, there is // not much that can be done with values of this type. type aberrantMessage struct { v reflect.Value } // Reset implements the v1 proto.Message.Reset method. func (m aberrantMessage) Reset() { if mr, ok := m.v.Interface().(interface{ Reset() }); ok { mr.Reset() return } if m.v.Kind() == reflect.Ptr && !m.v.IsNil() { m.v.Elem().Set(reflect.Zero(m.v.Type().Elem())) } } func (m aberrantMessage) ProtoReflect() pref.Message { return m } func (m aberrantMessage) Descriptor() pref.MessageDescriptor { return LegacyLoadMessageDesc(m.v.Type()) } func (m aberrantMessage) Type() pref.MessageType { return aberrantMessageType{m.v.Type()} } func (m aberrantMessage) New() pref.Message { if m.v.Type().Kind() == reflect.Ptr { return aberrantMessage{reflect.New(m.v.Type().Elem())} } return aberrantMessage{reflect.Zero(m.v.Type())} } func (m aberrantMessage) Interface() pref.ProtoMessage { return m } func (m aberrantMessage) Range(f func(pref.FieldDescriptor, pref.Value) bool) { return } func (m aberrantMessage) Has(pref.FieldDescriptor) bool { return false } func (m aberrantMessage) Clear(pref.FieldDescriptor) { panic("invalid Message.Clear on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Get(fd pref.FieldDescriptor) pref.Value { if fd.Default().IsValid() { return fd.Default() } panic("invalid Message.Get on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Set(pref.FieldDescriptor, pref.Value) { panic("invalid Message.Set on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) Mutable(pref.FieldDescriptor) pref.Value { panic("invalid Message.Mutable on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) NewField(pref.FieldDescriptor) pref.Value { panic("invalid Message.NewField on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) WhichOneof(pref.OneofDescriptor) pref.FieldDescriptor { panic("invalid Message.WhichOneof descriptor on " + string(m.Descriptor().FullName())) } func (m aberrantMessage) GetUnknown() pref.RawFields { return nil } func (m aberrantMessage) SetUnknown(pref.RawFields) { // SetUnknown discards its input on messages which don't support unknown field storage. } func (m aberrantMessage) IsValid() bool { if m.v.Kind() == reflect.Ptr { return !m.v.IsNil() } return false } func (m aberrantMessage) ProtoMethods() *piface.Methods { return aberrantProtoMethods } func (m aberrantMessage) protoUnwrap() interface{} { return m.v.Interface() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/merge.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/proto" pref "google.golang.org/protobuf/reflect/protoreflect" piface "google.golang.org/protobuf/runtime/protoiface" ) type mergeOptions struct{} func (o mergeOptions) Merge(dst, src proto.Message) { proto.Merge(dst, src) } // merge is protoreflect.Methods.Merge. func (mi *MessageInfo) merge(in piface.MergeInput) piface.MergeOutput { dp, ok := mi.getPointer(in.Destination) if !ok { return piface.MergeOutput{} } sp, ok := mi.getPointer(in.Source) if !ok { return piface.MergeOutput{} } mi.mergePointer(dp, sp, mergeOptions{}) return piface.MergeOutput{Flags: piface.MergeComplete} } func (mi *MessageInfo) mergePointer(dst, src pointer, opts mergeOptions) { mi.init() if dst.IsNil() { panic(fmt.Sprintf("invalid value: merging into nil message")) } if src.IsNil() { return } for _, f := range mi.orderedCoderFields { if f.funcs.merge == nil { continue } sfptr := src.Apply(f.offset) if f.isPointer && sfptr.Elem().IsNil() { continue } f.funcs.merge(dst.Apply(f.offset), sfptr, f, opts) } if mi.extensionOffset.IsValid() { sext := src.Apply(mi.extensionOffset).Extensions() dext := dst.Apply(mi.extensionOffset).Extensions() if *dext == nil { *dext = make(map[int32]ExtensionField) } for num, sx := range *sext { xt := sx.Type() xi := getExtensionFieldInfo(xt) if xi.funcs.merge == nil { continue } dx := (*dext)[num] var dv pref.Value if dx.Type() == sx.Type() { dv = dx.Value() } if !dv.IsValid() && xi.unmarshalNeedsValue { dv = xt.New() } dv = xi.funcs.merge(dv, sx.Value(), opts) dx.Set(sx.Type(), dv) (*dext)[num] = dx } } if mi.unknownOffset.IsValid() { su := mi.getUnknownBytes(src) if su != nil && len(*su) > 0 { du := mi.mutableUnknownBytes(dst) *du = append(*du, *su...) } } } func mergeScalarValue(dst, src pref.Value, opts mergeOptions) pref.Value { return src } func mergeBytesValue(dst, src pref.Value, opts mergeOptions) pref.Value { return pref.ValueOfBytes(append(emptyBuf[:], src.Bytes()...)) } func mergeListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { dstl.Append(srcl.Get(i)) } return dst } func mergeBytesListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { sb := srcl.Get(i).Bytes() db := append(emptyBuf[:], sb...) dstl.Append(pref.ValueOfBytes(db)) } return dst } func mergeMessageListValue(dst, src pref.Value, opts mergeOptions) pref.Value { dstl := dst.List() srcl := src.List() for i, llen := 0, srcl.Len(); i < llen; i++ { sm := srcl.Get(i).Message() dm := proto.Clone(sm.Interface()).ProtoReflect() dstl.Append(pref.ValueOfMessage(dm)) } return dst } func mergeMessageValue(dst, src pref.Value, opts mergeOptions) pref.Value { opts.Merge(dst.Message().Interface(), src.Message().Interface()) return dst } func mergeMessage(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { if f.mi != nil { if dst.Elem().IsNil() { dst.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) } f.mi.mergePointer(dst.Elem(), src.Elem(), opts) } else { dm := dst.AsValueOf(f.ft).Elem() sm := src.AsValueOf(f.ft).Elem() if dm.IsNil() { dm.Set(reflect.New(f.ft.Elem())) } opts.Merge(asMessage(dm), asMessage(sm)) } } func mergeMessageSlice(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { for _, sp := range src.PointerSlice() { dm := reflect.New(f.ft.Elem().Elem()) if f.mi != nil { f.mi.mergePointer(pointerOfValue(dm), sp, opts) } else { opts.Merge(asMessage(dm), asMessage(sp.AsValueOf(f.ft.Elem().Elem()))) } dst.AppendPointerSlice(pointerOfValue(dm)) } } func mergeBytes(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Bytes() = append(emptyBuf[:], *src.Bytes()...) } func mergeBytesNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Bytes() if len(v) > 0 { *dst.Bytes() = append(emptyBuf[:], v...) } } func mergeBytesSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.BytesSlice() for _, v := range *src.BytesSlice() { *ds = append(*ds, append(emptyBuf[:], v...)) } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/merge_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import () func mergeBool(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Bool() = *src.Bool() } func mergeBoolNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Bool() if v != false { *dst.Bool() = v } } func mergeBoolPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.BoolPtr() if p != nil { v := *p *dst.BoolPtr() = &v } } func mergeBoolSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.BoolSlice() ss := src.BoolSlice() *ds = append(*ds, *ss...) } func mergeInt32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Int32() = *src.Int32() } func mergeInt32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Int32() if v != 0 { *dst.Int32() = v } } func mergeInt32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Int32Ptr() if p != nil { v := *p *dst.Int32Ptr() = &v } } func mergeInt32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Int32Slice() ss := src.Int32Slice() *ds = append(*ds, *ss...) } func mergeUint32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Uint32() = *src.Uint32() } func mergeUint32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Uint32() if v != 0 { *dst.Uint32() = v } } func mergeUint32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Uint32Ptr() if p != nil { v := *p *dst.Uint32Ptr() = &v } } func mergeUint32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Uint32Slice() ss := src.Uint32Slice() *ds = append(*ds, *ss...) } func mergeInt64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Int64() = *src.Int64() } func mergeInt64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Int64() if v != 0 { *dst.Int64() = v } } func mergeInt64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Int64Ptr() if p != nil { v := *p *dst.Int64Ptr() = &v } } func mergeInt64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Int64Slice() ss := src.Int64Slice() *ds = append(*ds, *ss...) } func mergeUint64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Uint64() = *src.Uint64() } func mergeUint64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Uint64() if v != 0 { *dst.Uint64() = v } } func mergeUint64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Uint64Ptr() if p != nil { v := *p *dst.Uint64Ptr() = &v } } func mergeUint64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Uint64Slice() ss := src.Uint64Slice() *ds = append(*ds, *ss...) } func mergeFloat32(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Float32() = *src.Float32() } func mergeFloat32NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Float32() if v != 0 { *dst.Float32() = v } } func mergeFloat32Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Float32Ptr() if p != nil { v := *p *dst.Float32Ptr() = &v } } func mergeFloat32Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Float32Slice() ss := src.Float32Slice() *ds = append(*ds, *ss...) } func mergeFloat64(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.Float64() = *src.Float64() } func mergeFloat64NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.Float64() if v != 0 { *dst.Float64() = v } } func mergeFloat64Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.Float64Ptr() if p != nil { v := *p *dst.Float64Ptr() = &v } } func mergeFloat64Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.Float64Slice() ss := src.Float64Slice() *ds = append(*ds, *ss...) } func mergeString(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { *dst.String() = *src.String() } func mergeStringNoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { v := *src.String() if v != "" { *dst.String() = v } } func mergeStringPtr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { p := *src.StringPtr() if p != nil { v := *p *dst.StringPtr() = &v } } func mergeStringSlice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { ds := dst.StringSlice() ss := src.StringSlice() *ds = append(*ds, *ss...) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/message.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "strconv" "strings" "sync" "sync/atomic" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/reflect/protoreflect" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) // MessageInfo provides protobuf related functionality for a given Go type // that represents a message. A given instance of MessageInfo is tied to // exactly one Go type, which must be a pointer to a struct type. // // The exported fields must be populated before any methods are called // and cannot be mutated after set. type MessageInfo struct { // GoReflectType is the underlying message Go type and must be populated. GoReflectType reflect.Type // pointer to struct // Desc is the underlying message descriptor type and must be populated. Desc pref.MessageDescriptor // Exporter must be provided in a purego environment in order to provide // access to unexported fields. Exporter exporter // OneofWrappers is list of pointers to oneof wrapper struct types. OneofWrappers []interface{} initMu sync.Mutex // protects all unexported fields initDone uint32 reflectMessageInfo // for reflection implementation coderMessageInfo // for fast-path method implementations } // exporter is a function that returns a reference to the ith field of v, // where v is a pointer to a struct. It returns nil if it does not support // exporting the requested field (e.g., already exported). type exporter func(v interface{}, i int) interface{} // getMessageInfo returns the MessageInfo for any message type that // is generated by our implementation of protoc-gen-go (for v2 and on). // If it is unable to obtain a MessageInfo, it returns nil. func getMessageInfo(mt reflect.Type) *MessageInfo { m, ok := reflect.Zero(mt).Interface().(pref.ProtoMessage) if !ok { return nil } mr, ok := m.ProtoReflect().(interface{ ProtoMessageInfo() *MessageInfo }) if !ok { return nil } return mr.ProtoMessageInfo() } func (mi *MessageInfo) init() { // This function is called in the hot path. Inline the sync.Once logic, // since allocating a closure for Once.Do is expensive. // Keep init small to ensure that it can be inlined. if atomic.LoadUint32(&mi.initDone) == 0 { mi.initOnce() } } func (mi *MessageInfo) initOnce() { mi.initMu.Lock() defer mi.initMu.Unlock() if mi.initDone == 1 { return } t := mi.GoReflectType if t.Kind() != reflect.Ptr && t.Elem().Kind() != reflect.Struct { panic(fmt.Sprintf("got %v, want *struct kind", t)) } t = t.Elem() si := mi.makeStructInfo(t) mi.makeReflectFuncs(t, si) mi.makeCoderMethods(t, si) atomic.StoreUint32(&mi.initDone, 1) } // getPointer returns the pointer for a message, which should be of // the type of the MessageInfo. If the message is of a different type, // it returns ok==false. func (mi *MessageInfo) getPointer(m pref.Message) (p pointer, ok bool) { switch m := m.(type) { case *messageState: return m.pointer(), m.messageInfo() == mi case *messageReflectWrapper: return m.pointer(), m.messageInfo() == mi } return pointer{}, false } type ( SizeCache = int32 WeakFields = map[int32]protoreflect.ProtoMessage UnknownFields = unknownFieldsA // TODO: switch to unknownFieldsB unknownFieldsA = []byte unknownFieldsB = *[]byte ExtensionFields = map[int32]ExtensionField ) var ( sizecacheType = reflect.TypeOf(SizeCache(0)) weakFieldsType = reflect.TypeOf(WeakFields(nil)) unknownFieldsAType = reflect.TypeOf(unknownFieldsA(nil)) unknownFieldsBType = reflect.TypeOf(unknownFieldsB(nil)) extensionFieldsType = reflect.TypeOf(ExtensionFields(nil)) ) type structInfo struct { sizecacheOffset offset sizecacheType reflect.Type weakOffset offset weakType reflect.Type unknownOffset offset unknownType reflect.Type extensionOffset offset extensionType reflect.Type fieldsByNumber map[pref.FieldNumber]reflect.StructField oneofsByName map[pref.Name]reflect.StructField oneofWrappersByType map[reflect.Type]pref.FieldNumber oneofWrappersByNumber map[pref.FieldNumber]reflect.Type } func (mi *MessageInfo) makeStructInfo(t reflect.Type) structInfo { si := structInfo{ sizecacheOffset: invalidOffset, weakOffset: invalidOffset, unknownOffset: invalidOffset, extensionOffset: invalidOffset, fieldsByNumber: map[pref.FieldNumber]reflect.StructField{}, oneofsByName: map[pref.Name]reflect.StructField{}, oneofWrappersByType: map[reflect.Type]pref.FieldNumber{}, oneofWrappersByNumber: map[pref.FieldNumber]reflect.Type{}, } fieldLoop: for i := 0; i < t.NumField(); i++ { switch f := t.Field(i); f.Name { case genid.SizeCache_goname, genid.SizeCacheA_goname: if f.Type == sizecacheType { si.sizecacheOffset = offsetOf(f, mi.Exporter) si.sizecacheType = f.Type } case genid.WeakFields_goname, genid.WeakFieldsA_goname: if f.Type == weakFieldsType { si.weakOffset = offsetOf(f, mi.Exporter) si.weakType = f.Type } case genid.UnknownFields_goname, genid.UnknownFieldsA_goname: if f.Type == unknownFieldsAType || f.Type == unknownFieldsBType { si.unknownOffset = offsetOf(f, mi.Exporter) si.unknownType = f.Type } case genid.ExtensionFields_goname, genid.ExtensionFieldsA_goname, genid.ExtensionFieldsB_goname: if f.Type == extensionFieldsType { si.extensionOffset = offsetOf(f, mi.Exporter) si.extensionType = f.Type } default: for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { n, _ := strconv.ParseUint(s, 10, 64) si.fieldsByNumber[pref.FieldNumber(n)] = f continue fieldLoop } } if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 { si.oneofsByName[pref.Name(s)] = f continue fieldLoop } } } // Derive a mapping of oneof wrappers to fields. oneofWrappers := mi.OneofWrappers for _, method := range []string{"XXX_OneofFuncs", "XXX_OneofWrappers"} { if fn, ok := reflect.PtrTo(t).MethodByName(method); ok { for _, v := range fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))}) { if vs, ok := v.Interface().([]interface{}); ok { oneofWrappers = vs } } } } for _, v := range oneofWrappers { tf := reflect.TypeOf(v).Elem() f := tf.Field(0) for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") { if len(s) > 0 && strings.Trim(s, "0123456789") == "" { n, _ := strconv.ParseUint(s, 10, 64) si.oneofWrappersByType[tf] = pref.FieldNumber(n) si.oneofWrappersByNumber[pref.FieldNumber(n)] = tf break } } } return si } func (mi *MessageInfo) New() protoreflect.Message { return mi.MessageOf(reflect.New(mi.GoReflectType.Elem()).Interface()) } func (mi *MessageInfo) Zero() protoreflect.Message { return mi.MessageOf(reflect.Zero(mi.GoReflectType).Interface()) } func (mi *MessageInfo) Descriptor() protoreflect.MessageDescriptor { return mi.Desc } func (mi *MessageInfo) Enum(i int) protoreflect.EnumType { mi.init() fd := mi.Desc.Fields().Get(i) return Export{}.EnumTypeOf(mi.fieldTypes[fd.Number()]) } func (mi *MessageInfo) Message(i int) protoreflect.MessageType { mi.init() fd := mi.Desc.Fields().Get(i) switch { case fd.IsWeak(): mt, _ := preg.GlobalTypes.FindMessageByName(fd.Message().FullName()) return mt case fd.IsMap(): return mapEntryType{fd.Message(), mi.fieldTypes[fd.Number()]} default: return Export{}.MessageTypeOf(mi.fieldTypes[fd.Number()]) } } type mapEntryType struct { desc protoreflect.MessageDescriptor valType interface{} // zero value of enum or message type } func (mt mapEntryType) New() protoreflect.Message { return nil } func (mt mapEntryType) Zero() protoreflect.Message { return nil } func (mt mapEntryType) Descriptor() protoreflect.MessageDescriptor { return mt.desc } func (mt mapEntryType) Enum(i int) protoreflect.EnumType { fd := mt.desc.Fields().Get(i) if fd.Enum() == nil { return nil } return Export{}.EnumTypeOf(mt.valType) } func (mt mapEntryType) Message(i int) protoreflect.MessageType { fd := mt.desc.Fields().Get(i) if fd.Message() == nil { return nil } return Export{}.MessageTypeOf(mt.valType) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/message_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "reflect" "google.golang.org/protobuf/internal/detrand" "google.golang.org/protobuf/internal/pragma" pref "google.golang.org/protobuf/reflect/protoreflect" ) type reflectMessageInfo struct { fields map[pref.FieldNumber]*fieldInfo oneofs map[pref.Name]*oneofInfo // fieldTypes contains the zero value of an enum or message field. // For lists, it contains the element type. // For maps, it contains the entry value type. fieldTypes map[pref.FieldNumber]interface{} // denseFields is a subset of fields where: // 0 < fieldDesc.Number() < len(denseFields) // It provides faster access to the fieldInfo, but may be incomplete. denseFields []*fieldInfo // rangeInfos is a list of all fields (not belonging to a oneof) and oneofs. rangeInfos []interface{} // either *fieldInfo or *oneofInfo getUnknown func(pointer) pref.RawFields setUnknown func(pointer, pref.RawFields) extensionMap func(pointer) *extensionMap nilMessage atomicNilMessage } // makeReflectFuncs generates the set of functions to support reflection. func (mi *MessageInfo) makeReflectFuncs(t reflect.Type, si structInfo) { mi.makeKnownFieldsFunc(si) mi.makeUnknownFieldsFunc(t, si) mi.makeExtensionFieldsFunc(t, si) mi.makeFieldTypes(si) } // makeKnownFieldsFunc generates functions for operations that can be performed // on each protobuf message field. It takes in a reflect.Type representing the // Go struct and matches message fields with struct fields. // // This code assumes that the struct is well-formed and panics if there are // any discrepancies. func (mi *MessageInfo) makeKnownFieldsFunc(si structInfo) { mi.fields = map[pref.FieldNumber]*fieldInfo{} md := mi.Desc fds := md.Fields() for i := 0; i < fds.Len(); i++ { fd := fds.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } var fi fieldInfo switch { case fs.Type == nil: fi = fieldInfoForMissing(fd) // never occurs for officially generated message types case isOneof: fi = fieldInfoForOneof(fd, fs, mi.Exporter, si.oneofWrappersByNumber[fd.Number()]) case fd.IsMap(): fi = fieldInfoForMap(fd, fs, mi.Exporter) case fd.IsList(): fi = fieldInfoForList(fd, fs, mi.Exporter) case fd.IsWeak(): fi = fieldInfoForWeakMessage(fd, si.weakOffset) case fd.Message() != nil: fi = fieldInfoForMessage(fd, fs, mi.Exporter) default: fi = fieldInfoForScalar(fd, fs, mi.Exporter) } mi.fields[fd.Number()] = &fi } mi.oneofs = map[pref.Name]*oneofInfo{} for i := 0; i < md.Oneofs().Len(); i++ { od := md.Oneofs().Get(i) mi.oneofs[od.Name()] = makeOneofInfo(od, si, mi.Exporter) } mi.denseFields = make([]*fieldInfo, fds.Len()*2) for i := 0; i < fds.Len(); i++ { if fd := fds.Get(i); int(fd.Number()) < len(mi.denseFields) { mi.denseFields[fd.Number()] = mi.fields[fd.Number()] } } for i := 0; i < fds.Len(); { fd := fds.Get(i) if od := fd.ContainingOneof(); od != nil && !od.IsSynthetic() { mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()]) i += od.Fields().Len() } else { mi.rangeInfos = append(mi.rangeInfos, mi.fields[fd.Number()]) i++ } } // Introduce instability to iteration order, but keep it deterministic. if len(mi.rangeInfos) > 1 && detrand.Bool() { i := detrand.Intn(len(mi.rangeInfos) - 1) mi.rangeInfos[i], mi.rangeInfos[i+1] = mi.rangeInfos[i+1], mi.rangeInfos[i] } } func (mi *MessageInfo) makeUnknownFieldsFunc(t reflect.Type, si structInfo) { switch { case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsAType: // Handle as []byte. mi.getUnknown = func(p pointer) pref.RawFields { if p.IsNil() { return nil } return *p.Apply(mi.unknownOffset).Bytes() } mi.setUnknown = func(p pointer, b pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } *p.Apply(mi.unknownOffset).Bytes() = b } case si.unknownOffset.IsValid() && si.unknownType == unknownFieldsBType: // Handle as *[]byte. mi.getUnknown = func(p pointer) pref.RawFields { if p.IsNil() { return nil } bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { return nil } return **bp } mi.setUnknown = func(p pointer, b pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } bp := p.Apply(mi.unknownOffset).BytesPtr() if *bp == nil { *bp = new([]byte) } **bp = b } default: mi.getUnknown = func(pointer) pref.RawFields { return nil } mi.setUnknown = func(p pointer, _ pref.RawFields) { if p.IsNil() { panic("invalid SetUnknown on nil Message") } } } } func (mi *MessageInfo) makeExtensionFieldsFunc(t reflect.Type, si structInfo) { if si.extensionOffset.IsValid() { mi.extensionMap = func(p pointer) *extensionMap { if p.IsNil() { return (*extensionMap)(nil) } v := p.Apply(si.extensionOffset).AsValueOf(extensionFieldsType) return (*extensionMap)(v.Interface().(*map[int32]ExtensionField)) } } else { mi.extensionMap = func(pointer) *extensionMap { return (*extensionMap)(nil) } } } func (mi *MessageInfo) makeFieldTypes(si structInfo) { md := mi.Desc fds := md.Fields() for i := 0; i < fds.Len(); i++ { var ft reflect.Type fd := fds.Get(i) fs := si.fieldsByNumber[fd.Number()] isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() if isOneof { fs = si.oneofsByName[fd.ContainingOneof().Name()] } var isMessage bool switch { case fs.Type == nil: continue // never occurs for officially generated message types case isOneof: if fd.Enum() != nil || fd.Message() != nil { ft = si.oneofWrappersByNumber[fd.Number()].Field(0).Type } case fd.IsMap(): if fd.MapValue().Enum() != nil || fd.MapValue().Message() != nil { ft = fs.Type.Elem() } isMessage = fd.MapValue().Message() != nil case fd.IsList(): if fd.Enum() != nil || fd.Message() != nil { ft = fs.Type.Elem() } isMessage = fd.Message() != nil case fd.Enum() != nil: ft = fs.Type if fd.HasPresence() && ft.Kind() == reflect.Ptr { ft = ft.Elem() } case fd.Message() != nil: ft = fs.Type if fd.IsWeak() { ft = nil } isMessage = true } if isMessage && ft != nil && ft.Kind() != reflect.Ptr { ft = reflect.PtrTo(ft) // never occurs for officially generated message types } if ft != nil { if mi.fieldTypes == nil { mi.fieldTypes = make(map[pref.FieldNumber]interface{}) } mi.fieldTypes[fd.Number()] = reflect.Zero(ft).Interface() } } } type extensionMap map[int32]ExtensionField func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) { if m != nil { for _, x := range *m { xd := x.Type().TypeDescriptor() v := x.Value() if xd.IsList() && v.List().Len() == 0 { continue } if !f(xd, v) { return } } } } func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) { if m == nil { return false } xd := xt.TypeDescriptor() x, ok := (*m)[int32(xd.Number())] if !ok { return false } switch { case xd.IsList(): return x.Value().List().Len() > 0 case xd.IsMap(): return x.Value().Map().Len() > 0 case xd.Message() != nil: return x.Value().Message().IsValid() } return true } func (m *extensionMap) Clear(xt pref.ExtensionType) { delete(*m, int32(xt.TypeDescriptor().Number())) } func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value { xd := xt.TypeDescriptor() if m != nil { if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } } return xt.Zero() } func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) { xd := xt.TypeDescriptor() isValid := true switch { case !xt.IsValidValue(v): isValid = false case xd.IsList(): isValid = v.List().IsValid() case xd.IsMap(): isValid = v.Map().IsValid() case xd.Message() != nil: isValid = v.Message().IsValid() } if !isValid { panic(fmt.Sprintf("%v: assigning invalid value", xt.TypeDescriptor().FullName())) } if *m == nil { *m = make(map[int32]ExtensionField) } var x ExtensionField x.Set(xt, v) (*m)[int32(xd.Number())] = x } func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value { xd := xt.TypeDescriptor() if xd.Kind() != pref.MessageKind && xd.Kind() != pref.GroupKind && !xd.IsList() && !xd.IsMap() { panic("invalid Mutable on field with non-composite type") } if x, ok := (*m)[int32(xd.Number())]; ok { return x.Value() } v := xt.New() m.Set(xt, v) return v } // MessageState is a data structure that is nested as the first field in a // concrete message. It provides a way to implement the ProtoReflect method // in an allocation-free way without needing to have a shadow Go type generated // for every message type. This technique only works using unsafe. // // // Example generated code: // // type M struct { // state protoimpl.MessageState // // Field1 int32 // Field2 string // Field3 *BarMessage // ... // } // // func (m *M) ProtoReflect() protoreflect.Message { // mi := &file_fizz_buzz_proto_msgInfos[5] // if protoimpl.UnsafeEnabled && m != nil { // ms := protoimpl.X.MessageStateOf(Pointer(m)) // if ms.LoadMessageInfo() == nil { // ms.StoreMessageInfo(mi) // } // return ms // } // return mi.MessageOf(m) // } // // The MessageState type holds a *MessageInfo, which must be atomically set to // the message info associated with a given message instance. // By unsafely converting a *M into a *MessageState, the MessageState object // has access to all the information needed to implement protobuf reflection. // It has access to the message info as its first field, and a pointer to the // MessageState is identical to a pointer to the concrete message value. // // // Requirements: // • The type M must implement protoreflect.ProtoMessage. // • The address of m must not be nil. // • The address of m and the address of m.state must be equal, // even though they are different Go types. type MessageState struct { pragma.NoUnkeyedLiterals pragma.DoNotCompare pragma.DoNotCopy atomicMessageInfo *MessageInfo } type messageState MessageState var ( _ pref.Message = (*messageState)(nil) _ unwrapper = (*messageState)(nil) ) // messageDataType is a tuple of a pointer to the message data and // a pointer to the message type. It is a generalized way of providing a // reflective view over a message instance. The disadvantage of this approach // is the need to allocate this tuple of 16B. type messageDataType struct { p pointer mi *MessageInfo } type ( messageReflectWrapper messageDataType messageIfaceWrapper messageDataType ) var ( _ pref.Message = (*messageReflectWrapper)(nil) _ unwrapper = (*messageReflectWrapper)(nil) _ pref.ProtoMessage = (*messageIfaceWrapper)(nil) _ unwrapper = (*messageIfaceWrapper)(nil) ) // MessageOf returns a reflective view over a message. The input must be a // pointer to a named Go struct. If the provided type has a ProtoReflect method, // it must be implemented by calling this method. func (mi *MessageInfo) MessageOf(m interface{}) pref.Message { if reflect.TypeOf(m) != mi.GoReflectType { panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoReflectType)) } p := pointerOfIface(m) if p.IsNil() { return mi.nilMessage.Init(mi) } return &messageReflectWrapper{p, mi} } func (m *messageReflectWrapper) pointer() pointer { return m.p } func (m *messageReflectWrapper) messageInfo() *MessageInfo { return m.mi } // Reset implements the v1 proto.Message.Reset method. func (m *messageIfaceWrapper) Reset() { if mr, ok := m.protoUnwrap().(interface{ Reset() }); ok { mr.Reset() return } rv := reflect.ValueOf(m.protoUnwrap()) if rv.Kind() == reflect.Ptr && !rv.IsNil() { rv.Elem().Set(reflect.Zero(rv.Type().Elem())) } } func (m *messageIfaceWrapper) ProtoReflect() pref.Message { return (*messageReflectWrapper)(m) } func (m *messageIfaceWrapper) protoUnwrap() interface{} { return m.p.AsIfaceOf(m.mi.GoReflectType.Elem()) } // checkField verifies that the provided field descriptor is valid. // Exactly one of the returned values is populated. func (mi *MessageInfo) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.ExtensionType) { var fi *fieldInfo if n := fd.Number(); 0 < n && int(n) < len(mi.denseFields) { fi = mi.denseFields[n] } else { fi = mi.fields[n] } if fi != nil { if fi.fieldDesc != fd { if got, want := fd.FullName(), fi.fieldDesc.FullName(); got != want { panic(fmt.Sprintf("mismatching field: got %v, want %v", got, want)) } panic(fmt.Sprintf("mismatching field: %v", fd.FullName())) } return fi, nil } if fd.IsExtension() { if got, want := fd.ContainingMessage().FullName(), mi.Desc.FullName(); got != want { // TODO: Should this be exact containing message descriptor match? panic(fmt.Sprintf("extension %v has mismatching containing message: got %v, want %v", fd.FullName(), got, want)) } if !mi.Desc.ExtensionRanges().Has(fd.Number()) { panic(fmt.Sprintf("extension %v extends %v outside the extension range", fd.FullName(), mi.Desc.FullName())) } xtd, ok := fd.(pref.ExtensionTypeDescriptor) if !ok { panic(fmt.Sprintf("extension %v does not implement protoreflect.ExtensionTypeDescriptor", fd.FullName())) } return nil, xtd.Type() } panic(fmt.Sprintf("field %v is invalid", fd.FullName())) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "math" "reflect" "sync" "google.golang.org/protobuf/internal/flags" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" ) type fieldInfo struct { fieldDesc pref.FieldDescriptor // These fields are used for protobuf reflection support. has func(pointer) bool clear func(pointer) get func(pointer) pref.Value set func(pointer, pref.Value) mutable func(pointer) pref.Value newMessage func() pref.Message newField func() pref.Value } func fieldInfoForMissing(fd pref.FieldDescriptor) fieldInfo { // This never occurs for generated message types. // It implies that a hand-crafted type has missing Go fields // for specific protobuf message fields. return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { return false }, clear: func(p pointer) { panic("missing Go struct field for " + string(fd.FullName())) }, get: func(p pointer) pref.Value { return fd.Default() }, set: func(p pointer, v pref.Value) { panic("missing Go struct field for " + string(fd.FullName())) }, mutable: func(p pointer) pref.Value { panic("missing Go struct field for " + string(fd.FullName())) }, newMessage: func() pref.Message { panic("missing Go struct field for " + string(fd.FullName())) }, newField: func() pref.Value { if v := fd.Default(); v.IsValid() { return v } panic("missing Go struct field for " + string(fd.FullName())) }, } } func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Interface { panic(fmt.Sprintf("field %v has invalid type: got %v, want interface kind", fd.FullName(), ft)) } if ot.Kind() != reflect.Struct { panic(fmt.Sprintf("field %v has invalid type: got %v, want struct kind", fd.FullName(), ot)) } if !reflect.PtrTo(ot).Implements(ft) { panic(fmt.Sprintf("field %v has invalid type: %v does not implement %v", fd.FullName(), ot, ft)) } conv := NewConverter(ot.Field(0).Type, fd) isMessage := fd.Message() != nil // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ // NOTE: The logic below intentionally assumes that oneof fields are // well-formatted. That is, the oneof interface never contains a // typed nil pointer to one of the wrapper structs. fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { return false } return true }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot { // NOTE: We intentionally don't check for rv.Elem().IsNil() // so that (*OneofWrapperType)(nil) gets cleared to nil. return } rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { return conv.Zero() } rv = rv.Elem().Elem().Field(0) return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { rv.Set(reflect.New(ot)) } rv = rv.Elem().Elem().Field(0) rv.Set(conv.GoValueOf(v)) }, mutable: func(p pointer) pref.Value { if !isMessage { panic(fmt.Sprintf("field %v with invalid Mutable call on field with non-composite type", fd.FullName())) } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() { rv.Set(reflect.New(ot)) } rv = rv.Elem().Elem().Field(0) if rv.Kind() == reflect.Ptr && rv.IsNil() { rv.Set(conv.GoValueOf(pref.ValueOfMessage(conv.New().Message()))) } return conv.PBValueOf(rv) }, newMessage: func() pref.Message { return conv.New().Message() }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Map { panic(fmt.Sprintf("field %v has invalid type: got %v, want map kind", fd.FullName(), ft)) } conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return rv.Len() > 0 }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.Len() == 0 { return conv.Zero() } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() pv := conv.GoValueOf(v) if pv.IsNil() { panic(fmt.Sprintf("map field %v cannot be set with read-only value", fd.FullName())) } rv.Set(pv) }, mutable: func(p pointer) pref.Value { v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if v.IsNil() { v.Set(reflect.MakeMap(fs.Type)) } return conv.PBValueOf(v) }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type if ft.Kind() != reflect.Slice { panic(fmt.Sprintf("field %v has invalid type: got %v, want slice kind", fd.FullName(), ft)) } conv := NewConverter(reflect.PtrTo(ft), fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return rv.Len() > 0 }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type) if rv.Elem().Len() == 0 { return conv.Zero() } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() pv := conv.GoValueOf(v) if pv.IsNil() { panic(fmt.Sprintf("list field %v cannot be set with read-only value", fd.FullName())) } rv.Set(pv.Elem()) }, mutable: func(p pointer) pref.Value { v := p.Apply(fieldOffset).AsValueOf(fs.Type) return conv.PBValueOf(v) }, newField: func() pref.Value { return conv.New() }, } } var ( nilBytes = reflect.ValueOf([]byte(nil)) emptyBytes = reflect.ValueOf([]byte{}) ) func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type nullable := fd.HasPresence() isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 if nullable { if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice { // This never occurs for generated message types. // Despite the protobuf type system specifying presence, // the Go field type cannot represent it. nullable = false } if ft.Kind() == reflect.Ptr { ft = ft.Elem() } } conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable { return !rv.IsNil() } switch rv.Kind() { case reflect.Bool: return rv.Bool() case reflect.Int32, reflect.Int64: return rv.Int() != 0 case reflect.Uint32, reflect.Uint64: return rv.Uint() != 0 case reflect.Float32, reflect.Float64: return rv.Float() != 0 || math.Signbit(rv.Float()) case reflect.String, reflect.Slice: return rv.Len() > 0 default: panic(fmt.Sprintf("field %v has invalid type: %v", fd.FullName(), rv.Type())) // should never happen } }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable { if rv.IsNil() { return conv.Zero() } if rv.Kind() == reflect.Ptr { rv = rv.Elem() } } return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if nullable && rv.Kind() == reflect.Ptr { if rv.IsNil() { rv.Set(reflect.New(ft)) } rv = rv.Elem() } rv.Set(conv.GoValueOf(v)) if isBytes && rv.Len() == 0 { if nullable { rv.Set(emptyBytes) // preserve presence } else { rv.Set(nilBytes) // do not preserve presence } } }, newField: func() pref.Value { return conv.New() }, } } func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldInfo { if !flags.ProtoLegacy { panic("no support for proto1 weak fields") } var once sync.Once var messageType pref.MessageType lazyInit := func() { once.Do(func() { messageName := fd.Message().FullName() messageType, _ = preg.GlobalTypes.FindMessageByName(messageName) if messageType == nil { panic(fmt.Sprintf("weak message %v for field %v is not linked in", messageName, fd.FullName())) } }) } num := fd.Number() return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } _, ok := p.Apply(weakOffset).WeakFields().get(num) return ok }, clear: func(p pointer) { p.Apply(weakOffset).WeakFields().clear(num) }, get: func(p pointer) pref.Value { lazyInit() if p.IsNil() { return pref.ValueOfMessage(messageType.Zero()) } m, ok := p.Apply(weakOffset).WeakFields().get(num) if !ok { return pref.ValueOfMessage(messageType.Zero()) } return pref.ValueOfMessage(m.ProtoReflect()) }, set: func(p pointer, v pref.Value) { lazyInit() m := v.Message() if m.Descriptor() != messageType.Descriptor() { if got, want := m.Descriptor().FullName(), messageType.Descriptor().FullName(); got != want { panic(fmt.Sprintf("field %v has mismatching message descriptor: got %v, want %v", fd.FullName(), got, want)) } panic(fmt.Sprintf("field %v has mismatching message descriptor: %v", fd.FullName(), m.Descriptor().FullName())) } p.Apply(weakOffset).WeakFields().set(num, m.Interface()) }, mutable: func(p pointer) pref.Value { lazyInit() fs := p.Apply(weakOffset).WeakFields() m, ok := fs.get(num) if !ok { m = messageType.New().Interface() fs.set(num, m) } return pref.ValueOfMessage(m.ProtoReflect()) }, newMessage: func() pref.Message { lazyInit() return messageType.New() }, newField: func() pref.Value { lazyInit() return pref.ValueOfMessage(messageType.New()) }, } } func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo { ft := fs.Type conv := NewConverter(ft, fd) // TODO: Implement unsafe fast path? fieldOffset := offsetOf(fs, x) return fieldInfo{ fieldDesc: fd, has: func(p pointer) bool { if p.IsNil() { return false } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() != reflect.Ptr { return !isZero(rv) } return !rv.IsNil() }, clear: func(p pointer) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(reflect.Zero(rv.Type())) }, get: func(p pointer) pref.Value { if p.IsNil() { return conv.Zero() } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() return conv.PBValueOf(rv) }, set: func(p pointer, v pref.Value) { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() rv.Set(conv.GoValueOf(v)) if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { panic(fmt.Sprintf("field %v has invalid nil pointer", fd.FullName())) } }, mutable: func(p pointer) pref.Value { rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if fs.Type.Kind() == reflect.Ptr && rv.IsNil() { rv.Set(conv.GoValueOf(conv.New())) } return conv.PBValueOf(rv) }, newMessage: func() pref.Message { return conv.New().Message() }, newField: func() pref.Value { return conv.New() }, } } type oneofInfo struct { oneofDesc pref.OneofDescriptor which func(pointer) pref.FieldNumber } func makeOneofInfo(od pref.OneofDescriptor, si structInfo, x exporter) *oneofInfo { oi := &oneofInfo{oneofDesc: od} if od.IsSynthetic() { fs := si.fieldsByNumber[od.Fields().Get(0).Number()] fieldOffset := offsetOf(fs, x) oi.which = func(p pointer) pref.FieldNumber { if p.IsNil() { return 0 } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() { // valid on either *T or []byte return 0 } return od.Fields().Get(0).Number() } } else { fs := si.oneofsByName[od.Name()] fieldOffset := offsetOf(fs, x) oi.which = func(p pointer) pref.FieldNumber { if p.IsNil() { return 0 } rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem() if rv.IsNil() { return 0 } rv = rv.Elem() if rv.IsNil() { return 0 } return si.oneofWrappersByType[rv.Type().Elem()] } } return oi } // isZero is identical to reflect.Value.IsZero. // TODO: Remove this when Go1.13 is the minimally supported Go version. func isZero(v reflect.Value) bool { switch v.Kind() { case reflect.Bool: return !v.Bool() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return v.Int() == 0 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: return v.Uint() == 0 case reflect.Float32, reflect.Float64: return math.Float64bits(v.Float()) == 0 case reflect.Complex64, reflect.Complex128: c := v.Complex() return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 case reflect.Array: for i := 0; i < v.Len(); i++ { if !isZero(v.Index(i)) { return false } } return true case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: return v.IsNil() case reflect.String: return v.Len() == 0 case reflect.Struct: for i := 0; i < v.NumField(); i++ { if !isZero(v.Field(i)) { return false } } return true default: panic(&reflect.ValueError{"reflect.Value.IsZero", v.Kind()}) } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package impl import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) func (m *messageState) Descriptor() protoreflect.MessageDescriptor { return m.messageInfo().Desc } func (m *messageState) Type() protoreflect.MessageType { return m.messageInfo() } func (m *messageState) New() protoreflect.Message { return m.messageInfo().New() } func (m *messageState) Interface() protoreflect.ProtoMessage { return m.protoUnwrap().(protoreflect.ProtoMessage) } func (m *messageState) protoUnwrap() interface{} { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageState) ProtoMethods() *protoiface.Methods { m.messageInfo().init() return &m.messageInfo().methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code // to be able to retrieve a v2 MessageInfo struct. // // WARNING: This method is exempt from the compatibility promise and // may be removed in the future without warning. func (m *messageState) ProtoMessageInfo() *MessageInfo { return m.messageInfo() } func (m *messageState) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { m.messageInfo().init() for _, ri := range m.messageInfo().rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { if !f(ri.fieldDesc, ri.get(m.pointer())) { return } } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { fi := m.messageInfo().fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } m.messageInfo().extensionMap(m.pointer()).Range(f) } func (m *messageState) Has(fd protoreflect.FieldDescriptor) bool { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.has(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Has(xt) } } func (m *messageState) Clear(fd protoreflect.FieldDescriptor) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.clear(m.pointer()) } else { m.messageInfo().extensionMap(m.pointer()).Clear(xt) } } func (m *messageState) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.get(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Get(xt) } } func (m *messageState) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { m.messageInfo().extensionMap(m.pointer()).Set(xt, v) } } func (m *messageState) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) } } func (m *messageState) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.newField() } else { return xt.New() } } func (m *messageState) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { m.messageInfo().init() if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageState) GetUnknown() protoreflect.RawFields { m.messageInfo().init() return m.messageInfo().getUnknown(m.pointer()) } func (m *messageState) SetUnknown(b protoreflect.RawFields) { m.messageInfo().init() m.messageInfo().setUnknown(m.pointer(), b) } func (m *messageState) IsValid() bool { return !m.pointer().IsNil() } func (m *messageReflectWrapper) Descriptor() protoreflect.MessageDescriptor { return m.messageInfo().Desc } func (m *messageReflectWrapper) Type() protoreflect.MessageType { return m.messageInfo() } func (m *messageReflectWrapper) New() protoreflect.Message { return m.messageInfo().New() } func (m *messageReflectWrapper) Interface() protoreflect.ProtoMessage { if m, ok := m.protoUnwrap().(protoreflect.ProtoMessage); ok { return m } return (*messageIfaceWrapper)(m) } func (m *messageReflectWrapper) protoUnwrap() interface{} { return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) } func (m *messageReflectWrapper) ProtoMethods() *protoiface.Methods { m.messageInfo().init() return &m.messageInfo().methods } // ProtoMessageInfo is a pseudo-internal API for allowing the v1 code // to be able to retrieve a v2 MessageInfo struct. // // WARNING: This method is exempt from the compatibility promise and // may be removed in the future without warning. func (m *messageReflectWrapper) ProtoMessageInfo() *MessageInfo { return m.messageInfo() } func (m *messageReflectWrapper) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { m.messageInfo().init() for _, ri := range m.messageInfo().rangeInfos { switch ri := ri.(type) { case *fieldInfo: if ri.has(m.pointer()) { if !f(ri.fieldDesc, ri.get(m.pointer())) { return } } case *oneofInfo: if n := ri.which(m.pointer()); n > 0 { fi := m.messageInfo().fields[n] if !f(fi.fieldDesc, fi.get(m.pointer())) { return } } } } m.messageInfo().extensionMap(m.pointer()).Range(f) } func (m *messageReflectWrapper) Has(fd protoreflect.FieldDescriptor) bool { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.has(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Has(xt) } } func (m *messageReflectWrapper) Clear(fd protoreflect.FieldDescriptor) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.clear(m.pointer()) } else { m.messageInfo().extensionMap(m.pointer()).Clear(xt) } } func (m *messageReflectWrapper) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.get(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Get(xt) } } func (m *messageReflectWrapper) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { fi.set(m.pointer(), v) } else { m.messageInfo().extensionMap(m.pointer()).Set(xt, v) } } func (m *messageReflectWrapper) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.mutable(m.pointer()) } else { return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) } } func (m *messageReflectWrapper) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { m.messageInfo().init() if fi, xt := m.messageInfo().checkField(fd); fi != nil { return fi.newField() } else { return xt.New() } } func (m *messageReflectWrapper) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { m.messageInfo().init() if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { return od.Fields().ByNumber(oi.which(m.pointer())) } panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) } func (m *messageReflectWrapper) GetUnknown() protoreflect.RawFields { m.messageInfo().init() return m.messageInfo().getUnknown(m.pointer()) } func (m *messageReflectWrapper) SetUnknown(b protoreflect.RawFields) { m.messageInfo().init() m.messageInfo().setUnknown(m.pointer(), b) } func (m *messageReflectWrapper) IsValid() bool { return !m.pointer().IsNil() } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package impl import ( "fmt" "reflect" "sync" ) const UnsafeEnabled = false // Pointer is an opaque pointer type. type Pointer interface{} // offset represents the offset to a struct field, accessible from a pointer. // The offset is the field index into a struct. type offset struct { index int export exporter } // offsetOf returns a field offset for the struct field. func offsetOf(f reflect.StructField, x exporter) offset { if len(f.Index) != 1 { panic("embedded structs are not supported") } if f.PkgPath == "" { return offset{index: f.Index[0]} // field is already exported } if x == nil { panic("exporter must be provided for unexported field") } return offset{index: f.Index[0], export: x} } // IsValid reports whether the offset is valid. func (f offset) IsValid() bool { return f.index >= 0 } // invalidOffset is an invalid field offset. var invalidOffset = offset{index: -1} // zeroOffset is a noop when calling pointer.Apply. var zeroOffset = offset{index: 0} // pointer is an abstract representation of a pointer to a struct or field. type pointer struct{ v reflect.Value } // pointerOf returns p as a pointer. func pointerOf(p Pointer) pointer { return pointerOfIface(p) } // pointerOfValue returns v as a pointer. func pointerOfValue(v reflect.Value) pointer { return pointer{v: v} } // pointerOfIface returns the pointer portion of an interface. func pointerOfIface(v interface{}) pointer { return pointer{v: reflect.ValueOf(v)} } // IsNil reports whether the pointer is nil. func (p pointer) IsNil() bool { return p.v.IsNil() } // Apply adds an offset to the pointer to derive a new pointer // to a specified field. The current pointer must be pointing at a struct. func (p pointer) Apply(f offset) pointer { if f.export != nil { if v := reflect.ValueOf(f.export(p.v.Interface(), f.index)); v.IsValid() { return pointer{v: v} } } return pointer{v: p.v.Elem().Field(f.index).Addr()} } // AsValueOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) func (p pointer) AsValueOf(t reflect.Type) reflect.Value { if got := p.v.Type().Elem(); got != t { panic(fmt.Sprintf("invalid type: got %v, want %v", got, t)) } return p.v } // AsIfaceOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to p.AsValueOf(t).Interface() func (p pointer) AsIfaceOf(t reflect.Type) interface{} { return p.AsValueOf(t).Interface() } func (p pointer) Bool() *bool { return p.v.Interface().(*bool) } func (p pointer) BoolPtr() **bool { return p.v.Interface().(**bool) } func (p pointer) BoolSlice() *[]bool { return p.v.Interface().(*[]bool) } func (p pointer) Int32() *int32 { return p.v.Interface().(*int32) } func (p pointer) Int32Ptr() **int32 { return p.v.Interface().(**int32) } func (p pointer) Int32Slice() *[]int32 { return p.v.Interface().(*[]int32) } func (p pointer) Int64() *int64 { return p.v.Interface().(*int64) } func (p pointer) Int64Ptr() **int64 { return p.v.Interface().(**int64) } func (p pointer) Int64Slice() *[]int64 { return p.v.Interface().(*[]int64) } func (p pointer) Uint32() *uint32 { return p.v.Interface().(*uint32) } func (p pointer) Uint32Ptr() **uint32 { return p.v.Interface().(**uint32) } func (p pointer) Uint32Slice() *[]uint32 { return p.v.Interface().(*[]uint32) } func (p pointer) Uint64() *uint64 { return p.v.Interface().(*uint64) } func (p pointer) Uint64Ptr() **uint64 { return p.v.Interface().(**uint64) } func (p pointer) Uint64Slice() *[]uint64 { return p.v.Interface().(*[]uint64) } func (p pointer) Float32() *float32 { return p.v.Interface().(*float32) } func (p pointer) Float32Ptr() **float32 { return p.v.Interface().(**float32) } func (p pointer) Float32Slice() *[]float32 { return p.v.Interface().(*[]float32) } func (p pointer) Float64() *float64 { return p.v.Interface().(*float64) } func (p pointer) Float64Ptr() **float64 { return p.v.Interface().(**float64) } func (p pointer) Float64Slice() *[]float64 { return p.v.Interface().(*[]float64) } func (p pointer) String() *string { return p.v.Interface().(*string) } func (p pointer) StringPtr() **string { return p.v.Interface().(**string) } func (p pointer) StringSlice() *[]string { return p.v.Interface().(*[]string) } func (p pointer) Bytes() *[]byte { return p.v.Interface().(*[]byte) } func (p pointer) BytesPtr() **[]byte { return p.v.Interface().(**[]byte) } func (p pointer) BytesSlice() *[][]byte { return p.v.Interface().(*[][]byte) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.v.Interface().(*WeakFields)) } func (p pointer) Extensions() *map[int32]ExtensionField { return p.v.Interface().(*map[int32]ExtensionField) } func (p pointer) Elem() pointer { return pointer{v: p.v.Elem()} } // PointerSlice copies []*T from p as a new []pointer. // This behavior differs from the implementation in pointer_unsafe.go. func (p pointer) PointerSlice() []pointer { // TODO: reconsider this if p.v.IsNil() { return nil } n := p.v.Elem().Len() s := make([]pointer, n) for i := 0; i < n; i++ { s[i] = pointer{v: p.v.Elem().Index(i)} } return s } // AppendPointerSlice appends v to p, which must be a []*T. func (p pointer) AppendPointerSlice(v pointer) { sp := p.v.Elem() sp.Set(reflect.Append(sp, v.v)) } // SetPointer sets *p to v. func (p pointer) SetPointer(v pointer) { p.v.Elem().Set(v.v) } func (Export) MessageStateOf(p Pointer) *messageState { panic("not supported") } func (ms *messageState) pointer() pointer { panic("not supported") } func (ms *messageState) messageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) LoadMessageInfo() *MessageInfo { panic("not supported") } func (ms *messageState) StoreMessageInfo(mi *MessageInfo) { panic("not supported") } type atomicNilMessage struct { once sync.Once m messageReflectWrapper } func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { m.once.Do(func() { m.m.p = pointerOfIface(reflect.Zero(mi.GoReflectType).Interface()) m.m.mi = mi }) return &m.m } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package impl import ( "reflect" "sync/atomic" "unsafe" ) const UnsafeEnabled = true // Pointer is an opaque pointer type. type Pointer unsafe.Pointer // offset represents the offset to a struct field, accessible from a pointer. // The offset is the byte offset to the field from the start of the struct. type offset uintptr // offsetOf returns a field offset for the struct field. func offsetOf(f reflect.StructField, x exporter) offset { return offset(f.Offset) } // IsValid reports whether the offset is valid. func (f offset) IsValid() bool { return f != invalidOffset } // invalidOffset is an invalid field offset. var invalidOffset = ^offset(0) // zeroOffset is a noop when calling pointer.Apply. var zeroOffset = offset(0) // pointer is a pointer to a message struct or field. type pointer struct{ p unsafe.Pointer } // pointerOf returns p as a pointer. func pointerOf(p Pointer) pointer { return pointer{p: unsafe.Pointer(p)} } // pointerOfValue returns v as a pointer. func pointerOfValue(v reflect.Value) pointer { return pointer{p: unsafe.Pointer(v.Pointer())} } // pointerOfIface returns the pointer portion of an interface. func pointerOfIface(v interface{}) pointer { type ifaceHeader struct { Type unsafe.Pointer Data unsafe.Pointer } return pointer{p: (*ifaceHeader)(unsafe.Pointer(&v)).Data} } // IsNil reports whether the pointer is nil. func (p pointer) IsNil() bool { return p.p == nil } // Apply adds an offset to the pointer to derive a new pointer // to a specified field. The pointer must be valid and pointing at a struct. func (p pointer) Apply(f offset) pointer { if p.IsNil() { panic("invalid nil pointer") } return pointer{p: unsafe.Pointer(uintptr(p.p) + uintptr(f))} } // AsValueOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to reflect.ValueOf(p.AsIfaceOf(t)) func (p pointer) AsValueOf(t reflect.Type) reflect.Value { return reflect.NewAt(t, p.p) } // AsIfaceOf treats p as a pointer to an object of type t and returns the value. // It is equivalent to p.AsValueOf(t).Interface() func (p pointer) AsIfaceOf(t reflect.Type) interface{} { // TODO: Use tricky unsafe magic to directly create ifaceHeader. return p.AsValueOf(t).Interface() } func (p pointer) Bool() *bool { return (*bool)(p.p) } func (p pointer) BoolPtr() **bool { return (**bool)(p.p) } func (p pointer) BoolSlice() *[]bool { return (*[]bool)(p.p) } func (p pointer) Int32() *int32 { return (*int32)(p.p) } func (p pointer) Int32Ptr() **int32 { return (**int32)(p.p) } func (p pointer) Int32Slice() *[]int32 { return (*[]int32)(p.p) } func (p pointer) Int64() *int64 { return (*int64)(p.p) } func (p pointer) Int64Ptr() **int64 { return (**int64)(p.p) } func (p pointer) Int64Slice() *[]int64 { return (*[]int64)(p.p) } func (p pointer) Uint32() *uint32 { return (*uint32)(p.p) } func (p pointer) Uint32Ptr() **uint32 { return (**uint32)(p.p) } func (p pointer) Uint32Slice() *[]uint32 { return (*[]uint32)(p.p) } func (p pointer) Uint64() *uint64 { return (*uint64)(p.p) } func (p pointer) Uint64Ptr() **uint64 { return (**uint64)(p.p) } func (p pointer) Uint64Slice() *[]uint64 { return (*[]uint64)(p.p) } func (p pointer) Float32() *float32 { return (*float32)(p.p) } func (p pointer) Float32Ptr() **float32 { return (**float32)(p.p) } func (p pointer) Float32Slice() *[]float32 { return (*[]float32)(p.p) } func (p pointer) Float64() *float64 { return (*float64)(p.p) } func (p pointer) Float64Ptr() **float64 { return (**float64)(p.p) } func (p pointer) Float64Slice() *[]float64 { return (*[]float64)(p.p) } func (p pointer) String() *string { return (*string)(p.p) } func (p pointer) StringPtr() **string { return (**string)(p.p) } func (p pointer) StringSlice() *[]string { return (*[]string)(p.p) } func (p pointer) Bytes() *[]byte { return (*[]byte)(p.p) } func (p pointer) BytesPtr() **[]byte { return (**[]byte)(p.p) } func (p pointer) BytesSlice() *[][]byte { return (*[][]byte)(p.p) } func (p pointer) WeakFields() *weakFields { return (*weakFields)(p.p) } func (p pointer) Extensions() *map[int32]ExtensionField { return (*map[int32]ExtensionField)(p.p) } func (p pointer) Elem() pointer { return pointer{p: *(*unsafe.Pointer)(p.p)} } // PointerSlice loads []*T from p as a []pointer. // The value returned is aliased with the original slice. // This behavior differs from the implementation in pointer_reflect.go. func (p pointer) PointerSlice() []pointer { // Super-tricky - p should point to a []*T where T is a // message type. We load it as []pointer. return *(*[]pointer)(p.p) } // AppendPointerSlice appends v to p, which must be a []*T. func (p pointer) AppendPointerSlice(v pointer) { *(*[]pointer)(p.p) = append(*(*[]pointer)(p.p), v) } // SetPointer sets *p to v. func (p pointer) SetPointer(v pointer) { *(*unsafe.Pointer)(p.p) = (unsafe.Pointer)(v.p) } // Static check that MessageState does not exceed the size of a pointer. const _ = uint(unsafe.Sizeof(unsafe.Pointer(nil)) - unsafe.Sizeof(MessageState{})) func (Export) MessageStateOf(p Pointer) *messageState { // Super-tricky - see documentation on MessageState. return (*messageState)(unsafe.Pointer(p)) } func (ms *messageState) pointer() pointer { // Super-tricky - see documentation on MessageState. return pointer{p: unsafe.Pointer(ms)} } func (ms *messageState) messageInfo() *MessageInfo { mi := ms.LoadMessageInfo() if mi == nil { panic("invalid nil message info; this suggests memory corruption due to a race or shallow copy on the message struct") } return mi } func (ms *messageState) LoadMessageInfo() *MessageInfo { return (*MessageInfo)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)))) } func (ms *messageState) StoreMessageInfo(mi *MessageInfo) { atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&ms.atomicMessageInfo)), unsafe.Pointer(mi)) } type atomicNilMessage struct{ p unsafe.Pointer } // p is a *messageReflectWrapper func (m *atomicNilMessage) Init(mi *MessageInfo) *messageReflectWrapper { if p := atomic.LoadPointer(&m.p); p != nil { return (*messageReflectWrapper)(p) } w := &messageReflectWrapper{mi: mi} atomic.CompareAndSwapPointer(&m.p, nil, (unsafe.Pointer)(w)) return (*messageReflectWrapper)(atomic.LoadPointer(&m.p)) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/validate.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" "math" "math/bits" "reflect" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/strs" pref "google.golang.org/protobuf/reflect/protoreflect" preg "google.golang.org/protobuf/reflect/protoregistry" piface "google.golang.org/protobuf/runtime/protoiface" ) // ValidationStatus is the result of validating the wire-format encoding of a message. type ValidationStatus int const ( // ValidationUnknown indicates that unmarshaling the message might succeed or fail. // The validator was unable to render a judgement. // // The only causes of this status are an aberrant message type appearing somewhere // in the message or a failure in the extension resolver. ValidationUnknown ValidationStatus = iota + 1 // ValidationInvalid indicates that unmarshaling the message will fail. ValidationInvalid // ValidationValid indicates that unmarshaling the message will succeed. ValidationValid ) func (v ValidationStatus) String() string { switch v { case ValidationUnknown: return "ValidationUnknown" case ValidationInvalid: return "ValidationInvalid" case ValidationValid: return "ValidationValid" default: return fmt.Sprintf("ValidationStatus(%d)", int(v)) } } // Validate determines whether the contents of the buffer are a valid wire encoding // of the message type. // // This function is exposed for testing. func Validate(mt pref.MessageType, in piface.UnmarshalInput) (out piface.UnmarshalOutput, _ ValidationStatus) { mi, ok := mt.(*MessageInfo) if !ok { return out, ValidationUnknown } if in.Resolver == nil { in.Resolver = preg.GlobalTypes } o, st := mi.validate(in.Buf, 0, unmarshalOptions{ flags: in.Flags, resolver: in.Resolver, }) if o.initialized { out.Flags |= piface.UnmarshalInitialized } return out, st } type validationInfo struct { mi *MessageInfo typ validationType keyType, valType validationType // For non-required fields, requiredBit is 0. // // For required fields, requiredBit's nth bit is set, where n is a // unique index in the range [0, MessageInfo.numRequiredFields). // // If there are more than 64 required fields, requiredBit is 0. requiredBit uint64 } type validationType uint8 const ( validationTypeOther validationType = iota validationTypeMessage validationTypeGroup validationTypeMap validationTypeRepeatedVarint validationTypeRepeatedFixed32 validationTypeRepeatedFixed64 validationTypeVarint validationTypeFixed32 validationTypeFixed64 validationTypeBytes validationTypeUTF8String validationTypeMessageSetItem ) func newFieldValidationInfo(mi *MessageInfo, si structInfo, fd pref.FieldDescriptor, ft reflect.Type) validationInfo { var vi validationInfo switch { case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic(): switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok { vi.mi = getMessageInfo(ot.Field(0).Type) } case pref.GroupKind: vi.typ = validationTypeGroup if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok { vi.mi = getMessageInfo(ot.Field(0).Type) } case pref.StringKind: if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } } default: vi = newValidationInfo(fd, ft) } if fd.Cardinality() == pref.Required { // Avoid overflow. The required field check is done with a 64-bit mask, with // any message containing more than 64 required fields always reported as // potentially uninitialized, so it is not important to get a precise count // of the required fields past 64. if mi.numRequiredFields < math.MaxUint8 { mi.numRequiredFields++ vi.requiredBit = 1 << (mi.numRequiredFields - 1) } } return vi } func newValidationInfo(fd pref.FieldDescriptor, ft reflect.Type) validationInfo { var vi validationInfo switch { case fd.IsList(): switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if ft.Kind() == reflect.Slice { vi.mi = getMessageInfo(ft.Elem()) } case pref.GroupKind: vi.typ = validationTypeGroup if ft.Kind() == reflect.Slice { vi.mi = getMessageInfo(ft.Elem()) } case pref.StringKind: vi.typ = validationTypeBytes if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } default: switch wireTypes[fd.Kind()] { case protowire.VarintType: vi.typ = validationTypeRepeatedVarint case protowire.Fixed32Type: vi.typ = validationTypeRepeatedFixed32 case protowire.Fixed64Type: vi.typ = validationTypeRepeatedFixed64 } } case fd.IsMap(): vi.typ = validationTypeMap switch fd.MapKey().Kind() { case pref.StringKind: if strs.EnforceUTF8(fd) { vi.keyType = validationTypeUTF8String } } switch fd.MapValue().Kind() { case pref.MessageKind: vi.valType = validationTypeMessage if ft.Kind() == reflect.Map { vi.mi = getMessageInfo(ft.Elem()) } case pref.StringKind: if strs.EnforceUTF8(fd) { vi.valType = validationTypeUTF8String } } default: switch fd.Kind() { case pref.MessageKind: vi.typ = validationTypeMessage if !fd.IsWeak() { vi.mi = getMessageInfo(ft) } case pref.GroupKind: vi.typ = validationTypeGroup vi.mi = getMessageInfo(ft) case pref.StringKind: vi.typ = validationTypeBytes if strs.EnforceUTF8(fd) { vi.typ = validationTypeUTF8String } default: switch wireTypes[fd.Kind()] { case protowire.VarintType: vi.typ = validationTypeVarint case protowire.Fixed32Type: vi.typ = validationTypeFixed32 case protowire.Fixed64Type: vi.typ = validationTypeFixed64 case protowire.BytesType: vi.typ = validationTypeBytes } } } return vi } func (mi *MessageInfo) validate(b []byte, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, result ValidationStatus) { mi.init() type validationState struct { typ validationType keyType, valType validationType endGroup protowire.Number mi *MessageInfo tail []byte requiredMask uint64 } // Pre-allocate some slots to avoid repeated slice reallocation. states := make([]validationState, 0, 16) states = append(states, validationState{ typ: validationTypeMessage, mi: mi, }) if groupTag > 0 { states[0].typ = validationTypeGroup states[0].endGroup = groupTag } initialized := true start := len(b) State: for len(states) > 0 { st := &states[len(states)-1] for len(b) > 0 { // Parse the tag (field number and wire type). var tag uint64 if b[0] < 0x80 { tag = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { tag = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int tag, n = protowire.ConsumeVarint(b) if n < 0 { return out, ValidationInvalid } b = b[n:] } var num protowire.Number if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) { return out, ValidationInvalid } else { num = protowire.Number(n) } wtyp := protowire.Type(tag & 7) if wtyp == protowire.EndGroupType { if st.endGroup == num { goto PopState } return out, ValidationInvalid } var vi validationInfo switch { case st.typ == validationTypeMap: switch num { case genid.MapEntry_Key_field_number: vi.typ = st.keyType case genid.MapEntry_Value_field_number: vi.typ = st.valType vi.mi = st.mi vi.requiredBit = 1 } case flags.ProtoLegacy && st.mi.isMessageSet: switch num { case messageset.FieldItem: vi.typ = validationTypeMessageSetItem } default: var f *coderFieldInfo if int(num) < len(st.mi.denseCoderFields) { f = st.mi.denseCoderFields[num] } else { f = st.mi.coderFields[num] } if f != nil { vi = f.validation if vi.typ == validationTypeMessage && vi.mi == nil { // Probable weak field. // // TODO: Consider storing the results of this lookup somewhere // rather than recomputing it on every validation. fd := st.mi.Desc.Fields().ByNumber(num) if fd == nil || !fd.IsWeak() { break } messageName := fd.Message().FullName() messageType, err := preg.GlobalTypes.FindMessageByName(messageName) switch err { case nil: vi.mi, _ = messageType.(*MessageInfo) case preg.NotFound: vi.typ = validationTypeBytes default: return out, ValidationUnknown } } break } // Possible extension field. // // TODO: We should return ValidationUnknown when: // 1. The resolver is not frozen. (More extensions may be added to it.) // 2. The resolver returns preg.NotFound. // In this case, a type added to the resolver in the future could cause // unmarshaling to begin failing. Supporting this requires some way to // determine if the resolver is frozen. xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), num) if err != nil && err != preg.NotFound { return out, ValidationUnknown } if err == nil { vi = getExtensionFieldInfo(xt).validation } } if vi.requiredBit != 0 { // Check that the field has a compatible wire type. // We only need to consider non-repeated field types, // since repeated fields (and maps) can never be required. ok := false switch vi.typ { case validationTypeVarint: ok = wtyp == protowire.VarintType case validationTypeFixed32: ok = wtyp == protowire.Fixed32Type case validationTypeFixed64: ok = wtyp == protowire.Fixed64Type case validationTypeBytes, validationTypeUTF8String, validationTypeMessage: ok = wtyp == protowire.BytesType case validationTypeGroup: ok = wtyp == protowire.StartGroupType } if ok { st.requiredMask |= vi.requiredBit } } switch wtyp { case protowire.VarintType: if len(b) >= 10 { switch { case b[0] < 0x80: b = b[1:] case b[1] < 0x80: b = b[2:] case b[2] < 0x80: b = b[3:] case b[3] < 0x80: b = b[4:] case b[4] < 0x80: b = b[5:] case b[5] < 0x80: b = b[6:] case b[6] < 0x80: b = b[7:] case b[7] < 0x80: b = b[8:] case b[8] < 0x80: b = b[9:] case b[9] < 0x80 && b[9] < 2: b = b[10:] default: return out, ValidationInvalid } } else { switch { case len(b) > 0 && b[0] < 0x80: b = b[1:] case len(b) > 1 && b[1] < 0x80: b = b[2:] case len(b) > 2 && b[2] < 0x80: b = b[3:] case len(b) > 3 && b[3] < 0x80: b = b[4:] case len(b) > 4 && b[4] < 0x80: b = b[5:] case len(b) > 5 && b[5] < 0x80: b = b[6:] case len(b) > 6 && b[6] < 0x80: b = b[7:] case len(b) > 7 && b[7] < 0x80: b = b[8:] case len(b) > 8 && b[8] < 0x80: b = b[9:] case len(b) > 9 && b[9] < 2: b = b[10:] default: return out, ValidationInvalid } } continue State case protowire.BytesType: var size uint64 if len(b) >= 1 && b[0] < 0x80 { size = uint64(b[0]) b = b[1:] } else if len(b) >= 2 && b[1] < 128 { size = uint64(b[0]&0x7f) + uint64(b[1])<<7 b = b[2:] } else { var n int size, n = protowire.ConsumeVarint(b) if n < 0 { return out, ValidationInvalid } b = b[n:] } if size > uint64(len(b)) { return out, ValidationInvalid } v := b[:size] b = b[size:] switch vi.typ { case validationTypeMessage: if vi.mi == nil { return out, ValidationUnknown } vi.mi.init() fallthrough case validationTypeMap: if vi.mi != nil { vi.mi.init() } states = append(states, validationState{ typ: vi.typ, keyType: vi.keyType, valType: vi.valType, mi: vi.mi, tail: b, }) b = v continue State case validationTypeRepeatedVarint: // Packed field. for len(v) > 0 { _, n := protowire.ConsumeVarint(v) if n < 0 { return out, ValidationInvalid } v = v[n:] } case validationTypeRepeatedFixed32: // Packed field. if len(v)%4 != 0 { return out, ValidationInvalid } case validationTypeRepeatedFixed64: // Packed field. if len(v)%8 != 0 { return out, ValidationInvalid } case validationTypeUTF8String: if !utf8.Valid(v) { return out, ValidationInvalid } } case protowire.Fixed32Type: if len(b) < 4 { return out, ValidationInvalid } b = b[4:] case protowire.Fixed64Type: if len(b) < 8 { return out, ValidationInvalid } b = b[8:] case protowire.StartGroupType: switch { case vi.typ == validationTypeGroup: if vi.mi == nil { return out, ValidationUnknown } vi.mi.init() states = append(states, validationState{ typ: validationTypeGroup, mi: vi.mi, endGroup: num, }) continue State case flags.ProtoLegacy && vi.typ == validationTypeMessageSetItem: typeid, v, n, err := messageset.ConsumeFieldValue(b, false) if err != nil { return out, ValidationInvalid } xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), typeid) switch { case err == preg.NotFound: b = b[n:] case err != nil: return out, ValidationUnknown default: xvi := getExtensionFieldInfo(xt).validation if xvi.mi != nil { xvi.mi.init() } states = append(states, validationState{ typ: xvi.typ, mi: xvi.mi, tail: b[n:], }) b = v continue State } default: n := protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return out, ValidationInvalid } b = b[n:] } default: return out, ValidationInvalid } } if st.endGroup != 0 { return out, ValidationInvalid } if len(b) != 0 { return out, ValidationInvalid } b = st.tail PopState: numRequiredFields := 0 switch st.typ { case validationTypeMessage, validationTypeGroup: numRequiredFields = int(st.mi.numRequiredFields) case validationTypeMap: // If this is a map field with a message value that contains // required fields, require that the value be present. if st.mi != nil && st.mi.numRequiredFields > 0 { numRequiredFields = 1 } } // If there are more than 64 required fields, this check will // always fail and we will report that the message is potentially // uninitialized. if numRequiredFields > 0 && bits.OnesCount64(st.requiredMask) != numRequiredFields { initialized = false } states = states[:len(states)-1] } out.n = start - len(b) if initialized { out.initialized = true } return out, ValidationValid } ================================================ FILE: vendor/google.golang.org/protobuf/internal/impl/weak.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package impl import ( "fmt" pref "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) // weakFields adds methods to the exported WeakFields type for internal use. // // The exported type is an alias to an unnamed type, so methods can't be // defined directly on it. type weakFields WeakFields func (w weakFields) get(num pref.FieldNumber) (pref.ProtoMessage, bool) { m, ok := w[int32(num)] return m, ok } func (w *weakFields) set(num pref.FieldNumber, m pref.ProtoMessage) { if *w == nil { *w = make(weakFields) } (*w)[int32(num)] = m } func (w *weakFields) clear(num pref.FieldNumber) { delete(*w, int32(num)) } func (Export) HasWeak(w WeakFields, num pref.FieldNumber) bool { _, ok := w[int32(num)] return ok } func (Export) ClearWeak(w *WeakFields, num pref.FieldNumber) { delete(*w, int32(num)) } func (Export) GetWeak(w WeakFields, num pref.FieldNumber, name pref.FullName) pref.ProtoMessage { if m, ok := w[int32(num)]; ok { return m } mt, _ := protoregistry.GlobalTypes.FindMessageByName(name) if mt == nil { panic(fmt.Sprintf("message %v for weak field is not linked in", name)) } return mt.Zero().Interface() } func (Export) SetWeak(w *WeakFields, num pref.FieldNumber, name pref.FullName, m pref.ProtoMessage) { if m != nil { mt, _ := protoregistry.GlobalTypes.FindMessageByName(name) if mt == nil { panic(fmt.Sprintf("message %v for weak field is not linked in", name)) } if mt != m.ProtoReflect().Type() { panic(fmt.Sprintf("invalid message type for weak field: got %T, want %T", m, mt.Zero().Interface())) } } if m == nil || !m.ProtoReflect().IsValid() { delete(*w, int32(num)) return } if *w == nil { *w = make(weakFields) } (*w)[int32(num)] = m } ================================================ FILE: vendor/google.golang.org/protobuf/internal/order/order.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package order import ( pref "google.golang.org/protobuf/reflect/protoreflect" ) // FieldOrder specifies the ordering to visit message fields. // It is a function that reports whether x is ordered before y. type FieldOrder func(x, y pref.FieldDescriptor) bool var ( // AnyFieldOrder specifies no specific field ordering. AnyFieldOrder FieldOrder = nil // LegacyFieldOrder sorts fields in the same ordering as emitted by // wire serialization in the github.com/golang/protobuf implementation. LegacyFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { ox, oy := x.ContainingOneof(), y.ContainingOneof() inOneof := func(od pref.OneofDescriptor) bool { return od != nil && !od.IsSynthetic() } // Extension fields sort before non-extension fields. if x.IsExtension() != y.IsExtension() { return x.IsExtension() && !y.IsExtension() } // Fields not within a oneof sort before those within a oneof. if inOneof(ox) != inOneof(oy) { return !inOneof(ox) && inOneof(oy) } // Fields in disjoint oneof sets are sorted by declaration index. if ox != nil && oy != nil && ox != oy { return ox.Index() < oy.Index() } // Fields sorted by field number. return x.Number() < y.Number() } // NumberFieldOrder sorts fields by their field number. NumberFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { return x.Number() < y.Number() } // IndexNameFieldOrder sorts non-extension fields before extension fields. // Non-extensions are sorted according to their declaration index. // Extensions are sorted according to their full name. IndexNameFieldOrder FieldOrder = func(x, y pref.FieldDescriptor) bool { // Non-extension fields sort before extension fields. if x.IsExtension() != y.IsExtension() { return !x.IsExtension() && y.IsExtension() } // Extensions sorted by fullname. if x.IsExtension() && y.IsExtension() { return x.FullName() < y.FullName() } // Non-extensions sorted by declaration index. return x.Index() < y.Index() } ) // KeyOrder specifies the ordering to visit map entries. // It is a function that reports whether x is ordered before y. type KeyOrder func(x, y pref.MapKey) bool var ( // AnyKeyOrder specifies no specific key ordering. AnyKeyOrder KeyOrder = nil // GenericKeyOrder sorts false before true, numeric keys in ascending order, // and strings in lexicographical ordering according to UTF-8 codepoints. GenericKeyOrder KeyOrder = func(x, y pref.MapKey) bool { switch x.Interface().(type) { case bool: return !x.Bool() && y.Bool() case int32, int64: return x.Int() < y.Int() case uint32, uint64: return x.Uint() < y.Uint() case string: return x.String() < y.String() default: panic("invalid map key type") } } ) ================================================ FILE: vendor/google.golang.org/protobuf/internal/order/range.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package order provides ordered access to messages and maps. package order import ( "sort" "sync" pref "google.golang.org/protobuf/reflect/protoreflect" ) type messageField struct { fd pref.FieldDescriptor v pref.Value } var messageFieldPool = sync.Pool{ New: func() interface{} { return new([]messageField) }, } type ( // FieldRnger is an interface for visiting all fields in a message. // The protoreflect.Message type implements this interface. FieldRanger interface{ Range(VisitField) } // VisitField is called everytime a message field is visited. VisitField = func(pref.FieldDescriptor, pref.Value) bool ) // RangeFields iterates over the fields of fs according to the specified order. func RangeFields(fs FieldRanger, less FieldOrder, fn VisitField) { if less == nil { fs.Range(fn) return } // Obtain a pre-allocated scratch buffer. p := messageFieldPool.Get().(*[]messageField) fields := (*p)[:0] defer func() { if cap(fields) < 1024 { *p = fields messageFieldPool.Put(p) } }() // Collect all fields in the message and sort them. fs.Range(func(fd pref.FieldDescriptor, v pref.Value) bool { fields = append(fields, messageField{fd, v}) return true }) sort.Slice(fields, func(i, j int) bool { return less(fields[i].fd, fields[j].fd) }) // Visit the fields in the specified ordering. for _, f := range fields { if !fn(f.fd, f.v) { return } } } type mapEntry struct { k pref.MapKey v pref.Value } var mapEntryPool = sync.Pool{ New: func() interface{} { return new([]mapEntry) }, } type ( // EntryRanger is an interface for visiting all fields in a message. // The protoreflect.Map type implements this interface. EntryRanger interface{ Range(VisitEntry) } // VisitEntry is called everytime a map entry is visited. VisitEntry = func(pref.MapKey, pref.Value) bool ) // RangeEntries iterates over the entries of es according to the specified order. func RangeEntries(es EntryRanger, less KeyOrder, fn VisitEntry) { if less == nil { es.Range(fn) return } // Obtain a pre-allocated scratch buffer. p := mapEntryPool.Get().(*[]mapEntry) entries := (*p)[:0] defer func() { if cap(entries) < 1024 { *p = entries mapEntryPool.Put(p) } }() // Collect all entries in the map and sort them. es.Range(func(k pref.MapKey, v pref.Value) bool { entries = append(entries, mapEntry{k, v}) return true }) sort.Slice(entries, func(i, j int) bool { return less(entries[i].k, entries[j].k) }) // Visit the entries in the specified ordering. for _, e := range entries { if !fn(e.k, e.v) { return } } } ================================================ FILE: vendor/google.golang.org/protobuf/internal/pragma/pragma.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package pragma provides types that can be embedded into a struct to // statically enforce or prevent certain language properties. package pragma import "sync" // NoUnkeyedLiterals can be embedded in a struct to prevent unkeyed literals. type NoUnkeyedLiterals struct{} // DoNotImplement can be embedded in an interface to prevent trivial // implementations of the interface. // // This is useful to prevent unauthorized implementations of an interface // so that it can be extended in the future for any protobuf language changes. type DoNotImplement interface{ ProtoInternal(DoNotImplement) } // DoNotCompare can be embedded in a struct to prevent comparability. type DoNotCompare [0]func() // DoNotCopy can be embedded in a struct to help prevent shallow copies. // This does not rely on a Go language feature, but rather a special case // within the vet checker. // // See https://golang.org/issues/8005. type DoNotCopy [0]sync.Mutex ================================================ FILE: vendor/google.golang.org/protobuf/internal/set/ints.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package set provides simple set data structures for uint64s. package set import "math/bits" // int64s represents a set of integers within the range of 0..63. type int64s uint64 func (bs *int64s) Len() int { return bits.OnesCount64(uint64(*bs)) } func (bs *int64s) Has(n uint64) bool { return uint64(*bs)&(uint64(1)< 0 } func (bs *int64s) Set(n uint64) { *(*uint64)(bs) |= uint64(1) << n } func (bs *int64s) Clear(n uint64) { *(*uint64)(bs) &^= uint64(1) << n } // Ints represents a set of integers within the range of 0..math.MaxUint64. type Ints struct { lo int64s hi map[uint64]struct{} } func (bs *Ints) Len() int { return bs.lo.Len() + len(bs.hi) } func (bs *Ints) Has(n uint64) bool { if n < 64 { return bs.lo.Has(n) } _, ok := bs.hi[n] return ok } func (bs *Ints) Set(n uint64) { if n < 64 { bs.lo.Set(n) return } if bs.hi == nil { bs.hi = make(map[uint64]struct{}) } bs.hi[n] = struct{}{} } func (bs *Ints) Clear(n uint64) { if n < 64 { bs.lo.Clear(n) return } delete(bs.hi, n) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/strs/strings.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package strs provides string manipulation functionality specific to protobuf. package strs import ( "go/token" "strings" "unicode" "unicode/utf8" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/reflect/protoreflect" ) // EnforceUTF8 reports whether to enforce strict UTF-8 validation. func EnforceUTF8(fd protoreflect.FieldDescriptor) bool { if flags.ProtoLegacy { if fd, ok := fd.(interface{ EnforceUTF8() bool }); ok { return fd.EnforceUTF8() } } return fd.Syntax() == protoreflect.Proto3 } // GoCamelCase camel-cases a protobuf name for use as a Go identifier. // // If there is an interior underscore followed by a lower case letter, // drop the underscore and convert the letter to upper case. func GoCamelCase(s string) string { // Invariant: if the next letter is lower case, it must be converted // to upper case. // That is, we process a word at a time, where words are marked by _ or // upper case letter. Digits are treated as words. var b []byte for i := 0; i < len(s); i++ { c := s[i] switch { case c == '.' && i+1 < len(s) && isASCIILower(s[i+1]): // Skip over '.' in ".{{lowercase}}". case c == '.': b = append(b, '_') // convert '.' to '_' case c == '_' && (i == 0 || s[i-1] == '.'): // Convert initial '_' to ensure we start with a capital letter. // Do the same for '_' after '.' to match historic behavior. b = append(b, 'X') // convert '_' to 'X' case c == '_' && i+1 < len(s) && isASCIILower(s[i+1]): // Skip over '_' in "_{{lowercase}}". case isASCIIDigit(c): b = append(b, c) default: // Assume we have a letter now - if not, it's a bogus identifier. // The next word is a sequence of characters that must start upper case. if isASCIILower(c) { c -= 'a' - 'A' // convert lowercase to uppercase } b = append(b, c) // Accept lower case sequence that follows. for ; i+1 < len(s) && isASCIILower(s[i+1]); i++ { b = append(b, s[i+1]) } } } return string(b) } // GoSanitized converts a string to a valid Go identifier. func GoSanitized(s string) string { // Sanitize the input to the set of valid characters, // which must be '_' or be in the Unicode L or N categories. s = strings.Map(func(r rune) rune { if unicode.IsLetter(r) || unicode.IsDigit(r) { return r } return '_' }, s) // Prepend '_' in the event of a Go keyword conflict or if // the identifier is invalid (does not start in the Unicode L category). r, _ := utf8.DecodeRuneInString(s) if token.Lookup(s).IsKeyword() || !unicode.IsLetter(r) { return "_" + s } return s } // JSONCamelCase converts a snake_case identifier to a camelCase identifier, // according to the protobuf JSON specification. func JSONCamelCase(s string) string { var b []byte var wasUnderscore bool for i := 0; i < len(s); i++ { // proto identifiers are always ASCII c := s[i] if c != '_' { if wasUnderscore && isASCIILower(c) { c -= 'a' - 'A' // convert to uppercase } b = append(b, c) } wasUnderscore = c == '_' } return string(b) } // JSONSnakeCase converts a camelCase identifier to a snake_case identifier, // according to the protobuf JSON specification. func JSONSnakeCase(s string) string { var b []byte for i := 0; i < len(s); i++ { // proto identifiers are always ASCII c := s[i] if isASCIIUpper(c) { b = append(b, '_') c += 'a' - 'A' // convert to lowercase } b = append(b, c) } return string(b) } // MapEntryName derives the name of the map entry message given the field name. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:254-276,6057 func MapEntryName(s string) string { var b []byte upperNext := true for _, c := range s { switch { case c == '_': upperNext = true case upperNext: b = append(b, byte(unicode.ToUpper(c))) upperNext = false default: b = append(b, byte(c)) } } b = append(b, "Entry"...) return string(b) } // EnumValueName derives the camel-cased enum value name. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:297-313 func EnumValueName(s string) string { var b []byte upperNext := true for _, c := range s { switch { case c == '_': upperNext = true case upperNext: b = append(b, byte(unicode.ToUpper(c))) upperNext = false default: b = append(b, byte(unicode.ToLower(c))) upperNext = false } } return string(b) } // TrimEnumPrefix trims the enum name prefix from an enum value name, // where the prefix is all lowercase without underscores. // See protoc v3.8.0: src/google/protobuf/descriptor.cc:330-375 func TrimEnumPrefix(s, prefix string) string { s0 := s // original input for len(s) > 0 && len(prefix) > 0 { if s[0] == '_' { s = s[1:] continue } if unicode.ToLower(rune(s[0])) != rune(prefix[0]) { return s0 // no prefix match } s, prefix = s[1:], prefix[1:] } if len(prefix) > 0 { return s0 // no prefix match } s = strings.TrimLeft(s, "_") if len(s) == 0 { return s0 // avoid returning empty string } return s } func isASCIILower(c byte) bool { return 'a' <= c && c <= 'z' } func isASCIIUpper(c byte) bool { return 'A' <= c && c <= 'Z' } func isASCIIDigit(c byte) bool { return '0' <= c && c <= '9' } ================================================ FILE: vendor/google.golang.org/protobuf/internal/strs/strings_pure.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package strs import pref "google.golang.org/protobuf/reflect/protoreflect" func UnsafeString(b []byte) string { return string(b) } func UnsafeBytes(s string) []byte { return []byte(s) } type Builder struct{} func (*Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName { return prefix.Append(name) } func (*Builder) MakeString(b []byte) string { return string(b) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package strs import ( "unsafe" pref "google.golang.org/protobuf/reflect/protoreflect" ) type ( stringHeader struct { Data unsafe.Pointer Len int } sliceHeader struct { Data unsafe.Pointer Len int Cap int } ) // UnsafeString returns an unsafe string reference of b. // The caller must treat the input slice as immutable. // // WARNING: Use carefully. The returned result must not leak to the end user // unless the input slice is provably immutable. func UnsafeString(b []byte) (s string) { src := (*sliceHeader)(unsafe.Pointer(&b)) dst := (*stringHeader)(unsafe.Pointer(&s)) dst.Data = src.Data dst.Len = src.Len return s } // UnsafeBytes returns an unsafe bytes slice reference of s. // The caller must treat returned slice as immutable. // // WARNING: Use carefully. The returned result must not leak to the end user. func UnsafeBytes(s string) (b []byte) { src := (*stringHeader)(unsafe.Pointer(&s)) dst := (*sliceHeader)(unsafe.Pointer(&b)) dst.Data = src.Data dst.Len = src.Len dst.Cap = src.Len return b } // Builder builds a set of strings with shared lifetime. // This differs from strings.Builder, which is for building a single string. type Builder struct { buf []byte } // AppendFullName is equivalent to protoreflect.FullName.Append, // but optimized for large batches where each name has a shared lifetime. func (sb *Builder) AppendFullName(prefix pref.FullName, name pref.Name) pref.FullName { n := len(prefix) + len(".") + len(name) if len(prefix) == 0 { n -= len(".") } sb.grow(n) sb.buf = append(sb.buf, prefix...) sb.buf = append(sb.buf, '.') sb.buf = append(sb.buf, name...) return pref.FullName(sb.last(n)) } // MakeString is equivalent to string(b), but optimized for large batches // with a shared lifetime. func (sb *Builder) MakeString(b []byte) string { sb.grow(len(b)) sb.buf = append(sb.buf, b...) return sb.last(len(b)) } func (sb *Builder) grow(n int) { if cap(sb.buf)-len(sb.buf) >= n { return } // Unlike strings.Builder, we do not need to copy over the contents // of the old buffer since our builder provides no API for // retrieving previously created strings. sb.buf = make([]byte, 2*(cap(sb.buf)+n)) } func (sb *Builder) last(n int) string { return UnsafeString(sb.buf[len(sb.buf)-n:]) } ================================================ FILE: vendor/google.golang.org/protobuf/internal/version/version.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package version records versioning information about this module. package version import ( "fmt" "strings" ) // These constants determine the current version of this module. // // // For our release process, we enforce the following rules: // * Tagged releases use a tag that is identical to String. // * Tagged releases never reference a commit where the String // contains "devel". // * The set of all commits in this repository where String // does not contain "devel" must have a unique String. // // // Steps for tagging a new release: // 1. Create a new CL. // // 2. Update Minor, Patch, and/or PreRelease as necessary. // PreRelease must not contain the string "devel". // // 3. Since the last released minor version, have there been any changes to // generator that relies on new functionality in the runtime? // If yes, then increment RequiredGenerated. // // 4. Since the last released minor version, have there been any changes to // the runtime that removes support for old .pb.go source code? // If yes, then increment SupportMinimum. // // 5. Send out the CL for review and submit it. // Note that the next CL in step 8 must be submitted after this CL // without any other CLs in-between. // // 6. Tag a new version, where the tag is is the current String. // // 7. Write release notes for all notable changes // between this release and the last release. // // 8. Create a new CL. // // 9. Update PreRelease to include the string "devel". // For example: "" -> "devel" or "rc.1" -> "rc.1.devel" // // 10. Send out the CL for review and submit it. const ( Major = 1 Minor = 26 Patch = 0 PreRelease = "" ) // String formats the version string for this module in semver format. // // Examples: // v1.20.1 // v1.21.0-rc.1 func String() string { v := fmt.Sprintf("v%d.%d.%d", Major, Minor, Patch) if PreRelease != "" { v += "-" + PreRelease // TODO: Add metadata about the commit or build hash. // See https://golang.org/issue/29814 // See https://golang.org/issue/33533 var metadata string if strings.Contains(PreRelease, "devel") && metadata != "" { v += "+" + metadata } } return v } ================================================ FILE: vendor/google.golang.org/protobuf/proto/checkinit.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // CheckInitialized returns an error if any required fields in m are not set. func CheckInitialized(m Message) error { // Treat a nil message interface as an "untyped" empty message, // which we assume to have no required fields. if m == nil { return nil } return checkInitialized(m.ProtoReflect()) } // CheckInitialized returns an error if any required fields in m are not set. func checkInitialized(m protoreflect.Message) error { if methods := protoMethods(m); methods != nil && methods.CheckInitialized != nil { _, err := methods.CheckInitialized(protoiface.CheckInitializedInput{ Message: m, }) return err } return checkInitializedSlow(m) } func checkInitializedSlow(m protoreflect.Message) error { md := m.Descriptor() fds := md.Fields() for i, nums := 0, md.RequiredNumbers(); i < nums.Len(); i++ { fd := fds.ByNumber(nums.Get(i)) if !m.Has(fd) { return errors.RequiredNotSet(string(fd.FullName())) } } var err error m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { switch { case fd.IsList(): if fd.Message() == nil { return true } for i, list := 0, v.List(); i < list.Len() && err == nil; i++ { err = checkInitialized(list.Get(i).Message()) } case fd.IsMap(): if fd.MapValue().Message() == nil { return true } v.Map().Range(func(key protoreflect.MapKey, v protoreflect.Value) bool { err = checkInitialized(v.Message()) return err == nil }) default: if fd.Message() == nil { return true } err = checkInitialized(v.Message()) } return err == nil }) return err } ================================================ FILE: vendor/google.golang.org/protobuf/proto/decode.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/genid" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" "google.golang.org/protobuf/runtime/protoiface" ) // UnmarshalOptions configures the unmarshaler. // // Example usage: // err := UnmarshalOptions{DiscardUnknown: true}.Unmarshal(b, m) type UnmarshalOptions struct { pragma.NoUnkeyedLiterals // Merge merges the input into the destination message. // The default behavior is to always reset the message before unmarshaling, // unless Merge is specified. Merge bool // AllowPartial accepts input for messages that will result in missing // required fields. If AllowPartial is false (the default), Unmarshal will // return an error if there are any missing required fields. AllowPartial bool // If DiscardUnknown is set, unknown fields are ignored. DiscardUnknown bool // Resolver is used for looking up types when unmarshaling extension fields. // If nil, this defaults to using protoregistry.GlobalTypes. Resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } // Unmarshal parses the wire-format message in b and places the result in m. // The provided message must be mutable (e.g., a non-nil pointer to a message). func Unmarshal(b []byte, m Message) error { _, err := UnmarshalOptions{}.unmarshal(b, m.ProtoReflect()) return err } // Unmarshal parses the wire-format message in b and places the result in m. // The provided message must be mutable (e.g., a non-nil pointer to a message). func (o UnmarshalOptions) Unmarshal(b []byte, m Message) error { _, err := o.unmarshal(b, m.ProtoReflect()) return err } // UnmarshalState parses a wire-format message and places the result in m. // // This method permits fine-grained control over the unmarshaler. // Most users should use Unmarshal instead. func (o UnmarshalOptions) UnmarshalState(in protoiface.UnmarshalInput) (protoiface.UnmarshalOutput, error) { return o.unmarshal(in.Buf, in.Message) } // unmarshal is a centralized function that all unmarshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for unmarshal that do not go through this. func (o UnmarshalOptions) unmarshal(b []byte, m protoreflect.Message) (out protoiface.UnmarshalOutput, err error) { if o.Resolver == nil { o.Resolver = protoregistry.GlobalTypes } if !o.Merge { Reset(m.Interface()) } allowPartial := o.AllowPartial o.Merge = true o.AllowPartial = true methods := protoMethods(m) if methods != nil && methods.Unmarshal != nil && !(o.DiscardUnknown && methods.Flags&protoiface.SupportUnmarshalDiscardUnknown == 0) { in := protoiface.UnmarshalInput{ Message: m, Buf: b, Resolver: o.Resolver, } if o.DiscardUnknown { in.Flags |= protoiface.UnmarshalDiscardUnknown } out, err = methods.Unmarshal(in) } else { err = o.unmarshalMessageSlow(b, m) } if err != nil { return out, err } if allowPartial || (out.Flags&protoiface.UnmarshalInitialized != 0) { return out, nil } return out, checkInitialized(m) } func (o UnmarshalOptions) unmarshalMessage(b []byte, m protoreflect.Message) error { _, err := o.unmarshal(b, m) return err } func (o UnmarshalOptions) unmarshalMessageSlow(b []byte, m protoreflect.Message) error { md := m.Descriptor() if messageset.IsMessageSet(md) { return o.unmarshalMessageSet(b, m) } fields := md.Fields() for len(b) > 0 { // Parse the tag (field number and wire type). num, wtyp, tagLen := protowire.ConsumeTag(b) if tagLen < 0 { return errDecode } if num > protowire.MaxValidNumber { return errDecode } // Find the field descriptor for this field number. fd := fields.ByNumber(num) if fd == nil && md.ExtensionRanges().Has(num) { extType, err := o.Resolver.FindExtensionByNumber(md.FullName(), num) if err != nil && err != protoregistry.NotFound { return errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err) } if extType != nil { fd = extType.TypeDescriptor() } } var err error if fd == nil { err = errUnknown } else if flags.ProtoLegacy { if fd.IsWeak() && fd.Message().IsPlaceholder() { err = errUnknown // weak referent is not linked in } } // Parse the field value. var valLen int switch { case err != nil: case fd.IsList(): valLen, err = o.unmarshalList(b[tagLen:], wtyp, m.Mutable(fd).List(), fd) case fd.IsMap(): valLen, err = o.unmarshalMap(b[tagLen:], wtyp, m.Mutable(fd).Map(), fd) default: valLen, err = o.unmarshalSingular(b[tagLen:], wtyp, m, fd) } if err != nil { if err != errUnknown { return err } valLen = protowire.ConsumeFieldValue(num, wtyp, b[tagLen:]) if valLen < 0 { return errDecode } if !o.DiscardUnknown { m.SetUnknown(append(m.GetUnknown(), b[:tagLen+valLen]...)) } } b = b[tagLen+valLen:] } return nil } func (o UnmarshalOptions) unmarshalSingular(b []byte, wtyp protowire.Type, m protoreflect.Message, fd protoreflect.FieldDescriptor) (n int, err error) { v, n, err := o.unmarshalScalar(b, wtyp, fd) if err != nil { return 0, err } switch fd.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: m2 := m.Mutable(fd).Message() if err := o.unmarshalMessage(v.Bytes(), m2); err != nil { return n, err } default: // Non-message scalars replace the previous value. m.Set(fd, v) } return n, nil } func (o UnmarshalOptions) unmarshalMap(b []byte, wtyp protowire.Type, mapv protoreflect.Map, fd protoreflect.FieldDescriptor) (n int, err error) { if wtyp != protowire.BytesType { return 0, errUnknown } b, n = protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } var ( keyField = fd.MapKey() valField = fd.MapValue() key protoreflect.Value val protoreflect.Value haveKey bool haveVal bool ) switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: val = mapv.NewValue() } // Map entries are represented as a two-element message with fields // containing the key and value. for len(b) > 0 { num, wtyp, n := protowire.ConsumeTag(b) if n < 0 { return 0, errDecode } if num > protowire.MaxValidNumber { return 0, errDecode } b = b[n:] err = errUnknown switch num { case genid.MapEntry_Key_field_number: key, n, err = o.unmarshalScalar(b, wtyp, keyField) if err != nil { break } haveKey = true case genid.MapEntry_Value_field_number: var v protoreflect.Value v, n, err = o.unmarshalScalar(b, wtyp, valField) if err != nil { break } switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: if err := o.unmarshalMessage(v.Bytes(), val.Message()); err != nil { return 0, err } default: val = v } haveVal = true } if err == errUnknown { n = protowire.ConsumeFieldValue(num, wtyp, b) if n < 0 { return 0, errDecode } } else if err != nil { return 0, err } b = b[n:] } // Every map entry should have entries for key and value, but this is not strictly required. if !haveKey { key = keyField.Default() } if !haveVal { switch valField.Kind() { case protoreflect.GroupKind, protoreflect.MessageKind: default: val = valField.Default() } } mapv.Set(key.MapKey(), val) return n, nil } // errUnknown is used internally to indicate fields which should be added // to the unknown field set of a message. It is never returned from an exported // function. var errUnknown = errors.New("BUG: internal error (unknown)") var errDecode = errors.New("cannot parse invalid wire-format data") ================================================ FILE: vendor/google.golang.org/protobuf/proto/decode_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" ) // unmarshalScalar decodes a value of the given kind. // // Message values are decoded into a []byte which aliases the input data. func (o UnmarshalOptions) unmarshalScalar(b []byte, wtyp protowire.Type, fd protoreflect.FieldDescriptor) (val protoreflect.Value, n int, err error) { switch fd.Kind() { case protoreflect.BoolKind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBool(protowire.DecodeBool(v)), n, nil case protoreflect.EnumKind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfEnum(protoreflect.EnumNumber(v)), n, nil case protoreflect.Int32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(v)), n, nil case protoreflect.Sint32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32))), n, nil case protoreflect.Uint32Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint32(uint32(v)), n, nil case protoreflect.Int64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(int64(v)), n, nil case protoreflect.Sint64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(protowire.DecodeZigZag(v)), n, nil case protoreflect.Uint64Kind: if wtyp != protowire.VarintType { return val, 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint64(v), n, nil case protoreflect.Sfixed32Kind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt32(int32(v)), n, nil case protoreflect.Fixed32Kind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint32(uint32(v)), n, nil case protoreflect.FloatKind: if wtyp != protowire.Fixed32Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v))), n, nil case protoreflect.Sfixed64Kind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfInt64(int64(v)), n, nil case protoreflect.Fixed64Kind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfUint64(v), n, nil case protoreflect.DoubleKind: if wtyp != protowire.Fixed64Type { return val, 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfFloat64(math.Float64frombits(v)), n, nil case protoreflect.StringKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } if strs.EnforceUTF8(fd) && !utf8.Valid(v) { return protoreflect.Value{}, 0, errors.InvalidUTF8(string(fd.FullName())) } return protoreflect.ValueOfString(string(v)), n, nil case protoreflect.BytesKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(append(emptyBuf[:], v...)), n, nil case protoreflect.MessageKind: if wtyp != protowire.BytesType { return val, 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(v), n, nil case protoreflect.GroupKind: if wtyp != protowire.StartGroupType { return val, 0, errUnknown } v, n := protowire.ConsumeGroup(fd.Number(), b) if n < 0 { return val, 0, errDecode } return protoreflect.ValueOfBytes(v), n, nil default: return val, 0, errUnknown } } func (o UnmarshalOptions) unmarshalList(b []byte, wtyp protowire.Type, list protoreflect.List, fd protoreflect.FieldDescriptor) (n int, err error) { switch fd.Kind() { case protoreflect.BoolKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfBool(protowire.DecodeBool(v))) return n, nil case protoreflect.EnumKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfEnum(protoreflect.EnumNumber(v))) return n, nil case protoreflect.Int32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) return n, nil case protoreflect.Sint32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(protowire.DecodeZigZag(v & math.MaxUint32)))) return n, nil case protoreflect.Uint32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint32(uint32(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) return n, nil case protoreflect.Int64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(int64(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) return n, nil case protoreflect.Sint64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(protowire.DecodeZigZag(v))) return n, nil case protoreflect.Uint64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeVarint(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint64(v)) } return n, nil } if wtyp != protowire.VarintType { return 0, errUnknown } v, n := protowire.ConsumeVarint(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint64(v)) return n, nil case protoreflect.Sfixed32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt32(int32(v))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt32(int32(v))) return n, nil case protoreflect.Fixed32Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint32(uint32(v))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint32(uint32(v))) return n, nil case protoreflect.FloatKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed32(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) } return n, nil } if wtyp != protowire.Fixed32Type { return 0, errUnknown } v, n := protowire.ConsumeFixed32(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfFloat32(math.Float32frombits(uint32(v)))) return n, nil case protoreflect.Sfixed64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfInt64(int64(v))) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfInt64(int64(v))) return n, nil case protoreflect.Fixed64Kind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfUint64(v)) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfUint64(v)) return n, nil case protoreflect.DoubleKind: if wtyp == protowire.BytesType { buf, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } for len(buf) > 0 { v, n := protowire.ConsumeFixed64(buf) if n < 0 { return 0, errDecode } buf = buf[n:] list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) } return n, nil } if wtyp != protowire.Fixed64Type { return 0, errUnknown } v, n := protowire.ConsumeFixed64(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfFloat64(math.Float64frombits(v))) return n, nil case protoreflect.StringKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } if strs.EnforceUTF8(fd) && !utf8.Valid(v) { return 0, errors.InvalidUTF8(string(fd.FullName())) } list.Append(protoreflect.ValueOfString(string(v))) return n, nil case protoreflect.BytesKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } list.Append(protoreflect.ValueOfBytes(append(emptyBuf[:], v...))) return n, nil case protoreflect.MessageKind: if wtyp != protowire.BytesType { return 0, errUnknown } v, n := protowire.ConsumeBytes(b) if n < 0 { return 0, errDecode } m := list.NewElement() if err := o.unmarshalMessage(v, m.Message()); err != nil { return 0, err } list.Append(m) return n, nil case protoreflect.GroupKind: if wtyp != protowire.StartGroupType { return 0, errUnknown } v, n := protowire.ConsumeGroup(fd.Number(), b) if n < 0 { return 0, errDecode } m := list.NewElement() if err := o.unmarshalMessage(v, m.Message()); err != nil { return 0, err } list.Append(m) return n, nil default: return 0, errUnknown } } // We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices. var emptyBuf [0]byte ================================================ FILE: vendor/google.golang.org/protobuf/proto/doc.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package proto provides functions operating on protocol buffer messages. // // For documentation on protocol buffers in general, see: // // https://developers.google.com/protocol-buffers // // For a tutorial on using protocol buffers with Go, see: // // https://developers.google.com/protocol-buffers/docs/gotutorial // // For a guide to generated Go protocol buffer code, see: // // https://developers.google.com/protocol-buffers/docs/reference/go-generated // // // Binary serialization // // This package contains functions to convert to and from the wire format, // an efficient binary serialization of protocol buffers. // // • Size reports the size of a message in the wire format. // // • Marshal converts a message to the wire format. // The MarshalOptions type provides more control over wire marshaling. // // • Unmarshal converts a message from the wire format. // The UnmarshalOptions type provides more control over wire unmarshaling. // // // Basic message operations // // • Clone makes a deep copy of a message. // // • Merge merges the content of a message into another. // // • Equal compares two messages. For more control over comparisons // and detailed reporting of differences, see package // "google.golang.org/protobuf/testing/protocmp". // // • Reset clears the content of a message. // // • CheckInitialized reports whether all required fields in a message are set. // // // Optional scalar constructors // // The API for some generated messages represents optional scalar fields // as pointers to a value. For example, an optional string field has the // Go type *string. // // • Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, and String // take a value and return a pointer to a new instance of it, // to simplify construction of optional field values. // // Generated enum types usually have an Enum method which performs the // same operation. // // Optional scalar fields are only supported in proto2. // // // Extension accessors // // • HasExtension, GetExtension, SetExtension, and ClearExtension // access extension field values in a protocol buffer message. // // Extension fields are only supported in proto2. // // // Related packages // // • Package "google.golang.org/protobuf/encoding/protojson" converts messages to // and from JSON. // // • Package "google.golang.org/protobuf/encoding/prototext" converts messages to // and from the text format. // // • Package "google.golang.org/protobuf/reflect/protoreflect" provides a // reflection interface for protocol buffer data types. // // • Package "google.golang.org/protobuf/testing/protocmp" provides features // to compare protocol buffer messages with the "github.com/google/go-cmp/cmp" // package. // // • Package "google.golang.org/protobuf/types/dynamicpb" provides a dynamic // message type, suitable for working with messages where the protocol buffer // type is only known at runtime. // // This module contains additional packages for more specialized use cases. // Consult the individual package documentation for details. package proto ================================================ FILE: vendor/google.golang.org/protobuf/proto/encode.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // MarshalOptions configures the marshaler. // // Example usage: // b, err := MarshalOptions{Deterministic: true}.Marshal(m) type MarshalOptions struct { pragma.NoUnkeyedLiterals // AllowPartial allows messages that have missing required fields to marshal // without returning an error. If AllowPartial is false (the default), // Marshal will return an error if there are any missing required fields. AllowPartial bool // Deterministic controls whether the same message will always be // serialized to the same bytes within the same binary. // // Setting this option guarantees that repeated serialization of // the same message will return the same bytes, and that different // processes of the same binary (which may be executing on different // machines) will serialize equal messages to the same bytes. // It has no effect on the resulting size of the encoded message compared // to a non-deterministic marshal. // // Note that the deterministic serialization is NOT canonical across // languages. It is not guaranteed to remain stable over time. It is // unstable across different builds with schema changes due to unknown // fields. Users who need canonical serialization (e.g., persistent // storage in a canonical form, fingerprinting, etc.) must define // their own canonicalization specification and implement their own // serializer rather than relying on this API. // // If deterministic serialization is requested, map entries will be // sorted by keys in lexographical order. This is an implementation // detail and subject to change. Deterministic bool // UseCachedSize indicates that the result of a previous Size call // may be reused. // // Setting this option asserts that: // // 1. Size has previously been called on this message with identical // options (except for UseCachedSize itself). // // 2. The message and all its submessages have not changed in any // way since the Size call. // // If either of these invariants is violated, // the results are undefined and may include panics or corrupted output. // // Implementations MAY take this option into account to provide // better performance, but there is no guarantee that they will do so. // There is absolutely no guarantee that Size followed by Marshal with // UseCachedSize set will perform equivalently to Marshal alone. UseCachedSize bool } // Marshal returns the wire-format encoding of m. func Marshal(m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to output. if m == nil { return nil, nil } out, err := MarshalOptions{}.marshal(nil, m.ProtoReflect()) if len(out.Buf) == 0 && err == nil { out.Buf = emptyBytesForMessage(m) } return out.Buf, err } // Marshal returns the wire-format encoding of m. func (o MarshalOptions) Marshal(m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to output. if m == nil { return nil, nil } out, err := o.marshal(nil, m.ProtoReflect()) if len(out.Buf) == 0 && err == nil { out.Buf = emptyBytesForMessage(m) } return out.Buf, err } // emptyBytesForMessage returns a nil buffer if and only if m is invalid, // otherwise it returns a non-nil empty buffer. // // This is to assist the edge-case where user-code does the following: // m1.OptionalBytes, _ = proto.Marshal(m2) // where they expect the proto2 "optional_bytes" field to be populated // if any only if m2 is a valid message. func emptyBytesForMessage(m Message) []byte { if m == nil || !m.ProtoReflect().IsValid() { return nil } return emptyBuf[:] } // MarshalAppend appends the wire-format encoding of m to b, // returning the result. func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) { // Treat nil message interface as an empty message; nothing to append. if m == nil { return b, nil } out, err := o.marshal(b, m.ProtoReflect()) return out.Buf, err } // MarshalState returns the wire-format encoding of a message. // // This method permits fine-grained control over the marshaler. // Most users should use Marshal instead. func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) { return o.marshal(in.Buf, in.Message) } // marshal is a centralized function that all marshal operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for marshal that do not go through this. func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoiface.MarshalOutput, err error) { allowPartial := o.AllowPartial o.AllowPartial = true if methods := protoMethods(m); methods != nil && methods.Marshal != nil && !(o.Deterministic && methods.Flags&protoiface.SupportMarshalDeterministic == 0) { in := protoiface.MarshalInput{ Message: m, Buf: b, } if o.Deterministic { in.Flags |= protoiface.MarshalDeterministic } if o.UseCachedSize { in.Flags |= protoiface.MarshalUseCachedSize } if methods.Size != nil { sout := methods.Size(protoiface.SizeInput{ Message: m, Flags: in.Flags, }) if cap(b) < len(b)+sout.Size { in.Buf = make([]byte, len(b), growcap(cap(b), len(b)+sout.Size)) copy(in.Buf, b) } in.Flags |= protoiface.MarshalUseCachedSize } out, err = methods.Marshal(in) } else { out.Buf, err = o.marshalMessageSlow(b, m) } if err != nil { return out, err } if allowPartial { return out, nil } return out, checkInitialized(m) } func (o MarshalOptions) marshalMessage(b []byte, m protoreflect.Message) ([]byte, error) { out, err := o.marshal(b, m) return out.Buf, err } // growcap scales up the capacity of a slice. // // Given a slice with a current capacity of oldcap and a desired // capacity of wantcap, growcap returns a new capacity >= wantcap. // // The algorithm is mostly identical to the one used by append as of Go 1.14. func growcap(oldcap, wantcap int) (newcap int) { if wantcap > oldcap*2 { newcap = wantcap } else if oldcap < 1024 { // The Go 1.14 runtime takes this case when len(s) < 1024, // not when cap(s) < 1024. The difference doesn't seem // significant here. newcap = oldcap * 2 } else { newcap = oldcap for 0 < newcap && newcap < wantcap { newcap += newcap / 4 } if newcap <= 0 { newcap = wantcap } } return newcap } func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]byte, error) { if messageset.IsMessageSet(m.Descriptor()) { return o.marshalMessageSet(b, m) } fieldOrder := order.AnyFieldOrder if o.Deterministic { // TODO: This should use a more natural ordering like NumberFieldOrder, // but doing so breaks golden tests that make invalid assumption about // output stability of this implementation. fieldOrder = order.LegacyFieldOrder } var err error order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { b, err = o.marshalField(b, fd, v) return err == nil }) if err != nil { return b, err } b = append(b, m.GetUnknown()...) return b, nil } func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { switch { case fd.IsList(): return o.marshalList(b, fd, value.List()) case fd.IsMap(): return o.marshalMap(b, fd, value.Map()) default: b = protowire.AppendTag(b, fd.Number(), wireTypes[fd.Kind()]) return o.marshalSingular(b, fd, value) } } func (o MarshalOptions) marshalList(b []byte, fd protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) { if fd.IsPacked() && list.Len() > 0 { b = protowire.AppendTag(b, fd.Number(), protowire.BytesType) b, pos := appendSpeculativeLength(b) for i, llen := 0, list.Len(); i < llen; i++ { var err error b, err = o.marshalSingular(b, fd, list.Get(i)) if err != nil { return b, err } } b = finishSpeculativeLength(b, pos) return b, nil } kind := fd.Kind() for i, llen := 0, list.Len(); i < llen; i++ { var err error b = protowire.AppendTag(b, fd.Number(), wireTypes[kind]) b, err = o.marshalSingular(b, fd, list.Get(i)) if err != nil { return b, err } } return b, nil } func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) { keyf := fd.MapKey() valf := fd.MapValue() keyOrder := order.AnyKeyOrder if o.Deterministic { keyOrder = order.GenericKeyOrder } var err error order.RangeEntries(mapv, keyOrder, func(key protoreflect.MapKey, value protoreflect.Value) bool { b = protowire.AppendTag(b, fd.Number(), protowire.BytesType) var pos int b, pos = appendSpeculativeLength(b) b, err = o.marshalField(b, keyf, key.Value()) if err != nil { return false } b, err = o.marshalField(b, valf, value) if err != nil { return false } b = finishSpeculativeLength(b, pos) return true }) return b, err } // When encoding length-prefixed fields, we speculatively set aside some number of bytes // for the length, encode the data, and then encode the length (shifting the data if necessary // to make room). const speculativeLength = 1 func appendSpeculativeLength(b []byte) ([]byte, int) { pos := len(b) b = append(b, "\x00\x00\x00\x00"[:speculativeLength]...) return b, pos } func finishSpeculativeLength(b []byte, pos int) []byte { mlen := len(b) - pos - speculativeLength msiz := protowire.SizeVarint(uint64(mlen)) if msiz != speculativeLength { for i := 0; i < msiz-speculativeLength; i++ { b = append(b, 0) } copy(b[pos+msiz:], b[pos+speculativeLength:]) b = b[:pos+msiz+mlen] } protowire.AppendVarint(b[:pos], uint64(mlen)) return b } ================================================ FILE: vendor/google.golang.org/protobuf/proto/encode_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "math" "unicode/utf8" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/strs" "google.golang.org/protobuf/reflect/protoreflect" ) var wireTypes = map[protoreflect.Kind]protowire.Type{ protoreflect.BoolKind: protowire.VarintType, protoreflect.EnumKind: protowire.VarintType, protoreflect.Int32Kind: protowire.VarintType, protoreflect.Sint32Kind: protowire.VarintType, protoreflect.Uint32Kind: protowire.VarintType, protoreflect.Int64Kind: protowire.VarintType, protoreflect.Sint64Kind: protowire.VarintType, protoreflect.Uint64Kind: protowire.VarintType, protoreflect.Sfixed32Kind: protowire.Fixed32Type, protoreflect.Fixed32Kind: protowire.Fixed32Type, protoreflect.FloatKind: protowire.Fixed32Type, protoreflect.Sfixed64Kind: protowire.Fixed64Type, protoreflect.Fixed64Kind: protowire.Fixed64Type, protoreflect.DoubleKind: protowire.Fixed64Type, protoreflect.StringKind: protowire.BytesType, protoreflect.BytesKind: protowire.BytesType, protoreflect.MessageKind: protowire.BytesType, protoreflect.GroupKind: protowire.StartGroupType, } func (o MarshalOptions) marshalSingular(b []byte, fd protoreflect.FieldDescriptor, v protoreflect.Value) ([]byte, error) { switch fd.Kind() { case protoreflect.BoolKind: b = protowire.AppendVarint(b, protowire.EncodeBool(v.Bool())) case protoreflect.EnumKind: b = protowire.AppendVarint(b, uint64(v.Enum())) case protoreflect.Int32Kind: b = protowire.AppendVarint(b, uint64(int32(v.Int()))) case protoreflect.Sint32Kind: b = protowire.AppendVarint(b, protowire.EncodeZigZag(int64(int32(v.Int())))) case protoreflect.Uint32Kind: b = protowire.AppendVarint(b, uint64(uint32(v.Uint()))) case protoreflect.Int64Kind: b = protowire.AppendVarint(b, uint64(v.Int())) case protoreflect.Sint64Kind: b = protowire.AppendVarint(b, protowire.EncodeZigZag(v.Int())) case protoreflect.Uint64Kind: b = protowire.AppendVarint(b, v.Uint()) case protoreflect.Sfixed32Kind: b = protowire.AppendFixed32(b, uint32(v.Int())) case protoreflect.Fixed32Kind: b = protowire.AppendFixed32(b, uint32(v.Uint())) case protoreflect.FloatKind: b = protowire.AppendFixed32(b, math.Float32bits(float32(v.Float()))) case protoreflect.Sfixed64Kind: b = protowire.AppendFixed64(b, uint64(v.Int())) case protoreflect.Fixed64Kind: b = protowire.AppendFixed64(b, v.Uint()) case protoreflect.DoubleKind: b = protowire.AppendFixed64(b, math.Float64bits(v.Float())) case protoreflect.StringKind: if strs.EnforceUTF8(fd) && !utf8.ValidString(v.String()) { return b, errors.InvalidUTF8(string(fd.FullName())) } b = protowire.AppendString(b, v.String()) case protoreflect.BytesKind: b = protowire.AppendBytes(b, v.Bytes()) case protoreflect.MessageKind: var pos int var err error b, pos = appendSpeculativeLength(b) b, err = o.marshalMessage(b, v.Message()) if err != nil { return b, err } b = finishSpeculativeLength(b, pos) case protoreflect.GroupKind: var err error b, err = o.marshalMessage(b, v.Message()) if err != nil { return b, err } b = protowire.AppendVarint(b, protowire.EncodeTag(fd.Number(), protowire.EndGroupType)) default: return b, errors.New("invalid kind %v", fd.Kind()) } return b, nil } ================================================ FILE: vendor/google.golang.org/protobuf/proto/equal.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "bytes" "math" "reflect" "google.golang.org/protobuf/encoding/protowire" pref "google.golang.org/protobuf/reflect/protoreflect" ) // Equal reports whether two messages are equal. // If two messages marshal to the same bytes under deterministic serialization, // then Equal is guaranteed to report true. // // Two messages are equal if they belong to the same message descriptor, // have the same set of populated known and extension field values, // and the same set of unknown fields values. If either of the top-level // messages are invalid, then Equal reports true only if both are invalid. // // Scalar values are compared with the equivalent of the == operator in Go, // except bytes values which are compared using bytes.Equal and // floating point values which specially treat NaNs as equal. // Message values are compared by recursively calling Equal. // Lists are equal if each element value is also equal. // Maps are equal if they have the same set of keys, where the pair of values // for each key is also equal. func Equal(x, y Message) bool { if x == nil || y == nil { return x == nil && y == nil } mx := x.ProtoReflect() my := y.ProtoReflect() if mx.IsValid() != my.IsValid() { return false } return equalMessage(mx, my) } // equalMessage compares two messages. func equalMessage(mx, my pref.Message) bool { if mx.Descriptor() != my.Descriptor() { return false } nx := 0 equal := true mx.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { nx++ vy := my.Get(fd) equal = my.Has(fd) && equalField(fd, vx, vy) return equal }) if !equal { return false } ny := 0 my.Range(func(fd pref.FieldDescriptor, vx pref.Value) bool { ny++ return true }) if nx != ny { return false } return equalUnknown(mx.GetUnknown(), my.GetUnknown()) } // equalField compares two fields. func equalField(fd pref.FieldDescriptor, x, y pref.Value) bool { switch { case fd.IsList(): return equalList(fd, x.List(), y.List()) case fd.IsMap(): return equalMap(fd, x.Map(), y.Map()) default: return equalValue(fd, x, y) } } // equalMap compares two maps. func equalMap(fd pref.FieldDescriptor, x, y pref.Map) bool { if x.Len() != y.Len() { return false } equal := true x.Range(func(k pref.MapKey, vx pref.Value) bool { vy := y.Get(k) equal = y.Has(k) && equalValue(fd.MapValue(), vx, vy) return equal }) return equal } // equalList compares two lists. func equalList(fd pref.FieldDescriptor, x, y pref.List) bool { if x.Len() != y.Len() { return false } for i := x.Len() - 1; i >= 0; i-- { if !equalValue(fd, x.Get(i), y.Get(i)) { return false } } return true } // equalValue compares two singular values. func equalValue(fd pref.FieldDescriptor, x, y pref.Value) bool { switch fd.Kind() { case pref.BoolKind: return x.Bool() == y.Bool() case pref.EnumKind: return x.Enum() == y.Enum() case pref.Int32Kind, pref.Sint32Kind, pref.Int64Kind, pref.Sint64Kind, pref.Sfixed32Kind, pref.Sfixed64Kind: return x.Int() == y.Int() case pref.Uint32Kind, pref.Uint64Kind, pref.Fixed32Kind, pref.Fixed64Kind: return x.Uint() == y.Uint() case pref.FloatKind, pref.DoubleKind: fx := x.Float() fy := y.Float() if math.IsNaN(fx) || math.IsNaN(fy) { return math.IsNaN(fx) && math.IsNaN(fy) } return fx == fy case pref.StringKind: return x.String() == y.String() case pref.BytesKind: return bytes.Equal(x.Bytes(), y.Bytes()) case pref.MessageKind, pref.GroupKind: return equalMessage(x.Message(), y.Message()) default: return x.Interface() == y.Interface() } } // equalUnknown compares unknown fields by direct comparison on the raw bytes // of each individual field number. func equalUnknown(x, y pref.RawFields) bool { if len(x) != len(y) { return false } if bytes.Equal([]byte(x), []byte(y)) { return true } mx := make(map[pref.FieldNumber]pref.RawFields) my := make(map[pref.FieldNumber]pref.RawFields) for len(x) > 0 { fnum, _, n := protowire.ConsumeField(x) mx[fnum] = append(mx[fnum], x[:n]...) x = x[n:] } for len(y) > 0 { fnum, _, n := protowire.ConsumeField(y) my[fnum] = append(my[fnum], y[:n]...) y = y[n:] } return reflect.DeepEqual(mx, my) } ================================================ FILE: vendor/google.golang.org/protobuf/proto/extension.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/reflect/protoreflect" ) // HasExtension reports whether an extension field is populated. // It returns false if m is invalid or if xt does not extend m. func HasExtension(m Message, xt protoreflect.ExtensionType) bool { // Treat nil message interface as an empty message; no populated fields. if m == nil { return false } // As a special-case, we reports invalid or mismatching descriptors // as always not being populated (since they aren't). if xt == nil || m.ProtoReflect().Descriptor() != xt.TypeDescriptor().ContainingMessage() { return false } return m.ProtoReflect().Has(xt.TypeDescriptor()) } // ClearExtension clears an extension field such that subsequent // HasExtension calls return false. // It panics if m is invalid or if xt does not extend m. func ClearExtension(m Message, xt protoreflect.ExtensionType) { m.ProtoReflect().Clear(xt.TypeDescriptor()) } // GetExtension retrieves the value for an extension field. // If the field is unpopulated, it returns the default value for // scalars and an immutable, empty value for lists or messages. // It panics if xt does not extend m. func GetExtension(m Message, xt protoreflect.ExtensionType) interface{} { // Treat nil message interface as an empty message; return the default. if m == nil { return xt.InterfaceOf(xt.Zero()) } return xt.InterfaceOf(m.ProtoReflect().Get(xt.TypeDescriptor())) } // SetExtension stores the value of an extension field. // It panics if m is invalid, xt does not extend m, or if type of v // is invalid for the specified extension field. func SetExtension(m Message, xt protoreflect.ExtensionType, v interface{}) { xd := xt.TypeDescriptor() pv := xt.ValueOf(v) // Specially treat an invalid list, map, or message as clear. isValid := true switch { case xd.IsList(): isValid = pv.List().IsValid() case xd.IsMap(): isValid = pv.Map().IsValid() case xd.Message() != nil: isValid = pv.Message().IsValid() } if !isValid { m.ProtoReflect().Clear(xd) return } m.ProtoReflect().Set(xd, pv) } // RangeExtensions iterates over every populated extension field in m in an // undefined order, calling f for each extension type and value encountered. // It returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current extension field. func RangeExtensions(m Message, f func(protoreflect.ExtensionType, interface{}) bool) { // Treat nil message interface as an empty message; nothing to range over. if m == nil { return } m.ProtoReflect().Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { if fd.IsExtension() { xt := fd.(protoreflect.ExtensionTypeDescriptor).Type() vi := xt.InterfaceOf(v) return f(xt, vi) } return true }) } ================================================ FILE: vendor/google.golang.org/protobuf/proto/merge.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // Merge merges src into dst, which must be a message with the same descriptor. // // Populated scalar fields in src are copied to dst, while populated // singular messages in src are merged into dst by recursively calling Merge. // The elements of every list field in src is appended to the corresponded // list fields in dst. The entries of every map field in src is copied into // the corresponding map field in dst, possibly replacing existing entries. // The unknown fields of src are appended to the unknown fields of dst. // // It is semantically equivalent to unmarshaling the encoded form of src // into dst with the UnmarshalOptions.Merge option specified. func Merge(dst, src Message) { // TODO: Should nil src be treated as semantically equivalent to a // untyped, read-only, empty message? What about a nil dst? dstMsg, srcMsg := dst.ProtoReflect(), src.ProtoReflect() if dstMsg.Descriptor() != srcMsg.Descriptor() { if got, want := dstMsg.Descriptor().FullName(), srcMsg.Descriptor().FullName(); got != want { panic(fmt.Sprintf("descriptor mismatch: %v != %v", got, want)) } panic("descriptor mismatch") } mergeOptions{}.mergeMessage(dstMsg, srcMsg) } // Clone returns a deep copy of m. // If the top-level message is invalid, it returns an invalid message as well. func Clone(m Message) Message { // NOTE: Most usages of Clone assume the following properties: // t := reflect.TypeOf(m) // t == reflect.TypeOf(m.ProtoReflect().New().Interface()) // t == reflect.TypeOf(m.ProtoReflect().Type().Zero().Interface()) // // Embedding protobuf messages breaks this since the parent type will have // a forwarded ProtoReflect method, but the Interface method will return // the underlying embedded message type. if m == nil { return nil } src := m.ProtoReflect() if !src.IsValid() { return src.Type().Zero().Interface() } dst := src.New() mergeOptions{}.mergeMessage(dst, src) return dst.Interface() } // mergeOptions provides a namespace for merge functions, and can be // exported in the future if we add user-visible merge options. type mergeOptions struct{} func (o mergeOptions) mergeMessage(dst, src protoreflect.Message) { methods := protoMethods(dst) if methods != nil && methods.Merge != nil { in := protoiface.MergeInput{ Destination: dst, Source: src, } out := methods.Merge(in) if out.Flags&protoiface.MergeComplete != 0 { return } } if !dst.IsValid() { panic(fmt.Sprintf("cannot merge into invalid %v message", dst.Descriptor().FullName())) } src.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { switch { case fd.IsList(): o.mergeList(dst.Mutable(fd).List(), v.List(), fd) case fd.IsMap(): o.mergeMap(dst.Mutable(fd).Map(), v.Map(), fd.MapValue()) case fd.Message() != nil: o.mergeMessage(dst.Mutable(fd).Message(), v.Message()) case fd.Kind() == protoreflect.BytesKind: dst.Set(fd, o.cloneBytes(v)) default: dst.Set(fd, v) } return true }) if len(src.GetUnknown()) > 0 { dst.SetUnknown(append(dst.GetUnknown(), src.GetUnknown()...)) } } func (o mergeOptions) mergeList(dst, src protoreflect.List, fd protoreflect.FieldDescriptor) { // Merge semantics appends to the end of the existing list. for i, n := 0, src.Len(); i < n; i++ { switch v := src.Get(i); { case fd.Message() != nil: dstv := dst.NewElement() o.mergeMessage(dstv.Message(), v.Message()) dst.Append(dstv) case fd.Kind() == protoreflect.BytesKind: dst.Append(o.cloneBytes(v)) default: dst.Append(v) } } } func (o mergeOptions) mergeMap(dst, src protoreflect.Map, fd protoreflect.FieldDescriptor) { // Merge semantics replaces, rather than merges into existing entries. src.Range(func(k protoreflect.MapKey, v protoreflect.Value) bool { switch { case fd.Message() != nil: dstv := dst.NewValue() o.mergeMessage(dstv.Message(), v.Message()) dst.Set(k, dstv) case fd.Kind() == protoreflect.BytesKind: dst.Set(k, o.cloneBytes(v)) default: dst.Set(k, v) } return true }) } func (o mergeOptions) cloneBytes(v protoreflect.Value) protoreflect.Value { return protoreflect.ValueOfBytes(append([]byte{}, v.Bytes()...)) } ================================================ FILE: vendor/google.golang.org/protobuf/proto/messageset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/internal/order" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/reflect/protoregistry" ) func (o MarshalOptions) sizeMessageSet(m protoreflect.Message) (size int) { m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { size += messageset.SizeField(fd.Number()) size += protowire.SizeTag(messageset.FieldMessage) size += protowire.SizeBytes(o.size(v.Message())) return true }) size += messageset.SizeUnknown(m.GetUnknown()) return size } func (o MarshalOptions) marshalMessageSet(b []byte, m protoreflect.Message) ([]byte, error) { if !flags.ProtoLegacy { return b, errors.New("no support for message_set_wire_format") } fieldOrder := order.AnyFieldOrder if o.Deterministic { fieldOrder = order.NumberFieldOrder } var err error order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { b, err = o.marshalMessageSetField(b, fd, v) return err == nil }) if err != nil { return b, err } return messageset.AppendUnknown(b, m.GetUnknown()) } func (o MarshalOptions) marshalMessageSetField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) { b = messageset.AppendFieldStart(b, fd.Number()) b = protowire.AppendTag(b, messageset.FieldMessage, protowire.BytesType) b = protowire.AppendVarint(b, uint64(o.Size(value.Message().Interface()))) b, err := o.marshalMessage(b, value.Message()) if err != nil { return b, err } b = messageset.AppendFieldEnd(b) return b, nil } func (o UnmarshalOptions) unmarshalMessageSet(b []byte, m protoreflect.Message) error { if !flags.ProtoLegacy { return errors.New("no support for message_set_wire_format") } return messageset.Unmarshal(b, false, func(num protowire.Number, v []byte) error { err := o.unmarshalMessageSetField(m, num, v) if err == errUnknown { unknown := m.GetUnknown() unknown = protowire.AppendTag(unknown, num, protowire.BytesType) unknown = protowire.AppendBytes(unknown, v) m.SetUnknown(unknown) return nil } return err }) } func (o UnmarshalOptions) unmarshalMessageSetField(m protoreflect.Message, num protowire.Number, v []byte) error { md := m.Descriptor() if !md.ExtensionRanges().Has(num) { return errUnknown } xt, err := o.Resolver.FindExtensionByNumber(md.FullName(), num) if err == protoregistry.NotFound { return errUnknown } if err != nil { return errors.New("%v: unable to resolve extension %v: %v", md.FullName(), num, err) } xd := xt.TypeDescriptor() if err := o.unmarshalMessage(v, m.Mutable(xd).Message()); err != nil { return err } return nil } ================================================ FILE: vendor/google.golang.org/protobuf/proto/proto.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/reflect/protoreflect" ) // Message is the top-level interface that all messages must implement. // It provides access to a reflective view of a message. // Any implementation of this interface may be used with all functions in the // protobuf module that accept a Message, except where otherwise specified. // // This is the v2 interface definition for protobuf messages. // The v1 interface definition is "github.com/golang/protobuf/proto".Message. // // To convert a v1 message to a v2 message, // use "github.com/golang/protobuf/proto".MessageV2. // To convert a v2 message to a v1 message, // use "github.com/golang/protobuf/proto".MessageV1. type Message = protoreflect.ProtoMessage // Error matches all errors produced by packages in the protobuf module. // // That is, errors.Is(err, Error) reports whether an error is produced // by this module. var Error error func init() { Error = errors.Error } // MessageName returns the full name of m. // If m is nil, it returns an empty string. func MessageName(m Message) protoreflect.FullName { if m == nil { return "" } return m.ProtoReflect().Descriptor().FullName() } ================================================ FILE: vendor/google.golang.org/protobuf/proto/proto_methods.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The protoreflect build tag disables use of fast-path methods. // +build !protoreflect package proto import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) const hasProtoMethods = true func protoMethods(m protoreflect.Message) *protoiface.Methods { return m.ProtoMethods() } ================================================ FILE: vendor/google.golang.org/protobuf/proto/proto_reflect.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // The protoreflect build tag disables use of fast-path methods. // +build protoreflect package proto import ( "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) const hasProtoMethods = false func protoMethods(m protoreflect.Message) *protoiface.Methods { return nil } ================================================ FILE: vendor/google.golang.org/protobuf/proto/reset.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "fmt" "google.golang.org/protobuf/reflect/protoreflect" ) // Reset clears every field in the message. // The resulting message shares no observable memory with its previous state // other than the memory for the message itself. func Reset(m Message) { if mr, ok := m.(interface{ Reset() }); ok && hasProtoMethods { mr.Reset() return } resetMessage(m.ProtoReflect()) } func resetMessage(m protoreflect.Message) { if !m.IsValid() { panic(fmt.Sprintf("cannot reset invalid %v message", m.Descriptor().FullName())) } // Clear all known fields. fds := m.Descriptor().Fields() for i := 0; i < fds.Len(); i++ { m.Clear(fds.Get(i)) } // Clear extension fields. m.Range(func(fd protoreflect.FieldDescriptor, _ protoreflect.Value) bool { m.Clear(fd) return true }) // Clear unknown fields. m.SetUnknown(nil) } ================================================ FILE: vendor/google.golang.org/protobuf/proto/size.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/reflect/protoreflect" "google.golang.org/protobuf/runtime/protoiface" ) // Size returns the size in bytes of the wire-format encoding of m. func Size(m Message) int { return MarshalOptions{}.Size(m) } // Size returns the size in bytes of the wire-format encoding of m. func (o MarshalOptions) Size(m Message) int { // Treat a nil message interface as an empty message; nothing to output. if m == nil { return 0 } return o.size(m.ProtoReflect()) } // size is a centralized function that all size operations go through. // For profiling purposes, avoid changing the name of this function or // introducing other code paths for size that do not go through this. func (o MarshalOptions) size(m protoreflect.Message) (size int) { methods := protoMethods(m) if methods != nil && methods.Size != nil { out := methods.Size(protoiface.SizeInput{ Message: m, }) return out.Size } if methods != nil && methods.Marshal != nil { // This is not efficient, but we don't have any choice. // This case is mainly used for legacy types with a Marshal method. out, _ := methods.Marshal(protoiface.MarshalInput{ Message: m, }) return len(out.Buf) } return o.sizeMessageSlow(m) } func (o MarshalOptions) sizeMessageSlow(m protoreflect.Message) (size int) { if messageset.IsMessageSet(m.Descriptor()) { return o.sizeMessageSet(m) } m.Range(func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool { size += o.sizeField(fd, v) return true }) size += len(m.GetUnknown()) return size } func (o MarshalOptions) sizeField(fd protoreflect.FieldDescriptor, value protoreflect.Value) (size int) { num := fd.Number() switch { case fd.IsList(): return o.sizeList(num, fd, value.List()) case fd.IsMap(): return o.sizeMap(num, fd, value.Map()) default: return protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), value) } } func (o MarshalOptions) sizeList(num protowire.Number, fd protoreflect.FieldDescriptor, list protoreflect.List) (size int) { if fd.IsPacked() && list.Len() > 0 { content := 0 for i, llen := 0, list.Len(); i < llen; i++ { content += o.sizeSingular(num, fd.Kind(), list.Get(i)) } return protowire.SizeTag(num) + protowire.SizeBytes(content) } for i, llen := 0, list.Len(); i < llen; i++ { size += protowire.SizeTag(num) + o.sizeSingular(num, fd.Kind(), list.Get(i)) } return size } func (o MarshalOptions) sizeMap(num protowire.Number, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) (size int) { mapv.Range(func(key protoreflect.MapKey, value protoreflect.Value) bool { size += protowire.SizeTag(num) size += protowire.SizeBytes(o.sizeField(fd.MapKey(), key.Value()) + o.sizeField(fd.MapValue(), value)) return true }) return size } ================================================ FILE: vendor/google.golang.org/protobuf/proto/size_gen.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-types. DO NOT EDIT. package proto import ( "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/reflect/protoreflect" ) func (o MarshalOptions) sizeSingular(num protowire.Number, kind protoreflect.Kind, v protoreflect.Value) int { switch kind { case protoreflect.BoolKind: return protowire.SizeVarint(protowire.EncodeBool(v.Bool())) case protoreflect.EnumKind: return protowire.SizeVarint(uint64(v.Enum())) case protoreflect.Int32Kind: return protowire.SizeVarint(uint64(int32(v.Int()))) case protoreflect.Sint32Kind: return protowire.SizeVarint(protowire.EncodeZigZag(int64(int32(v.Int())))) case protoreflect.Uint32Kind: return protowire.SizeVarint(uint64(uint32(v.Uint()))) case protoreflect.Int64Kind: return protowire.SizeVarint(uint64(v.Int())) case protoreflect.Sint64Kind: return protowire.SizeVarint(protowire.EncodeZigZag(v.Int())) case protoreflect.Uint64Kind: return protowire.SizeVarint(v.Uint()) case protoreflect.Sfixed32Kind: return protowire.SizeFixed32() case protoreflect.Fixed32Kind: return protowire.SizeFixed32() case protoreflect.FloatKind: return protowire.SizeFixed32() case protoreflect.Sfixed64Kind: return protowire.SizeFixed64() case protoreflect.Fixed64Kind: return protowire.SizeFixed64() case protoreflect.DoubleKind: return protowire.SizeFixed64() case protoreflect.StringKind: return protowire.SizeBytes(len(v.String())) case protoreflect.BytesKind: return protowire.SizeBytes(len(v.Bytes())) case protoreflect.MessageKind: return protowire.SizeBytes(o.size(v.Message())) case protoreflect.GroupKind: return protowire.SizeGroup(num, o.size(v.Message())) default: return 0 } } ================================================ FILE: vendor/google.golang.org/protobuf/proto/wrappers.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package proto // Bool stores v in a new bool value and returns a pointer to it. func Bool(v bool) *bool { return &v } // Int32 stores v in a new int32 value and returns a pointer to it. func Int32(v int32) *int32 { return &v } // Int64 stores v in a new int64 value and returns a pointer to it. func Int64(v int64) *int64 { return &v } // Float32 stores v in a new float32 value and returns a pointer to it. func Float32(v float32) *float32 { return &v } // Float64 stores v in a new float64 value and returns a pointer to it. func Float64(v float64) *float64 { return &v } // Uint32 stores v in a new uint32 value and returns a pointer to it. func Uint32(v uint32) *uint32 { return &v } // Uint64 stores v in a new uint64 value and returns a pointer to it. func Uint64(v uint64) *uint64 { return &v } // String stores v in a new string value and returns a pointer to it. func String(v string) *string { return &v } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go ================================================ // Copyright 2020 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "google.golang.org/protobuf/internal/pragma" ) // The following types are used by the fast-path Message.ProtoMethods method. // // To avoid polluting the public protoreflect API with types used only by // low-level implementations, the canonical definitions of these types are // in the runtime/protoiface package. The definitions here and in protoiface // must be kept in sync. type ( methods = struct { pragma.NoUnkeyedLiterals Flags supportFlags Size func(sizeInput) sizeOutput Marshal func(marshalInput) (marshalOutput, error) Unmarshal func(unmarshalInput) (unmarshalOutput, error) Merge func(mergeInput) mergeOutput CheckInitialized func(checkInitializedInput) (checkInitializedOutput, error) } supportFlags = uint64 sizeInput = struct { pragma.NoUnkeyedLiterals Message Message Flags uint8 } sizeOutput = struct { pragma.NoUnkeyedLiterals Size int } marshalInput = struct { pragma.NoUnkeyedLiterals Message Message Buf []byte Flags uint8 } marshalOutput = struct { pragma.NoUnkeyedLiterals Buf []byte } unmarshalInput = struct { pragma.NoUnkeyedLiterals Message Message Buf []byte Flags uint8 Resolver interface { FindExtensionByName(field FullName) (ExtensionType, error) FindExtensionByNumber(message FullName, field FieldNumber) (ExtensionType, error) } } unmarshalOutput = struct { pragma.NoUnkeyedLiterals Flags uint8 } mergeInput = struct { pragma.NoUnkeyedLiterals Source Message Destination Message } mergeOutput = struct { pragma.NoUnkeyedLiterals Flags uint8 } checkInitializedInput = struct { pragma.NoUnkeyedLiterals Message Message } checkInitializedOutput = struct { pragma.NoUnkeyedLiterals } ) ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoreflect provides interfaces to dynamically manipulate messages. // // This package includes type descriptors which describe the structure of types // defined in proto source files and value interfaces which provide the // ability to examine and manipulate the contents of messages. // // // Protocol Buffer Descriptors // // Protobuf descriptors (e.g., EnumDescriptor or MessageDescriptor) // are immutable objects that represent protobuf type information. // They are wrappers around the messages declared in descriptor.proto. // Protobuf descriptors alone lack any information regarding Go types. // // Enums and messages generated by this module implement Enum and ProtoMessage, // where the Descriptor and ProtoReflect.Descriptor accessors respectively // return the protobuf descriptor for the values. // // The protobuf descriptor interfaces are not meant to be implemented by // user code since they might need to be extended in the future to support // additions to the protobuf language. // The "google.golang.org/protobuf/reflect/protodesc" package converts between // google.protobuf.DescriptorProto messages and protobuf descriptors. // // // Go Type Descriptors // // A type descriptor (e.g., EnumType or MessageType) is a constructor for // a concrete Go type that represents the associated protobuf descriptor. // There is commonly a one-to-one relationship between protobuf descriptors and // Go type descriptors, but it can potentially be a one-to-many relationship. // // Enums and messages generated by this module implement Enum and ProtoMessage, // where the Type and ProtoReflect.Type accessors respectively // return the protobuf descriptor for the values. // // The "google.golang.org/protobuf/types/dynamicpb" package can be used to // create Go type descriptors from protobuf descriptors. // // // Value Interfaces // // The Enum and Message interfaces provide a reflective view over an // enum or message instance. For enums, it provides the ability to retrieve // the enum value number for any concrete enum type. For messages, it provides // the ability to access or manipulate fields of the message. // // To convert a proto.Message to a protoreflect.Message, use the // former's ProtoReflect method. Since the ProtoReflect method is new to the // v2 message interface, it may not be present on older message implementations. // The "github.com/golang/protobuf/proto".MessageReflect function can be used // to obtain a reflective view on older messages. // // // Relationships // // The following diagrams demonstrate the relationships between // various types declared in this package. // // // ┌───────────────────────────────────┐ // V │ // ┌────────────── New(n) ─────────────┐ │ // │ │ │ // │ ┌──── Descriptor() ──┐ │ ┌── Number() ──┐ │ // │ │ V V │ V │ // ╔════════════╗ ╔════════════════╗ ╔════════╗ ╔════════════╗ // ║ EnumType ║ ║ EnumDescriptor ║ ║ Enum ║ ║ EnumNumber ║ // ╚════════════╝ ╚════════════════╝ ╚════════╝ ╚════════════╝ // Λ Λ │ │ // │ └─── Descriptor() ──┘ │ // │ │ // └────────────────── Type() ───────┘ // // • An EnumType describes a concrete Go enum type. // It has an EnumDescriptor and can construct an Enum instance. // // • An EnumDescriptor describes an abstract protobuf enum type. // // • An Enum is a concrete enum instance. Generated enums implement Enum. // // // ┌──────────────── New() ─────────────────┐ // │ │ // │ ┌─── Descriptor() ─────┐ │ ┌── Interface() ───┐ // │ │ V V │ V // ╔═════════════╗ ╔═══════════════════╗ ╔═════════╗ ╔══════════════╗ // ║ MessageType ║ ║ MessageDescriptor ║ ║ Message ║ ║ ProtoMessage ║ // ╚═════════════╝ ╚═══════════════════╝ ╚═════════╝ ╚══════════════╝ // Λ Λ │ │ Λ │ // │ └──── Descriptor() ────┘ │ └─ ProtoReflect() ─┘ // │ │ // └─────────────────── Type() ─────────┘ // // • A MessageType describes a concrete Go message type. // It has a MessageDescriptor and can construct a Message instance. // // • A MessageDescriptor describes an abstract protobuf message type. // // • A Message is a concrete message instance. Generated messages implement // ProtoMessage, which can convert to/from a Message. // // // ┌── TypeDescriptor() ──┐ ┌───── Descriptor() ─────┐ // │ V │ V // ╔═══════════════╗ ╔═════════════════════════╗ ╔═════════════════════╗ // ║ ExtensionType ║ ║ ExtensionTypeDescriptor ║ ║ ExtensionDescriptor ║ // ╚═══════════════╝ ╚═════════════════════════╝ ╚═════════════════════╝ // Λ │ │ Λ │ Λ // └─────── Type() ───────┘ │ └─── may implement ────┘ │ // │ │ // └────── implements ────────┘ // // • An ExtensionType describes a concrete Go implementation of an extension. // It has an ExtensionTypeDescriptor and can convert to/from // abstract Values and Go values. // // • An ExtensionTypeDescriptor is an ExtensionDescriptor // which also has an ExtensionType. // // • An ExtensionDescriptor describes an abstract protobuf extension field and // may not always be an ExtensionTypeDescriptor. package protoreflect import ( "fmt" "strings" "google.golang.org/protobuf/encoding/protowire" "google.golang.org/protobuf/internal/pragma" ) type doNotImplement pragma.DoNotImplement // ProtoMessage is the top-level interface that all proto messages implement. // This is declared in the protoreflect package to avoid a cyclic dependency; // use the proto.Message type instead, which aliases this type. type ProtoMessage interface{ ProtoReflect() Message } // Syntax is the language version of the proto file. type Syntax syntax type syntax int8 // keep exact type opaque as the int type may change const ( Proto2 Syntax = 2 Proto3 Syntax = 3 ) // IsValid reports whether the syntax is valid. func (s Syntax) IsValid() bool { switch s { case Proto2, Proto3: return true default: return false } } // String returns s as a proto source identifier (e.g., "proto2"). func (s Syntax) String() string { switch s { case Proto2: return "proto2" case Proto3: return "proto3" default: return fmt.Sprintf("", s) } } // GoString returns s as a Go source identifier (e.g., "Proto2"). func (s Syntax) GoString() string { switch s { case Proto2: return "Proto2" case Proto3: return "Proto3" default: return fmt.Sprintf("Syntax(%d)", s) } } // Cardinality determines whether a field is optional, required, or repeated. type Cardinality cardinality type cardinality int8 // keep exact type opaque as the int type may change // Constants as defined by the google.protobuf.Cardinality enumeration. const ( Optional Cardinality = 1 // appears zero or one times Required Cardinality = 2 // appears exactly one time; invalid with Proto3 Repeated Cardinality = 3 // appears zero or more times ) // IsValid reports whether the cardinality is valid. func (c Cardinality) IsValid() bool { switch c { case Optional, Required, Repeated: return true default: return false } } // String returns c as a proto source identifier (e.g., "optional"). func (c Cardinality) String() string { switch c { case Optional: return "optional" case Required: return "required" case Repeated: return "repeated" default: return fmt.Sprintf("", c) } } // GoString returns c as a Go source identifier (e.g., "Optional"). func (c Cardinality) GoString() string { switch c { case Optional: return "Optional" case Required: return "Required" case Repeated: return "Repeated" default: return fmt.Sprintf("Cardinality(%d)", c) } } // Kind indicates the basic proto kind of a field. type Kind kind type kind int8 // keep exact type opaque as the int type may change // Constants as defined by the google.protobuf.Field.Kind enumeration. const ( BoolKind Kind = 8 EnumKind Kind = 14 Int32Kind Kind = 5 Sint32Kind Kind = 17 Uint32Kind Kind = 13 Int64Kind Kind = 3 Sint64Kind Kind = 18 Uint64Kind Kind = 4 Sfixed32Kind Kind = 15 Fixed32Kind Kind = 7 FloatKind Kind = 2 Sfixed64Kind Kind = 16 Fixed64Kind Kind = 6 DoubleKind Kind = 1 StringKind Kind = 9 BytesKind Kind = 12 MessageKind Kind = 11 GroupKind Kind = 10 ) // IsValid reports whether the kind is valid. func (k Kind) IsValid() bool { switch k { case BoolKind, EnumKind, Int32Kind, Sint32Kind, Uint32Kind, Int64Kind, Sint64Kind, Uint64Kind, Sfixed32Kind, Fixed32Kind, FloatKind, Sfixed64Kind, Fixed64Kind, DoubleKind, StringKind, BytesKind, MessageKind, GroupKind: return true default: return false } } // String returns k as a proto source identifier (e.g., "bool"). func (k Kind) String() string { switch k { case BoolKind: return "bool" case EnumKind: return "enum" case Int32Kind: return "int32" case Sint32Kind: return "sint32" case Uint32Kind: return "uint32" case Int64Kind: return "int64" case Sint64Kind: return "sint64" case Uint64Kind: return "uint64" case Sfixed32Kind: return "sfixed32" case Fixed32Kind: return "fixed32" case FloatKind: return "float" case Sfixed64Kind: return "sfixed64" case Fixed64Kind: return "fixed64" case DoubleKind: return "double" case StringKind: return "string" case BytesKind: return "bytes" case MessageKind: return "message" case GroupKind: return "group" default: return fmt.Sprintf("", k) } } // GoString returns k as a Go source identifier (e.g., "BoolKind"). func (k Kind) GoString() string { switch k { case BoolKind: return "BoolKind" case EnumKind: return "EnumKind" case Int32Kind: return "Int32Kind" case Sint32Kind: return "Sint32Kind" case Uint32Kind: return "Uint32Kind" case Int64Kind: return "Int64Kind" case Sint64Kind: return "Sint64Kind" case Uint64Kind: return "Uint64Kind" case Sfixed32Kind: return "Sfixed32Kind" case Fixed32Kind: return "Fixed32Kind" case FloatKind: return "FloatKind" case Sfixed64Kind: return "Sfixed64Kind" case Fixed64Kind: return "Fixed64Kind" case DoubleKind: return "DoubleKind" case StringKind: return "StringKind" case BytesKind: return "BytesKind" case MessageKind: return "MessageKind" case GroupKind: return "GroupKind" default: return fmt.Sprintf("Kind(%d)", k) } } // FieldNumber is the field number in a message. type FieldNumber = protowire.Number // FieldNumbers represent a list of field numbers. type FieldNumbers interface { // Len reports the number of fields in the list. Len() int // Get returns the ith field number. It panics if out of bounds. Get(i int) FieldNumber // Has reports whether n is within the list of fields. Has(n FieldNumber) bool doNotImplement } // FieldRanges represent a list of field number ranges. type FieldRanges interface { // Len reports the number of ranges in the list. Len() int // Get returns the ith range. It panics if out of bounds. Get(i int) [2]FieldNumber // start inclusive; end exclusive // Has reports whether n is within any of the ranges. Has(n FieldNumber) bool doNotImplement } // EnumNumber is the numeric value for an enum. type EnumNumber int32 // EnumRanges represent a list of enum number ranges. type EnumRanges interface { // Len reports the number of ranges in the list. Len() int // Get returns the ith range. It panics if out of bounds. Get(i int) [2]EnumNumber // start inclusive; end inclusive // Has reports whether n is within any of the ranges. Has(n EnumNumber) bool doNotImplement } // Name is the short name for a proto declaration. This is not the name // as used in Go source code, which might not be identical to the proto name. type Name string // e.g., "Kind" // IsValid reports whether s is a syntactically valid name. // An empty name is invalid. func (s Name) IsValid() bool { return consumeIdent(string(s)) == len(s) } // Names represent a list of names. type Names interface { // Len reports the number of names in the list. Len() int // Get returns the ith name. It panics if out of bounds. Get(i int) Name // Has reports whether s matches any names in the list. Has(s Name) bool doNotImplement } // FullName is a qualified name that uniquely identifies a proto declaration. // A qualified name is the concatenation of the proto package along with the // fully-declared name (i.e., name of parent preceding the name of the child), // with a '.' delimiter placed between each Name. // // This should not have any leading or trailing dots. type FullName string // e.g., "google.protobuf.Field.Kind" // IsValid reports whether s is a syntactically valid full name. // An empty full name is invalid. func (s FullName) IsValid() bool { i := consumeIdent(string(s)) if i < 0 { return false } for len(s) > i { if s[i] != '.' { return false } i++ n := consumeIdent(string(s[i:])) if n < 0 { return false } i += n } return true } func consumeIdent(s string) (i int) { if len(s) == 0 || !isLetter(s[i]) { return -1 } i++ for len(s) > i && isLetterDigit(s[i]) { i++ } return i } func isLetter(c byte) bool { return c == '_' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') } func isLetterDigit(c byte) bool { return isLetter(c) || ('0' <= c && c <= '9') } // Name returns the short name, which is the last identifier segment. // A single segment FullName is the Name itself. func (n FullName) Name() Name { if i := strings.LastIndexByte(string(n), '.'); i >= 0 { return Name(n[i+1:]) } return Name(n) } // Parent returns the full name with the trailing identifier removed. // A single segment FullName has no parent. func (n FullName) Parent() FullName { if i := strings.LastIndexByte(string(n), '.'); i >= 0 { return n[:i] } return "" } // Append returns the qualified name appended with the provided short name. // // Invariant: n == n.Parent().Append(n.Name()) // assuming n is valid func (n FullName) Append(s Name) FullName { if n == "" { return FullName(s) } return n + "." + FullName(s) } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/source.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "strconv" ) // SourceLocations is a list of source locations. type SourceLocations interface { // Len reports the number of source locations in the proto file. Len() int // Get returns the ith SourceLocation. It panics if out of bounds. Get(int) SourceLocation // ByPath returns the SourceLocation for the given path, // returning the first location if multiple exist for the same path. // If multiple locations exist for the same path, // then SourceLocation.Next index can be used to identify the // index of the next SourceLocation. // If no location exists for this path, it returns the zero value. ByPath(path SourcePath) SourceLocation // ByDescriptor returns the SourceLocation for the given descriptor, // returning the first location if multiple exist for the same path. // If no location exists for this descriptor, it returns the zero value. ByDescriptor(desc Descriptor) SourceLocation doNotImplement } // SourceLocation describes a source location and // corresponds with the google.protobuf.SourceCodeInfo.Location message. type SourceLocation struct { // Path is the path to the declaration from the root file descriptor. // The contents of this slice must not be mutated. Path SourcePath // StartLine and StartColumn are the zero-indexed starting location // in the source file for the declaration. StartLine, StartColumn int // EndLine and EndColumn are the zero-indexed ending location // in the source file for the declaration. // In the descriptor.proto, the end line may be omitted if it is identical // to the start line. Here, it is always populated. EndLine, EndColumn int // LeadingDetachedComments are the leading detached comments // for the declaration. The contents of this slice must not be mutated. LeadingDetachedComments []string // LeadingComments is the leading attached comment for the declaration. LeadingComments string // TrailingComments is the trailing attached comment for the declaration. TrailingComments string // Next is an index into SourceLocations for the next source location that // has the same Path. It is zero if there is no next location. Next int } // SourcePath identifies part of a file descriptor for a source location. // The SourcePath is a sequence of either field numbers or indexes into // a repeated field that form a path starting from the root file descriptor. // // See google.protobuf.SourceCodeInfo.Location.path. type SourcePath []int32 // Equal reports whether p1 equals p2. func (p1 SourcePath) Equal(p2 SourcePath) bool { if len(p1) != len(p2) { return false } for i := range p1 { if p1[i] != p2[i] { return false } } return true } // String formats the path in a humanly readable manner. // The output is guaranteed to be deterministic, // making it suitable for use as a key into a Go map. // It is not guaranteed to be stable as the exact output could change // in a future version of this module. // // Example output: // .message_type[6].nested_type[15].field[3] func (p SourcePath) String() string { b := p.appendFileDescriptorProto(nil) for _, i := range p { b = append(b, '.') b = strconv.AppendInt(b, int64(i), 10) } return string(b) } type appendFunc func(*SourcePath, []byte) []byte func (p *SourcePath) appendSingularField(b []byte, name string, f appendFunc) []byte { if len(*p) == 0 { return b } b = append(b, '.') b = append(b, name...) *p = (*p)[1:] if f != nil { b = f(p, b) } return b } func (p *SourcePath) appendRepeatedField(b []byte, name string, f appendFunc) []byte { b = p.appendSingularField(b, name, nil) if len(*p) == 0 || (*p)[0] < 0 { return b } b = append(b, '[') b = strconv.AppendUint(b, uint64((*p)[0]), 10) b = append(b, ']') *p = (*p)[1:] if f != nil { b = f(p, b) } return b } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Code generated by generate-protos. DO NOT EDIT. package protoreflect func (p *SourcePath) appendFileDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "package", nil) case 3: b = p.appendRepeatedField(b, "dependency", nil) case 10: b = p.appendRepeatedField(b, "public_dependency", nil) case 11: b = p.appendRepeatedField(b, "weak_dependency", nil) case 4: b = p.appendRepeatedField(b, "message_type", (*SourcePath).appendDescriptorProto) case 5: b = p.appendRepeatedField(b, "enum_type", (*SourcePath).appendEnumDescriptorProto) case 6: b = p.appendRepeatedField(b, "service", (*SourcePath).appendServiceDescriptorProto) case 7: b = p.appendRepeatedField(b, "extension", (*SourcePath).appendFieldDescriptorProto) case 8: b = p.appendSingularField(b, "options", (*SourcePath).appendFileOptions) case 9: b = p.appendSingularField(b, "source_code_info", (*SourcePath).appendSourceCodeInfo) case 12: b = p.appendSingularField(b, "syntax", nil) } return b } func (p *SourcePath) appendDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "field", (*SourcePath).appendFieldDescriptorProto) case 6: b = p.appendRepeatedField(b, "extension", (*SourcePath).appendFieldDescriptorProto) case 3: b = p.appendRepeatedField(b, "nested_type", (*SourcePath).appendDescriptorProto) case 4: b = p.appendRepeatedField(b, "enum_type", (*SourcePath).appendEnumDescriptorProto) case 5: b = p.appendRepeatedField(b, "extension_range", (*SourcePath).appendDescriptorProto_ExtensionRange) case 8: b = p.appendRepeatedField(b, "oneof_decl", (*SourcePath).appendOneofDescriptorProto) case 7: b = p.appendSingularField(b, "options", (*SourcePath).appendMessageOptions) case 9: b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendDescriptorProto_ReservedRange) case 10: b = p.appendRepeatedField(b, "reserved_name", nil) } return b } func (p *SourcePath) appendEnumDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "value", (*SourcePath).appendEnumValueDescriptorProto) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendEnumOptions) case 4: b = p.appendRepeatedField(b, "reserved_range", (*SourcePath).appendEnumDescriptorProto_EnumReservedRange) case 5: b = p.appendRepeatedField(b, "reserved_name", nil) } return b } func (p *SourcePath) appendServiceDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendRepeatedField(b, "method", (*SourcePath).appendMethodDescriptorProto) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendServiceOptions) } return b } func (p *SourcePath) appendFieldDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 3: b = p.appendSingularField(b, "number", nil) case 4: b = p.appendSingularField(b, "label", nil) case 5: b = p.appendSingularField(b, "type", nil) case 6: b = p.appendSingularField(b, "type_name", nil) case 2: b = p.appendSingularField(b, "extendee", nil) case 7: b = p.appendSingularField(b, "default_value", nil) case 9: b = p.appendSingularField(b, "oneof_index", nil) case 10: b = p.appendSingularField(b, "json_name", nil) case 8: b = p.appendSingularField(b, "options", (*SourcePath).appendFieldOptions) case 17: b = p.appendSingularField(b, "proto3_optional", nil) } return b } func (p *SourcePath) appendFileOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "java_package", nil) case 8: b = p.appendSingularField(b, "java_outer_classname", nil) case 10: b = p.appendSingularField(b, "java_multiple_files", nil) case 20: b = p.appendSingularField(b, "java_generate_equals_and_hash", nil) case 27: b = p.appendSingularField(b, "java_string_check_utf8", nil) case 9: b = p.appendSingularField(b, "optimize_for", nil) case 11: b = p.appendSingularField(b, "go_package", nil) case 16: b = p.appendSingularField(b, "cc_generic_services", nil) case 17: b = p.appendSingularField(b, "java_generic_services", nil) case 18: b = p.appendSingularField(b, "py_generic_services", nil) case 42: b = p.appendSingularField(b, "php_generic_services", nil) case 23: b = p.appendSingularField(b, "deprecated", nil) case 31: b = p.appendSingularField(b, "cc_enable_arenas", nil) case 36: b = p.appendSingularField(b, "objc_class_prefix", nil) case 37: b = p.appendSingularField(b, "csharp_namespace", nil) case 39: b = p.appendSingularField(b, "swift_prefix", nil) case 40: b = p.appendSingularField(b, "php_class_prefix", nil) case 41: b = p.appendSingularField(b, "php_namespace", nil) case 44: b = p.appendSingularField(b, "php_metadata_namespace", nil) case 45: b = p.appendSingularField(b, "ruby_package", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendSourceCodeInfo(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendRepeatedField(b, "location", (*SourcePath).appendSourceCodeInfo_Location) } return b } func (p *SourcePath) appendDescriptorProto_ExtensionRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendExtensionRangeOptions) } return b } func (p *SourcePath) appendOneofDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "options", (*SourcePath).appendOneofOptions) } return b } func (p *SourcePath) appendMessageOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "message_set_wire_format", nil) case 2: b = p.appendSingularField(b, "no_standard_descriptor_accessor", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 7: b = p.appendSingularField(b, "map_entry", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendDescriptorProto_ReservedRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) } return b } func (p *SourcePath) appendEnumValueDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "number", nil) case 3: b = p.appendSingularField(b, "options", (*SourcePath).appendEnumValueOptions) } return b } func (p *SourcePath) appendEnumOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 2: b = p.appendSingularField(b, "allow_alias", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendEnumDescriptorProto_EnumReservedRange(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "start", nil) case 2: b = p.appendSingularField(b, "end", nil) } return b } func (p *SourcePath) appendMethodDescriptorProto(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name", nil) case 2: b = p.appendSingularField(b, "input_type", nil) case 3: b = p.appendSingularField(b, "output_type", nil) case 4: b = p.appendSingularField(b, "options", (*SourcePath).appendMethodOptions) case 5: b = p.appendSingularField(b, "client_streaming", nil) case 6: b = p.appendSingularField(b, "server_streaming", nil) } return b } func (p *SourcePath) appendServiceOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 33: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendFieldOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "ctype", nil) case 2: b = p.appendSingularField(b, "packed", nil) case 6: b = p.appendSingularField(b, "jstype", nil) case 5: b = p.appendSingularField(b, "lazy", nil) case 3: b = p.appendSingularField(b, "deprecated", nil) case 10: b = p.appendSingularField(b, "weak", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendUninterpretedOption(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 2: b = p.appendRepeatedField(b, "name", (*SourcePath).appendUninterpretedOption_NamePart) case 3: b = p.appendSingularField(b, "identifier_value", nil) case 4: b = p.appendSingularField(b, "positive_int_value", nil) case 5: b = p.appendSingularField(b, "negative_int_value", nil) case 6: b = p.appendSingularField(b, "double_value", nil) case 7: b = p.appendSingularField(b, "string_value", nil) case 8: b = p.appendSingularField(b, "aggregate_value", nil) } return b } func (p *SourcePath) appendSourceCodeInfo_Location(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendRepeatedField(b, "path", nil) case 2: b = p.appendRepeatedField(b, "span", nil) case 3: b = p.appendSingularField(b, "leading_comments", nil) case 4: b = p.appendSingularField(b, "trailing_comments", nil) case 6: b = p.appendRepeatedField(b, "leading_detached_comments", nil) } return b } func (p *SourcePath) appendExtensionRangeOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendOneofOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendEnumValueOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "deprecated", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendMethodOptions(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 33: b = p.appendSingularField(b, "deprecated", nil) case 34: b = p.appendSingularField(b, "idempotency_level", nil) case 999: b = p.appendRepeatedField(b, "uninterpreted_option", (*SourcePath).appendUninterpretedOption) } return b } func (p *SourcePath) appendUninterpretedOption_NamePart(b []byte) []byte { if len(*p) == 0 { return b } switch (*p)[0] { case 1: b = p.appendSingularField(b, "name_part", nil) case 2: b = p.appendSingularField(b, "is_extension", nil) } return b } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/type.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect // Descriptor provides a set of accessors that are common to every descriptor. // Each descriptor type wraps the equivalent google.protobuf.XXXDescriptorProto, // but provides efficient lookup and immutability. // // Each descriptor is comparable. Equality implies that the two types are // exactly identical. However, it is possible for the same semantically // identical proto type to be represented by multiple type descriptors. // // For example, suppose we have t1 and t2 which are both MessageDescriptors. // If t1 == t2, then the types are definitely equal and all accessors return // the same information. However, if t1 != t2, then it is still possible that // they still represent the same proto type (e.g., t1.FullName == t2.FullName). // This can occur if a descriptor type is created dynamically, or multiple // versions of the same proto type are accidentally linked into the Go binary. type Descriptor interface { // ParentFile returns the parent file descriptor that this descriptor // is declared within. The parent file for the file descriptor is itself. // // Support for this functionality is optional and may return nil. ParentFile() FileDescriptor // Parent returns the parent containing this descriptor declaration. // The following shows the mapping from child type to possible parent types: // // ╔═════════════════════╤═══════════════════════════════════╗ // ║ Child type │ Possible parent types ║ // ╠═════════════════════╪═══════════════════════════════════╣ // ║ FileDescriptor │ nil ║ // ║ MessageDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ FieldDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ OneofDescriptor │ MessageDescriptor ║ // ║ EnumDescriptor │ FileDescriptor, MessageDescriptor ║ // ║ EnumValueDescriptor │ EnumDescriptor ║ // ║ ServiceDescriptor │ FileDescriptor ║ // ║ MethodDescriptor │ ServiceDescriptor ║ // ╚═════════════════════╧═══════════════════════════════════╝ // // Support for this functionality is optional and may return nil. Parent() Descriptor // Index returns the index of this descriptor within its parent. // It returns 0 if the descriptor does not have a parent or if the parent // is unknown. Index() int // Syntax is the protobuf syntax. Syntax() Syntax // e.g., Proto2 or Proto3 // Name is the short name of the declaration (i.e., FullName.Name). Name() Name // e.g., "Any" // FullName is the fully-qualified name of the declaration. // // The FullName is a concatenation of the full name of the type that this // type is declared within and the declaration name. For example, // field "foo_field" in message "proto.package.MyMessage" is // uniquely identified as "proto.package.MyMessage.foo_field". // Enum values are an exception to the rule (see EnumValueDescriptor). FullName() FullName // e.g., "google.protobuf.Any" // IsPlaceholder reports whether type information is missing since a // dependency is not resolved, in which case only name information is known. // // Placeholder types may only be returned by the following accessors // as a result of unresolved dependencies or weak imports: // // ╔═══════════════════════════════════╤═════════════════════╗ // ║ Accessor │ Descriptor ║ // ╠═══════════════════════════════════╪═════════════════════╣ // ║ FileImports.FileDescriptor │ FileDescriptor ║ // ║ FieldDescriptor.Enum │ EnumDescriptor ║ // ║ FieldDescriptor.Message │ MessageDescriptor ║ // ║ FieldDescriptor.DefaultEnumValue │ EnumValueDescriptor ║ // ║ FieldDescriptor.ContainingMessage │ MessageDescriptor ║ // ║ MethodDescriptor.Input │ MessageDescriptor ║ // ║ MethodDescriptor.Output │ MessageDescriptor ║ // ╚═══════════════════════════════════╧═════════════════════╝ // // If true, only Name and FullName are valid. // For FileDescriptor, the Path is also valid. IsPlaceholder() bool // Options returns the descriptor options. The caller must not modify // the returned value. // // To avoid a dependency cycle, this function returns a proto.Message value. // The proto message type returned for each descriptor type is as follows: // ╔═════════════════════╤══════════════════════════════════════════╗ // ║ Go type │ Protobuf message type ║ // ╠═════════════════════╪══════════════════════════════════════════╣ // ║ FileDescriptor │ google.protobuf.FileOptions ║ // ║ EnumDescriptor │ google.protobuf.EnumOptions ║ // ║ EnumValueDescriptor │ google.protobuf.EnumValueOptions ║ // ║ MessageDescriptor │ google.protobuf.MessageOptions ║ // ║ FieldDescriptor │ google.protobuf.FieldOptions ║ // ║ OneofDescriptor │ google.protobuf.OneofOptions ║ // ║ ServiceDescriptor │ google.protobuf.ServiceOptions ║ // ║ MethodDescriptor │ google.protobuf.MethodOptions ║ // ╚═════════════════════╧══════════════════════════════════════════╝ // // This method returns a typed nil-pointer if no options are present. // The caller must import the descriptorpb package to use this. Options() ProtoMessage doNotImplement } // FileDescriptor describes the types in a complete proto file and // corresponds with the google.protobuf.FileDescriptorProto message. // // Top-level declarations: // EnumDescriptor, MessageDescriptor, FieldDescriptor, and/or ServiceDescriptor. type FileDescriptor interface { Descriptor // Descriptor.FullName is identical to Package // Path returns the file name, relative to the source tree root. Path() string // e.g., "path/to/file.proto" // Package returns the protobuf package namespace. Package() FullName // e.g., "google.protobuf" // Imports is a list of imported proto files. Imports() FileImports // Enums is a list of the top-level enum declarations. Enums() EnumDescriptors // Messages is a list of the top-level message declarations. Messages() MessageDescriptors // Extensions is a list of the top-level extension declarations. Extensions() ExtensionDescriptors // Services is a list of the top-level service declarations. Services() ServiceDescriptors // SourceLocations is a list of source locations. SourceLocations() SourceLocations isFileDescriptor } type isFileDescriptor interface{ ProtoType(FileDescriptor) } // FileImports is a list of file imports. type FileImports interface { // Len reports the number of files imported by this proto file. Len() int // Get returns the ith FileImport. It panics if out of bounds. Get(i int) FileImport doNotImplement } // FileImport is the declaration for a proto file import. type FileImport struct { // FileDescriptor is the file type for the given import. // It is a placeholder descriptor if IsWeak is set or if a dependency has // not been regenerated to implement the new reflection APIs. FileDescriptor // IsPublic reports whether this is a public import, which causes this file // to alias declarations within the imported file. The intended use cases // for this feature is the ability to move proto files without breaking // existing dependencies. // // The current file and the imported file must be within proto package. IsPublic bool // IsWeak reports whether this is a weak import, which does not impose // a direct dependency on the target file. // // Weak imports are a legacy proto1 feature. Equivalent behavior is // achieved using proto2 extension fields or proto3 Any messages. IsWeak bool } // MessageDescriptor describes a message and // corresponds with the google.protobuf.DescriptorProto message. // // Nested declarations: // FieldDescriptor, OneofDescriptor, FieldDescriptor, EnumDescriptor, // and/or MessageDescriptor. type MessageDescriptor interface { Descriptor // IsMapEntry indicates that this is an auto-generated message type to // represent the entry type for a map field. // // Map entry messages have only two fields: // • a "key" field with a field number of 1 // • a "value" field with a field number of 2 // The key and value types are determined by these two fields. // // If IsMapEntry is true, it implies that FieldDescriptor.IsMap is true // for some field with this message type. IsMapEntry() bool // Fields is a list of nested field declarations. Fields() FieldDescriptors // Oneofs is a list of nested oneof declarations. Oneofs() OneofDescriptors // ReservedNames is a list of reserved field names. ReservedNames() Names // ReservedRanges is a list of reserved ranges of field numbers. ReservedRanges() FieldRanges // RequiredNumbers is a list of required field numbers. // In Proto3, it is always an empty list. RequiredNumbers() FieldNumbers // ExtensionRanges is the field ranges used for extension fields. // In Proto3, it is always an empty ranges. ExtensionRanges() FieldRanges // ExtensionRangeOptions returns the ith extension range options. // // To avoid a dependency cycle, this method returns a proto.Message value, // which always contains a google.protobuf.ExtensionRangeOptions message. // This method returns a typed nil-pointer if no options are present. // The caller must import the descriptorpb package to use this. ExtensionRangeOptions(i int) ProtoMessage // Enums is a list of nested enum declarations. Enums() EnumDescriptors // Messages is a list of nested message declarations. Messages() MessageDescriptors // Extensions is a list of nested extension declarations. Extensions() ExtensionDescriptors isMessageDescriptor } type isMessageDescriptor interface{ ProtoType(MessageDescriptor) } // MessageType encapsulates a MessageDescriptor with a concrete Go implementation. // It is recommended that implementations of this interface also implement the // MessageFieldTypes interface. type MessageType interface { // New returns a newly allocated empty message. // It may return nil for synthetic messages representing a map entry. New() Message // Zero returns an empty, read-only message. // It may return nil for synthetic messages representing a map entry. Zero() Message // Descriptor returns the message descriptor. // // Invariant: t.Descriptor() == t.New().Descriptor() Descriptor() MessageDescriptor } // MessageFieldTypes extends a MessageType by providing type information // regarding enums and messages referenced by the message fields. type MessageFieldTypes interface { MessageType // Enum returns the EnumType for the ith field in Descriptor.Fields. // It returns nil if the ith field is not an enum kind. // It panics if out of bounds. // // Invariant: mt.Enum(i).Descriptor() == mt.Descriptor().Fields(i).Enum() Enum(i int) EnumType // Message returns the MessageType for the ith field in Descriptor.Fields. // It returns nil if the ith field is not a message or group kind. // It panics if out of bounds. // // Invariant: mt.Message(i).Descriptor() == mt.Descriptor().Fields(i).Message() Message(i int) MessageType } // MessageDescriptors is a list of message declarations. type MessageDescriptors interface { // Len reports the number of messages. Len() int // Get returns the ith MessageDescriptor. It panics if out of bounds. Get(i int) MessageDescriptor // ByName returns the MessageDescriptor for a message named s. // It returns nil if not found. ByName(s Name) MessageDescriptor doNotImplement } // FieldDescriptor describes a field within a message and // corresponds with the google.protobuf.FieldDescriptorProto message. // // It is used for both normal fields defined within the parent message // (e.g., MessageDescriptor.Fields) and fields that extend some remote message // (e.g., FileDescriptor.Extensions or MessageDescriptor.Extensions). type FieldDescriptor interface { Descriptor // Number reports the unique number for this field. Number() FieldNumber // Cardinality reports the cardinality for this field. Cardinality() Cardinality // Kind reports the basic kind for this field. Kind() Kind // HasJSONName reports whether this field has an explicitly set JSON name. HasJSONName() bool // JSONName reports the name used for JSON serialization. // It is usually the camel-cased form of the field name. // Extension fields are represented by the full name surrounded by brackets. JSONName() string // TextName reports the name used for text serialization. // It is usually the name of the field, except that groups use the name // of the inlined message, and extension fields are represented by the // full name surrounded by brackets. TextName() string // HasPresence reports whether the field distinguishes between unpopulated // and default values. HasPresence() bool // IsExtension reports whether this is an extension field. If false, // then Parent and ContainingMessage refer to the same message. // Otherwise, ContainingMessage and Parent likely differ. IsExtension() bool // HasOptionalKeyword reports whether the "optional" keyword was explicitly // specified in the source .proto file. HasOptionalKeyword() bool // IsWeak reports whether this is a weak field, which does not impose a // direct dependency on the target type. // If true, then Message returns a placeholder type. IsWeak() bool // IsPacked reports whether repeated primitive numeric kinds should be // serialized using a packed encoding. // If true, then it implies Cardinality is Repeated. IsPacked() bool // IsList reports whether this field represents a list, // where the value type for the associated field is a List. // It is equivalent to checking whether Cardinality is Repeated and // that IsMap reports false. IsList() bool // IsMap reports whether this field represents a map, // where the value type for the associated field is a Map. // It is equivalent to checking whether Cardinality is Repeated, // that the Kind is MessageKind, and that Message.IsMapEntry reports true. IsMap() bool // MapKey returns the field descriptor for the key in the map entry. // It returns nil if IsMap reports false. MapKey() FieldDescriptor // MapValue returns the field descriptor for the value in the map entry. // It returns nil if IsMap reports false. MapValue() FieldDescriptor // HasDefault reports whether this field has a default value. HasDefault() bool // Default returns the default value for scalar fields. // For proto2, it is the default value as specified in the proto file, // or the zero value if unspecified. // For proto3, it is always the zero value of the scalar. // The Value type is determined by the Kind. Default() Value // DefaultEnumValue returns the enum value descriptor for the default value // of an enum field, and is nil for any other kind of field. DefaultEnumValue() EnumValueDescriptor // ContainingOneof is the containing oneof that this field belongs to, // and is nil if this field is not part of a oneof. ContainingOneof() OneofDescriptor // ContainingMessage is the containing message that this field belongs to. // For extension fields, this may not necessarily be the parent message // that the field is declared within. ContainingMessage() MessageDescriptor // Enum is the enum descriptor if Kind is EnumKind. // It returns nil for any other Kind. Enum() EnumDescriptor // Message is the message descriptor if Kind is // MessageKind or GroupKind. It returns nil for any other Kind. Message() MessageDescriptor isFieldDescriptor } type isFieldDescriptor interface{ ProtoType(FieldDescriptor) } // FieldDescriptors is a list of field declarations. type FieldDescriptors interface { // Len reports the number of fields. Len() int // Get returns the ith FieldDescriptor. It panics if out of bounds. Get(i int) FieldDescriptor // ByName returns the FieldDescriptor for a field named s. // It returns nil if not found. ByName(s Name) FieldDescriptor // ByJSONName returns the FieldDescriptor for a field with s as the JSON name. // It returns nil if not found. ByJSONName(s string) FieldDescriptor // ByTextName returns the FieldDescriptor for a field with s as the text name. // It returns nil if not found. ByTextName(s string) FieldDescriptor // ByNumber returns the FieldDescriptor for a field numbered n. // It returns nil if not found. ByNumber(n FieldNumber) FieldDescriptor doNotImplement } // OneofDescriptor describes a oneof field set within a given message and // corresponds with the google.protobuf.OneofDescriptorProto message. type OneofDescriptor interface { Descriptor // IsSynthetic reports whether this is a synthetic oneof created to support // proto3 optional semantics. If true, Fields contains exactly one field // with HasOptionalKeyword specified. IsSynthetic() bool // Fields is a list of fields belonging to this oneof. Fields() FieldDescriptors isOneofDescriptor } type isOneofDescriptor interface{ ProtoType(OneofDescriptor) } // OneofDescriptors is a list of oneof declarations. type OneofDescriptors interface { // Len reports the number of oneof fields. Len() int // Get returns the ith OneofDescriptor. It panics if out of bounds. Get(i int) OneofDescriptor // ByName returns the OneofDescriptor for a oneof named s. // It returns nil if not found. ByName(s Name) OneofDescriptor doNotImplement } // ExtensionDescriptor is an alias of FieldDescriptor for documentation. type ExtensionDescriptor = FieldDescriptor // ExtensionTypeDescriptor is an ExtensionDescriptor with an associated ExtensionType. type ExtensionTypeDescriptor interface { ExtensionDescriptor // Type returns the associated ExtensionType. Type() ExtensionType // Descriptor returns the plain ExtensionDescriptor without the // associated ExtensionType. Descriptor() ExtensionDescriptor } // ExtensionDescriptors is a list of field declarations. type ExtensionDescriptors interface { // Len reports the number of fields. Len() int // Get returns the ith ExtensionDescriptor. It panics if out of bounds. Get(i int) ExtensionDescriptor // ByName returns the ExtensionDescriptor for a field named s. // It returns nil if not found. ByName(s Name) ExtensionDescriptor doNotImplement } // ExtensionType encapsulates an ExtensionDescriptor with a concrete // Go implementation. The nested field descriptor must be for a extension field. // // While a normal field is a member of the parent message that it is declared // within (see Descriptor.Parent), an extension field is a member of some other // target message (see ExtensionDescriptor.Extendee) and may have no // relationship with the parent. However, the full name of an extension field is // relative to the parent that it is declared within. // // For example: // syntax = "proto2"; // package example; // message FooMessage { // extensions 100 to max; // } // message BarMessage { // extends FooMessage { optional BarMessage bar_field = 100; } // } // // Field "bar_field" is an extension of FooMessage, but its full name is // "example.BarMessage.bar_field" instead of "example.FooMessage.bar_field". type ExtensionType interface { // New returns a new value for the field. // For scalars, this returns the default value in native Go form. New() Value // Zero returns a new value for the field. // For scalars, this returns the default value in native Go form. // For composite types, this returns an empty, read-only message, list, or map. Zero() Value // TypeDescriptor returns the extension type descriptor. TypeDescriptor() ExtensionTypeDescriptor // ValueOf wraps the input and returns it as a Value. // ValueOf panics if the input value is invalid or not the appropriate type. // // ValueOf is more extensive than protoreflect.ValueOf for a given field's // value as it has more type information available. ValueOf(interface{}) Value // InterfaceOf completely unwraps the Value to the underlying Go type. // InterfaceOf panics if the input is nil or does not represent the // appropriate underlying Go type. For composite types, it panics if the // value is not mutable. // // InterfaceOf is able to unwrap the Value further than Value.Interface // as it has more type information available. InterfaceOf(Value) interface{} // IsValidValue reports whether the Value is valid to assign to the field. IsValidValue(Value) bool // IsValidInterface reports whether the input is valid to assign to the field. IsValidInterface(interface{}) bool } // EnumDescriptor describes an enum and // corresponds with the google.protobuf.EnumDescriptorProto message. // // Nested declarations: // EnumValueDescriptor. type EnumDescriptor interface { Descriptor // Values is a list of nested enum value declarations. Values() EnumValueDescriptors // ReservedNames is a list of reserved enum names. ReservedNames() Names // ReservedRanges is a list of reserved ranges of enum numbers. ReservedRanges() EnumRanges isEnumDescriptor } type isEnumDescriptor interface{ ProtoType(EnumDescriptor) } // EnumType encapsulates an EnumDescriptor with a concrete Go implementation. type EnumType interface { // New returns an instance of this enum type with its value set to n. New(n EnumNumber) Enum // Descriptor returns the enum descriptor. // // Invariant: t.Descriptor() == t.New(0).Descriptor() Descriptor() EnumDescriptor } // EnumDescriptors is a list of enum declarations. type EnumDescriptors interface { // Len reports the number of enum types. Len() int // Get returns the ith EnumDescriptor. It panics if out of bounds. Get(i int) EnumDescriptor // ByName returns the EnumDescriptor for an enum named s. // It returns nil if not found. ByName(s Name) EnumDescriptor doNotImplement } // EnumValueDescriptor describes an enum value and // corresponds with the google.protobuf.EnumValueDescriptorProto message. // // All other proto declarations are in the namespace of the parent. // However, enum values do not follow this rule and are within the namespace // of the parent's parent (i.e., they are a sibling of the containing enum). // Thus, a value named "FOO_VALUE" declared within an enum uniquely identified // as "proto.package.MyEnum" has a full name of "proto.package.FOO_VALUE". type EnumValueDescriptor interface { Descriptor // Number returns the enum value as an integer. Number() EnumNumber isEnumValueDescriptor } type isEnumValueDescriptor interface{ ProtoType(EnumValueDescriptor) } // EnumValueDescriptors is a list of enum value declarations. type EnumValueDescriptors interface { // Len reports the number of enum values. Len() int // Get returns the ith EnumValueDescriptor. It panics if out of bounds. Get(i int) EnumValueDescriptor // ByName returns the EnumValueDescriptor for the enum value named s. // It returns nil if not found. ByName(s Name) EnumValueDescriptor // ByNumber returns the EnumValueDescriptor for the enum value numbered n. // If multiple have the same number, the first one defined is returned // It returns nil if not found. ByNumber(n EnumNumber) EnumValueDescriptor doNotImplement } // ServiceDescriptor describes a service and // corresponds with the google.protobuf.ServiceDescriptorProto message. // // Nested declarations: MethodDescriptor. type ServiceDescriptor interface { Descriptor // Methods is a list of nested message declarations. Methods() MethodDescriptors isServiceDescriptor } type isServiceDescriptor interface{ ProtoType(ServiceDescriptor) } // ServiceDescriptors is a list of service declarations. type ServiceDescriptors interface { // Len reports the number of services. Len() int // Get returns the ith ServiceDescriptor. It panics if out of bounds. Get(i int) ServiceDescriptor // ByName returns the ServiceDescriptor for a service named s. // It returns nil if not found. ByName(s Name) ServiceDescriptor doNotImplement } // MethodDescriptor describes a method and // corresponds with the google.protobuf.MethodDescriptorProto message. type MethodDescriptor interface { Descriptor // Input is the input message descriptor. Input() MessageDescriptor // Output is the output message descriptor. Output() MessageDescriptor // IsStreamingClient reports whether the client streams multiple messages. IsStreamingClient() bool // IsStreamingServer reports whether the server streams multiple messages. IsStreamingServer() bool isMethodDescriptor } type isMethodDescriptor interface{ ProtoType(MethodDescriptor) } // MethodDescriptors is a list of method declarations. type MethodDescriptors interface { // Len reports the number of methods. Len() int // Get returns the ith MethodDescriptor. It panics if out of bounds. Get(i int) MethodDescriptor // ByName returns the MethodDescriptor for a service method named s. // It returns nil if not found. ByName(s Name) MethodDescriptor doNotImplement } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/value.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import "google.golang.org/protobuf/encoding/protowire" // Enum is a reflection interface for a concrete enum value, // which provides type information and a getter for the enum number. // Enum does not provide a mutable API since enums are commonly backed by // Go constants, which are not addressable. type Enum interface { // Descriptor returns enum descriptor, which contains only the protobuf // type information for the enum. Descriptor() EnumDescriptor // Type returns the enum type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the enum descriptor be used instead. Type() EnumType // Number returns the enum value as an integer. Number() EnumNumber } // Message is a reflective interface for a concrete message value, // encapsulating both type and value information for the message. // // Accessor/mutators for individual fields are keyed by FieldDescriptor. // For non-extension fields, the descriptor must exactly match the // field known by the parent message. // For extension fields, the descriptor must implement ExtensionTypeDescriptor, // extend the parent message (i.e., have the same message FullName), and // be within the parent's extension range. // // Each field Value can be a scalar or a composite type (Message, List, or Map). // See Value for the Go types associated with a FieldDescriptor. // Providing a Value that is invalid or of an incorrect type panics. type Message interface { // Descriptor returns message descriptor, which contains only the protobuf // type information for the message. Descriptor() MessageDescriptor // Type returns the message type, which encapsulates both Go and protobuf // type information. If the Go type information is not needed, // it is recommended that the message descriptor be used instead. Type() MessageType // New returns a newly allocated and mutable empty message. New() Message // Interface unwraps the message reflection interface and // returns the underlying ProtoMessage interface. Interface() ProtoMessage // Range iterates over every populated field in an undefined order, // calling f for each field descriptor and value encountered. // Range returns immediately if f returns false. // While iterating, mutating operations may only be performed // on the current field descriptor. Range(f func(FieldDescriptor, Value) bool) // Has reports whether a field is populated. // // Some fields have the property of nullability where it is possible to // distinguish between the default value of a field and whether the field // was explicitly populated with the default value. Singular message fields, // member fields of a oneof, and proto2 scalar fields are nullable. Such // fields are populated only if explicitly set. // // In other cases (aside from the nullable cases above), // a proto3 scalar field is populated if it contains a non-zero value, and // a repeated field is populated if it is non-empty. Has(FieldDescriptor) bool // Clear clears the field such that a subsequent Has call reports false. // // Clearing an extension field clears both the extension type and value // associated with the given field number. // // Clear is a mutating operation and unsafe for concurrent use. Clear(FieldDescriptor) // Get retrieves the value for a field. // // For unpopulated scalars, it returns the default value, where // the default value of a bytes scalar is guaranteed to be a copy. // For unpopulated composite types, it returns an empty, read-only view // of the value; to obtain a mutable reference, use Mutable. Get(FieldDescriptor) Value // Set stores the value for a field. // // For a field belonging to a oneof, it implicitly clears any other field // that may be currently set within the same oneof. // For extension fields, it implicitly stores the provided ExtensionType. // When setting a composite type, it is unspecified whether the stored value // aliases the source's memory in any way. If the composite value is an // empty, read-only value, then it panics. // // Set is a mutating operation and unsafe for concurrent use. Set(FieldDescriptor, Value) // Mutable returns a mutable reference to a composite type. // // If the field is unpopulated, it may allocate a composite value. // For a field belonging to a oneof, it implicitly clears any other field // that may be currently set within the same oneof. // For extension fields, it implicitly stores the provided ExtensionType // if not already stored. // It panics if the field does not contain a composite type. // // Mutable is a mutating operation and unsafe for concurrent use. Mutable(FieldDescriptor) Value // NewField returns a new value that is assignable to the field // for the given descriptor. For scalars, this returns the default value. // For lists, maps, and messages, this returns a new, empty, mutable value. NewField(FieldDescriptor) Value // WhichOneof reports which field within the oneof is populated, // returning nil if none are populated. // It panics if the oneof descriptor does not belong to this message. WhichOneof(OneofDescriptor) FieldDescriptor // GetUnknown retrieves the entire list of unknown fields. // The caller may only mutate the contents of the RawFields // if the mutated bytes are stored back into the message with SetUnknown. GetUnknown() RawFields // SetUnknown stores an entire list of unknown fields. // The raw fields must be syntactically valid according to the wire format. // An implementation may panic if this is not the case. // Once stored, the caller must not mutate the content of the RawFields. // An empty RawFields may be passed to clear the fields. // // SetUnknown is a mutating operation and unsafe for concurrent use. SetUnknown(RawFields) // IsValid reports whether the message is valid. // // An invalid message is an empty, read-only value. // // An invalid message often corresponds to a nil pointer of the concrete // message type, but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool // ProtoMethods returns optional fast-path implementions of various operations. // This method may return nil. // // The returned methods type is identical to // "google.golang.org/protobuf/runtime/protoiface".Methods. // Consult the protoiface package documentation for details. ProtoMethods() *methods } // RawFields is the raw bytes for an ordered sequence of fields. // Each field contains both the tag (representing field number and wire type), // and also the wire data itself. type RawFields []byte // IsValid reports whether b is syntactically correct wire format. func (b RawFields) IsValid() bool { for len(b) > 0 { _, _, n := protowire.ConsumeField(b) if n < 0 { return false } b = b[n:] } return true } // List is a zero-indexed, ordered list. // The element Value type is determined by FieldDescriptor.Kind. // Providing a Value that is invalid or of an incorrect type panics. type List interface { // Len reports the number of entries in the List. // Get, Set, and Truncate panic with out of bound indexes. Len() int // Get retrieves the value at the given index. // It never returns an invalid value. Get(int) Value // Set stores a value for the given index. // When setting a composite type, it is unspecified whether the set // value aliases the source's memory in any way. // // Set is a mutating operation and unsafe for concurrent use. Set(int, Value) // Append appends the provided value to the end of the list. // When appending a composite type, it is unspecified whether the appended // value aliases the source's memory in any way. // // Append is a mutating operation and unsafe for concurrent use. Append(Value) // AppendMutable appends a new, empty, mutable message value to the end // of the list and returns it. // It panics if the list does not contain a message type. AppendMutable() Value // Truncate truncates the list to a smaller length. // // Truncate is a mutating operation and unsafe for concurrent use. Truncate(int) // NewElement returns a new value for a list element. // For enums, this returns the first enum value. // For other scalars, this returns the zero value. // For messages, this returns a new, empty, mutable value. NewElement() Value // IsValid reports whether the list is valid. // // An invalid list is an empty, read-only value. // // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool } // Map is an unordered, associative map. // The entry MapKey type is determined by FieldDescriptor.MapKey.Kind. // The entry Value type is determined by FieldDescriptor.MapValue.Kind. // Providing a MapKey or Value that is invalid or of an incorrect type panics. type Map interface { // Len reports the number of elements in the map. Len() int // Range iterates over every map entry in an undefined order, // calling f for each key and value encountered. // Range calls f Len times unless f returns false, which stops iteration. // While iterating, mutating operations may only be performed // on the current map key. Range(f func(MapKey, Value) bool) // Has reports whether an entry with the given key is in the map. Has(MapKey) bool // Clear clears the entry associated with they given key. // The operation does nothing if there is no entry associated with the key. // // Clear is a mutating operation and unsafe for concurrent use. Clear(MapKey) // Get retrieves the value for an entry with the given key. // It returns an invalid value for non-existent entries. Get(MapKey) Value // Set stores the value for an entry with the given key. // It panics when given a key or value that is invalid or the wrong type. // When setting a composite type, it is unspecified whether the set // value aliases the source's memory in any way. // // Set is a mutating operation and unsafe for concurrent use. Set(MapKey, Value) // Mutable retrieves a mutable reference to the entry for the given key. // If no entry exists for the key, it creates a new, empty, mutable value // and stores it as the entry for the key. // It panics if the map value is not a message. Mutable(MapKey) Value // NewValue returns a new value assignable as a map value. // For enums, this returns the first enum value. // For other scalars, this returns the zero value. // For messages, this returns a new, empty, mutable value. NewValue() Value // IsValid reports whether the map is valid. // // An invalid map is an empty, read-only value. // // An invalid message often corresponds to a nil Go map value, // but the details are implementation dependent. // Validity is not part of the protobuf data model, and may not // be preserved in marshaling or other operations. IsValid() bool } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build purego appengine package protoreflect import "google.golang.org/protobuf/internal/pragma" type valueType int const ( nilType valueType = iota boolType int32Type int64Type uint32Type uint64Type float32Type float64Type stringType bytesType enumType ifaceType ) // value is a union where only one type can be represented at a time. // This uses a distinct field for each type. This is type safe in Go, but // occupies more memory than necessary (72B). type value struct { pragma.DoNotCompare // 0B typ valueType // 8B num uint64 // 8B str string // 16B bin []byte // 24B iface interface{} // 16B } func valueOfString(v string) Value { return Value{typ: stringType, str: v} } func valueOfBytes(v []byte) Value { return Value{typ: bytesType, bin: v} } func valueOfIface(v interface{}) Value { return Value{typ: ifaceType, iface: v} } func (v Value) getString() string { return v.str } func (v Value) getBytes() []byte { return v.bin } func (v Value) getIface() interface{} { return v.iface } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoreflect import ( "fmt" "math" ) // Value is a union where only one Go type may be set at a time. // The Value is used to represent all possible values a field may take. // The following shows which Go type is used to represent each proto Kind: // // ╔════════════╤═════════════════════════════════════╗ // ║ Go type │ Protobuf kind ║ // ╠════════════╪═════════════════════════════════════╣ // ║ bool │ BoolKind ║ // ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ // ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ // ║ uint32 │ Uint32Kind, Fixed32Kind ║ // ║ uint64 │ Uint64Kind, Fixed64Kind ║ // ║ float32 │ FloatKind ║ // ║ float64 │ DoubleKind ║ // ║ string │ StringKind ║ // ║ []byte │ BytesKind ║ // ║ EnumNumber │ EnumKind ║ // ║ Message │ MessageKind, GroupKind ║ // ╚════════════╧═════════════════════════════════════╝ // // Multiple protobuf Kinds may be represented by a single Go type if the type // can losslessly represent the information for the proto kind. For example, // Int64Kind, Sint64Kind, and Sfixed64Kind are all represented by int64, // but use different integer encoding methods. // // The List or Map types are used if the field cardinality is repeated. // A field is a List if FieldDescriptor.IsList reports true. // A field is a Map if FieldDescriptor.IsMap reports true. // // Converting to/from a Value and a concrete Go value panics on type mismatch. // For example, ValueOf("hello").Int() panics because this attempts to // retrieve an int64 from a string. type Value value // The protoreflect API uses a custom Value union type instead of interface{} // to keep the future open for performance optimizations. Using an interface{} // always incurs an allocation for primitives (e.g., int64) since it needs to // be boxed on the heap (as interfaces can only contain pointers natively). // Instead, we represent the Value union as a flat struct that internally keeps // track of which type is set. Using unsafe, the Value union can be reduced // down to 24B, which is identical in size to a slice. // // The latest compiler (Go1.11) currently suffers from some limitations: // • With inlining, the compiler should be able to statically prove that // only one of these switch cases are taken and inline one specific case. // See https://golang.org/issue/22310. // ValueOf returns a Value initialized with the concrete value stored in v. // This panics if the type does not match one of the allowed types in the // Value union. func ValueOf(v interface{}) Value { switch v := v.(type) { case nil: return Value{} case bool: return ValueOfBool(v) case int32: return ValueOfInt32(v) case int64: return ValueOfInt64(v) case uint32: return ValueOfUint32(v) case uint64: return ValueOfUint64(v) case float32: return ValueOfFloat32(v) case float64: return ValueOfFloat64(v) case string: return ValueOfString(v) case []byte: return ValueOfBytes(v) case EnumNumber: return ValueOfEnum(v) case Message, List, Map: return valueOfIface(v) case ProtoMessage: panic(fmt.Sprintf("invalid proto.Message(%T) type, expected a protoreflect.Message type", v)) default: panic(fmt.Sprintf("invalid type: %T", v)) } } // ValueOfBool returns a new boolean value. func ValueOfBool(v bool) Value { if v { return Value{typ: boolType, num: 1} } else { return Value{typ: boolType, num: 0} } } // ValueOfInt32 returns a new int32 value. func ValueOfInt32(v int32) Value { return Value{typ: int32Type, num: uint64(v)} } // ValueOfInt64 returns a new int64 value. func ValueOfInt64(v int64) Value { return Value{typ: int64Type, num: uint64(v)} } // ValueOfUint32 returns a new uint32 value. func ValueOfUint32(v uint32) Value { return Value{typ: uint32Type, num: uint64(v)} } // ValueOfUint64 returns a new uint64 value. func ValueOfUint64(v uint64) Value { return Value{typ: uint64Type, num: v} } // ValueOfFloat32 returns a new float32 value. func ValueOfFloat32(v float32) Value { return Value{typ: float32Type, num: uint64(math.Float64bits(float64(v)))} } // ValueOfFloat64 returns a new float64 value. func ValueOfFloat64(v float64) Value { return Value{typ: float64Type, num: uint64(math.Float64bits(float64(v)))} } // ValueOfString returns a new string value. func ValueOfString(v string) Value { return valueOfString(v) } // ValueOfBytes returns a new bytes value. func ValueOfBytes(v []byte) Value { return valueOfBytes(v[:len(v):len(v)]) } // ValueOfEnum returns a new enum value. func ValueOfEnum(v EnumNumber) Value { return Value{typ: enumType, num: uint64(v)} } // ValueOfMessage returns a new Message value. func ValueOfMessage(v Message) Value { return valueOfIface(v) } // ValueOfList returns a new List value. func ValueOfList(v List) Value { return valueOfIface(v) } // ValueOfMap returns a new Map value. func ValueOfMap(v Map) Value { return valueOfIface(v) } // IsValid reports whether v is populated with a value. func (v Value) IsValid() bool { return v.typ != nilType } // Interface returns v as an interface{}. // // Invariant: v == ValueOf(v).Interface() func (v Value) Interface() interface{} { switch v.typ { case nilType: return nil case boolType: return v.Bool() case int32Type: return int32(v.Int()) case int64Type: return int64(v.Int()) case uint32Type: return uint32(v.Uint()) case uint64Type: return uint64(v.Uint()) case float32Type: return float32(v.Float()) case float64Type: return float64(v.Float()) case stringType: return v.String() case bytesType: return v.Bytes() case enumType: return v.Enum() default: return v.getIface() } } func (v Value) typeName() string { switch v.typ { case nilType: return "nil" case boolType: return "bool" case int32Type: return "int32" case int64Type: return "int64" case uint32Type: return "uint32" case uint64Type: return "uint64" case float32Type: return "float32" case float64Type: return "float64" case stringType: return "string" case bytesType: return "bytes" case enumType: return "enum" default: switch v := v.getIface().(type) { case Message: return "message" case List: return "list" case Map: return "map" default: return fmt.Sprintf("", v) } } } func (v Value) panicMessage(what string) string { return fmt.Sprintf("type mismatch: cannot convert %v to %s", v.typeName(), what) } // Bool returns v as a bool and panics if the type is not a bool. func (v Value) Bool() bool { switch v.typ { case boolType: return v.num > 0 default: panic(v.panicMessage("bool")) } } // Int returns v as a int64 and panics if the type is not a int32 or int64. func (v Value) Int() int64 { switch v.typ { case int32Type, int64Type: return int64(v.num) default: panic(v.panicMessage("int")) } } // Uint returns v as a uint64 and panics if the type is not a uint32 or uint64. func (v Value) Uint() uint64 { switch v.typ { case uint32Type, uint64Type: return uint64(v.num) default: panic(v.panicMessage("uint")) } } // Float returns v as a float64 and panics if the type is not a float32 or float64. func (v Value) Float() float64 { switch v.typ { case float32Type, float64Type: return math.Float64frombits(uint64(v.num)) default: panic(v.panicMessage("float")) } } // String returns v as a string. Since this method implements fmt.Stringer, // this returns the formatted string value for any non-string type. func (v Value) String() string { switch v.typ { case stringType: return v.getString() default: return fmt.Sprint(v.Interface()) } } // Bytes returns v as a []byte and panics if the type is not a []byte. func (v Value) Bytes() []byte { switch v.typ { case bytesType: return v.getBytes() default: panic(v.panicMessage("bytes")) } } // Enum returns v as a EnumNumber and panics if the type is not a EnumNumber. func (v Value) Enum() EnumNumber { switch v.typ { case enumType: return EnumNumber(v.num) default: panic(v.panicMessage("enum")) } } // Message returns v as a Message and panics if the type is not a Message. func (v Value) Message() Message { switch vi := v.getIface().(type) { case Message: return vi default: panic(v.panicMessage("message")) } } // List returns v as a List and panics if the type is not a List. func (v Value) List() List { switch vi := v.getIface().(type) { case List: return vi default: panic(v.panicMessage("list")) } } // Map returns v as a Map and panics if the type is not a Map. func (v Value) Map() Map { switch vi := v.getIface().(type) { case Map: return vi default: panic(v.panicMessage("map")) } } // MapKey returns v as a MapKey and panics for invalid MapKey types. func (v Value) MapKey() MapKey { switch v.typ { case boolType, int32Type, int64Type, uint32Type, uint64Type, stringType: return MapKey(v) default: panic(v.panicMessage("map key")) } } // MapKey is used to index maps, where the Go type of the MapKey must match // the specified key Kind (see MessageDescriptor.IsMapEntry). // The following shows what Go type is used to represent each proto Kind: // // ╔═════════╤═════════════════════════════════════╗ // ║ Go type │ Protobuf kind ║ // ╠═════════╪═════════════════════════════════════╣ // ║ bool │ BoolKind ║ // ║ int32 │ Int32Kind, Sint32Kind, Sfixed32Kind ║ // ║ int64 │ Int64Kind, Sint64Kind, Sfixed64Kind ║ // ║ uint32 │ Uint32Kind, Fixed32Kind ║ // ║ uint64 │ Uint64Kind, Fixed64Kind ║ // ║ string │ StringKind ║ // ╚═════════╧═════════════════════════════════════╝ // // A MapKey is constructed and accessed through a Value: // k := ValueOf("hash").MapKey() // convert string to MapKey // s := k.String() // convert MapKey to string // // The MapKey is a strict subset of valid types used in Value; // converting a Value to a MapKey with an invalid type panics. type MapKey value // IsValid reports whether k is populated with a value. func (k MapKey) IsValid() bool { return Value(k).IsValid() } // Interface returns k as an interface{}. func (k MapKey) Interface() interface{} { return Value(k).Interface() } // Bool returns k as a bool and panics if the type is not a bool. func (k MapKey) Bool() bool { return Value(k).Bool() } // Int returns k as a int64 and panics if the type is not a int32 or int64. func (k MapKey) Int() int64 { return Value(k).Int() } // Uint returns k as a uint64 and panics if the type is not a uint32 or uint64. func (k MapKey) Uint() uint64 { return Value(k).Uint() } // String returns k as a string. Since this method implements fmt.Stringer, // this returns the formatted string value for any non-string type. func (k MapKey) String() string { return Value(k).String() } // Value returns k as a Value. func (k MapKey) Value() Value { return Value(k) } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // +build !purego,!appengine package protoreflect import ( "unsafe" "google.golang.org/protobuf/internal/pragma" ) type ( stringHeader struct { Data unsafe.Pointer Len int } sliceHeader struct { Data unsafe.Pointer Len int Cap int } ifaceHeader struct { Type unsafe.Pointer Data unsafe.Pointer } ) var ( nilType = typeOf(nil) boolType = typeOf(*new(bool)) int32Type = typeOf(*new(int32)) int64Type = typeOf(*new(int64)) uint32Type = typeOf(*new(uint32)) uint64Type = typeOf(*new(uint64)) float32Type = typeOf(*new(float32)) float64Type = typeOf(*new(float64)) stringType = typeOf(*new(string)) bytesType = typeOf(*new([]byte)) enumType = typeOf(*new(EnumNumber)) ) // typeOf returns a pointer to the Go type information. // The pointer is comparable and equal if and only if the types are identical. func typeOf(t interface{}) unsafe.Pointer { return (*ifaceHeader)(unsafe.Pointer(&t)).Type } // value is a union where only one type can be represented at a time. // The struct is 24B large on 64-bit systems and requires the minimum storage // necessary to represent each possible type. // // The Go GC needs to be able to scan variables containing pointers. // As such, pointers and non-pointers cannot be intermixed. type value struct { pragma.DoNotCompare // 0B // typ stores the type of the value as a pointer to the Go type. typ unsafe.Pointer // 8B // ptr stores the data pointer for a String, Bytes, or interface value. ptr unsafe.Pointer // 8B // num stores a Bool, Int32, Int64, Uint32, Uint64, Float32, Float64, or // Enum value as a raw uint64. // // It is also used to store the length of a String or Bytes value; // the capacity is ignored. num uint64 // 8B } func valueOfString(v string) Value { p := (*stringHeader)(unsafe.Pointer(&v)) return Value{typ: stringType, ptr: p.Data, num: uint64(len(v))} } func valueOfBytes(v []byte) Value { p := (*sliceHeader)(unsafe.Pointer(&v)) return Value{typ: bytesType, ptr: p.Data, num: uint64(len(v))} } func valueOfIface(v interface{}) Value { p := (*ifaceHeader)(unsafe.Pointer(&v)) return Value{typ: p.Type, ptr: p.Data} } func (v Value) getString() (x string) { *(*stringHeader)(unsafe.Pointer(&x)) = stringHeader{Data: v.ptr, Len: int(v.num)} return x } func (v Value) getBytes() (x []byte) { *(*sliceHeader)(unsafe.Pointer(&x)) = sliceHeader{Data: v.ptr, Len: int(v.num), Cap: int(v.num)} return x } func (v Value) getIface() (x interface{}) { *(*ifaceHeader)(unsafe.Pointer(&x)) = ifaceHeader{Type: v.typ, Data: v.ptr} return x } ================================================ FILE: vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoregistry provides data structures to register and lookup // protobuf descriptor types. // // The Files registry contains file descriptors and provides the ability // to iterate over the files or lookup a specific descriptor within the files. // Files only contains protobuf descriptors and has no understanding of Go // type information that may be associated with each descriptor. // // The Types registry contains descriptor types for which there is a known // Go type associated with that descriptor. It provides the ability to iterate // over the registered types or lookup a type by name. package protoregistry import ( "fmt" "os" "strings" "sync" "google.golang.org/protobuf/internal/encoding/messageset" "google.golang.org/protobuf/internal/errors" "google.golang.org/protobuf/internal/flags" "google.golang.org/protobuf/reflect/protoreflect" ) // conflictPolicy configures the policy for handling registration conflicts. // // It can be over-written at compile time with a linker-initialized variable: // go build -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn" // // It can be over-written at program execution with an environment variable: // GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn ./main // // Neither of the above are covered by the compatibility promise and // may be removed in a future release of this module. var conflictPolicy = "panic" // "panic" | "warn" | "ignore" // ignoreConflict reports whether to ignore a registration conflict // given the descriptor being registered and the error. // It is a variable so that the behavior is easily overridden in another file. var ignoreConflict = func(d protoreflect.Descriptor, err error) bool { const env = "GOLANG_PROTOBUF_REGISTRATION_CONFLICT" const faq = "https://developers.google.com/protocol-buffers/docs/reference/go/faq#namespace-conflict" policy := conflictPolicy if v := os.Getenv(env); v != "" { policy = v } switch policy { case "panic": panic(fmt.Sprintf("%v\nSee %v\n", err, faq)) case "warn": fmt.Fprintf(os.Stderr, "WARNING: %v\nSee %v\n\n", err, faq) return true case "ignore": return true default: panic("invalid " + env + " value: " + os.Getenv(env)) } } var globalMutex sync.RWMutex // GlobalFiles is a global registry of file descriptors. var GlobalFiles *Files = new(Files) // GlobalTypes is the registry used by default for type lookups // unless a local registry is provided by the user. var GlobalTypes *Types = new(Types) // NotFound is a sentinel error value to indicate that the type was not found. // // Since registry lookup can happen in the critical performance path, resolvers // must return this exact error value, not an error wrapping it. var NotFound = errors.New("not found") // Files is a registry for looking up or iterating over files and the // descriptors contained within them. // The Find and Range methods are safe for concurrent use. type Files struct { // The map of descsByName contains: // EnumDescriptor // EnumValueDescriptor // MessageDescriptor // ExtensionDescriptor // ServiceDescriptor // *packageDescriptor // // Note that files are stored as a slice, since a package may contain // multiple files. Only top-level declarations are registered. // Note that enum values are in the top-level since that are in the same // scope as the parent enum. descsByName map[protoreflect.FullName]interface{} filesByPath map[string]protoreflect.FileDescriptor } type packageDescriptor struct { files []protoreflect.FileDescriptor } // RegisterFile registers the provided file descriptor. // // If any descriptor within the file conflicts with the descriptor of any // previously registered file (e.g., two enums with the same full name), // then the file is not registered and an error is returned. // // It is permitted for multiple files to have the same file path. func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error { if r == GlobalFiles { globalMutex.Lock() defer globalMutex.Unlock() } if r.descsByName == nil { r.descsByName = map[protoreflect.FullName]interface{}{ "": &packageDescriptor{}, } r.filesByPath = make(map[string]protoreflect.FileDescriptor) } path := file.Path() if prev := r.filesByPath[path]; prev != nil { r.checkGenProtoConflict(path) err := errors.New("file %q is already registered", file.Path()) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(file, err) { err = nil } return err } for name := file.Package(); name != ""; name = name.Parent() { switch prev := r.descsByName[name]; prev.(type) { case nil, *packageDescriptor: default: err := errors.New("file %q has a package name conflict over %v", file.Path(), name) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(file, err) { err = nil } return err } } var err error var hasConflict bool rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) { if prev := r.descsByName[d.FullName()]; prev != nil { hasConflict = true err = errors.New("file %q has a name conflict over %v", file.Path(), d.FullName()) err = amendErrorWithCaller(err, prev, file) if r == GlobalFiles && ignoreConflict(d, err) { err = nil } } }) if hasConflict { return err } for name := file.Package(); name != ""; name = name.Parent() { if r.descsByName[name] == nil { r.descsByName[name] = &packageDescriptor{} } } p := r.descsByName[file.Package()].(*packageDescriptor) p.files = append(p.files, file) rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) { r.descsByName[d.FullName()] = d }) r.filesByPath[path] = file return nil } // Several well-known types were hosted in the google.golang.org/genproto module // but were later moved to this module. To avoid a weak dependency on the // genproto module (and its relatively large set of transitive dependencies), // we rely on a registration conflict to determine whether the genproto version // is too old (i.e., does not contain aliases to the new type declarations). func (r *Files) checkGenProtoConflict(path string) { if r != GlobalFiles { return } var prevPath string const prevModule = "google.golang.org/genproto" const prevVersion = "cb27e3aa (May 26th, 2020)" switch path { case "google/protobuf/field_mask.proto": prevPath = prevModule + "/protobuf/field_mask" case "google/protobuf/api.proto": prevPath = prevModule + "/protobuf/api" case "google/protobuf/type.proto": prevPath = prevModule + "/protobuf/ptype" case "google/protobuf/source_context.proto": prevPath = prevModule + "/protobuf/source_context" default: return } pkgName := strings.TrimSuffix(strings.TrimPrefix(path, "google/protobuf/"), ".proto") pkgName = strings.Replace(pkgName, "_", "", -1) + "pb" // e.g., "field_mask" => "fieldmaskpb" currPath := "google.golang.org/protobuf/types/known/" + pkgName panic(fmt.Sprintf(""+ "duplicate registration of %q\n"+ "\n"+ "The generated definition for this file has moved:\n"+ "\tfrom: %q\n"+ "\tto: %q\n"+ "A dependency on the %q module must\n"+ "be at version %v or higher.\n"+ "\n"+ "Upgrade the dependency by running:\n"+ "\tgo get -u %v\n", path, prevPath, currPath, prevModule, prevVersion, prevPath)) } // FindDescriptorByName looks up a descriptor by the full name. // // This returns (nil, NotFound) if not found. func (r *Files) FindDescriptorByName(name protoreflect.FullName) (protoreflect.Descriptor, error) { if r == nil { return nil, NotFound } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } prefix := name suffix := nameSuffix("") for prefix != "" { if d, ok := r.descsByName[prefix]; ok { switch d := d.(type) { case protoreflect.EnumDescriptor: if d.FullName() == name { return d, nil } case protoreflect.EnumValueDescriptor: if d.FullName() == name { return d, nil } case protoreflect.MessageDescriptor: if d.FullName() == name { return d, nil } if d := findDescriptorInMessage(d, suffix); d != nil && d.FullName() == name { return d, nil } case protoreflect.ExtensionDescriptor: if d.FullName() == name { return d, nil } case protoreflect.ServiceDescriptor: if d.FullName() == name { return d, nil } if d := d.Methods().ByName(suffix.Pop()); d != nil && d.FullName() == name { return d, nil } } return nil, NotFound } prefix = prefix.Parent() suffix = nameSuffix(name[len(prefix)+len("."):]) } return nil, NotFound } func findDescriptorInMessage(md protoreflect.MessageDescriptor, suffix nameSuffix) protoreflect.Descriptor { name := suffix.Pop() if suffix == "" { if ed := md.Enums().ByName(name); ed != nil { return ed } for i := md.Enums().Len() - 1; i >= 0; i-- { if vd := md.Enums().Get(i).Values().ByName(name); vd != nil { return vd } } if xd := md.Extensions().ByName(name); xd != nil { return xd } if fd := md.Fields().ByName(name); fd != nil { return fd } if od := md.Oneofs().ByName(name); od != nil { return od } } if md := md.Messages().ByName(name); md != nil { if suffix == "" { return md } return findDescriptorInMessage(md, suffix) } return nil } type nameSuffix string func (s *nameSuffix) Pop() (name protoreflect.Name) { if i := strings.IndexByte(string(*s), '.'); i >= 0 { name, *s = protoreflect.Name((*s)[:i]), (*s)[i+1:] } else { name, *s = protoreflect.Name((*s)), "" } return name } // FindFileByPath looks up a file by the path. // // This returns (nil, NotFound) if not found. func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) { if r == nil { return nil, NotFound } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } if fd, ok := r.filesByPath[path]; ok { return fd, nil } return nil, NotFound } // NumFiles reports the number of registered files. func (r *Files) NumFiles() int { if r == nil { return 0 } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } return len(r.filesByPath) } // RangeFiles iterates over all registered files while f returns true. // The iteration order is undefined. func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) { if r == nil { return } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } for _, file := range r.filesByPath { if !f(file) { return } } } // NumFilesByPackage reports the number of registered files in a proto package. func (r *Files) NumFilesByPackage(name protoreflect.FullName) int { if r == nil { return 0 } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } p, ok := r.descsByName[name].(*packageDescriptor) if !ok { return 0 } return len(p.files) } // RangeFilesByPackage iterates over all registered files in a given proto package // while f returns true. The iteration order is undefined. func (r *Files) RangeFilesByPackage(name protoreflect.FullName, f func(protoreflect.FileDescriptor) bool) { if r == nil { return } if r == GlobalFiles { globalMutex.RLock() defer globalMutex.RUnlock() } p, ok := r.descsByName[name].(*packageDescriptor) if !ok { return } for _, file := range p.files { if !f(file) { return } } } // rangeTopLevelDescriptors iterates over all top-level descriptors in a file // which will be directly entered into the registry. func rangeTopLevelDescriptors(fd protoreflect.FileDescriptor, f func(protoreflect.Descriptor)) { eds := fd.Enums() for i := eds.Len() - 1; i >= 0; i-- { f(eds.Get(i)) vds := eds.Get(i).Values() for i := vds.Len() - 1; i >= 0; i-- { f(vds.Get(i)) } } mds := fd.Messages() for i := mds.Len() - 1; i >= 0; i-- { f(mds.Get(i)) } xds := fd.Extensions() for i := xds.Len() - 1; i >= 0; i-- { f(xds.Get(i)) } sds := fd.Services() for i := sds.Len() - 1; i >= 0; i-- { f(sds.Get(i)) } } // MessageTypeResolver is an interface for looking up messages. // // A compliant implementation must deterministically return the same type // if no error is encountered. // // The Types type implements this interface. type MessageTypeResolver interface { // FindMessageByName looks up a message by its full name. // E.g., "google.protobuf.Any" // // This return (nil, NotFound) if not found. FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) // FindMessageByURL looks up a message by a URL identifier. // See documentation on google.protobuf.Any.type_url for the URL format. // // This returns (nil, NotFound) if not found. FindMessageByURL(url string) (protoreflect.MessageType, error) } // ExtensionTypeResolver is an interface for looking up extensions. // // A compliant implementation must deterministically return the same type // if no error is encountered. // // The Types type implements this interface. type ExtensionTypeResolver interface { // FindExtensionByName looks up a extension field by the field's full name. // Note that this is the full name of the field as determined by // where the extension is declared and is unrelated to the full name of the // message being extended. // // This returns (nil, NotFound) if not found. FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) // FindExtensionByNumber looks up a extension field by the field number // within some parent message, identified by full name. // // This returns (nil, NotFound) if not found. FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } var ( _ MessageTypeResolver = (*Types)(nil) _ ExtensionTypeResolver = (*Types)(nil) ) // Types is a registry for looking up or iterating over descriptor types. // The Find and Range methods are safe for concurrent use. type Types struct { typesByName typesByName extensionsByMessage extensionsByMessage numEnums int numMessages int numExtensions int } type ( typesByName map[protoreflect.FullName]interface{} extensionsByMessage map[protoreflect.FullName]extensionsByNumber extensionsByNumber map[protoreflect.FieldNumber]protoreflect.ExtensionType ) // RegisterMessage registers the provided message type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterMessage(mt protoreflect.MessageType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. md := mt.Descriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } if err := r.register("message", md, mt); err != nil { return err } r.numMessages++ return nil } // RegisterEnum registers the provided enum type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterEnum(et protoreflect.EnumType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. ed := et.Descriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } if err := r.register("enum", ed, et); err != nil { return err } r.numEnums++ return nil } // RegisterExtension registers the provided extension type. // // If a naming conflict occurs, the type is not registered and an error is returned. func (r *Types) RegisterExtension(xt protoreflect.ExtensionType) error { // Under rare circumstances getting the descriptor might recursively // examine the registry, so fetch it before locking. // // A known case where this can happen: Fetching the TypeDescriptor for a // legacy ExtensionDesc can consult the global registry. xd := xt.TypeDescriptor() if r == GlobalTypes { globalMutex.Lock() defer globalMutex.Unlock() } field := xd.Number() message := xd.ContainingMessage().FullName() if prev := r.extensionsByMessage[message][field]; prev != nil { err := errors.New("extension number %d is already registered on message %v", field, message) err = amendErrorWithCaller(err, prev, xt) if !(r == GlobalTypes && ignoreConflict(xd, err)) { return err } } if err := r.register("extension", xd, xt); err != nil { return err } if r.extensionsByMessage == nil { r.extensionsByMessage = make(extensionsByMessage) } if r.extensionsByMessage[message] == nil { r.extensionsByMessage[message] = make(extensionsByNumber) } r.extensionsByMessage[message][field] = xt r.numExtensions++ return nil } func (r *Types) register(kind string, desc protoreflect.Descriptor, typ interface{}) error { name := desc.FullName() prev := r.typesByName[name] if prev != nil { err := errors.New("%v %v is already registered", kind, name) err = amendErrorWithCaller(err, prev, typ) if !(r == GlobalTypes && ignoreConflict(desc, err)) { return err } } if r.typesByName == nil { r.typesByName = make(typesByName) } r.typesByName[name] = typ return nil } // FindEnumByName looks up an enum by its full name. // E.g., "google.protobuf.Field.Kind". // // This returns (nil, NotFound) if not found. func (r *Types) FindEnumByName(enum protoreflect.FullName) (protoreflect.EnumType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[enum]; v != nil { if et, _ := v.(protoreflect.EnumType); et != nil { return et, nil } return nil, errors.New("found wrong type: got %v, want enum", typeName(v)) } return nil, NotFound } // FindMessageByName looks up a message by its full name, // e.g. "google.protobuf.Any". // // This returns (nil, NotFound) if not found. func (r *Types) FindMessageByName(message protoreflect.FullName) (protoreflect.MessageType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[message]; v != nil { if mt, _ := v.(protoreflect.MessageType); mt != nil { return mt, nil } return nil, errors.New("found wrong type: got %v, want message", typeName(v)) } return nil, NotFound } // FindMessageByURL looks up a message by a URL identifier. // See documentation on google.protobuf.Any.type_url for the URL format. // // This returns (nil, NotFound) if not found. func (r *Types) FindMessageByURL(url string) (protoreflect.MessageType, error) { // This function is similar to FindMessageByName but // truncates anything before and including '/' in the URL. if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } message := protoreflect.FullName(url) if i := strings.LastIndexByte(url, '/'); i >= 0 { message = message[i+len("/"):] } if v := r.typesByName[message]; v != nil { if mt, _ := v.(protoreflect.MessageType); mt != nil { return mt, nil } return nil, errors.New("found wrong type: got %v, want message", typeName(v)) } return nil, NotFound } // FindExtensionByName looks up a extension field by the field's full name. // Note that this is the full name of the field as determined by // where the extension is declared and is unrelated to the full name of the // message being extended. // // This returns (nil, NotFound) if not found. func (r *Types) FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if v := r.typesByName[field]; v != nil { if xt, _ := v.(protoreflect.ExtensionType); xt != nil { return xt, nil } // MessageSet extensions are special in that the name of the extension // is the name of the message type used to extend the MessageSet. // This naming scheme is used by text and JSON serialization. // // This feature is protected by the ProtoLegacy flag since MessageSets // are a proto1 feature that is long deprecated. if flags.ProtoLegacy { if _, ok := v.(protoreflect.MessageType); ok { field := field.Append(messageset.ExtensionName) if v := r.typesByName[field]; v != nil { if xt, _ := v.(protoreflect.ExtensionType); xt != nil { if messageset.IsMessageSetExtension(xt.TypeDescriptor()) { return xt, nil } } } } } return nil, errors.New("found wrong type: got %v, want extension", typeName(v)) } return nil, NotFound } // FindExtensionByNumber looks up a extension field by the field number // within some parent message, identified by full name. // // This returns (nil, NotFound) if not found. func (r *Types) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) { if r == nil { return nil, NotFound } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } if xt, ok := r.extensionsByMessage[message][field]; ok { return xt, nil } return nil, NotFound } // NumEnums reports the number of registered enums. func (r *Types) NumEnums() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numEnums } // RangeEnums iterates over all registered enums while f returns true. // Iteration order is undefined. func (r *Types) RangeEnums(f func(protoreflect.EnumType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if et, ok := typ.(protoreflect.EnumType); ok { if !f(et) { return } } } } // NumMessages reports the number of registered messages. func (r *Types) NumMessages() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numMessages } // RangeMessages iterates over all registered messages while f returns true. // Iteration order is undefined. func (r *Types) RangeMessages(f func(protoreflect.MessageType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if mt, ok := typ.(protoreflect.MessageType); ok { if !f(mt) { return } } } } // NumExtensions reports the number of registered extensions. func (r *Types) NumExtensions() int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return r.numExtensions } // RangeExtensions iterates over all registered extensions while f returns true. // Iteration order is undefined. func (r *Types) RangeExtensions(f func(protoreflect.ExtensionType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, typ := range r.typesByName { if xt, ok := typ.(protoreflect.ExtensionType); ok { if !f(xt) { return } } } } // NumExtensionsByMessage reports the number of registered extensions for // a given message type. func (r *Types) NumExtensionsByMessage(message protoreflect.FullName) int { if r == nil { return 0 } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } return len(r.extensionsByMessage[message]) } // RangeExtensionsByMessage iterates over all registered extensions filtered // by a given message type while f returns true. Iteration order is undefined. func (r *Types) RangeExtensionsByMessage(message protoreflect.FullName, f func(protoreflect.ExtensionType) bool) { if r == nil { return } if r == GlobalTypes { globalMutex.RLock() defer globalMutex.RUnlock() } for _, xt := range r.extensionsByMessage[message] { if !f(xt) { return } } } func typeName(t interface{}) string { switch t.(type) { case protoreflect.EnumType: return "enum" case protoreflect.MessageType: return "message" case protoreflect.ExtensionType: return "extension" default: return fmt.Sprintf("%T", t) } } func amendErrorWithCaller(err error, prev, curr interface{}) error { prevPkg := goPackage(prev) currPkg := goPackage(curr) if prevPkg == "" || currPkg == "" || prevPkg == currPkg { return err } return errors.New("%s\n\tpreviously from: %q\n\tcurrently from: %q", err, prevPkg, currPkg) } func goPackage(v interface{}) string { switch d := v.(type) { case protoreflect.EnumType: v = d.Descriptor() case protoreflect.MessageType: v = d.Descriptor() case protoreflect.ExtensionType: v = d.TypeDescriptor() } if d, ok := v.(protoreflect.Descriptor); ok { v = d.ParentFile() } if d, ok := v.(interface{ GoPackagePath() string }); ok { return d.GoPackagePath() } return "" } ================================================ FILE: vendor/google.golang.org/protobuf/runtime/protoiface/legacy.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoiface type MessageV1 interface { Reset() String() string ProtoMessage() } type ExtensionRangeV1 struct { Start, End int32 // both inclusive } ================================================ FILE: vendor/google.golang.org/protobuf/runtime/protoiface/methods.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoiface contains types referenced or implemented by messages. // // WARNING: This package should only be imported by message implementations. // The functionality found in this package should be accessed through // higher-level abstractions provided by the proto package. package protoiface import ( "google.golang.org/protobuf/internal/pragma" "google.golang.org/protobuf/reflect/protoreflect" ) // Methods is a set of optional fast-path implementations of various operations. type Methods = struct { pragma.NoUnkeyedLiterals // Flags indicate support for optional features. Flags SupportFlags // Size returns the size in bytes of the wire-format encoding of a message. // Marshal must be provided if a custom Size is provided. Size func(SizeInput) SizeOutput // Marshal formats a message in the wire-format encoding to the provided buffer. // Size should be provided if a custom Marshal is provided. // It must not return an error for a partial message. Marshal func(MarshalInput) (MarshalOutput, error) // Unmarshal parses the wire-format encoding and merges the result into a message. // It must not reset the target message or return an error for a partial message. Unmarshal func(UnmarshalInput) (UnmarshalOutput, error) // Merge merges the contents of a source message into a destination message. Merge func(MergeInput) MergeOutput // CheckInitialized returns an error if any required fields in the message are not set. CheckInitialized func(CheckInitializedInput) (CheckInitializedOutput, error) } // SupportFlags indicate support for optional features. type SupportFlags = uint64 const ( // SupportMarshalDeterministic reports whether MarshalOptions.Deterministic is supported. SupportMarshalDeterministic SupportFlags = 1 << iota // SupportUnmarshalDiscardUnknown reports whether UnmarshalOptions.DiscardUnknown is supported. SupportUnmarshalDiscardUnknown ) // SizeInput is input to the Size method. type SizeInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Flags MarshalInputFlags } // SizeOutput is output from the Size method. type SizeOutput = struct { pragma.NoUnkeyedLiterals Size int } // MarshalInput is input to the Marshal method. type MarshalInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Buf []byte // output is appended to this buffer Flags MarshalInputFlags } // MarshalOutput is output from the Marshal method. type MarshalOutput = struct { pragma.NoUnkeyedLiterals Buf []byte // contains marshaled message } // MarshalInputFlags configure the marshaler. // Most flags correspond to fields in proto.MarshalOptions. type MarshalInputFlags = uint8 const ( MarshalDeterministic MarshalInputFlags = 1 << iota MarshalUseCachedSize ) // UnmarshalInput is input to the Unmarshal method. type UnmarshalInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message Buf []byte // input buffer Flags UnmarshalInputFlags Resolver interface { FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error) FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error) } } // UnmarshalOutput is output from the Unmarshal method. type UnmarshalOutput = struct { pragma.NoUnkeyedLiterals Flags UnmarshalOutputFlags } // UnmarshalInputFlags configure the unmarshaler. // Most flags correspond to fields in proto.UnmarshalOptions. type UnmarshalInputFlags = uint8 const ( UnmarshalDiscardUnknown UnmarshalInputFlags = 1 << iota ) // UnmarshalOutputFlags are output from the Unmarshal method. type UnmarshalOutputFlags = uint8 const ( // UnmarshalInitialized may be set on return if all required fields are known to be set. // If unset, then it does not necessarily indicate that the message is uninitialized, // only that its status could not be confirmed. UnmarshalInitialized UnmarshalOutputFlags = 1 << iota ) // MergeInput is input to the Merge method. type MergeInput = struct { pragma.NoUnkeyedLiterals Source protoreflect.Message Destination protoreflect.Message } // MergeOutput is output from the Merge method. type MergeOutput = struct { pragma.NoUnkeyedLiterals Flags MergeOutputFlags } // MergeOutputFlags are output from the Merge method. type MergeOutputFlags = uint8 const ( // MergeComplete reports whether the merge was performed. // If unset, the merger must have made no changes to the destination. MergeComplete MergeOutputFlags = 1 << iota ) // CheckInitializedInput is input to the CheckInitialized method. type CheckInitializedInput = struct { pragma.NoUnkeyedLiterals Message protoreflect.Message } // CheckInitializedOutput is output from the CheckInitialized method. type CheckInitializedOutput = struct { pragma.NoUnkeyedLiterals } ================================================ FILE: vendor/google.golang.org/protobuf/runtime/protoimpl/impl.go ================================================ // Copyright 2018 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Package protoimpl contains the default implementation for messages // generated by protoc-gen-go. // // WARNING: This package should only ever be imported by generated messages. // The compatibility agreement covers nothing except for functionality needed // to keep existing generated messages operational. Breakages that occur due // to unauthorized usages of this package are not the author's responsibility. package protoimpl import ( "google.golang.org/protobuf/internal/filedesc" "google.golang.org/protobuf/internal/filetype" "google.golang.org/protobuf/internal/impl" ) // UnsafeEnabled specifies whether package unsafe can be used. const UnsafeEnabled = impl.UnsafeEnabled type ( // Types used by generated code in init functions. DescBuilder = filedesc.Builder TypeBuilder = filetype.Builder // Types used by generated code to implement EnumType, MessageType, and ExtensionType. EnumInfo = impl.EnumInfo MessageInfo = impl.MessageInfo ExtensionInfo = impl.ExtensionInfo // Types embedded in generated messages. MessageState = impl.MessageState SizeCache = impl.SizeCache WeakFields = impl.WeakFields UnknownFields = impl.UnknownFields ExtensionFields = impl.ExtensionFields ExtensionFieldV1 = impl.ExtensionField Pointer = impl.Pointer ) var X impl.Export ================================================ FILE: vendor/google.golang.org/protobuf/runtime/protoimpl/version.go ================================================ // Copyright 2019 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package protoimpl import ( "google.golang.org/protobuf/internal/version" ) const ( // MaxVersion is the maximum supported version for generated .pb.go files. // It is always the current version of the module. MaxVersion = version.Minor // GenVersion is the runtime version required by generated .pb.go files. // This is incremented when generated code relies on new functionality // in the runtime. GenVersion = 20 // MinVersion is the minimum supported version for generated .pb.go files. // This is incremented when the runtime drops support for old code. MinVersion = 0 ) // EnforceVersion is used by code generated by protoc-gen-go // to statically enforce minimum and maximum versions of this package. // A compilation failure implies either that: // * the runtime package is too old and needs to be updated OR // * the generated code is too old and needs to be regenerated. // // The runtime package can be upgraded by running: // go get google.golang.org/protobuf // // The generated code can be regenerated by running: // protoc --go_out=${PROTOC_GEN_GO_ARGS} ${PROTO_FILES} // // Example usage by generated code: // const ( // // Verify that this generated code is sufficiently up-to-date. // _ = protoimpl.EnforceVersion(genVersion - protoimpl.MinVersion) // // Verify that runtime/protoimpl is sufficiently up-to-date. // _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - genVersion) // ) // // The genVersion is the current minor version used to generated the code. // This compile-time check relies on negative integer overflow of a uint // being a compilation failure (guaranteed by the Go specification). type EnforceVersion uint // This enforces the following invariant: // MinVersion ≤ GenVersion ≤ MaxVersion const ( _ = EnforceVersion(GenVersion - MinVersion) _ = EnforceVersion(MaxVersion - GenVersion) ) ================================================ FILE: vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go ================================================ // 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. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. // // The messages in this file describe the definitions found in .proto files. // A valid .proto file can be translated directly to a FileDescriptorProto // without any other information (e.g. without reading its imports). // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/descriptor.proto package descriptorpb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoiface "google.golang.org/protobuf/runtime/protoiface" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) type FieldDescriptorProto_Type int32 const ( // 0 is reserved for errors. // Order is weird for historical reasons. FieldDescriptorProto_TYPE_DOUBLE FieldDescriptorProto_Type = 1 FieldDescriptorProto_TYPE_FLOAT FieldDescriptorProto_Type = 2 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if // negative values are likely. FieldDescriptorProto_TYPE_INT64 FieldDescriptorProto_Type = 3 FieldDescriptorProto_TYPE_UINT64 FieldDescriptorProto_Type = 4 // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if // negative values are likely. FieldDescriptorProto_TYPE_INT32 FieldDescriptorProto_Type = 5 FieldDescriptorProto_TYPE_FIXED64 FieldDescriptorProto_Type = 6 FieldDescriptorProto_TYPE_FIXED32 FieldDescriptorProto_Type = 7 FieldDescriptorProto_TYPE_BOOL FieldDescriptorProto_Type = 8 FieldDescriptorProto_TYPE_STRING FieldDescriptorProto_Type = 9 // Tag-delimited aggregate. // Group type is deprecated and not supported in proto3. However, Proto3 // implementations should still be able to parse the group wire format and // treat group fields as unknown fields. FieldDescriptorProto_TYPE_GROUP FieldDescriptorProto_Type = 10 FieldDescriptorProto_TYPE_MESSAGE FieldDescriptorProto_Type = 11 // Length-delimited aggregate. // New in version 2. FieldDescriptorProto_TYPE_BYTES FieldDescriptorProto_Type = 12 FieldDescriptorProto_TYPE_UINT32 FieldDescriptorProto_Type = 13 FieldDescriptorProto_TYPE_ENUM FieldDescriptorProto_Type = 14 FieldDescriptorProto_TYPE_SFIXED32 FieldDescriptorProto_Type = 15 FieldDescriptorProto_TYPE_SFIXED64 FieldDescriptorProto_Type = 16 FieldDescriptorProto_TYPE_SINT32 FieldDescriptorProto_Type = 17 // Uses ZigZag encoding. FieldDescriptorProto_TYPE_SINT64 FieldDescriptorProto_Type = 18 // Uses ZigZag encoding. ) // Enum value maps for FieldDescriptorProto_Type. var ( FieldDescriptorProto_Type_name = map[int32]string{ 1: "TYPE_DOUBLE", 2: "TYPE_FLOAT", 3: "TYPE_INT64", 4: "TYPE_UINT64", 5: "TYPE_INT32", 6: "TYPE_FIXED64", 7: "TYPE_FIXED32", 8: "TYPE_BOOL", 9: "TYPE_STRING", 10: "TYPE_GROUP", 11: "TYPE_MESSAGE", 12: "TYPE_BYTES", 13: "TYPE_UINT32", 14: "TYPE_ENUM", 15: "TYPE_SFIXED32", 16: "TYPE_SFIXED64", 17: "TYPE_SINT32", 18: "TYPE_SINT64", } FieldDescriptorProto_Type_value = map[string]int32{ "TYPE_DOUBLE": 1, "TYPE_FLOAT": 2, "TYPE_INT64": 3, "TYPE_UINT64": 4, "TYPE_INT32": 5, "TYPE_FIXED64": 6, "TYPE_FIXED32": 7, "TYPE_BOOL": 8, "TYPE_STRING": 9, "TYPE_GROUP": 10, "TYPE_MESSAGE": 11, "TYPE_BYTES": 12, "TYPE_UINT32": 13, "TYPE_ENUM": 14, "TYPE_SFIXED32": 15, "TYPE_SFIXED64": 16, "TYPE_SINT32": 17, "TYPE_SINT64": 18, } ) func (x FieldDescriptorProto_Type) Enum() *FieldDescriptorProto_Type { p := new(FieldDescriptorProto_Type) *p = x return p } func (x FieldDescriptorProto_Type) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldDescriptorProto_Type) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[0].Descriptor() } func (FieldDescriptorProto_Type) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[0] } func (x FieldDescriptorProto_Type) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldDescriptorProto_Type) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldDescriptorProto_Type(num) return nil } // Deprecated: Use FieldDescriptorProto_Type.Descriptor instead. func (FieldDescriptorProto_Type) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4, 0} } type FieldDescriptorProto_Label int32 const ( // 0 is reserved for errors FieldDescriptorProto_LABEL_OPTIONAL FieldDescriptorProto_Label = 1 FieldDescriptorProto_LABEL_REQUIRED FieldDescriptorProto_Label = 2 FieldDescriptorProto_LABEL_REPEATED FieldDescriptorProto_Label = 3 ) // Enum value maps for FieldDescriptorProto_Label. var ( FieldDescriptorProto_Label_name = map[int32]string{ 1: "LABEL_OPTIONAL", 2: "LABEL_REQUIRED", 3: "LABEL_REPEATED", } FieldDescriptorProto_Label_value = map[string]int32{ "LABEL_OPTIONAL": 1, "LABEL_REQUIRED": 2, "LABEL_REPEATED": 3, } ) func (x FieldDescriptorProto_Label) Enum() *FieldDescriptorProto_Label { p := new(FieldDescriptorProto_Label) *p = x return p } func (x FieldDescriptorProto_Label) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldDescriptorProto_Label) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[1].Descriptor() } func (FieldDescriptorProto_Label) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[1] } func (x FieldDescriptorProto_Label) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldDescriptorProto_Label) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldDescriptorProto_Label(num) return nil } // Deprecated: Use FieldDescriptorProto_Label.Descriptor instead. func (FieldDescriptorProto_Label) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4, 1} } // Generated classes can be optimized for speed or code size. type FileOptions_OptimizeMode int32 const ( FileOptions_SPEED FileOptions_OptimizeMode = 1 // Generate complete code for parsing, serialization, // etc. FileOptions_CODE_SIZE FileOptions_OptimizeMode = 2 // Use ReflectionOps to implement these methods. FileOptions_LITE_RUNTIME FileOptions_OptimizeMode = 3 // Generate code using MessageLite and the lite runtime. ) // Enum value maps for FileOptions_OptimizeMode. var ( FileOptions_OptimizeMode_name = map[int32]string{ 1: "SPEED", 2: "CODE_SIZE", 3: "LITE_RUNTIME", } FileOptions_OptimizeMode_value = map[string]int32{ "SPEED": 1, "CODE_SIZE": 2, "LITE_RUNTIME": 3, } ) func (x FileOptions_OptimizeMode) Enum() *FileOptions_OptimizeMode { p := new(FileOptions_OptimizeMode) *p = x return p } func (x FileOptions_OptimizeMode) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FileOptions_OptimizeMode) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[2].Descriptor() } func (FileOptions_OptimizeMode) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[2] } func (x FileOptions_OptimizeMode) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FileOptions_OptimizeMode) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FileOptions_OptimizeMode(num) return nil } // Deprecated: Use FileOptions_OptimizeMode.Descriptor instead. func (FileOptions_OptimizeMode) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10, 0} } type FieldOptions_CType int32 const ( // Default mode. FieldOptions_STRING FieldOptions_CType = 0 FieldOptions_CORD FieldOptions_CType = 1 FieldOptions_STRING_PIECE FieldOptions_CType = 2 ) // Enum value maps for FieldOptions_CType. var ( FieldOptions_CType_name = map[int32]string{ 0: "STRING", 1: "CORD", 2: "STRING_PIECE", } FieldOptions_CType_value = map[string]int32{ "STRING": 0, "CORD": 1, "STRING_PIECE": 2, } ) func (x FieldOptions_CType) Enum() *FieldOptions_CType { p := new(FieldOptions_CType) *p = x return p } func (x FieldOptions_CType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldOptions_CType) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[3].Descriptor() } func (FieldOptions_CType) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[3] } func (x FieldOptions_CType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldOptions_CType) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldOptions_CType(num) return nil } // Deprecated: Use FieldOptions_CType.Descriptor instead. func (FieldOptions_CType) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 0} } type FieldOptions_JSType int32 const ( // Use the default type. FieldOptions_JS_NORMAL FieldOptions_JSType = 0 // Use JavaScript strings. FieldOptions_JS_STRING FieldOptions_JSType = 1 // Use JavaScript numbers. FieldOptions_JS_NUMBER FieldOptions_JSType = 2 ) // Enum value maps for FieldOptions_JSType. var ( FieldOptions_JSType_name = map[int32]string{ 0: "JS_NORMAL", 1: "JS_STRING", 2: "JS_NUMBER", } FieldOptions_JSType_value = map[string]int32{ "JS_NORMAL": 0, "JS_STRING": 1, "JS_NUMBER": 2, } ) func (x FieldOptions_JSType) Enum() *FieldOptions_JSType { p := new(FieldOptions_JSType) *p = x return p } func (x FieldOptions_JSType) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (FieldOptions_JSType) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[4].Descriptor() } func (FieldOptions_JSType) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[4] } func (x FieldOptions_JSType) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *FieldOptions_JSType) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = FieldOptions_JSType(num) return nil } // Deprecated: Use FieldOptions_JSType.Descriptor instead. func (FieldOptions_JSType) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12, 1} } // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, // or neither? HTTP based RPC implementation may choose GET verb for safe // methods, and PUT verb for idempotent methods instead of the default POST. type MethodOptions_IdempotencyLevel int32 const ( MethodOptions_IDEMPOTENCY_UNKNOWN MethodOptions_IdempotencyLevel = 0 MethodOptions_NO_SIDE_EFFECTS MethodOptions_IdempotencyLevel = 1 // implies idempotent MethodOptions_IDEMPOTENT MethodOptions_IdempotencyLevel = 2 // idempotent, but may have side effects ) // Enum value maps for MethodOptions_IdempotencyLevel. var ( MethodOptions_IdempotencyLevel_name = map[int32]string{ 0: "IDEMPOTENCY_UNKNOWN", 1: "NO_SIDE_EFFECTS", 2: "IDEMPOTENT", } MethodOptions_IdempotencyLevel_value = map[string]int32{ "IDEMPOTENCY_UNKNOWN": 0, "NO_SIDE_EFFECTS": 1, "IDEMPOTENT": 2, } ) func (x MethodOptions_IdempotencyLevel) Enum() *MethodOptions_IdempotencyLevel { p := new(MethodOptions_IdempotencyLevel) *p = x return p } func (x MethodOptions_IdempotencyLevel) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (MethodOptions_IdempotencyLevel) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_descriptor_proto_enumTypes[5].Descriptor() } func (MethodOptions_IdempotencyLevel) Type() protoreflect.EnumType { return &file_google_protobuf_descriptor_proto_enumTypes[5] } func (x MethodOptions_IdempotencyLevel) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *MethodOptions_IdempotencyLevel) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = MethodOptions_IdempotencyLevel(num) return nil } // Deprecated: Use MethodOptions_IdempotencyLevel.Descriptor instead. func (MethodOptions_IdempotencyLevel) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17, 0} } // The protocol compiler can output a FileDescriptorSet containing the .proto // files it parses. type FileDescriptorSet struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields File []*FileDescriptorProto `protobuf:"bytes,1,rep,name=file" json:"file,omitempty"` } func (x *FileDescriptorSet) Reset() { *x = FileDescriptorSet{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileDescriptorSet) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileDescriptorSet) ProtoMessage() {} func (x *FileDescriptorSet) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 FileDescriptorSet.ProtoReflect.Descriptor instead. func (*FileDescriptorSet) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{0} } func (x *FileDescriptorSet) GetFile() []*FileDescriptorProto { if x != nil { return x.File } return nil } // Describes a complete .proto file. type FileDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // file name, relative to root of source tree Package *string `protobuf:"bytes,2,opt,name=package" json:"package,omitempty"` // e.g. "foo", "foo.bar", etc. // Names of files imported by this file. Dependency []string `protobuf:"bytes,3,rep,name=dependency" json:"dependency,omitempty"` // Indexes of the public imported files in the dependency list above. PublicDependency []int32 `protobuf:"varint,10,rep,name=public_dependency,json=publicDependency" json:"public_dependency,omitempty"` // Indexes of the weak imported files in the dependency list. // For Google-internal migration only. Do not use. WeakDependency []int32 `protobuf:"varint,11,rep,name=weak_dependency,json=weakDependency" json:"weak_dependency,omitempty"` // All top-level definitions in this file. MessageType []*DescriptorProto `protobuf:"bytes,4,rep,name=message_type,json=messageType" json:"message_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,5,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` Service []*ServiceDescriptorProto `protobuf:"bytes,6,rep,name=service" json:"service,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,7,rep,name=extension" json:"extension,omitempty"` Options *FileOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` // This field contains optional information about the original source code. // You may safely remove this entire field without harming runtime // functionality of the descriptors -- the information is needed only by // development tools. SourceCodeInfo *SourceCodeInfo `protobuf:"bytes,9,opt,name=source_code_info,json=sourceCodeInfo" json:"source_code_info,omitempty"` // The syntax of the proto file. // The supported values are "proto2" and "proto3". Syntax *string `protobuf:"bytes,12,opt,name=syntax" json:"syntax,omitempty"` } func (x *FileDescriptorProto) Reset() { *x = FileDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileDescriptorProto) ProtoMessage() {} func (x *FileDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 FileDescriptorProto.ProtoReflect.Descriptor instead. func (*FileDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{1} } func (x *FileDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *FileDescriptorProto) GetPackage() string { if x != nil && x.Package != nil { return *x.Package } return "" } func (x *FileDescriptorProto) GetDependency() []string { if x != nil { return x.Dependency } return nil } func (x *FileDescriptorProto) GetPublicDependency() []int32 { if x != nil { return x.PublicDependency } return nil } func (x *FileDescriptorProto) GetWeakDependency() []int32 { if x != nil { return x.WeakDependency } return nil } func (x *FileDescriptorProto) GetMessageType() []*DescriptorProto { if x != nil { return x.MessageType } return nil } func (x *FileDescriptorProto) GetEnumType() []*EnumDescriptorProto { if x != nil { return x.EnumType } return nil } func (x *FileDescriptorProto) GetService() []*ServiceDescriptorProto { if x != nil { return x.Service } return nil } func (x *FileDescriptorProto) GetExtension() []*FieldDescriptorProto { if x != nil { return x.Extension } return nil } func (x *FileDescriptorProto) GetOptions() *FileOptions { if x != nil { return x.Options } return nil } func (x *FileDescriptorProto) GetSourceCodeInfo() *SourceCodeInfo { if x != nil { return x.SourceCodeInfo } return nil } func (x *FileDescriptorProto) GetSyntax() string { if x != nil && x.Syntax != nil { return *x.Syntax } return "" } // Describes a message type. type DescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Field []*FieldDescriptorProto `protobuf:"bytes,2,rep,name=field" json:"field,omitempty"` Extension []*FieldDescriptorProto `protobuf:"bytes,6,rep,name=extension" json:"extension,omitempty"` NestedType []*DescriptorProto `protobuf:"bytes,3,rep,name=nested_type,json=nestedType" json:"nested_type,omitempty"` EnumType []*EnumDescriptorProto `protobuf:"bytes,4,rep,name=enum_type,json=enumType" json:"enum_type,omitempty"` ExtensionRange []*DescriptorProto_ExtensionRange `protobuf:"bytes,5,rep,name=extension_range,json=extensionRange" json:"extension_range,omitempty"` OneofDecl []*OneofDescriptorProto `protobuf:"bytes,8,rep,name=oneof_decl,json=oneofDecl" json:"oneof_decl,omitempty"` Options *MessageOptions `protobuf:"bytes,7,opt,name=options" json:"options,omitempty"` ReservedRange []*DescriptorProto_ReservedRange `protobuf:"bytes,9,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved field names, which may not be used by fields in the same message. // A given name may only be reserved once. ReservedName []string `protobuf:"bytes,10,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` } func (x *DescriptorProto) Reset() { *x = DescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto) ProtoMessage() {} func (x *DescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 DescriptorProto.ProtoReflect.Descriptor instead. func (*DescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2} } func (x *DescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *DescriptorProto) GetField() []*FieldDescriptorProto { if x != nil { return x.Field } return nil } func (x *DescriptorProto) GetExtension() []*FieldDescriptorProto { if x != nil { return x.Extension } return nil } func (x *DescriptorProto) GetNestedType() []*DescriptorProto { if x != nil { return x.NestedType } return nil } func (x *DescriptorProto) GetEnumType() []*EnumDescriptorProto { if x != nil { return x.EnumType } return nil } func (x *DescriptorProto) GetExtensionRange() []*DescriptorProto_ExtensionRange { if x != nil { return x.ExtensionRange } return nil } func (x *DescriptorProto) GetOneofDecl() []*OneofDescriptorProto { if x != nil { return x.OneofDecl } return nil } func (x *DescriptorProto) GetOptions() *MessageOptions { if x != nil { return x.Options } return nil } func (x *DescriptorProto) GetReservedRange() []*DescriptorProto_ReservedRange { if x != nil { return x.ReservedRange } return nil } func (x *DescriptorProto) GetReservedName() []string { if x != nil { return x.ReservedName } return nil } type ExtensionRangeOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } func (x *ExtensionRangeOptions) Reset() { *x = ExtensionRangeOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ExtensionRangeOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*ExtensionRangeOptions) ProtoMessage() {} func (x *ExtensionRangeOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_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 ExtensionRangeOptions.ProtoReflect.Descriptor instead. func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{3} } var extRange_ExtensionRangeOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use ExtensionRangeOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*ExtensionRangeOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_ExtensionRangeOptions } func (x *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } // Describes a field within a message. type FieldDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,3,opt,name=number" json:"number,omitempty"` Label *FieldDescriptorProto_Label `protobuf:"varint,4,opt,name=label,enum=google.protobuf.FieldDescriptorProto_Label" json:"label,omitempty"` // If type_name is set, this need not be set. If both this and type_name // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. Type *FieldDescriptorProto_Type `protobuf:"varint,5,opt,name=type,enum=google.protobuf.FieldDescriptorProto_Type" json:"type,omitempty"` // For message and enum types, this is the name of the type. If the name // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping // rules are used to find the type (i.e. first the nested types within this // message are searched, then within the parent, on up to the root // namespace). TypeName *string `protobuf:"bytes,6,opt,name=type_name,json=typeName" json:"type_name,omitempty"` // For extensions, this is the name of the type being extended. It is // resolved in the same manner as type_name. Extendee *string `protobuf:"bytes,2,opt,name=extendee" json:"extendee,omitempty"` // For numeric types, contains the original text representation of the value. // For booleans, "true" or "false". // For strings, contains the default text contents (not escaped in any way). // For bytes, contains the C escaped value. All bytes >= 128 are escaped. // TODO(kenton): Base-64 encode? DefaultValue *string `protobuf:"bytes,7,opt,name=default_value,json=defaultValue" json:"default_value,omitempty"` // If set, gives the index of a oneof in the containing type's oneof_decl // list. This field is a member of that oneof. OneofIndex *int32 `protobuf:"varint,9,opt,name=oneof_index,json=oneofIndex" json:"oneof_index,omitempty"` // JSON name of this field. The value is set by protocol compiler. If the // user has set a "json_name" option on this field, that option's value // will be used. Otherwise, it's deduced from the field's name by converting // it to camelCase. JsonName *string `protobuf:"bytes,10,opt,name=json_name,json=jsonName" json:"json_name,omitempty"` Options *FieldOptions `protobuf:"bytes,8,opt,name=options" json:"options,omitempty"` // If true, this is a proto3 "optional". When a proto3 field is optional, it // tracks presence regardless of field type. // // When proto3_optional is true, this field must be belong to a oneof to // signal to old proto3 clients that presence is tracked for this field. This // oneof is known as a "synthetic" oneof, and this field must be its sole // member (each proto3 optional field gets its own synthetic oneof). Synthetic // oneofs exist in the descriptor only, and do not generate any API. Synthetic // oneofs must be ordered after all "real" oneofs. // // For message fields, proto3_optional doesn't create any semantic change, // since non-repeated message fields always track presence. However it still // indicates the semantic detail of whether the user wrote "optional" or not. // This can be useful for round-tripping the .proto file. For consistency we // give message fields a synthetic oneof also, even though it is not required // to track presence. This is especially important because the parser can't // tell if a field is a message or an enum, so it must always create a // synthetic oneof. // // Proto2 optional fields do not set this flag, because they already indicate // optional with `LABEL_OPTIONAL`. Proto3Optional *bool `protobuf:"varint,17,opt,name=proto3_optional,json=proto3Optional" json:"proto3_optional,omitempty"` } func (x *FieldDescriptorProto) Reset() { *x = FieldDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FieldDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*FieldDescriptorProto) ProtoMessage() {} func (x *FieldDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[4] 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 FieldDescriptorProto.ProtoReflect.Descriptor instead. func (*FieldDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{4} } func (x *FieldDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *FieldDescriptorProto) GetNumber() int32 { if x != nil && x.Number != nil { return *x.Number } return 0 } func (x *FieldDescriptorProto) GetLabel() FieldDescriptorProto_Label { if x != nil && x.Label != nil { return *x.Label } return FieldDescriptorProto_LABEL_OPTIONAL } func (x *FieldDescriptorProto) GetType() FieldDescriptorProto_Type { if x != nil && x.Type != nil { return *x.Type } return FieldDescriptorProto_TYPE_DOUBLE } func (x *FieldDescriptorProto) GetTypeName() string { if x != nil && x.TypeName != nil { return *x.TypeName } return "" } func (x *FieldDescriptorProto) GetExtendee() string { if x != nil && x.Extendee != nil { return *x.Extendee } return "" } func (x *FieldDescriptorProto) GetDefaultValue() string { if x != nil && x.DefaultValue != nil { return *x.DefaultValue } return "" } func (x *FieldDescriptorProto) GetOneofIndex() int32 { if x != nil && x.OneofIndex != nil { return *x.OneofIndex } return 0 } func (x *FieldDescriptorProto) GetJsonName() string { if x != nil && x.JsonName != nil { return *x.JsonName } return "" } func (x *FieldDescriptorProto) GetOptions() *FieldOptions { if x != nil { return x.Options } return nil } func (x *FieldDescriptorProto) GetProto3Optional() bool { if x != nil && x.Proto3Optional != nil { return *x.Proto3Optional } return false } // Describes a oneof. type OneofDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Options *OneofOptions `protobuf:"bytes,2,opt,name=options" json:"options,omitempty"` } func (x *OneofDescriptorProto) Reset() { *x = OneofDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OneofDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*OneofDescriptorProto) ProtoMessage() {} func (x *OneofDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[5] 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 OneofDescriptorProto.ProtoReflect.Descriptor instead. func (*OneofDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{5} } func (x *OneofDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *OneofDescriptorProto) GetOptions() *OneofOptions { if x != nil { return x.Options } return nil } // Describes an enum type. type EnumDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Value []*EnumValueDescriptorProto `protobuf:"bytes,2,rep,name=value" json:"value,omitempty"` Options *EnumOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` // Range of reserved numeric values. Reserved numeric values may not be used // by enum values in the same enum declaration. Reserved ranges may not // overlap. ReservedRange []*EnumDescriptorProto_EnumReservedRange `protobuf:"bytes,4,rep,name=reserved_range,json=reservedRange" json:"reserved_range,omitempty"` // Reserved enum value names, which may not be reused. A given name may only // be reserved once. ReservedName []string `protobuf:"bytes,5,rep,name=reserved_name,json=reservedName" json:"reserved_name,omitempty"` } func (x *EnumDescriptorProto) Reset() { *x = EnumDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumDescriptorProto) ProtoMessage() {} func (x *EnumDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[6] 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 EnumDescriptorProto.ProtoReflect.Descriptor instead. func (*EnumDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{6} } func (x *EnumDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *EnumDescriptorProto) GetValue() []*EnumValueDescriptorProto { if x != nil { return x.Value } return nil } func (x *EnumDescriptorProto) GetOptions() *EnumOptions { if x != nil { return x.Options } return nil } func (x *EnumDescriptorProto) GetReservedRange() []*EnumDescriptorProto_EnumReservedRange { if x != nil { return x.ReservedRange } return nil } func (x *EnumDescriptorProto) GetReservedName() []string { if x != nil { return x.ReservedName } return nil } // Describes a value within an enum. type EnumValueDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Number *int32 `protobuf:"varint,2,opt,name=number" json:"number,omitempty"` Options *EnumValueOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *EnumValueDescriptorProto) Reset() { *x = EnumValueDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumValueDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumValueDescriptorProto) ProtoMessage() {} func (x *EnumValueDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[7] 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 EnumValueDescriptorProto.ProtoReflect.Descriptor instead. func (*EnumValueDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{7} } func (x *EnumValueDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *EnumValueDescriptorProto) GetNumber() int32 { if x != nil && x.Number != nil { return *x.Number } return 0 } func (x *EnumValueDescriptorProto) GetOptions() *EnumValueOptions { if x != nil { return x.Options } return nil } // Describes a service. type ServiceDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` Method []*MethodDescriptorProto `protobuf:"bytes,2,rep,name=method" json:"method,omitempty"` Options *ServiceOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *ServiceDescriptorProto) Reset() { *x = ServiceDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ServiceDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*ServiceDescriptorProto) ProtoMessage() {} func (x *ServiceDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[8] 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 ServiceDescriptorProto.ProtoReflect.Descriptor instead. func (*ServiceDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{8} } func (x *ServiceDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *ServiceDescriptorProto) GetMethod() []*MethodDescriptorProto { if x != nil { return x.Method } return nil } func (x *ServiceDescriptorProto) GetOptions() *ServiceOptions { if x != nil { return x.Options } return nil } // Describes a method of a service. type MethodDescriptorProto struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // Input and output type names. These are resolved in the same way as // FieldDescriptorProto.type_name, but must refer to a message type. InputType *string `protobuf:"bytes,2,opt,name=input_type,json=inputType" json:"input_type,omitempty"` OutputType *string `protobuf:"bytes,3,opt,name=output_type,json=outputType" json:"output_type,omitempty"` Options *MethodOptions `protobuf:"bytes,4,opt,name=options" json:"options,omitempty"` // Identifies if client streams multiple client messages ClientStreaming *bool `protobuf:"varint,5,opt,name=client_streaming,json=clientStreaming,def=0" json:"client_streaming,omitempty"` // Identifies if server streams multiple server messages ServerStreaming *bool `protobuf:"varint,6,opt,name=server_streaming,json=serverStreaming,def=0" json:"server_streaming,omitempty"` } // Default values for MethodDescriptorProto fields. const ( Default_MethodDescriptorProto_ClientStreaming = bool(false) Default_MethodDescriptorProto_ServerStreaming = bool(false) ) func (x *MethodDescriptorProto) Reset() { *x = MethodDescriptorProto{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MethodDescriptorProto) String() string { return protoimpl.X.MessageStringOf(x) } func (*MethodDescriptorProto) ProtoMessage() {} func (x *MethodDescriptorProto) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[9] 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 MethodDescriptorProto.ProtoReflect.Descriptor instead. func (*MethodDescriptorProto) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{9} } func (x *MethodDescriptorProto) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *MethodDescriptorProto) GetInputType() string { if x != nil && x.InputType != nil { return *x.InputType } return "" } func (x *MethodDescriptorProto) GetOutputType() string { if x != nil && x.OutputType != nil { return *x.OutputType } return "" } func (x *MethodDescriptorProto) GetOptions() *MethodOptions { if x != nil { return x.Options } return nil } func (x *MethodDescriptorProto) GetClientStreaming() bool { if x != nil && x.ClientStreaming != nil { return *x.ClientStreaming } return Default_MethodDescriptorProto_ClientStreaming } func (x *MethodDescriptorProto) GetServerStreaming() bool { if x != nil && x.ServerStreaming != nil { return *x.ServerStreaming } return Default_MethodDescriptorProto_ServerStreaming } type FileOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Sets the Java package where classes generated from this .proto will be // placed. By default, the proto package is used, but this is often // inappropriate because proto packages do not normally start with backwards // domain names. JavaPackage *string `protobuf:"bytes,1,opt,name=java_package,json=javaPackage" json:"java_package,omitempty"` // If set, all the classes from the .proto file are wrapped in a single // outer class with the given name. This applies to both Proto1 // (equivalent to the old "--one_java_file" option) and Proto2 (where // a .proto always translates to a single class, but you may want to // explicitly choose the class name). JavaOuterClassname *string `protobuf:"bytes,8,opt,name=java_outer_classname,json=javaOuterClassname" json:"java_outer_classname,omitempty"` // If set true, then the Java code generator will generate a separate .java // file for each top-level message, enum, and service defined in the .proto // file. Thus, these types will *not* be nested inside the outer class // named by java_outer_classname. However, the outer class will still be // generated to contain the file's getDescriptor() method as well as any // top-level extensions defined in the file. JavaMultipleFiles *bool `protobuf:"varint,10,opt,name=java_multiple_files,json=javaMultipleFiles,def=0" json:"java_multiple_files,omitempty"` // This option does nothing. // // Deprecated: Do not use. JavaGenerateEqualsAndHash *bool `protobuf:"varint,20,opt,name=java_generate_equals_and_hash,json=javaGenerateEqualsAndHash" json:"java_generate_equals_and_hash,omitempty"` // If set true, then the Java2 code generator will generate code that // throws an exception whenever an attempt is made to assign a non-UTF-8 // byte sequence to a string field. // Message reflection will do the same. // However, an extension field still accepts non-UTF-8 byte sequences. // This option has no effect on when used with the lite runtime. JavaStringCheckUtf8 *bool `protobuf:"varint,27,opt,name=java_string_check_utf8,json=javaStringCheckUtf8,def=0" json:"java_string_check_utf8,omitempty"` OptimizeFor *FileOptions_OptimizeMode `protobuf:"varint,9,opt,name=optimize_for,json=optimizeFor,enum=google.protobuf.FileOptions_OptimizeMode,def=1" json:"optimize_for,omitempty"` // Sets the Go package where structs generated from this .proto will be // placed. If omitted, the Go package will be derived from the following: // - The basename of the package import path, if provided. // - Otherwise, the package statement in the .proto file, if present. // - Otherwise, the basename of the .proto file, without extension. GoPackage *string `protobuf:"bytes,11,opt,name=go_package,json=goPackage" json:"go_package,omitempty"` // Should generic services be generated in each language? "Generic" services // are not specific to any particular RPC system. They are generated by the // main code generators in each language (without additional plugins). // Generic services were the only kind of service generation supported by // early versions of google.protobuf. // // Generic services are now considered deprecated in favor of using plugins // that generate code specific to your particular RPC system. Therefore, // these default to false. Old code which depends on generic services should // explicitly set them to true. CcGenericServices *bool `protobuf:"varint,16,opt,name=cc_generic_services,json=ccGenericServices,def=0" json:"cc_generic_services,omitempty"` JavaGenericServices *bool `protobuf:"varint,17,opt,name=java_generic_services,json=javaGenericServices,def=0" json:"java_generic_services,omitempty"` PyGenericServices *bool `protobuf:"varint,18,opt,name=py_generic_services,json=pyGenericServices,def=0" json:"py_generic_services,omitempty"` PhpGenericServices *bool `protobuf:"varint,42,opt,name=php_generic_services,json=phpGenericServices,def=0" json:"php_generic_services,omitempty"` // Is this file deprecated? // Depending on the target platform, this can emit Deprecated annotations // for everything in the file, or it will be completely ignored; in the very // least, this is a formalization for deprecating files. Deprecated *bool `protobuf:"varint,23,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Enables the use of arenas for the proto messages in this file. This applies // only to generated classes for C++. CcEnableArenas *bool `protobuf:"varint,31,opt,name=cc_enable_arenas,json=ccEnableArenas,def=1" json:"cc_enable_arenas,omitempty"` // Sets the objective c class prefix which is prepended to all objective c // generated classes from this .proto. There is no default. ObjcClassPrefix *string `protobuf:"bytes,36,opt,name=objc_class_prefix,json=objcClassPrefix" json:"objc_class_prefix,omitempty"` // Namespace for generated classes; defaults to the package. CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"` // By default Swift generators will take the proto package and CamelCase it // replacing '.' with underscore and use that to prefix the types/symbols // defined. When this options is provided, they will use this value instead // to prefix the types/symbols defined. SwiftPrefix *string `protobuf:"bytes,39,opt,name=swift_prefix,json=swiftPrefix" json:"swift_prefix,omitempty"` // Sets the php class prefix which is prepended to all php generated classes // from this .proto. Default is empty. PhpClassPrefix *string `protobuf:"bytes,40,opt,name=php_class_prefix,json=phpClassPrefix" json:"php_class_prefix,omitempty"` // Use this option to change the namespace of php generated classes. Default // is empty. When this option is empty, the package name will be used for // determining the namespace. PhpNamespace *string `protobuf:"bytes,41,opt,name=php_namespace,json=phpNamespace" json:"php_namespace,omitempty"` // Use this option to change the namespace of php generated metadata classes. // Default is empty. When this option is empty, the proto file name will be // used for determining the namespace. PhpMetadataNamespace *string `protobuf:"bytes,44,opt,name=php_metadata_namespace,json=phpMetadataNamespace" json:"php_metadata_namespace,omitempty"` // Use this option to change the package of ruby generated classes. Default // is empty. When this option is not set, the package name will be used for // determining the ruby package. RubyPackage *string `protobuf:"bytes,45,opt,name=ruby_package,json=rubyPackage" json:"ruby_package,omitempty"` // The parser stores options it doesn't recognize here. // See the documentation for the "Options" section above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for FileOptions fields. const ( Default_FileOptions_JavaMultipleFiles = bool(false) Default_FileOptions_JavaStringCheckUtf8 = bool(false) Default_FileOptions_OptimizeFor = FileOptions_SPEED Default_FileOptions_CcGenericServices = bool(false) Default_FileOptions_JavaGenericServices = bool(false) Default_FileOptions_PyGenericServices = bool(false) Default_FileOptions_PhpGenericServices = bool(false) Default_FileOptions_Deprecated = bool(false) Default_FileOptions_CcEnableArenas = bool(true) ) func (x *FileOptions) Reset() { *x = FileOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FileOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*FileOptions) ProtoMessage() {} func (x *FileOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[10] 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 FileOptions.ProtoReflect.Descriptor instead. func (*FileOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10} } var extRange_FileOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use FileOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*FileOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_FileOptions } func (x *FileOptions) GetJavaPackage() string { if x != nil && x.JavaPackage != nil { return *x.JavaPackage } return "" } func (x *FileOptions) GetJavaOuterClassname() string { if x != nil && x.JavaOuterClassname != nil { return *x.JavaOuterClassname } return "" } func (x *FileOptions) GetJavaMultipleFiles() bool { if x != nil && x.JavaMultipleFiles != nil { return *x.JavaMultipleFiles } return Default_FileOptions_JavaMultipleFiles } // Deprecated: Do not use. func (x *FileOptions) GetJavaGenerateEqualsAndHash() bool { if x != nil && x.JavaGenerateEqualsAndHash != nil { return *x.JavaGenerateEqualsAndHash } return false } func (x *FileOptions) GetJavaStringCheckUtf8() bool { if x != nil && x.JavaStringCheckUtf8 != nil { return *x.JavaStringCheckUtf8 } return Default_FileOptions_JavaStringCheckUtf8 } func (x *FileOptions) GetOptimizeFor() FileOptions_OptimizeMode { if x != nil && x.OptimizeFor != nil { return *x.OptimizeFor } return Default_FileOptions_OptimizeFor } func (x *FileOptions) GetGoPackage() string { if x != nil && x.GoPackage != nil { return *x.GoPackage } return "" } func (x *FileOptions) GetCcGenericServices() bool { if x != nil && x.CcGenericServices != nil { return *x.CcGenericServices } return Default_FileOptions_CcGenericServices } func (x *FileOptions) GetJavaGenericServices() bool { if x != nil && x.JavaGenericServices != nil { return *x.JavaGenericServices } return Default_FileOptions_JavaGenericServices } func (x *FileOptions) GetPyGenericServices() bool { if x != nil && x.PyGenericServices != nil { return *x.PyGenericServices } return Default_FileOptions_PyGenericServices } func (x *FileOptions) GetPhpGenericServices() bool { if x != nil && x.PhpGenericServices != nil { return *x.PhpGenericServices } return Default_FileOptions_PhpGenericServices } func (x *FileOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_FileOptions_Deprecated } func (x *FileOptions) GetCcEnableArenas() bool { if x != nil && x.CcEnableArenas != nil { return *x.CcEnableArenas } return Default_FileOptions_CcEnableArenas } func (x *FileOptions) GetObjcClassPrefix() string { if x != nil && x.ObjcClassPrefix != nil { return *x.ObjcClassPrefix } return "" } func (x *FileOptions) GetCsharpNamespace() string { if x != nil && x.CsharpNamespace != nil { return *x.CsharpNamespace } return "" } func (x *FileOptions) GetSwiftPrefix() string { if x != nil && x.SwiftPrefix != nil { return *x.SwiftPrefix } return "" } func (x *FileOptions) GetPhpClassPrefix() string { if x != nil && x.PhpClassPrefix != nil { return *x.PhpClassPrefix } return "" } func (x *FileOptions) GetPhpNamespace() string { if x != nil && x.PhpNamespace != nil { return *x.PhpNamespace } return "" } func (x *FileOptions) GetPhpMetadataNamespace() string { if x != nil && x.PhpMetadataNamespace != nil { return *x.PhpMetadataNamespace } return "" } func (x *FileOptions) GetRubyPackage() string { if x != nil && x.RubyPackage != nil { return *x.RubyPackage } return "" } func (x *FileOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type MessageOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Set true to use the old proto1 MessageSet wire format for extensions. // This is provided for backwards-compatibility with the MessageSet wire // format. You should not use this for any other reason: It's less // efficient, has fewer features, and is more complicated. // // The message must be defined exactly as follows: // message Foo { // option message_set_wire_format = true; // extensions 4 to max; // } // Note that the message cannot have any defined fields; MessageSets only // have extensions. // // All extensions of your type must be singular messages; e.g. they cannot // be int32s, enums, or repeated messages. // // Because this is an option, the above two restrictions are not enforced by // the protocol compiler. MessageSetWireFormat *bool `protobuf:"varint,1,opt,name=message_set_wire_format,json=messageSetWireFormat,def=0" json:"message_set_wire_format,omitempty"` // Disables the generation of the standard "descriptor()" accessor, which can // conflict with a field of the same name. This is meant to make migration // from proto1 easier; new code should avoid fields named "descriptor". NoStandardDescriptorAccessor *bool `protobuf:"varint,2,opt,name=no_standard_descriptor_accessor,json=noStandardDescriptorAccessor,def=0" json:"no_standard_descriptor_accessor,omitempty"` // Is this message deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the message, or it will be completely ignored; in the very least, // this is a formalization for deprecating messages. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // Whether the message is an automatically generated map entry type for the // maps field. // // For maps fields: // map map_field = 1; // The parsed descriptor looks like: // message MapFieldEntry { // option map_entry = true; // optional KeyType key = 1; // optional ValueType value = 2; // } // repeated MapFieldEntry map_field = 1; // // Implementations may choose not to generate the map_entry=true message, but // use a native map in the target language to hold the keys and values. // The reflection APIs in such implementations still need to work as // if the field is a repeated message field. // // NOTE: Do not set the option in .proto files. Always use the maps syntax // instead. The option should only be implicitly set by the proto compiler // parser. MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for MessageOptions fields. const ( Default_MessageOptions_MessageSetWireFormat = bool(false) Default_MessageOptions_NoStandardDescriptorAccessor = bool(false) Default_MessageOptions_Deprecated = bool(false) ) func (x *MessageOptions) Reset() { *x = MessageOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MessageOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*MessageOptions) ProtoMessage() {} func (x *MessageOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[11] 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 MessageOptions.ProtoReflect.Descriptor instead. func (*MessageOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{11} } var extRange_MessageOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use MessageOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*MessageOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_MessageOptions } func (x *MessageOptions) GetMessageSetWireFormat() bool { if x != nil && x.MessageSetWireFormat != nil { return *x.MessageSetWireFormat } return Default_MessageOptions_MessageSetWireFormat } func (x *MessageOptions) GetNoStandardDescriptorAccessor() bool { if x != nil && x.NoStandardDescriptorAccessor != nil { return *x.NoStandardDescriptorAccessor } return Default_MessageOptions_NoStandardDescriptorAccessor } func (x *MessageOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_MessageOptions_Deprecated } func (x *MessageOptions) GetMapEntry() bool { if x != nil && x.MapEntry != nil { return *x.MapEntry } return false } func (x *MessageOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type FieldOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The ctype option instructs the C++ code generator to use a different // representation of the field than it normally would. See the specific // options below. This option is not yet implemented in the open source // release -- sorry, we'll try to include it in a future version! Ctype *FieldOptions_CType `protobuf:"varint,1,opt,name=ctype,enum=google.protobuf.FieldOptions_CType,def=0" json:"ctype,omitempty"` // The packed option can be enabled for repeated primitive fields to enable // a more efficient representation on the wire. Rather than repeatedly // writing the tag and type for each element, the entire array is encoded as // a single length-delimited blob. In proto3, only explicit setting it to // false will avoid using packed encoding. Packed *bool `protobuf:"varint,2,opt,name=packed" json:"packed,omitempty"` // The jstype option determines the JavaScript type used for values of the // field. The option is permitted only for 64 bit integral and fixed types // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING // is represented as JavaScript string, which avoids loss of precision that // can happen when a large value is converted to a floating point JavaScript. // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to // use the JavaScript "number" type. The behavior of the default option // JS_NORMAL is implementation dependent. // // This option is an enum to permit additional types to be added, e.g. // goog.math.Integer. Jstype *FieldOptions_JSType `protobuf:"varint,6,opt,name=jstype,enum=google.protobuf.FieldOptions_JSType,def=0" json:"jstype,omitempty"` // Should this field be parsed lazily? Lazy applies only to message-type // fields. It means that when the outer message is initially parsed, the // inner message's contents will not be parsed but instead stored in encoded // form. The inner message will actually be parsed when it is first accessed. // // This is only a hint. Implementations are free to choose whether to use // eager or lazy parsing regardless of the value of this option. However, // setting this option true suggests that the protocol author believes that // using lazy parsing on this field is worth the additional bookkeeping // overhead typically needed to implement it. // // This option does not affect the public interface of any generated code; // all method signatures remain the same. Furthermore, thread-safety of the // interface is not affected by this option; const methods remain safe to // call from multiple threads concurrently, while non-const methods continue // to require exclusive access. // // // Note that implementations may choose not to check required fields within // a lazy sub-message. That is, calling IsInitialized() on the outer message // may return true even if the inner message has missing required fields. // This is necessary because otherwise the inner message would have to be // parsed in order to perform the check, defeating the purpose of lazy // parsing. An implementation which chooses not to check required fields // must be consistent about it. That is, for any particular sub-message, the // implementation must either *always* check its required fields, or *never* // check its required fields, regardless of whether or not the message has // been parsed. Lazy *bool `protobuf:"varint,5,opt,name=lazy,def=0" json:"lazy,omitempty"` // Is this field deprecated? // Depending on the target platform, this can emit Deprecated annotations // for accessors, or it will be completely ignored; in the very least, this // is a formalization for deprecating fields. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // For Google-internal migration only. Do not use. Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for FieldOptions fields. const ( Default_FieldOptions_Ctype = FieldOptions_STRING Default_FieldOptions_Jstype = FieldOptions_JS_NORMAL Default_FieldOptions_Lazy = bool(false) Default_FieldOptions_Deprecated = bool(false) Default_FieldOptions_Weak = bool(false) ) func (x *FieldOptions) Reset() { *x = FieldOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FieldOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*FieldOptions) ProtoMessage() {} func (x *FieldOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[12] 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 FieldOptions.ProtoReflect.Descriptor instead. func (*FieldOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12} } var extRange_FieldOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use FieldOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*FieldOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_FieldOptions } func (x *FieldOptions) GetCtype() FieldOptions_CType { if x != nil && x.Ctype != nil { return *x.Ctype } return Default_FieldOptions_Ctype } func (x *FieldOptions) GetPacked() bool { if x != nil && x.Packed != nil { return *x.Packed } return false } func (x *FieldOptions) GetJstype() FieldOptions_JSType { if x != nil && x.Jstype != nil { return *x.Jstype } return Default_FieldOptions_Jstype } func (x *FieldOptions) GetLazy() bool { if x != nil && x.Lazy != nil { return *x.Lazy } return Default_FieldOptions_Lazy } func (x *FieldOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_FieldOptions_Deprecated } func (x *FieldOptions) GetWeak() bool { if x != nil && x.Weak != nil { return *x.Weak } return Default_FieldOptions_Weak } func (x *FieldOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type OneofOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } func (x *OneofOptions) Reset() { *x = OneofOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *OneofOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*OneofOptions) ProtoMessage() {} func (x *OneofOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[13] 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 OneofOptions.ProtoReflect.Descriptor instead. func (*OneofOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{13} } var extRange_OneofOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use OneofOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*OneofOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_OneofOptions } func (x *OneofOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type EnumOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Set this option to true to allow mapping different tag names to the same // value. AllowAlias *bool `protobuf:"varint,2,opt,name=allow_alias,json=allowAlias" json:"allow_alias,omitempty"` // Is this enum deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum, or it will be completely ignored; in the very least, this // is a formalization for deprecating enums. Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for EnumOptions fields. const ( Default_EnumOptions_Deprecated = bool(false) ) func (x *EnumOptions) Reset() { *x = EnumOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumOptions) ProtoMessage() {} func (x *EnumOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[14] 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 EnumOptions.ProtoReflect.Descriptor instead. func (*EnumOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{14} } var extRange_EnumOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use EnumOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*EnumOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_EnumOptions } func (x *EnumOptions) GetAllowAlias() bool { if x != nil && x.AllowAlias != nil { return *x.AllowAlias } return false } func (x *EnumOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_EnumOptions_Deprecated } func (x *EnumOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type EnumValueOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this enum value deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the enum value, or it will be completely ignored; in the very least, // this is a formalization for deprecating enum values. Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for EnumValueOptions fields. const ( Default_EnumValueOptions_Deprecated = bool(false) ) func (x *EnumValueOptions) Reset() { *x = EnumValueOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumValueOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumValueOptions) ProtoMessage() {} func (x *EnumValueOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[15] 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 EnumValueOptions.ProtoReflect.Descriptor instead. func (*EnumValueOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{15} } var extRange_EnumValueOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use EnumValueOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*EnumValueOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_EnumValueOptions } func (x *EnumValueOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_EnumValueOptions_Deprecated } func (x *EnumValueOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type ServiceOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this service deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the service, or it will be completely ignored; in the very least, // this is a formalization for deprecating services. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for ServiceOptions fields. const ( Default_ServiceOptions_Deprecated = bool(false) ) func (x *ServiceOptions) Reset() { *x = ServiceOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *ServiceOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*ServiceOptions) ProtoMessage() {} func (x *ServiceOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[16] 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 ServiceOptions.ProtoReflect.Descriptor instead. func (*ServiceOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{16} } var extRange_ServiceOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use ServiceOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*ServiceOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_ServiceOptions } func (x *ServiceOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_ServiceOptions_Deprecated } func (x *ServiceOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } type MethodOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields extensionFields protoimpl.ExtensionFields // Is this method deprecated? // Depending on the target platform, this can emit Deprecated annotations // for the method, or it will be completely ignored; in the very least, // this is a formalization for deprecating methods. Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"` IdempotencyLevel *MethodOptions_IdempotencyLevel `protobuf:"varint,34,opt,name=idempotency_level,json=idempotencyLevel,enum=google.protobuf.MethodOptions_IdempotencyLevel,def=0" json:"idempotency_level,omitempty"` // The parser stores options it doesn't recognize here. See above. UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"` } // Default values for MethodOptions fields. const ( Default_MethodOptions_Deprecated = bool(false) Default_MethodOptions_IdempotencyLevel = MethodOptions_IDEMPOTENCY_UNKNOWN ) func (x *MethodOptions) Reset() { *x = MethodOptions{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[17] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *MethodOptions) String() string { return protoimpl.X.MessageStringOf(x) } func (*MethodOptions) ProtoMessage() {} func (x *MethodOptions) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[17] 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 MethodOptions.ProtoReflect.Descriptor instead. func (*MethodOptions) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17} } var extRange_MethodOptions = []protoiface.ExtensionRangeV1{ {Start: 1000, End: 536870911}, } // Deprecated: Use MethodOptions.ProtoReflect.Descriptor.ExtensionRanges instead. func (*MethodOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 { return extRange_MethodOptions } func (x *MethodOptions) GetDeprecated() bool { if x != nil && x.Deprecated != nil { return *x.Deprecated } return Default_MethodOptions_Deprecated } func (x *MethodOptions) GetIdempotencyLevel() MethodOptions_IdempotencyLevel { if x != nil && x.IdempotencyLevel != nil { return *x.IdempotencyLevel } return Default_MethodOptions_IdempotencyLevel } func (x *MethodOptions) GetUninterpretedOption() []*UninterpretedOption { if x != nil { return x.UninterpretedOption } return nil } // A message representing a option the parser does not recognize. This only // appears in options protos created by the compiler::Parser class. // DescriptorPool resolves these when building Descriptor objects. Therefore, // options protos in descriptor objects (e.g. returned by Descriptor::options(), // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions // in them. type UninterpretedOption struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Name []*UninterpretedOption_NamePart `protobuf:"bytes,2,rep,name=name" json:"name,omitempty"` // The value of the uninterpreted option, in whatever type the tokenizer // identified it as during parsing. Exactly one of these should be set. IdentifierValue *string `protobuf:"bytes,3,opt,name=identifier_value,json=identifierValue" json:"identifier_value,omitempty"` PositiveIntValue *uint64 `protobuf:"varint,4,opt,name=positive_int_value,json=positiveIntValue" json:"positive_int_value,omitempty"` NegativeIntValue *int64 `protobuf:"varint,5,opt,name=negative_int_value,json=negativeIntValue" json:"negative_int_value,omitempty"` DoubleValue *float64 `protobuf:"fixed64,6,opt,name=double_value,json=doubleValue" json:"double_value,omitempty"` StringValue []byte `protobuf:"bytes,7,opt,name=string_value,json=stringValue" json:"string_value,omitempty"` AggregateValue *string `protobuf:"bytes,8,opt,name=aggregate_value,json=aggregateValue" json:"aggregate_value,omitempty"` } func (x *UninterpretedOption) Reset() { *x = UninterpretedOption{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[18] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UninterpretedOption) String() string { return protoimpl.X.MessageStringOf(x) } func (*UninterpretedOption) ProtoMessage() {} func (x *UninterpretedOption) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[18] 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 UninterpretedOption.ProtoReflect.Descriptor instead. func (*UninterpretedOption) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{18} } func (x *UninterpretedOption) GetName() []*UninterpretedOption_NamePart { if x != nil { return x.Name } return nil } func (x *UninterpretedOption) GetIdentifierValue() string { if x != nil && x.IdentifierValue != nil { return *x.IdentifierValue } return "" } func (x *UninterpretedOption) GetPositiveIntValue() uint64 { if x != nil && x.PositiveIntValue != nil { return *x.PositiveIntValue } return 0 } func (x *UninterpretedOption) GetNegativeIntValue() int64 { if x != nil && x.NegativeIntValue != nil { return *x.NegativeIntValue } return 0 } func (x *UninterpretedOption) GetDoubleValue() float64 { if x != nil && x.DoubleValue != nil { return *x.DoubleValue } return 0 } func (x *UninterpretedOption) GetStringValue() []byte { if x != nil { return x.StringValue } return nil } func (x *UninterpretedOption) GetAggregateValue() string { if x != nil && x.AggregateValue != nil { return *x.AggregateValue } return "" } // Encapsulates information about the original source file from which a // FileDescriptorProto was generated. type SourceCodeInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // A Location identifies a piece of source code in a .proto file which // corresponds to a particular definition. This information is intended // to be useful to IDEs, code indexers, documentation generators, and similar // tools. // // For example, say we have a file like: // message Foo { // optional string foo = 1; // } // Let's look at just the field definition: // optional string foo = 1; // ^ ^^ ^^ ^ ^^^ // a bc de f ghi // We have the following locations: // span path represents // [a,i) [ 4, 0, 2, 0 ] The whole field definition. // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). // // Notes: // - A location may refer to a repeated field itself (i.e. not to any // particular index within it). This is used whenever a set of elements are // logically enclosed in a single code segment. For example, an entire // extend block (possibly containing multiple extension definitions) will // have an outer location whose path refers to the "extensions" repeated // field without an index. // - Multiple locations may have the same path. This happens when a single // logical declaration is spread out across multiple places. The most // obvious example is the "extend" block again -- there may be multiple // extend blocks in the same scope, each of which will have the same path. // - A location's span is not always a subset of its parent's span. For // example, the "extendee" of an extension declaration appears at the // beginning of the "extend" block and is shared by all extensions within // the block. // - Just because a location's span is a subset of some other location's span // does not mean that it is a descendant. For example, a "group" defines // both a type and a field in a single declaration. Thus, the locations // corresponding to the type and field and their components will overlap. // - Code which tries to interpret locations should probably be designed to // ignore those that it doesn't understand, as more types of locations could // be recorded in the future. Location []*SourceCodeInfo_Location `protobuf:"bytes,1,rep,name=location" json:"location,omitempty"` } func (x *SourceCodeInfo) Reset() { *x = SourceCodeInfo{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[19] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SourceCodeInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*SourceCodeInfo) ProtoMessage() {} func (x *SourceCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[19] 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 SourceCodeInfo.ProtoReflect.Descriptor instead. func (*SourceCodeInfo) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19} } func (x *SourceCodeInfo) GetLocation() []*SourceCodeInfo_Location { if x != nil { return x.Location } return nil } // Describes the relationship between generated code and its original source // file. A GeneratedCodeInfo message is associated with only one generated // source file, but may contain references to different source .proto files. type GeneratedCodeInfo struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // An Annotation connects some span of text in generated code to an element // of its generating .proto file. Annotation []*GeneratedCodeInfo_Annotation `protobuf:"bytes,1,rep,name=annotation" json:"annotation,omitempty"` } func (x *GeneratedCodeInfo) Reset() { *x = GeneratedCodeInfo{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[20] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GeneratedCodeInfo) String() string { return protoimpl.X.MessageStringOf(x) } func (*GeneratedCodeInfo) ProtoMessage() {} func (x *GeneratedCodeInfo) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[20] 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 GeneratedCodeInfo.ProtoReflect.Descriptor instead. func (*GeneratedCodeInfo) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20} } func (x *GeneratedCodeInfo) GetAnnotation() []*GeneratedCodeInfo_Annotation { if x != nil { return x.Annotation } return nil } type DescriptorProto_ExtensionRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Exclusive. Options *ExtensionRangeOptions `protobuf:"bytes,3,opt,name=options" json:"options,omitempty"` } func (x *DescriptorProto_ExtensionRange) Reset() { *x = DescriptorProto_ExtensionRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[21] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto_ExtensionRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto_ExtensionRange) ProtoMessage() {} func (x *DescriptorProto_ExtensionRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[21] 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 DescriptorProto_ExtensionRange.ProtoReflect.Descriptor instead. func (*DescriptorProto_ExtensionRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2, 0} } func (x *DescriptorProto_ExtensionRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *DescriptorProto_ExtensionRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } func (x *DescriptorProto_ExtensionRange) GetOptions() *ExtensionRangeOptions { if x != nil { return x.Options } return nil } // Range of reserved tag numbers. Reserved tag numbers may not be used by // fields or extension ranges in the same message. Reserved ranges may // not overlap. type DescriptorProto_ReservedRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Exclusive. } func (x *DescriptorProto_ReservedRange) Reset() { *x = DescriptorProto_ReservedRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[22] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DescriptorProto_ReservedRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*DescriptorProto_ReservedRange) ProtoMessage() {} func (x *DescriptorProto_ReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[22] 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 DescriptorProto_ReservedRange.ProtoReflect.Descriptor instead. func (*DescriptorProto_ReservedRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{2, 1} } func (x *DescriptorProto_ReservedRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *DescriptorProto_ReservedRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } // Range of reserved numeric values. Reserved values may not be used by // entries in the same enum. Reserved ranges may not overlap. // // Note that this is distinct from DescriptorProto.ReservedRange in that it // is inclusive such that it can appropriately represent the entire int32 // domain. type EnumDescriptorProto_EnumReservedRange struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Start *int32 `protobuf:"varint,1,opt,name=start" json:"start,omitempty"` // Inclusive. End *int32 `protobuf:"varint,2,opt,name=end" json:"end,omitempty"` // Inclusive. } func (x *EnumDescriptorProto_EnumReservedRange) Reset() { *x = EnumDescriptorProto_EnumReservedRange{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[23] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *EnumDescriptorProto_EnumReservedRange) String() string { return protoimpl.X.MessageStringOf(x) } func (*EnumDescriptorProto_EnumReservedRange) ProtoMessage() {} func (x *EnumDescriptorProto_EnumReservedRange) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[23] 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 EnumDescriptorProto_EnumReservedRange.ProtoReflect.Descriptor instead. func (*EnumDescriptorProto_EnumReservedRange) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{6, 0} } func (x *EnumDescriptorProto_EnumReservedRange) GetStart() int32 { if x != nil && x.Start != nil { return *x.Start } return 0 } func (x *EnumDescriptorProto_EnumReservedRange) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } // The name of the uninterpreted option. Each string represents a segment in // a dot-separated name. is_extension is true iff a segment represents an // extension (denoted with parentheses in options specs in .proto files). // E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents // "foo.(bar.baz).qux". type UninterpretedOption_NamePart struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields NamePart *string `protobuf:"bytes,1,req,name=name_part,json=namePart" json:"name_part,omitempty"` IsExtension *bool `protobuf:"varint,2,req,name=is_extension,json=isExtension" json:"is_extension,omitempty"` } func (x *UninterpretedOption_NamePart) Reset() { *x = UninterpretedOption_NamePart{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[24] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UninterpretedOption_NamePart) String() string { return protoimpl.X.MessageStringOf(x) } func (*UninterpretedOption_NamePart) ProtoMessage() {} func (x *UninterpretedOption_NamePart) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[24] 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 UninterpretedOption_NamePart.ProtoReflect.Descriptor instead. func (*UninterpretedOption_NamePart) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{18, 0} } func (x *UninterpretedOption_NamePart) GetNamePart() string { if x != nil && x.NamePart != nil { return *x.NamePart } return "" } func (x *UninterpretedOption_NamePart) GetIsExtension() bool { if x != nil && x.IsExtension != nil { return *x.IsExtension } return false } type SourceCodeInfo_Location struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Identifies which part of the FileDescriptorProto was defined at this // location. // // Each element is a field number or an index. They form a path from // the root FileDescriptorProto to the place where the definition. For // example, this path: // [ 4, 3, 2, 7, 1 ] // refers to: // file.message_type(3) // 4, 3 // .field(7) // 2, 7 // .name() // 1 // This is because FileDescriptorProto.message_type has field number 4: // repeated DescriptorProto message_type = 4; // and DescriptorProto.field has field number 2: // repeated FieldDescriptorProto field = 2; // and FieldDescriptorProto.name has field number 1: // optional string name = 1; // // Thus, the above path gives the location of a field name. If we removed // the last element: // [ 4, 3, 2, 7 ] // this path refers to the whole field declaration (from the beginning // of the label to the terminating semicolon). Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` // Always has exactly three or four elements: start line, start column, // end line (optional, otherwise assumed same as start line), end column. // These are packed into a single field for efficiency. Note that line // and column numbers are zero-based -- typically you will want to add // 1 to each before displaying to a user. Span []int32 `protobuf:"varint,2,rep,packed,name=span" json:"span,omitempty"` // If this SourceCodeInfo represents a complete declaration, these are any // comments appearing before and after the declaration which appear to be // attached to the declaration. // // A series of line comments appearing on consecutive lines, with no other // tokens appearing on those lines, will be treated as a single comment. // // leading_detached_comments will keep paragraphs of comments that appear // before (but not connected to) the current element. Each paragraph, // separated by empty lines, will be one comment element in the repeated // field. // // Only the comment content is provided; comment markers (e.g. //) are // stripped out. For block comments, leading whitespace and an asterisk // will be stripped from the beginning of each line other than the first. // Newlines are included in the output. // // Examples: // // optional int32 foo = 1; // Comment attached to foo. // // Comment attached to bar. // optional int32 bar = 2; // // optional string baz = 3; // // Comment attached to baz. // // Another line attached to baz. // // // Comment attached to qux. // // // // Another line attached to qux. // optional double qux = 4; // // // Detached comment for corge. This is not leading or trailing comments // // to qux or corge because there are blank lines separating it from // // both. // // // Detached comment for corge paragraph 2. // // optional string corge = 5; // /* Block comment attached // * to corge. Leading asterisks // * will be removed. */ // /* Block comment attached to // * grault. */ // optional int32 grault = 6; // // // ignored detached comments. LeadingComments *string `protobuf:"bytes,3,opt,name=leading_comments,json=leadingComments" json:"leading_comments,omitempty"` TrailingComments *string `protobuf:"bytes,4,opt,name=trailing_comments,json=trailingComments" json:"trailing_comments,omitempty"` LeadingDetachedComments []string `protobuf:"bytes,6,rep,name=leading_detached_comments,json=leadingDetachedComments" json:"leading_detached_comments,omitempty"` } func (x *SourceCodeInfo_Location) Reset() { *x = SourceCodeInfo_Location{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[25] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *SourceCodeInfo_Location) String() string { return protoimpl.X.MessageStringOf(x) } func (*SourceCodeInfo_Location) ProtoMessage() {} func (x *SourceCodeInfo_Location) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[25] 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 SourceCodeInfo_Location.ProtoReflect.Descriptor instead. func (*SourceCodeInfo_Location) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{19, 0} } func (x *SourceCodeInfo_Location) GetPath() []int32 { if x != nil { return x.Path } return nil } func (x *SourceCodeInfo_Location) GetSpan() []int32 { if x != nil { return x.Span } return nil } func (x *SourceCodeInfo_Location) GetLeadingComments() string { if x != nil && x.LeadingComments != nil { return *x.LeadingComments } return "" } func (x *SourceCodeInfo_Location) GetTrailingComments() string { if x != nil && x.TrailingComments != nil { return *x.TrailingComments } return "" } func (x *SourceCodeInfo_Location) GetLeadingDetachedComments() []string { if x != nil { return x.LeadingDetachedComments } return nil } type GeneratedCodeInfo_Annotation struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Identifies the element in the original source .proto file. This field // is formatted the same as SourceCodeInfo.Location.path. Path []int32 `protobuf:"varint,1,rep,packed,name=path" json:"path,omitempty"` // Identifies the filesystem path to the original source .proto. SourceFile *string `protobuf:"bytes,2,opt,name=source_file,json=sourceFile" json:"source_file,omitempty"` // Identifies the starting offset in bytes in the generated code // that relates to the identified object. Begin *int32 `protobuf:"varint,3,opt,name=begin" json:"begin,omitempty"` // Identifies the ending offset in bytes in the generated code that // relates to the identified offset. The end offset should be one past // the last relevant byte (so the length of the text = end - begin). End *int32 `protobuf:"varint,4,opt,name=end" json:"end,omitempty"` } func (x *GeneratedCodeInfo_Annotation) Reset() { *x = GeneratedCodeInfo_Annotation{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_descriptor_proto_msgTypes[26] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *GeneratedCodeInfo_Annotation) String() string { return protoimpl.X.MessageStringOf(x) } func (*GeneratedCodeInfo_Annotation) ProtoMessage() {} func (x *GeneratedCodeInfo_Annotation) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_descriptor_proto_msgTypes[26] 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 GeneratedCodeInfo_Annotation.ProtoReflect.Descriptor instead. func (*GeneratedCodeInfo_Annotation) Descriptor() ([]byte, []int) { return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{20, 0} } func (x *GeneratedCodeInfo_Annotation) GetPath() []int32 { if x != nil { return x.Path } return nil } func (x *GeneratedCodeInfo_Annotation) GetSourceFile() string { if x != nil && x.SourceFile != nil { return *x.SourceFile } return "" } func (x *GeneratedCodeInfo_Annotation) GetBegin() int32 { if x != nil && x.Begin != nil { return *x.Begin } return 0 } func (x *GeneratedCodeInfo_Annotation) GetEnd() int32 { if x != nil && x.End != nil { return *x.End } return 0 } var File_google_protobuf_descriptor_proto protoreflect.FileDescriptor var file_google_protobuf_descriptor_proto_rawDesc = []byte{ 0x0a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x4d, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x53, 0x65, 0x74, 0x12, 0x38, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x22, 0xe4, 0x04, 0x0a, 0x13, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x2b, 0x0a, 0x11, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x05, 0x52, 0x10, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x77, 0x65, 0x61, 0x6b, 0x5f, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x05, 0x52, 0x0e, 0x77, 0x65, 0x61, 0x6b, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x43, 0x0a, 0x0c, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x07, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x49, 0x0a, 0x10, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0e, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x79, 0x6e, 0x74, 0x61, 0x78, 0x22, 0xb9, 0x06, 0x0a, 0x0f, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3b, 0x0a, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x12, 0x43, 0x0a, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0b, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x0a, 0x6e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x41, 0x0a, 0x09, 0x65, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x08, 0x65, 0x6e, 0x75, 0x6d, 0x54, 0x79, 0x70, 0x65, 0x12, 0x58, 0x0a, 0x0f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0e, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x44, 0x0a, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x64, 0x65, 0x63, 0x6c, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x63, 0x6c, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x55, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x7a, 0x0a, 0x0e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x12, 0x40, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x1a, 0x37, 0x0a, 0x0d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x7c, 0x0a, 0x15, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc1, 0x06, 0x0a, 0x14, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x52, 0x05, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x3e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x79, 0x70, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6f, 0x6e, 0x65, 0x6f, 0x66, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x1b, 0x0a, 0x09, 0x6a, 0x73, 0x6f, 0x6e, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6a, 0x73, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x22, 0xb6, 0x02, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x44, 0x4f, 0x55, 0x42, 0x4c, 0x45, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4c, 0x4f, 0x41, 0x54, 0x10, 0x02, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x03, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x04, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x06, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x4f, 0x4f, 0x4c, 0x10, 0x08, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x09, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x47, 0x52, 0x4f, 0x55, 0x50, 0x10, 0x0a, 0x12, 0x10, 0x0a, 0x0c, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4d, 0x45, 0x53, 0x53, 0x41, 0x47, 0x45, 0x10, 0x0b, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x59, 0x54, 0x45, 0x53, 0x10, 0x0c, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x0d, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x45, 0x4e, 0x55, 0x4d, 0x10, 0x0e, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x33, 0x32, 0x10, 0x0f, 0x12, 0x11, 0x0a, 0x0d, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x46, 0x49, 0x58, 0x45, 0x44, 0x36, 0x34, 0x10, 0x10, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x33, 0x32, 0x10, 0x11, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x53, 0x49, 0x4e, 0x54, 0x36, 0x34, 0x10, 0x12, 0x22, 0x43, 0x0a, 0x05, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x51, 0x55, 0x49, 0x52, 0x45, 0x44, 0x10, 0x02, 0x12, 0x12, 0x0a, 0x0e, 0x4c, 0x41, 0x42, 0x45, 0x4c, 0x5f, 0x52, 0x45, 0x50, 0x45, 0x41, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x63, 0x0a, 0x14, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe3, 0x02, 0x0a, 0x13, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x36, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x5d, 0x0a, 0x0e, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x52, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x3b, 0x0a, 0x11, 0x45, 0x6e, 0x75, 0x6d, 0x52, 0x65, 0x73, 0x65, 0x72, 0x76, 0x65, 0x64, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x22, 0x83, 0x01, 0x0a, 0x18, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x3b, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa7, 0x01, 0x0a, 0x16, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x3e, 0x0a, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x06, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x12, 0x39, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x89, 0x02, 0x0a, 0x15, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x30, 0x0a, 0x10, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x12, 0x30, 0x0a, 0x10, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x22, 0x91, 0x09, 0x0a, 0x0b, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6a, 0x61, 0x76, 0x61, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6f, 0x75, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x6a, 0x61, 0x76, 0x61, 0x4f, 0x75, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x6a, 0x61, 0x76, 0x61, 0x4d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x12, 0x44, 0x0a, 0x1d, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x5f, 0x61, 0x6e, 0x64, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, 0x42, 0x02, 0x18, 0x01, 0x52, 0x19, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x45, 0x71, 0x75, 0x61, 0x6c, 0x73, 0x41, 0x6e, 0x64, 0x48, 0x61, 0x73, 0x68, 0x12, 0x3a, 0x0a, 0x16, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x5f, 0x75, 0x74, 0x66, 0x38, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x74, 0x66, 0x38, 0x12, 0x53, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x29, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x3a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x46, 0x6f, 0x72, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x6f, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6f, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x35, 0x0a, 0x13, 0x63, 0x63, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x63, 0x63, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x15, 0x6a, 0x61, 0x76, 0x61, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x13, 0x6a, 0x61, 0x76, 0x61, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x13, 0x70, 0x79, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x11, 0x70, 0x79, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x37, 0x0a, 0x14, 0x70, 0x68, 0x70, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x12, 0x70, 0x68, 0x70, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x17, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x2e, 0x0a, 0x10, 0x63, 0x63, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x04, 0x74, 0x72, 0x75, 0x65, 0x52, 0x0e, 0x63, 0x63, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x72, 0x65, 0x6e, 0x61, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6f, 0x62, 0x6a, 0x63, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6f, 0x62, 0x6a, 0x63, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x25, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x73, 0x68, 0x61, 0x72, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x77, 0x69, 0x66, 0x74, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x27, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x77, 0x69, 0x66, 0x74, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x68, 0x70, 0x5f, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x28, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x68, 0x70, 0x43, 0x6c, 0x61, 0x73, 0x73, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x68, 0x70, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x29, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x68, 0x70, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x70, 0x68, 0x70, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x70, 0x68, 0x70, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x62, 0x79, 0x5f, 0x70, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x75, 0x62, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x61, 0x67, 0x65, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x0c, 0x4f, 0x70, 0x74, 0x69, 0x6d, 0x69, 0x7a, 0x65, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x50, 0x45, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x44, 0x45, 0x5f, 0x53, 0x49, 0x5a, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c, 0x4c, 0x49, 0x54, 0x45, 0x5f, 0x52, 0x55, 0x4e, 0x54, 0x49, 0x4d, 0x45, 0x10, 0x03, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x26, 0x10, 0x27, 0x22, 0xd1, 0x02, 0x0a, 0x0e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x3c, 0x0a, 0x17, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x77, 0x69, 0x72, 0x65, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x14, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x53, 0x65, 0x74, 0x57, 0x69, 0x72, 0x65, 0x46, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x12, 0x4c, 0x0a, 0x1f, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x1c, 0x6e, 0x6f, 0x53, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x72, 0x64, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6f, 0x72, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x70, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x08, 0x10, 0x09, 0x4a, 0x04, 0x08, 0x09, 0x10, 0x0a, 0x22, 0xe2, 0x03, 0x0a, 0x0c, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x41, 0x0a, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x43, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x52, 0x05, 0x63, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x61, 0x63, 0x6b, 0x65, 0x64, 0x12, 0x47, 0x0a, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x3a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x52, 0x06, 0x6a, 0x73, 0x74, 0x79, 0x70, 0x65, 0x12, 0x19, 0x0a, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x6c, 0x61, 0x7a, 0x79, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x19, 0x0a, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x04, 0x77, 0x65, 0x61, 0x6b, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x0a, 0x05, 0x43, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x50, 0x49, 0x45, 0x43, 0x45, 0x10, 0x02, 0x22, 0x35, 0x0a, 0x06, 0x4a, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x53, 0x54, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x53, 0x5f, 0x4e, 0x55, 0x4d, 0x42, 0x45, 0x52, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x04, 0x10, 0x05, 0x22, 0x73, 0x0a, 0x0c, 0x4f, 0x6e, 0x65, 0x6f, 0x66, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xc0, 0x01, 0x0a, 0x0b, 0x45, 0x6e, 0x75, 0x6d, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x4a, 0x04, 0x08, 0x05, 0x10, 0x06, 0x22, 0x9e, 0x01, 0x0a, 0x10, 0x45, 0x6e, 0x75, 0x6d, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9c, 0x01, 0x0a, 0x0e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0xe0, 0x02, 0x0a, 0x0d, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x0a, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x08, 0x3a, 0x05, 0x66, 0x61, 0x6c, 0x73, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x70, 0x72, 0x65, 0x63, 0x61, 0x74, 0x65, 0x64, 0x12, 0x71, 0x0a, 0x11, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x4d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x3a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x52, 0x10, 0x69, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x58, 0x0a, 0x14, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0xe7, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x13, 0x75, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0x0a, 0x10, 0x49, 0x64, 0x65, 0x6d, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x17, 0x0a, 0x13, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x43, 0x59, 0x5f, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, 0x4e, 0x4f, 0x5f, 0x53, 0x49, 0x44, 0x45, 0x5f, 0x45, 0x46, 0x46, 0x45, 0x43, 0x54, 0x53, 0x10, 0x01, 0x12, 0x0e, 0x0a, 0x0a, 0x49, 0x44, 0x45, 0x4d, 0x50, 0x4f, 0x54, 0x45, 0x4e, 0x54, 0x10, 0x02, 0x2a, 0x09, 0x08, 0xe8, 0x07, 0x10, 0x80, 0x80, 0x80, 0x80, 0x02, 0x22, 0x9a, 0x03, 0x0a, 0x13, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x6e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x65, 0x74, 0x65, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x69, 0x6e, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x10, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x49, 0x6e, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0b, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x61, 0x67, 0x67, 0x72, 0x65, 0x67, 0x61, 0x74, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x4a, 0x0a, 0x08, 0x4e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x18, 0x01, 0x20, 0x02, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x61, 0x6d, 0x65, 0x50, 0x61, 0x72, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x65, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x02, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x45, 0x78, 0x74, 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0xa7, 0x02, 0x0a, 0x0e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xce, 0x01, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x16, 0x0a, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x18, 0x02, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x73, 0x70, 0x61, 0x6e, 0x12, 0x29, 0x0a, 0x10, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x74, 0x72, 0x61, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x19, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x6c, 0x65, 0x61, 0x64, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x74, 0x61, 0x63, 0x68, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xd1, 0x01, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x4d, 0x0a, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x6d, 0x0a, 0x0a, 0x41, 0x6e, 0x6e, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x42, 0x02, 0x10, 0x01, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x7e, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x10, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x48, 0x01, 0x5a, 0x2d, 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, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x70, 0x62, 0xf8, 0x01, 0x01, 0xa2, 0x02, 0x03, 0x47, 0x50, 0x42, 0xaa, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x52, 0x65, 0x66, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, } var ( file_google_protobuf_descriptor_proto_rawDescOnce sync.Once file_google_protobuf_descriptor_proto_rawDescData = file_google_protobuf_descriptor_proto_rawDesc ) func file_google_protobuf_descriptor_proto_rawDescGZIP() []byte { file_google_protobuf_descriptor_proto_rawDescOnce.Do(func() { file_google_protobuf_descriptor_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_descriptor_proto_rawDescData) }) return file_google_protobuf_descriptor_proto_rawDescData } var file_google_protobuf_descriptor_proto_enumTypes = make([]protoimpl.EnumInfo, 6) var file_google_protobuf_descriptor_proto_msgTypes = make([]protoimpl.MessageInfo, 27) var file_google_protobuf_descriptor_proto_goTypes = []interface{}{ (FieldDescriptorProto_Type)(0), // 0: google.protobuf.FieldDescriptorProto.Type (FieldDescriptorProto_Label)(0), // 1: google.protobuf.FieldDescriptorProto.Label (FileOptions_OptimizeMode)(0), // 2: google.protobuf.FileOptions.OptimizeMode (FieldOptions_CType)(0), // 3: google.protobuf.FieldOptions.CType (FieldOptions_JSType)(0), // 4: google.protobuf.FieldOptions.JSType (MethodOptions_IdempotencyLevel)(0), // 5: google.protobuf.MethodOptions.IdempotencyLevel (*FileDescriptorSet)(nil), // 6: google.protobuf.FileDescriptorSet (*FileDescriptorProto)(nil), // 7: google.protobuf.FileDescriptorProto (*DescriptorProto)(nil), // 8: google.protobuf.DescriptorProto (*ExtensionRangeOptions)(nil), // 9: google.protobuf.ExtensionRangeOptions (*FieldDescriptorProto)(nil), // 10: google.protobuf.FieldDescriptorProto (*OneofDescriptorProto)(nil), // 11: google.protobuf.OneofDescriptorProto (*EnumDescriptorProto)(nil), // 12: google.protobuf.EnumDescriptorProto (*EnumValueDescriptorProto)(nil), // 13: google.protobuf.EnumValueDescriptorProto (*ServiceDescriptorProto)(nil), // 14: google.protobuf.ServiceDescriptorProto (*MethodDescriptorProto)(nil), // 15: google.protobuf.MethodDescriptorProto (*FileOptions)(nil), // 16: google.protobuf.FileOptions (*MessageOptions)(nil), // 17: google.protobuf.MessageOptions (*FieldOptions)(nil), // 18: google.protobuf.FieldOptions (*OneofOptions)(nil), // 19: google.protobuf.OneofOptions (*EnumOptions)(nil), // 20: google.protobuf.EnumOptions (*EnumValueOptions)(nil), // 21: google.protobuf.EnumValueOptions (*ServiceOptions)(nil), // 22: google.protobuf.ServiceOptions (*MethodOptions)(nil), // 23: google.protobuf.MethodOptions (*UninterpretedOption)(nil), // 24: google.protobuf.UninterpretedOption (*SourceCodeInfo)(nil), // 25: google.protobuf.SourceCodeInfo (*GeneratedCodeInfo)(nil), // 26: google.protobuf.GeneratedCodeInfo (*DescriptorProto_ExtensionRange)(nil), // 27: google.protobuf.DescriptorProto.ExtensionRange (*DescriptorProto_ReservedRange)(nil), // 28: google.protobuf.DescriptorProto.ReservedRange (*EnumDescriptorProto_EnumReservedRange)(nil), // 29: google.protobuf.EnumDescriptorProto.EnumReservedRange (*UninterpretedOption_NamePart)(nil), // 30: google.protobuf.UninterpretedOption.NamePart (*SourceCodeInfo_Location)(nil), // 31: google.protobuf.SourceCodeInfo.Location (*GeneratedCodeInfo_Annotation)(nil), // 32: google.protobuf.GeneratedCodeInfo.Annotation } var file_google_protobuf_descriptor_proto_depIdxs = []int32{ 7, // 0: google.protobuf.FileDescriptorSet.file:type_name -> google.protobuf.FileDescriptorProto 8, // 1: google.protobuf.FileDescriptorProto.message_type:type_name -> google.protobuf.DescriptorProto 12, // 2: google.protobuf.FileDescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto 14, // 3: google.protobuf.FileDescriptorProto.service:type_name -> google.protobuf.ServiceDescriptorProto 10, // 4: google.protobuf.FileDescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto 16, // 5: google.protobuf.FileDescriptorProto.options:type_name -> google.protobuf.FileOptions 25, // 6: google.protobuf.FileDescriptorProto.source_code_info:type_name -> google.protobuf.SourceCodeInfo 10, // 7: google.protobuf.DescriptorProto.field:type_name -> google.protobuf.FieldDescriptorProto 10, // 8: google.protobuf.DescriptorProto.extension:type_name -> google.protobuf.FieldDescriptorProto 8, // 9: google.protobuf.DescriptorProto.nested_type:type_name -> google.protobuf.DescriptorProto 12, // 10: google.protobuf.DescriptorProto.enum_type:type_name -> google.protobuf.EnumDescriptorProto 27, // 11: google.protobuf.DescriptorProto.extension_range:type_name -> google.protobuf.DescriptorProto.ExtensionRange 11, // 12: google.protobuf.DescriptorProto.oneof_decl:type_name -> google.protobuf.OneofDescriptorProto 17, // 13: google.protobuf.DescriptorProto.options:type_name -> google.protobuf.MessageOptions 28, // 14: google.protobuf.DescriptorProto.reserved_range:type_name -> google.protobuf.DescriptorProto.ReservedRange 24, // 15: google.protobuf.ExtensionRangeOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 1, // 16: google.protobuf.FieldDescriptorProto.label:type_name -> google.protobuf.FieldDescriptorProto.Label 0, // 17: google.protobuf.FieldDescriptorProto.type:type_name -> google.protobuf.FieldDescriptorProto.Type 18, // 18: google.protobuf.FieldDescriptorProto.options:type_name -> google.protobuf.FieldOptions 19, // 19: google.protobuf.OneofDescriptorProto.options:type_name -> google.protobuf.OneofOptions 13, // 20: google.protobuf.EnumDescriptorProto.value:type_name -> google.protobuf.EnumValueDescriptorProto 20, // 21: google.protobuf.EnumDescriptorProto.options:type_name -> google.protobuf.EnumOptions 29, // 22: google.protobuf.EnumDescriptorProto.reserved_range:type_name -> google.protobuf.EnumDescriptorProto.EnumReservedRange 21, // 23: google.protobuf.EnumValueDescriptorProto.options:type_name -> google.protobuf.EnumValueOptions 15, // 24: google.protobuf.ServiceDescriptorProto.method:type_name -> google.protobuf.MethodDescriptorProto 22, // 25: google.protobuf.ServiceDescriptorProto.options:type_name -> google.protobuf.ServiceOptions 23, // 26: google.protobuf.MethodDescriptorProto.options:type_name -> google.protobuf.MethodOptions 2, // 27: google.protobuf.FileOptions.optimize_for:type_name -> google.protobuf.FileOptions.OptimizeMode 24, // 28: google.protobuf.FileOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 29: google.protobuf.MessageOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 3, // 30: google.protobuf.FieldOptions.ctype:type_name -> google.protobuf.FieldOptions.CType 4, // 31: google.protobuf.FieldOptions.jstype:type_name -> google.protobuf.FieldOptions.JSType 24, // 32: google.protobuf.FieldOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 33: google.protobuf.OneofOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 34: google.protobuf.EnumOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 35: google.protobuf.EnumValueOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 24, // 36: google.protobuf.ServiceOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 5, // 37: google.protobuf.MethodOptions.idempotency_level:type_name -> google.protobuf.MethodOptions.IdempotencyLevel 24, // 38: google.protobuf.MethodOptions.uninterpreted_option:type_name -> google.protobuf.UninterpretedOption 30, // 39: google.protobuf.UninterpretedOption.name:type_name -> google.protobuf.UninterpretedOption.NamePart 31, // 40: google.protobuf.SourceCodeInfo.location:type_name -> google.protobuf.SourceCodeInfo.Location 32, // 41: google.protobuf.GeneratedCodeInfo.annotation:type_name -> google.protobuf.GeneratedCodeInfo.Annotation 9, // 42: google.protobuf.DescriptorProto.ExtensionRange.options:type_name -> google.protobuf.ExtensionRangeOptions 43, // [43:43] is the sub-list for method output_type 43, // [43:43] is the sub-list for method input_type 43, // [43:43] is the sub-list for extension type_name 43, // [43:43] is the sub-list for extension extendee 0, // [0:43] is the sub-list for field type_name } func init() { file_google_protobuf_descriptor_proto_init() } func file_google_protobuf_descriptor_proto_init() { if File_google_protobuf_descriptor_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_protobuf_descriptor_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileDescriptorSet); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ExtensionRangeOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FieldDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OneofDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumValueDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MethodDescriptorProto); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FileOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MessageOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FieldOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*OneofOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumValueOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*ServiceOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*MethodOptions); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields case 3: return &v.extensionFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UninterpretedOption); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SourceCodeInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeneratedCodeInfo); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto_ExtensionRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DescriptorProto_ReservedRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*EnumDescriptorProto_EnumReservedRange); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[24].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UninterpretedOption_NamePart); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*SourceCodeInfo_Location); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_descriptor_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GeneratedCodeInfo_Annotation); 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_descriptor_proto_rawDesc, NumEnums: 6, NumMessages: 27, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_protobuf_descriptor_proto_goTypes, DependencyIndexes: file_google_protobuf_descriptor_proto_depIdxs, EnumInfos: file_google_protobuf_descriptor_proto_enumTypes, MessageInfos: file_google_protobuf_descriptor_proto_msgTypes, }.Build() File_google_protobuf_descriptor_proto = out.File file_google_protobuf_descriptor_proto_rawDesc = nil file_google_protobuf_descriptor_proto_goTypes = nil file_google_protobuf_descriptor_proto_depIdxs = nil } ================================================ FILE: vendor/google.golang.org/protobuf/types/known/emptypb/empty.pb.go ================================================ // 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 } ================================================ FILE: vendor/google.golang.org/protobuf/types/known/wrapperspb/wrappers.pb.go ================================================ // 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. // Wrappers for primitive (non-message) types. These types are useful // for embedding primitives in the `google.protobuf.Any` type and for places // where we need to distinguish between the absence of a primitive // typed field and its default value. // // These wrappers have no meaningful use within repeated fields as they lack // the ability to detect presence on individual elements. // These wrappers have no meaningful use within a map or a oneof since // individual entries of a map or fields of a oneof can already detect presence. // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/wrappers.proto package wrapperspb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" ) // Wrapper message for `double`. // // The JSON representation for `DoubleValue` is JSON number. type DoubleValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The double value. Value float64 `protobuf:"fixed64,1,opt,name=value,proto3" json:"value,omitempty"` } // Double stores v in a new DoubleValue and returns a pointer to it. func Double(v float64) *DoubleValue { return &DoubleValue{Value: v} } func (x *DoubleValue) Reset() { *x = DoubleValue{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *DoubleValue) String() string { return protoimpl.X.MessageStringOf(x) } func (*DoubleValue) ProtoMessage() {} func (x *DoubleValue) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_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 DoubleValue.ProtoReflect.Descriptor instead. func (*DoubleValue) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{0} } func (x *DoubleValue) GetValue() float64 { if x != nil { return x.Value } return 0 } // Wrapper message for `float`. // // The JSON representation for `FloatValue` is JSON number. type FloatValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The float value. Value float32 `protobuf:"fixed32,1,opt,name=value,proto3" json:"value,omitempty"` } // Float stores v in a new FloatValue and returns a pointer to it. func Float(v float32) *FloatValue { return &FloatValue{Value: v} } func (x *FloatValue) Reset() { *x = FloatValue{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *FloatValue) String() string { return protoimpl.X.MessageStringOf(x) } func (*FloatValue) ProtoMessage() {} func (x *FloatValue) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_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 FloatValue.ProtoReflect.Descriptor instead. func (*FloatValue) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{1} } func (x *FloatValue) GetValue() float32 { if x != nil { return x.Value } return 0 } // Wrapper message for `int64`. // // The JSON representation for `Int64Value` is JSON string. type Int64Value struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The int64 value. Value int64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` } // Int64 stores v in a new Int64Value and returns a pointer to it. func Int64(v int64) *Int64Value { return &Int64Value{Value: v} } func (x *Int64Value) Reset() { *x = Int64Value{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Int64Value) String() string { return protoimpl.X.MessageStringOf(x) } func (*Int64Value) ProtoMessage() {} func (x *Int64Value) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_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 Int64Value.ProtoReflect.Descriptor instead. func (*Int64Value) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{2} } func (x *Int64Value) GetValue() int64 { if x != nil { return x.Value } return 0 } // Wrapper message for `uint64`. // // The JSON representation for `UInt64Value` is JSON string. type UInt64Value struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The uint64 value. Value uint64 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` } // UInt64 stores v in a new UInt64Value and returns a pointer to it. func UInt64(v uint64) *UInt64Value { return &UInt64Value{Value: v} } func (x *UInt64Value) Reset() { *x = UInt64Value{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UInt64Value) String() string { return protoimpl.X.MessageStringOf(x) } func (*UInt64Value) ProtoMessage() {} func (x *UInt64Value) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_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 UInt64Value.ProtoReflect.Descriptor instead. func (*UInt64Value) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{3} } func (x *UInt64Value) GetValue() uint64 { if x != nil { return x.Value } return 0 } // Wrapper message for `int32`. // // The JSON representation for `Int32Value` is JSON number. type Int32Value struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The int32 value. Value int32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` } // Int32 stores v in a new Int32Value and returns a pointer to it. func Int32(v int32) *Int32Value { return &Int32Value{Value: v} } func (x *Int32Value) Reset() { *x = Int32Value{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Int32Value) String() string { return protoimpl.X.MessageStringOf(x) } func (*Int32Value) ProtoMessage() {} func (x *Int32Value) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_proto_msgTypes[4] 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 Int32Value.ProtoReflect.Descriptor instead. func (*Int32Value) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{4} } func (x *Int32Value) GetValue() int32 { if x != nil { return x.Value } return 0 } // Wrapper message for `uint32`. // // The JSON representation for `UInt32Value` is JSON number. type UInt32Value struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The uint32 value. Value uint32 `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` } // UInt32 stores v in a new UInt32Value and returns a pointer to it. func UInt32(v uint32) *UInt32Value { return &UInt32Value{Value: v} } func (x *UInt32Value) Reset() { *x = UInt32Value{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *UInt32Value) String() string { return protoimpl.X.MessageStringOf(x) } func (*UInt32Value) ProtoMessage() {} func (x *UInt32Value) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_proto_msgTypes[5] 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 UInt32Value.ProtoReflect.Descriptor instead. func (*UInt32Value) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{5} } func (x *UInt32Value) GetValue() uint32 { if x != nil { return x.Value } return 0 } // Wrapper message for `bool`. // // The JSON representation for `BoolValue` is JSON `true` and `false`. type BoolValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The bool value. Value bool `protobuf:"varint,1,opt,name=value,proto3" json:"value,omitempty"` } // Bool stores v in a new BoolValue and returns a pointer to it. func Bool(v bool) *BoolValue { return &BoolValue{Value: v} } func (x *BoolValue) Reset() { *x = BoolValue{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BoolValue) String() string { return protoimpl.X.MessageStringOf(x) } func (*BoolValue) ProtoMessage() {} func (x *BoolValue) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_proto_msgTypes[6] 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 BoolValue.ProtoReflect.Descriptor instead. func (*BoolValue) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{6} } func (x *BoolValue) GetValue() bool { if x != nil { return x.Value } return false } // Wrapper message for `string`. // // The JSON representation for `StringValue` is JSON string. type StringValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The string value. Value string `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } // String stores v in a new StringValue and returns a pointer to it. func String(v string) *StringValue { return &StringValue{Value: v} } func (x *StringValue) Reset() { *x = StringValue{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *StringValue) String() string { return protoimpl.X.MessageStringOf(x) } func (*StringValue) ProtoMessage() {} func (x *StringValue) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_proto_msgTypes[7] 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 StringValue.ProtoReflect.Descriptor instead. func (*StringValue) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{7} } func (x *StringValue) GetValue() string { if x != nil { return x.Value } return "" } // Wrapper message for `bytes`. // // The JSON representation for `BytesValue` is JSON string. type BytesValue struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The bytes value. Value []byte `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` } // Bytes stores v in a new BytesValue and returns a pointer to it. func Bytes(v []byte) *BytesValue { return &BytesValue{Value: v} } func (x *BytesValue) Reset() { *x = BytesValue{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_wrappers_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *BytesValue) String() string { return protoimpl.X.MessageStringOf(x) } func (*BytesValue) ProtoMessage() {} func (x *BytesValue) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_wrappers_proto_msgTypes[8] 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 BytesValue.ProtoReflect.Descriptor instead. func (*BytesValue) Descriptor() ([]byte, []int) { return file_google_protobuf_wrappers_proto_rawDescGZIP(), []int{8} } func (x *BytesValue) GetValue() []byte { if x != nil { return x.Value } return nil } var File_google_protobuf_wrappers_proto protoreflect.FileDescriptor var file_google_protobuf_wrappers_proto_rawDesc = []byte{ 0x0a, 0x1e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x0f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x22, 0x23, 0x0a, 0x0b, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x0a, 0x46, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x0a, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x55, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x09, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x23, 0x0a, 0x0b, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x22, 0x0a, 0x0a, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42, 0x83, 0x01, 0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x42, 0x0d, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x31, 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, 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 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_wrappers_proto_rawDescOnce sync.Once file_google_protobuf_wrappers_proto_rawDescData = file_google_protobuf_wrappers_proto_rawDesc ) func file_google_protobuf_wrappers_proto_rawDescGZIP() []byte { file_google_protobuf_wrappers_proto_rawDescOnce.Do(func() { file_google_protobuf_wrappers_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_wrappers_proto_rawDescData) }) return file_google_protobuf_wrappers_proto_rawDescData } var file_google_protobuf_wrappers_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_google_protobuf_wrappers_proto_goTypes = []interface{}{ (*DoubleValue)(nil), // 0: google.protobuf.DoubleValue (*FloatValue)(nil), // 1: google.protobuf.FloatValue (*Int64Value)(nil), // 2: google.protobuf.Int64Value (*UInt64Value)(nil), // 3: google.protobuf.UInt64Value (*Int32Value)(nil), // 4: google.protobuf.Int32Value (*UInt32Value)(nil), // 5: google.protobuf.UInt32Value (*BoolValue)(nil), // 6: google.protobuf.BoolValue (*StringValue)(nil), // 7: google.protobuf.StringValue (*BytesValue)(nil), // 8: google.protobuf.BytesValue } var file_google_protobuf_wrappers_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_wrappers_proto_init() } func file_google_protobuf_wrappers_proto_init() { if File_google_protobuf_wrappers_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_protobuf_wrappers_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*DoubleValue); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*FloatValue); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Int64Value); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UInt64Value); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Int32Value); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*UInt32Value); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BoolValue); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StringValue); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_wrappers_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BytesValue); 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_wrappers_proto_rawDesc, NumEnums: 0, NumMessages: 9, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_protobuf_wrappers_proto_goTypes, DependencyIndexes: file_google_protobuf_wrappers_proto_depIdxs, MessageInfos: file_google_protobuf_wrappers_proto_msgTypes, }.Build() File_google_protobuf_wrappers_proto = out.File file_google_protobuf_wrappers_proto_rawDesc = nil file_google_protobuf_wrappers_proto_goTypes = nil file_google_protobuf_wrappers_proto_depIdxs = nil } ================================================ FILE: vendor/google.golang.org/protobuf/types/pluginpb/plugin.pb.go ================================================ // 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. // Author: kenton@google.com (Kenton Varda) // // WARNING: The plugin interface is currently EXPERIMENTAL and is subject to // change. // // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is // just a program that reads a CodeGeneratorRequest from stdin and writes a // CodeGeneratorResponse to stdout. // // Plugins written using C++ can use google/protobuf/compiler/plugin.h instead // of dealing with the raw protocol defined here. // // A plugin executable needs only to be placed somewhere in the path. The // plugin should be named "protoc-gen-$NAME", and will then be used when the // flag "--${NAME}_out" is passed to protoc. // Code generated by protoc-gen-go. DO NOT EDIT. // source: google/protobuf/compiler/plugin.proto package pluginpb import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" descriptorpb "google.golang.org/protobuf/types/descriptorpb" reflect "reflect" sync "sync" ) // Sync with code_generator.h. type CodeGeneratorResponse_Feature int32 const ( CodeGeneratorResponse_FEATURE_NONE CodeGeneratorResponse_Feature = 0 CodeGeneratorResponse_FEATURE_PROTO3_OPTIONAL CodeGeneratorResponse_Feature = 1 ) // Enum value maps for CodeGeneratorResponse_Feature. var ( CodeGeneratorResponse_Feature_name = map[int32]string{ 0: "FEATURE_NONE", 1: "FEATURE_PROTO3_OPTIONAL", } CodeGeneratorResponse_Feature_value = map[string]int32{ "FEATURE_NONE": 0, "FEATURE_PROTO3_OPTIONAL": 1, } ) func (x CodeGeneratorResponse_Feature) Enum() *CodeGeneratorResponse_Feature { p := new(CodeGeneratorResponse_Feature) *p = x return p } func (x CodeGeneratorResponse_Feature) String() string { return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } func (CodeGeneratorResponse_Feature) Descriptor() protoreflect.EnumDescriptor { return file_google_protobuf_compiler_plugin_proto_enumTypes[0].Descriptor() } func (CodeGeneratorResponse_Feature) Type() protoreflect.EnumType { return &file_google_protobuf_compiler_plugin_proto_enumTypes[0] } func (x CodeGeneratorResponse_Feature) Number() protoreflect.EnumNumber { return protoreflect.EnumNumber(x) } // Deprecated: Do not use. func (x *CodeGeneratorResponse_Feature) UnmarshalJSON(b []byte) error { num, err := protoimpl.X.UnmarshalJSONEnum(x.Descriptor(), b) if err != nil { return err } *x = CodeGeneratorResponse_Feature(num) return nil } // Deprecated: Use CodeGeneratorResponse_Feature.Descriptor instead. func (CodeGeneratorResponse_Feature) EnumDescriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0} } // The version number of protocol compiler. type Version struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields 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"` } func (x *Version) Reset() { *x = Version{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *Version) String() string { return protoimpl.X.MessageStringOf(x) } func (*Version) ProtoMessage() {} func (x *Version) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[0] if 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 Version.ProtoReflect.Descriptor instead. func (*Version) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{0} } func (x *Version) GetMajor() int32 { if x != nil && x.Major != nil { return *x.Major } return 0 } func (x *Version) GetMinor() int32 { if x != nil && x.Minor != nil { return *x.Minor } return 0 } func (x *Version) GetPatch() int32 { if x != nil && x.Patch != nil { return *x.Patch } return 0 } func (x *Version) GetSuffix() string { if x != nil && x.Suffix != nil { return *x.Suffix } return "" } // An encoded CodeGeneratorRequest is written to the plugin's stdin. type CodeGeneratorRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // 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 []*descriptorpb.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"` } func (x *CodeGeneratorRequest) Reset() { *x = CodeGeneratorRequest{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorRequest) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorRequest) ProtoMessage() {} func (x *CodeGeneratorRequest) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[1] if 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 CodeGeneratorRequest.ProtoReflect.Descriptor instead. func (*CodeGeneratorRequest) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{1} } func (x *CodeGeneratorRequest) GetFileToGenerate() []string { if x != nil { return x.FileToGenerate } return nil } func (x *CodeGeneratorRequest) GetParameter() string { if x != nil && x.Parameter != nil { return *x.Parameter } return "" } func (x *CodeGeneratorRequest) GetProtoFile() []*descriptorpb.FileDescriptorProto { if x != nil { return x.ProtoFile } return nil } func (x *CodeGeneratorRequest) GetCompilerVersion() *Version { if x != nil { return x.CompilerVersion } return nil } // The plugin writes an encoded CodeGeneratorResponse to stdout. type CodeGeneratorResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // Error message. If non-empty, code generation failed. The plugin process // should exit with status code zero even if it reports an error in this way. // // This should be used to indicate errors in .proto files which prevent the // code generator from generating correct code. Errors which indicate a // problem in protoc itself -- such as the input CodeGeneratorRequest being // unparseable -- should be reported by writing a message to stderr and // exiting with a non-zero status code. Error *string `protobuf:"bytes,1,opt,name=error" json:"error,omitempty"` // A bitmask of supported features that the code generator supports. // This is a bitwise "or" of values from the Feature enum. SupportedFeatures *uint64 `protobuf:"varint,2,opt,name=supported_features,json=supportedFeatures" json:"supported_features,omitempty"` File []*CodeGeneratorResponse_File `protobuf:"bytes,15,rep,name=file" json:"file,omitempty"` } func (x *CodeGeneratorResponse) Reset() { *x = CodeGeneratorResponse{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorResponse) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorResponse) ProtoMessage() {} func (x *CodeGeneratorResponse) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[2] if 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 CodeGeneratorResponse.ProtoReflect.Descriptor instead. func (*CodeGeneratorResponse) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2} } func (x *CodeGeneratorResponse) GetError() string { if x != nil && x.Error != nil { return *x.Error } return "" } func (x *CodeGeneratorResponse) GetSupportedFeatures() uint64 { if x != nil && x.SupportedFeatures != nil { return *x.SupportedFeatures } return 0 } func (x *CodeGeneratorResponse) GetFile() []*CodeGeneratorResponse_File { if x != nil { return x.File } return nil } // Represents a single generated file. type CodeGeneratorResponse_File struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields // The file name, relative to the output directory. The name must not // contain "." or ".." components and must be relative, not be absolute (so, // the file cannot lie outside the output directory). "/" must be used as // the path separator, not "\". // // If the name is omitted, the content will be appended to the previous // file. This allows the generator to break large files into small chunks, // and allows the generated text to be streamed back to protoc so that large // files need not reside completely in memory at one time. Note that as of // this writing protoc does not optimize for this -- it will read the entire // CodeGeneratorResponse before writing files to disk. Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` // If non-empty, indicates that the named file should already exist, and the // content here is to be inserted into that file at a defined insertion // point. This feature allows a code generator to extend the output // produced by another code generator. The original generator may provide // insertion points by placing special annotations in the file that look // like: // @@protoc_insertion_point(NAME) // The annotation can have arbitrary text before and after it on the line, // which allows it to be placed in a comment. NAME should be replaced with // an identifier naming the point -- this is what other generators will use // as the insertion_point. Code inserted at this point will be placed // immediately above the line containing the insertion point (thus multiple // insertions to the same point will come out in the order they were added). // The double-@ is intended to make it unlikely that the generated code // could contain things that look like insertion points by accident. // // For example, the C++ code generator places the following line in the // .pb.h files that it generates: // // @@protoc_insertion_point(namespace_scope) // This line appears within the scope of the file's package namespace, but // outside of any particular class. Another plugin can then specify the // insertion_point "namespace_scope" to generate additional classes or // other declarations that should be placed in this scope. // // Note that if the line containing the insertion point begins with // whitespace, the same whitespace will be added to every line of the // inserted text. This is useful for languages like Python, where // indentation matters. In these languages, the insertion point comment // should be indented the same amount as any inserted code will need to be // in order to work correctly in that context. // // The code generator that generates the initial file and the one which // inserts into it must both run as part of a single invocation of protoc. // Code generators are executed in the order in which they appear on the // command line. // // If |insertion_point| is present, |name| must also be present. InsertionPoint *string `protobuf:"bytes,2,opt,name=insertion_point,json=insertionPoint" json:"insertion_point,omitempty"` // The file contents. Content *string `protobuf:"bytes,15,opt,name=content" json:"content,omitempty"` // Information describing the file content being inserted. If an insertion // point is used, this information will be appropriately offset and inserted // into the code generation metadata for the generated files. GeneratedCodeInfo *descriptorpb.GeneratedCodeInfo `protobuf:"bytes,16,opt,name=generated_code_info,json=generatedCodeInfo" json:"generated_code_info,omitempty"` } func (x *CodeGeneratorResponse_File) Reset() { *x = CodeGeneratorResponse_File{} if protoimpl.UnsafeEnabled { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } func (x *CodeGeneratorResponse_File) String() string { return protoimpl.X.MessageStringOf(x) } func (*CodeGeneratorResponse_File) ProtoMessage() {} func (x *CodeGeneratorResponse_File) ProtoReflect() protoreflect.Message { mi := &file_google_protobuf_compiler_plugin_proto_msgTypes[3] if 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 CodeGeneratorResponse_File.ProtoReflect.Descriptor instead. func (*CodeGeneratorResponse_File) Descriptor() ([]byte, []int) { return file_google_protobuf_compiler_plugin_proto_rawDescGZIP(), []int{2, 0} } func (x *CodeGeneratorResponse_File) GetName() string { if x != nil && x.Name != nil { return *x.Name } return "" } func (x *CodeGeneratorResponse_File) GetInsertionPoint() string { if x != nil && x.InsertionPoint != nil { return *x.InsertionPoint } return "" } func (x *CodeGeneratorResponse_File) GetContent() string { if x != nil && x.Content != nil { return *x.Content } return "" } func (x *CodeGeneratorResponse_File) GetGeneratedCodeInfo() *descriptorpb.GeneratedCodeInfo { if x != nil { return x.GeneratedCodeInfo } return nil } var File_google_protobuf_compiler_plugin_proto protoreflect.FileDescriptor var file_google_protobuf_compiler_plugin_proto_rawDesc = []byte{ 0x0a, 0x25, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x18, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x1a, 0x20, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x63, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x69, 0x6e, 0x6f, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x70, 0x61, 0x74, 0x63, 0x68, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x75, 0x66, 0x66, 0x69, 0x78, 0x22, 0xf1, 0x01, 0x0a, 0x14, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x74, 0x6f, 0x5f, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x54, 0x6f, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x43, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x52, 0x09, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x94, 0x03, 0x0a, 0x15, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2d, 0x0a, 0x12, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x11, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x73, 0x12, 0x48, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x1a, 0xb1, 0x01, 0x0a, 0x04, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x65, 0x72, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x52, 0x0a, 0x13, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x11, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x38, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x10, 0x0a, 0x0c, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x33, 0x5f, 0x4f, 0x50, 0x54, 0x49, 0x4f, 0x4e, 0x41, 0x4c, 0x10, 0x01, 0x42, 0x57, 0x0a, 0x1c, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x42, 0x0c, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x5a, 0x29, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2e, 0x6f, 0x72, 0x67, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x70, 0x62, } var ( file_google_protobuf_compiler_plugin_proto_rawDescOnce sync.Once file_google_protobuf_compiler_plugin_proto_rawDescData = file_google_protobuf_compiler_plugin_proto_rawDesc ) func file_google_protobuf_compiler_plugin_proto_rawDescGZIP() []byte { file_google_protobuf_compiler_plugin_proto_rawDescOnce.Do(func() { file_google_protobuf_compiler_plugin_proto_rawDescData = protoimpl.X.CompressGZIP(file_google_protobuf_compiler_plugin_proto_rawDescData) }) return file_google_protobuf_compiler_plugin_proto_rawDescData } var file_google_protobuf_compiler_plugin_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_protobuf_compiler_plugin_proto_msgTypes = make([]protoimpl.MessageInfo, 4) var file_google_protobuf_compiler_plugin_proto_goTypes = []interface{}{ (CodeGeneratorResponse_Feature)(0), // 0: google.protobuf.compiler.CodeGeneratorResponse.Feature (*Version)(nil), // 1: google.protobuf.compiler.Version (*CodeGeneratorRequest)(nil), // 2: google.protobuf.compiler.CodeGeneratorRequest (*CodeGeneratorResponse)(nil), // 3: google.protobuf.compiler.CodeGeneratorResponse (*CodeGeneratorResponse_File)(nil), // 4: google.protobuf.compiler.CodeGeneratorResponse.File (*descriptorpb.FileDescriptorProto)(nil), // 5: google.protobuf.FileDescriptorProto (*descriptorpb.GeneratedCodeInfo)(nil), // 6: google.protobuf.GeneratedCodeInfo } var file_google_protobuf_compiler_plugin_proto_depIdxs = []int32{ 5, // 0: google.protobuf.compiler.CodeGeneratorRequest.proto_file:type_name -> google.protobuf.FileDescriptorProto 1, // 1: google.protobuf.compiler.CodeGeneratorRequest.compiler_version:type_name -> google.protobuf.compiler.Version 4, // 2: google.protobuf.compiler.CodeGeneratorResponse.file:type_name -> google.protobuf.compiler.CodeGeneratorResponse.File 6, // 3: google.protobuf.compiler.CodeGeneratorResponse.File.generated_code_info:type_name -> google.protobuf.GeneratedCodeInfo 4, // [4:4] is the sub-list for method output_type 4, // [4:4] is the sub-list for method input_type 4, // [4:4] is the sub-list for extension type_name 4, // [4:4] is the sub-list for extension extendee 0, // [0:4] is the sub-list for field type_name } func init() { file_google_protobuf_compiler_plugin_proto_init() } func file_google_protobuf_compiler_plugin_proto_init() { if File_google_protobuf_compiler_plugin_proto != nil { return } if !protoimpl.UnsafeEnabled { file_google_protobuf_compiler_plugin_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Version); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorRequest); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorResponse); i { case 0: return &v.state case 1: return &v.sizeCache case 2: return &v.unknownFields default: return nil } } file_google_protobuf_compiler_plugin_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*CodeGeneratorResponse_File); 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_compiler_plugin_proto_rawDesc, NumEnums: 1, NumMessages: 4, NumExtensions: 0, NumServices: 0, }, GoTypes: file_google_protobuf_compiler_plugin_proto_goTypes, DependencyIndexes: file_google_protobuf_compiler_plugin_proto_depIdxs, EnumInfos: file_google_protobuf_compiler_plugin_proto_enumTypes, MessageInfos: file_google_protobuf_compiler_plugin_proto_msgTypes, }.Build() File_google_protobuf_compiler_plugin_proto = out.File file_google_protobuf_compiler_plugin_proto_rawDesc = nil file_google_protobuf_compiler_plugin_proto_goTypes = nil file_google_protobuf_compiler_plugin_proto_depIdxs = nil } ================================================ FILE: vendor_test.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp import ( "go/build" "os" "strings" "testing" ) func TestNoExternalDeps(t *testing.T) { // Twirp commits its vendor directory so that 'go get' works for its main // packages, but vendoring dependencies of the 'twirp' package could cause // problems for users. // // The simplest way to make things safe is to have no non-stdlib dependencies // in the twirp package. wd, err := os.Getwd() if err != nil { t.Fatalf("unable to get current working directory: %v", err) } // Gather all imports of the current package recursively allPkgs := make(map[string]bool) var walkImports func(string) walkImports = func(pkgName string) { if allPkgs[pkgName] { // already visited return } allPkgs[pkgName] = true pkg, err := build.Default.Import(pkgName, wd, 0) if err != nil { t.Fatalf("unable to import package %s: %s", pkgName, err) } for _, imported := range pkg.Imports { // Standard library packages don't have a '.' in them. if !strings.Contains(imported, ".") { continue } // This is a non-stdlib package. It's okay if it's a twirp package - as // long as it doesn't have any external deps itself. if strings.HasPrefix(imported, "github.com/twitchtv/twirp") { walkImports(imported) } else { t.Errorf("imported external dependency: %v, imported by %v", imported, pkgName) } } } walkImports("github.com/twitchtv/twirp") } ================================================ FILE: version_constant.go ================================================ // Copyright 2018 Twitch Interactive, Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not // use this file except in compliance with the License. A copy of the License is // located at // // http://www.apache.org/licenses/LICENSE-2.0 // // or in the "license" file accompanying this file. This file 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 twirp // TwirpPackageIsVersion7 is a constant referenced from generated code to // assert version compatibility at compile time. const TwirpPackageIsVersion7 = true // TwirpPackageMinVersion_8_1_0 is required from generated code to // assert version compatibility at compile time. const TwirpPackageMinVersion_8_1_0 = true ================================================ FILE: website/.gitignore ================================================ node_modules .DS_Store build/ yarn.lock package-lock.json i18n/* !i18n/en.json translated_docs ================================================ FILE: website/core/Footer.js ================================================ /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const React = require('react'); class Footer extends React.Component { render() { const currentYear = new Date().getFullYear(); return (

Copyright © {currentYear} Twitch Interactive, Inc.
); } } module.exports = Footer; ================================================ FILE: website/i18n/en.json ================================================ { "_comment": "This file is auto-generated by write-translations.js", "localized-strings": { "next": "Next", "previous": "Previous", "tagline": "Simple RPC framework powered by protobuf", "docs": { "best_practices": { "title": "Best Practices", "sidebar_label": "Best Practices" }, "command_line": { "title": "Generator Flags for the Protoc Compiler", "sidebar_label": "Generator Flags" }, "curl": { "title": "cURL", "sidebar_label": "cURL" }, "errors": { "title": "Errors", "sidebar_label": "Errors" }, "example": { "title": "Usage Example: Haberdasher", "sidebar_label": "Usage Example" }, "headers": { "title": "Using custom HTTP Headers", "sidebar_label": "Custom HTTP Headers" }, "hooks": { "title": "Hooks and Interceptors", "sidebar_label": "Hooks and Interceptors" }, "install": { "title": "Installing Twirp", "sidebar_label": "Installation" }, "intro": { "title": "Meet Twirp!", "sidebar_label": "Overview" }, "migrate_to_twirp": { "title": "Migrate APIs to Twirp", "sidebar_label": "Migrate APIs to Twirp" }, "mux": { "title": "Muxing Twirp with other HTTP services", "sidebar_label": "Muxing Twirp services" }, "proto_and_json": { "title": "Twirp's Serialization Schemes", "sidebar_label": "Protobuf and JSON" }, "routing": { "title": "Routing and Serialization", "sidebar_label": "Routing and Serialization" }, "spec_v5": { "title": "Twirp Wire Protocol (v5)", "sidebar_label": "Version 5 (Previous)" }, "spec_v6": { "title": "Twirp Wire Protocol (v6)", "sidebar_label": "Version 6 (Archived)" }, "spec_v7": { "title": "Twirp Wire Protocol (v7)", "sidebar_label": "Version 7 (Current)" }, "version_matrix": { "title": "Version Compatibility", "sidebar_label": "Version Compatibility" } }, "links": { "Docs": "Docs", "Spec": "Spec" }, "categories": { "Getting started": "Getting started", "Beyond the basics": "Beyond the basics", "Formal specification": "Formal specification" } }, "pages-strings": { "Help Translate|recruit community translators for your project": "Help Translate", "Edit this Doc|recruitment message asking to edit the doc source": "Edit", "Translate this Doc|recruitment message asking to translate the docs": "Translate" } } ================================================ FILE: website/package.json ================================================ { "scripts": { "examples": "docusaurus-examples", "start": "docusaurus-start", "build": "docusaurus-build", "publish-gh-pages": "docusaurus-publish", "write-translations": "docusaurus-write-translations", "version": "docusaurus-version", "rename-version": "docusaurus-rename-version" }, "devDependencies": { "docusaurus": "^1.0.5" } } ================================================ FILE: website/pages/en/help.js ================================================ /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const React = require('react'); const CompLibrary = require('../../core/CompLibrary.js'); const Container = CompLibrary.Container; const GridBlock = CompLibrary.GridBlock; const siteConfig = require(process.cwd() + '/siteConfig.js'); class Help extends React.Component { render() { const supportLinks = [ { content: 'Learn more using the [documentation on this site.](/test-site/docs/en/doc1.html)', title: 'Browse Docs', }, { content: 'Ask questions about the documentation and project', title: 'Join the community', }, { content: "Find out what's new with this project", title: 'Stay up to date', }, ]; return (

Need help?

This project is maintained by a dedicated group of people.

); } } module.exports = Help; ================================================ FILE: website/pages/en/index.js ================================================ /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const React = require('react'); const CompLibrary = require('../../core/CompLibrary.js'); const MarkdownBlock = CompLibrary.MarkdownBlock; /* Used to read markdown */ const Container = CompLibrary.Container; const GridBlock = CompLibrary.GridBlock; const siteConfig = require(process.cwd() + '/siteConfig.js'); function imgUrl(img) { return siteConfig.baseUrl + 'img/' + img; } function docUrl(doc, language) { return siteConfig.baseUrl + 'docs/' + (language ? language + '/' : '') + doc; } function pageUrl(page, language) { return siteConfig.baseUrl + (language ? language + '/' : '') + page; } class Button extends React.Component { render() { return ( ); } } Button.defaultProps = { target: '_self', }; const SplashContainer = props => (
{props.children}
); const Logo = props => (
); const ProjectTitle = props => (

{siteConfig.title} {siteConfig.tagline}

); const PromoSection = props => (
{props.children}
); class HomeSplash extends React.Component { render() { let language = this.props.language || ''; return (
); } } const Block = props => ( ); class Index extends React.Component { render() { let language = this.props.language || ''; return (
); } } module.exports = Index; ================================================ FILE: website/pages/en/users.js ================================================ /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ const React = require('react'); const CompLibrary = require('../../core/CompLibrary.js'); const Container = CompLibrary.Container; const siteConfig = require(process.cwd() + '/siteConfig.js'); class Users extends React.Component { render() { const showcase = siteConfig.users.map((user, i) => { return ( ); }); return (

Who's Using This?

This project is used by many folks

{showcase}

Are you using this project?

Add your company
); } } module.exports = Users; ================================================ FILE: website/sidebars.json ================================================ { "docs": { "Getting started": ["intro", "install", "example", "best_practices"], "Beyond the basics": [ "routing", "errors", "proto_and_json", "hooks", "mux", "headers", "command_line", "curl", "migrate_to_twirp", "version_matrix" ], "Formal specification": ["spec_v5", "spec_v6", "spec_v7"] } } ================================================ FILE: website/siteConfig.js ================================================ /** * Copyright (c) 2017-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ /* List of projects/orgs using your project for the users page */ const users = [ { caption: 'Twitch', image: '/test-site/img/twitch.png', infoLink: 'https://twitch.tv', pinned: true, }, ]; const siteConfig = { title: 'Twirp' /* title for your website */, tagline: 'Simple RPC framework powered by protobuf', url: 'https://twitchtv.github.io' /* your website url */, baseUrl: '/twirp/' /* base url for your project */, organizationName: 'twitchtv', projectName: 'twirp', headerLinks: [ {doc: 'intro', label: 'Docs'}, {doc: 'spec_v7', label: 'Spec'}, ], users, /* colors for website */ colors: { primaryColor: '#6441a5', secondaryColor: '#f1f1f1', }, // This copyright info is used in /core/Footer.js and blog rss/atom feeds. copyright: 'Copyright © ' + new Date().getFullYear() + ' Twitch Interactive, Inc.', // organizationName: 'deltice', // or set an env variable ORGANIZATION_NAME // projectName: 'test-site', // or set an env variable PROJECT_NAME highlight: { // Highlight.js theme to use for syntax highlighting in code blocks theme: 'tomorrow', }, scripts: ['https://buttons.github.io/buttons.js'], // You may provide arbitrary config keys to be used as needed by your template. repoUrl: 'https://github.com/twitchtv/twirp', }; module.exports = siteConfig; ================================================ FILE: website/static/.well-known/assetlinks.json ================================================ [{ "relation": ["lookalikes/allowlist"], "target" : { "namespace": "web", "site": "https://twitchtv.github.io" } },{ "relation": ["lookalikes/allowlist"], "target" : { "namespace": "web", "site": "https://twitch.tv" } }] ================================================ FILE: website/static/css/custom.css ================================================ /* your custom css */ @media only screen and (min-device-width: 360px) and (max-device-width: 736px) { } @media only screen and (min-width: 1024px) { } @media only screen and (max-width: 1023px) { } @media only screen and (min-width: 1400px) { } @media only screen and (min-width: 1500px) { } .mainContainer .wrapper p, .blockElement p, .mainContainer .wrapper ul li, .mainContainer .wrapper ol li { line-height: 1.5; }