├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Cargo.toml ├── README.md ├── bin └── protoc-win32.exe ├── include ├── google │ ├── README.md │ └── protobuf │ │ ├── any.proto │ │ ├── api.proto │ │ ├── compiler │ │ └── plugin.proto │ │ ├── descriptor.proto │ │ ├── duration.proto │ │ ├── empty.proto │ │ ├── field_mask.proto │ │ ├── source_context.proto │ │ ├── struct.proto │ │ ├── timestamp.proto │ │ ├── type.proto │ │ └── wrappers.proto └── rustproto.proto ├── src ├── lib.rs ├── prost_impl.rs ├── protobuf_impl.rs └── wrapper.rs └── tests ├── Cargo.toml ├── build.rs ├── proto └── nested.proto └── src └── lib.rs /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | pull_request: 5 | 6 | env: 7 | RUST_BACKTRACE: 1 8 | RUSTFLAGS: "--deny=warnings" 9 | 10 | jobs: 11 | Linux-Stable: 12 | name: Linux-Stable 13 | runs-on: ubuntu-latest 14 | steps: 15 | - uses: actions/checkout@v3 16 | - run: rustup component add rustfmt clippy 17 | - run: which cargo && cargo version 18 | - run: cargo fmt -- --check 19 | - run: cargo clippy --all 20 | - run: cargo test --all -- --nocapture 21 | - run: cargo test --no-default-features --features prost-codec --all -- --nocapture 22 | - run: cargo test --no-default-features --features grpcio-protobuf-codec --all -- --nocapture 23 | - run: cargo test --no-default-features --features grpcio-prost-codec --all -- --nocapture 24 | 25 | Linux-Nightly: 26 | name: Linux-Nightly 27 | runs-on: ubuntu-latest 28 | steps: 29 | - uses: actions/checkout@v3 30 | - run: rustup default nightly 31 | - run: which cargo && cargo version 32 | - run: cargo test --all -- --nocapture 33 | - run: cargo test --no-default-features --features prost-codec --all -- --nocapture 34 | - run: cargo test --no-default-features --features grpcio-protobuf-codec --all -- --nocapture 35 | - run: cargo test --no-default-features --features grpcio-prost-codec --all -- --nocapture 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | .idea 4 | .vscode 5 | Cargo.lock 6 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "protobuf-build" 3 | version = "0.15.1" 4 | authors = ["Nick Cameron "] 5 | edition = "2018" 6 | license = "Apache-2.0" 7 | repository = "https://github.com/tikv/protobuf-build" 8 | homepage = "https://github.com/tikv/protobuf-build" 9 | description = "Utility functions for generating Rust code from protobufs (using protobuf-rust or Prost)" 10 | 11 | [features] 12 | default = ["protobuf-codec"] 13 | protobuf-codec = ["protobuf-codegen", "protobuf/with-bytes"] 14 | grpcio-protobuf-codec = ["grpcio-compiler/protobuf-codec", "protobuf-codec"] 15 | prost-codec = ["syn", "quote", "prost-build", "proc-macro2"] 16 | grpcio-prost-codec = ["grpcio-compiler/prost-codec", "prost-codec"] 17 | 18 | [dependencies] 19 | proc-macro2 = { version = "1", optional = true } 20 | protobuf = { version = "2", optional = true } 21 | protobuf-codegen = { version = "2", optional = true } 22 | grpcio-compiler = { version = ">=0.8", default-features = false, optional = true } 23 | prost-build = { version = "0.11", optional = true } 24 | regex = { version = "1.3" } 25 | syn = { version = "1.0", features = ["full"], optional = true } 26 | quote = { version = "1.0", optional = true } 27 | bitflags = "1.2" 28 | 29 | [target.'cfg(not(windows))'.dependencies] 30 | protobuf-src = "1.1.0" 31 | 32 | [workspace] 33 | members = ["tests"] 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # protobuf-build 2 | 3 | 4 | [![Crates.io][cr-svg]][cr-url] 5 | [![Crates.io][cv-svg]][cr-url] 6 | [![Docs.rs][dv-svg]][dv-url] 7 | [![dependency status][dep-svg]][dep-rs] 8 | [![Build Status][tv-svg]][tv-url] 9 | 10 | [cr-svg]: https://img.shields.io/crates/d/protobuf-build.svg 11 | [cr-url]: https://crates.io/crates/protobuf-build 12 | [cv-svg]: https://img.shields.io/crates/v/protobuf-build.svg 13 | [dv-svg]: https://docs.rs/protobuf-build/badge.svg 14 | [dv-url]: https://docs.rs/protobuf-build 15 | [tv-svg]: https://travis-ci.org/tikv/protobuf-build.svg?branch=master 16 | [tv-url]: https://travis-ci.org/tikv/protobuf-build 17 | [dep-rs]: https://deps.rs/repo/github/tikv/protobuf-build 18 | [dep-svg]: https://deps.rs/repo/github/tikv/protobuf-build/status.svg 19 | 20 | Utility functions for generating Rust code from protobuf specifications. 21 | 22 | Can use [rust-protobuf](https://github.com/stepancheg/rust-protobuf) and 23 | [Prost](https://github.com/danburkert/prost). 24 | -------------------------------------------------------------------------------- /bin/protoc-win32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tikv/protobuf-build/cd2d52b4bc53e07d11d480ea283da4c8fe2f8e46/bin/protoc-win32.exe -------------------------------------------------------------------------------- /include/google/README.md: -------------------------------------------------------------------------------- 1 | Proto files from google protobuf, v21.5 2 | -------------------------------------------------------------------------------- /include/google/protobuf/any.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/anypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "AnyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | 42 | // `Any` contains an arbitrary serialized protocol buffer message along with a 43 | // URL that describes the type of the serialized message. 44 | // 45 | // Protobuf library provides support to pack/unpack Any values in the form 46 | // of utility functions or additional generated methods of the Any type. 47 | // 48 | // Example 1: Pack and unpack a message in C++. 49 | // 50 | // Foo foo = ...; 51 | // Any any; 52 | // any.PackFrom(foo); 53 | // ... 54 | // if (any.UnpackTo(&foo)) { 55 | // ... 56 | // } 57 | // 58 | // Example 2: Pack and unpack a message in Java. 59 | // 60 | // Foo foo = ...; 61 | // Any any = Any.pack(foo); 62 | // ... 63 | // if (any.is(Foo.class)) { 64 | // foo = any.unpack(Foo.class); 65 | // } 66 | // 67 | // Example 3: Pack and unpack a message in Python. 68 | // 69 | // foo = Foo(...) 70 | // any = Any() 71 | // any.Pack(foo) 72 | // ... 73 | // if any.Is(Foo.DESCRIPTOR): 74 | // any.Unpack(foo) 75 | // ... 76 | // 77 | // Example 4: Pack and unpack a message in Go 78 | // 79 | // foo := &pb.Foo{...} 80 | // any, err := anypb.New(foo) 81 | // if err != nil { 82 | // ... 83 | // } 84 | // ... 85 | // foo := &pb.Foo{} 86 | // if err := any.UnmarshalTo(foo); err != nil { 87 | // ... 88 | // } 89 | // 90 | // The pack methods provided by protobuf library will by default use 91 | // 'type.googleapis.com/full.type.name' as the type URL and the unpack 92 | // methods only use the fully qualified type name after the last '/' 93 | // in the type URL, for example "foo.bar.com/x/y.z" will yield type 94 | // name "y.z". 95 | // 96 | // 97 | // JSON 98 | // 99 | // The JSON representation of an `Any` value uses the regular 100 | // representation of the deserialized, embedded message, with an 101 | // additional field `@type` which contains the type URL. Example: 102 | // 103 | // package google.profile; 104 | // message Person { 105 | // string first_name = 1; 106 | // string last_name = 2; 107 | // } 108 | // 109 | // { 110 | // "@type": "type.googleapis.com/google.profile.Person", 111 | // "firstName": , 112 | // "lastName": 113 | // } 114 | // 115 | // If the embedded message type is well-known and has a custom JSON 116 | // representation, that representation will be embedded adding a field 117 | // `value` which holds the custom JSON in addition to the `@type` 118 | // field. Example (for message [google.protobuf.Duration][]): 119 | // 120 | // { 121 | // "@type": "type.googleapis.com/google.protobuf.Duration", 122 | // "value": "1.212s" 123 | // } 124 | // 125 | message Any { 126 | // A URL/resource name that uniquely identifies the type of the serialized 127 | // protocol buffer message. This string must contain at least 128 | // one "/" character. The last segment of the URL's path must represent 129 | // the fully qualified name of the type (as in 130 | // `path/google.protobuf.Duration`). The name should be in a canonical form 131 | // (e.g., leading "." is not accepted). 132 | // 133 | // In practice, teams usually precompile into the binary all types that they 134 | // expect it to use in the context of Any. However, for URLs which use the 135 | // scheme `http`, `https`, or no scheme, one can optionally set up a type 136 | // server that maps type URLs to message definitions as follows: 137 | // 138 | // * If no scheme is provided, `https` is assumed. 139 | // * An HTTP GET on the URL must yield a [google.protobuf.Type][] 140 | // value in binary format, or produce an error. 141 | // * Applications are allowed to cache lookup results based on the 142 | // URL, or have them precompiled into a binary to avoid any 143 | // lookup. Therefore, binary compatibility needs to be preserved 144 | // on changes to types. (Use versioned type names to manage 145 | // breaking changes.) 146 | // 147 | // Note: this functionality is not currently available in the official 148 | // protobuf release, and it is not used for type URLs beginning with 149 | // type.googleapis.com. 150 | // 151 | // Schemes other than `http`, `https` (or the empty scheme) might be 152 | // used with implementation specific semantics. 153 | // 154 | string type_url = 1; 155 | 156 | // Must be a valid serialized protocol buffer of the above specified type. 157 | bytes value = 2; 158 | } 159 | -------------------------------------------------------------------------------- /include/google/protobuf/api.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/source_context.proto"; 36 | import "google/protobuf/type.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option java_package = "com.google.protobuf"; 40 | option java_outer_classname = "ApiProto"; 41 | option java_multiple_files = true; 42 | option objc_class_prefix = "GPB"; 43 | option go_package = "google.golang.org/protobuf/types/known/apipb"; 44 | 45 | // Api is a light-weight descriptor for an API Interface. 46 | // 47 | // Interfaces are also described as "protocol buffer services" in some contexts, 48 | // such as by the "service" keyword in a .proto file, but they are different 49 | // from API Services, which represent a concrete implementation of an interface 50 | // as opposed to simply a description of methods and bindings. They are also 51 | // sometimes simply referred to as "APIs" in other contexts, such as the name of 52 | // this message itself. See https://cloud.google.com/apis/design/glossary for 53 | // detailed terminology. 54 | message Api { 55 | // The fully qualified name of this interface, including package name 56 | // followed by the interface's simple name. 57 | string name = 1; 58 | 59 | // The methods of this interface, in unspecified order. 60 | repeated Method methods = 2; 61 | 62 | // Any metadata attached to the interface. 63 | repeated Option options = 3; 64 | 65 | // A version string for this interface. If specified, must have the form 66 | // `major-version.minor-version`, as in `1.10`. If the minor version is 67 | // omitted, it defaults to zero. If the entire version field is empty, the 68 | // major version is derived from the package name, as outlined below. If the 69 | // field is not empty, the version in the package name will be verified to be 70 | // consistent with what is provided here. 71 | // 72 | // The versioning schema uses [semantic 73 | // versioning](http://semver.org) where the major version number 74 | // indicates a breaking change and the minor version an additive, 75 | // non-breaking change. Both version numbers are signals to users 76 | // what to expect from different versions, and should be carefully 77 | // chosen based on the product plan. 78 | // 79 | // The major version is also reflected in the package name of the 80 | // interface, which must end in `v`, as in 81 | // `google.feature.v1`. For major versions 0 and 1, the suffix can 82 | // be omitted. Zero major versions must only be used for 83 | // experimental, non-GA interfaces. 84 | // 85 | // 86 | string version = 4; 87 | 88 | // Source context for the protocol buffer service represented by this 89 | // message. 90 | SourceContext source_context = 5; 91 | 92 | // Included interfaces. See [Mixin][]. 93 | repeated Mixin mixins = 6; 94 | 95 | // The source syntax of the service. 96 | Syntax syntax = 7; 97 | } 98 | 99 | // Method represents a method of an API interface. 100 | message Method { 101 | // The simple name of this method. 102 | string name = 1; 103 | 104 | // A URL of the input message type. 105 | string request_type_url = 2; 106 | 107 | // If true, the request is streamed. 108 | bool request_streaming = 3; 109 | 110 | // The URL of the output message type. 111 | string response_type_url = 4; 112 | 113 | // If true, the response is streamed. 114 | bool response_streaming = 5; 115 | 116 | // Any metadata attached to the method. 117 | repeated Option options = 6; 118 | 119 | // The source syntax of this method. 120 | Syntax syntax = 7; 121 | } 122 | 123 | // Declares an API Interface to be included in this interface. The including 124 | // interface must redeclare all the methods from the included interface, but 125 | // documentation and options are inherited as follows: 126 | // 127 | // - If after comment and whitespace stripping, the documentation 128 | // string of the redeclared method is empty, it will be inherited 129 | // from the original method. 130 | // 131 | // - Each annotation belonging to the service config (http, 132 | // visibility) which is not set in the redeclared method will be 133 | // inherited. 134 | // 135 | // - If an http annotation is inherited, the path pattern will be 136 | // modified as follows. Any version prefix will be replaced by the 137 | // version of the including interface plus the [root][] path if 138 | // specified. 139 | // 140 | // Example of a simple mixin: 141 | // 142 | // package google.acl.v1; 143 | // service AccessControl { 144 | // // Get the underlying ACL object. 145 | // rpc GetAcl(GetAclRequest) returns (Acl) { 146 | // option (google.api.http).get = "/v1/{resource=**}:getAcl"; 147 | // } 148 | // } 149 | // 150 | // package google.storage.v2; 151 | // service Storage { 152 | // rpc GetAcl(GetAclRequest) returns (Acl); 153 | // 154 | // // Get a data record. 155 | // rpc GetData(GetDataRequest) returns (Data) { 156 | // option (google.api.http).get = "/v2/{resource=**}"; 157 | // } 158 | // } 159 | // 160 | // Example of a mixin configuration: 161 | // 162 | // apis: 163 | // - name: google.storage.v2.Storage 164 | // mixins: 165 | // - name: google.acl.v1.AccessControl 166 | // 167 | // The mixin construct implies that all methods in `AccessControl` are 168 | // also declared with same name and request/response types in 169 | // `Storage`. A documentation generator or annotation processor will 170 | // see the effective `Storage.GetAcl` method after inheriting 171 | // documentation and annotations as follows: 172 | // 173 | // service Storage { 174 | // // Get the underlying ACL object. 175 | // rpc GetAcl(GetAclRequest) returns (Acl) { 176 | // option (google.api.http).get = "/v2/{resource=**}:getAcl"; 177 | // } 178 | // ... 179 | // } 180 | // 181 | // Note how the version in the path pattern changed from `v1` to `v2`. 182 | // 183 | // If the `root` field in the mixin is specified, it should be a 184 | // relative path under which inherited HTTP paths are placed. Example: 185 | // 186 | // apis: 187 | // - name: google.storage.v2.Storage 188 | // mixins: 189 | // - name: google.acl.v1.AccessControl 190 | // root: acls 191 | // 192 | // This implies the following inherited HTTP annotation: 193 | // 194 | // service Storage { 195 | // // Get the underlying ACL object. 196 | // rpc GetAcl(GetAclRequest) returns (Acl) { 197 | // option (google.api.http).get = "/v2/acls/{resource=**}:getAcl"; 198 | // } 199 | // ... 200 | // } 201 | message Mixin { 202 | // The fully qualified name of the interface which is included. 203 | string name = 1; 204 | 205 | // If non-empty specifies a path under which inherited HTTP paths 206 | // are rooted. 207 | string root = 2; 208 | } 209 | -------------------------------------------------------------------------------- /include/google/protobuf/compiler/plugin.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // 33 | // WARNING: The plugin interface is currently EXPERIMENTAL and is subject to 34 | // change. 35 | // 36 | // protoc (aka the Protocol Compiler) can be extended via plugins. A plugin is 37 | // just a program that reads a CodeGeneratorRequest from stdin and writes a 38 | // CodeGeneratorResponse to stdout. 39 | // 40 | // Plugins written using C++ can use google/protobuf/compiler/plugin.h instead 41 | // of dealing with the raw protocol defined here. 42 | // 43 | // A plugin executable needs only to be placed somewhere in the path. The 44 | // plugin should be named "protoc-gen-$NAME", and will then be used when the 45 | // flag "--${NAME}_out" is passed to protoc. 46 | 47 | syntax = "proto2"; 48 | 49 | package google.protobuf.compiler; 50 | option java_package = "com.google.protobuf.compiler"; 51 | option java_outer_classname = "PluginProtos"; 52 | 53 | option go_package = "google.golang.org/protobuf/types/pluginpb"; 54 | 55 | import "google/protobuf/descriptor.proto"; 56 | 57 | // The version number of protocol compiler. 58 | message Version { 59 | optional int32 major = 1; 60 | optional int32 minor = 2; 61 | optional int32 patch = 3; 62 | // A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should 63 | // be empty for mainline stable releases. 64 | optional string suffix = 4; 65 | } 66 | 67 | // An encoded CodeGeneratorRequest is written to the plugin's stdin. 68 | message CodeGeneratorRequest { 69 | // The .proto files that were explicitly listed on the command-line. The 70 | // code generator should generate code only for these files. Each file's 71 | // descriptor will be included in proto_file, below. 72 | repeated string file_to_generate = 1; 73 | 74 | // The generator parameter passed on the command-line. 75 | optional string parameter = 2; 76 | 77 | // FileDescriptorProtos for all files in files_to_generate and everything 78 | // they import. The files will appear in topological order, so each file 79 | // appears before any file that imports it. 80 | // 81 | // protoc guarantees that all proto_files will be written after 82 | // the fields above, even though this is not technically guaranteed by the 83 | // protobuf wire format. This theoretically could allow a plugin to stream 84 | // in the FileDescriptorProtos and handle them one by one rather than read 85 | // the entire set into memory at once. However, as of this writing, this 86 | // is not similarly optimized on protoc's end -- it will store all fields in 87 | // memory at once before sending them to the plugin. 88 | // 89 | // Type names of fields and extensions in the FileDescriptorProto are always 90 | // fully qualified. 91 | repeated FileDescriptorProto proto_file = 15; 92 | 93 | // The version number of protocol compiler. 94 | optional Version compiler_version = 3; 95 | 96 | } 97 | 98 | // The plugin writes an encoded CodeGeneratorResponse to stdout. 99 | message CodeGeneratorResponse { 100 | // Error message. If non-empty, code generation failed. The plugin process 101 | // should exit with status code zero even if it reports an error in this way. 102 | // 103 | // This should be used to indicate errors in .proto files which prevent the 104 | // code generator from generating correct code. Errors which indicate a 105 | // problem in protoc itself -- such as the input CodeGeneratorRequest being 106 | // unparseable -- should be reported by writing a message to stderr and 107 | // exiting with a non-zero status code. 108 | optional string error = 1; 109 | 110 | // A bitmask of supported features that the code generator supports. 111 | // This is a bitwise "or" of values from the Feature enum. 112 | optional uint64 supported_features = 2; 113 | 114 | // Sync with code_generator.h. 115 | enum Feature { 116 | FEATURE_NONE = 0; 117 | FEATURE_PROTO3_OPTIONAL = 1; 118 | } 119 | 120 | // Represents a single generated file. 121 | message File { 122 | // The file name, relative to the output directory. The name must not 123 | // contain "." or ".." components and must be relative, not be absolute (so, 124 | // the file cannot lie outside the output directory). "/" must be used as 125 | // the path separator, not "\". 126 | // 127 | // If the name is omitted, the content will be appended to the previous 128 | // file. This allows the generator to break large files into small chunks, 129 | // and allows the generated text to be streamed back to protoc so that large 130 | // files need not reside completely in memory at one time. Note that as of 131 | // this writing protoc does not optimize for this -- it will read the entire 132 | // CodeGeneratorResponse before writing files to disk. 133 | optional string name = 1; 134 | 135 | // If non-empty, indicates that the named file should already exist, and the 136 | // content here is to be inserted into that file at a defined insertion 137 | // point. This feature allows a code generator to extend the output 138 | // produced by another code generator. The original generator may provide 139 | // insertion points by placing special annotations in the file that look 140 | // like: 141 | // @@protoc_insertion_point(NAME) 142 | // The annotation can have arbitrary text before and after it on the line, 143 | // which allows it to be placed in a comment. NAME should be replaced with 144 | // an identifier naming the point -- this is what other generators will use 145 | // as the insertion_point. Code inserted at this point will be placed 146 | // immediately above the line containing the insertion point (thus multiple 147 | // insertions to the same point will come out in the order they were added). 148 | // The double-@ is intended to make it unlikely that the generated code 149 | // could contain things that look like insertion points by accident. 150 | // 151 | // For example, the C++ code generator places the following line in the 152 | // .pb.h files that it generates: 153 | // // @@protoc_insertion_point(namespace_scope) 154 | // This line appears within the scope of the file's package namespace, but 155 | // outside of any particular class. Another plugin can then specify the 156 | // insertion_point "namespace_scope" to generate additional classes or 157 | // other declarations that should be placed in this scope. 158 | // 159 | // Note that if the line containing the insertion point begins with 160 | // whitespace, the same whitespace will be added to every line of the 161 | // inserted text. This is useful for languages like Python, where 162 | // indentation matters. In these languages, the insertion point comment 163 | // should be indented the same amount as any inserted code will need to be 164 | // in order to work correctly in that context. 165 | // 166 | // The code generator that generates the initial file and the one which 167 | // inserts into it must both run as part of a single invocation of protoc. 168 | // Code generators are executed in the order in which they appear on the 169 | // command line. 170 | // 171 | // If |insertion_point| is present, |name| must also be present. 172 | optional string insertion_point = 2; 173 | 174 | // The file contents. 175 | optional string content = 15; 176 | 177 | // Information describing the file content being inserted. If an insertion 178 | // point is used, this information will be appropriately offset and inserted 179 | // into the code generation metadata for the generated files. 180 | optional GeneratedCodeInfo generated_code_info = 16; 181 | } 182 | repeated File file = 15; 183 | } 184 | -------------------------------------------------------------------------------- /include/google/protobuf/descriptor.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Author: kenton@google.com (Kenton Varda) 32 | // Based on original Protocol Buffers design by 33 | // Sanjay Ghemawat, Jeff Dean, and others. 34 | // 35 | // The messages in this file describe the definitions found in .proto files. 36 | // A valid .proto file can be translated directly to a FileDescriptorProto 37 | // without any other information (e.g. without reading its imports). 38 | 39 | 40 | syntax = "proto2"; 41 | 42 | package google.protobuf; 43 | 44 | option go_package = "google.golang.org/protobuf/types/descriptorpb"; 45 | option java_package = "com.google.protobuf"; 46 | option java_outer_classname = "DescriptorProtos"; 47 | option csharp_namespace = "Google.Protobuf.Reflection"; 48 | option objc_class_prefix = "GPB"; 49 | option cc_enable_arenas = true; 50 | 51 | // descriptor.proto must be optimized for speed because reflection-based 52 | // algorithms don't work during bootstrapping. 53 | option optimize_for = SPEED; 54 | 55 | // The protocol compiler can output a FileDescriptorSet containing the .proto 56 | // files it parses. 57 | message FileDescriptorSet { 58 | repeated FileDescriptorProto file = 1; 59 | } 60 | 61 | // Describes a complete .proto file. 62 | message FileDescriptorProto { 63 | optional string name = 1; // file name, relative to root of source tree 64 | optional string package = 2; // e.g. "foo", "foo.bar", etc. 65 | 66 | // Names of files imported by this file. 67 | repeated string dependency = 3; 68 | // Indexes of the public imported files in the dependency list above. 69 | repeated int32 public_dependency = 10; 70 | // Indexes of the weak imported files in the dependency list. 71 | // For Google-internal migration only. Do not use. 72 | repeated int32 weak_dependency = 11; 73 | 74 | // All top-level definitions in this file. 75 | repeated DescriptorProto message_type = 4; 76 | repeated EnumDescriptorProto enum_type = 5; 77 | repeated ServiceDescriptorProto service = 6; 78 | repeated FieldDescriptorProto extension = 7; 79 | 80 | optional FileOptions options = 8; 81 | 82 | // This field contains optional information about the original source code. 83 | // You may safely remove this entire field without harming runtime 84 | // functionality of the descriptors -- the information is needed only by 85 | // development tools. 86 | optional SourceCodeInfo source_code_info = 9; 87 | 88 | // The syntax of the proto file. 89 | // The supported values are "proto2" and "proto3". 90 | optional string syntax = 12; 91 | } 92 | 93 | // Describes a message type. 94 | message DescriptorProto { 95 | optional string name = 1; 96 | 97 | repeated FieldDescriptorProto field = 2; 98 | repeated FieldDescriptorProto extension = 6; 99 | 100 | repeated DescriptorProto nested_type = 3; 101 | repeated EnumDescriptorProto enum_type = 4; 102 | 103 | message ExtensionRange { 104 | optional int32 start = 1; // Inclusive. 105 | optional int32 end = 2; // Exclusive. 106 | 107 | optional ExtensionRangeOptions options = 3; 108 | } 109 | repeated ExtensionRange extension_range = 5; 110 | 111 | repeated OneofDescriptorProto oneof_decl = 8; 112 | 113 | optional MessageOptions options = 7; 114 | 115 | // Range of reserved tag numbers. Reserved tag numbers may not be used by 116 | // fields or extension ranges in the same message. Reserved ranges may 117 | // not overlap. 118 | message ReservedRange { 119 | optional int32 start = 1; // Inclusive. 120 | optional int32 end = 2; // Exclusive. 121 | } 122 | repeated ReservedRange reserved_range = 9; 123 | // Reserved field names, which may not be used by fields in the same message. 124 | // A given name may only be reserved once. 125 | repeated string reserved_name = 10; 126 | } 127 | 128 | message ExtensionRangeOptions { 129 | // The parser stores options it doesn't recognize here. See above. 130 | repeated UninterpretedOption uninterpreted_option = 999; 131 | 132 | 133 | // Clients can define custom options in extensions of this message. See above. 134 | extensions 1000 to max; 135 | } 136 | 137 | // Describes a field within a message. 138 | message FieldDescriptorProto { 139 | enum Type { 140 | // 0 is reserved for errors. 141 | // Order is weird for historical reasons. 142 | TYPE_DOUBLE = 1; 143 | TYPE_FLOAT = 2; 144 | // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if 145 | // negative values are likely. 146 | TYPE_INT64 = 3; 147 | TYPE_UINT64 = 4; 148 | // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if 149 | // negative values are likely. 150 | TYPE_INT32 = 5; 151 | TYPE_FIXED64 = 6; 152 | TYPE_FIXED32 = 7; 153 | TYPE_BOOL = 8; 154 | TYPE_STRING = 9; 155 | // Tag-delimited aggregate. 156 | // Group type is deprecated and not supported in proto3. However, Proto3 157 | // implementations should still be able to parse the group wire format and 158 | // treat group fields as unknown fields. 159 | TYPE_GROUP = 10; 160 | TYPE_MESSAGE = 11; // Length-delimited aggregate. 161 | 162 | // New in version 2. 163 | TYPE_BYTES = 12; 164 | TYPE_UINT32 = 13; 165 | TYPE_ENUM = 14; 166 | TYPE_SFIXED32 = 15; 167 | TYPE_SFIXED64 = 16; 168 | TYPE_SINT32 = 17; // Uses ZigZag encoding. 169 | TYPE_SINT64 = 18; // Uses ZigZag encoding. 170 | } 171 | 172 | enum Label { 173 | // 0 is reserved for errors 174 | LABEL_OPTIONAL = 1; 175 | LABEL_REQUIRED = 2; 176 | LABEL_REPEATED = 3; 177 | } 178 | 179 | optional string name = 1; 180 | optional int32 number = 3; 181 | optional Label label = 4; 182 | 183 | // If type_name is set, this need not be set. If both this and type_name 184 | // are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP. 185 | optional Type type = 5; 186 | 187 | // For message and enum types, this is the name of the type. If the name 188 | // starts with a '.', it is fully-qualified. Otherwise, C++-like scoping 189 | // rules are used to find the type (i.e. first the nested types within this 190 | // message are searched, then within the parent, on up to the root 191 | // namespace). 192 | optional string type_name = 6; 193 | 194 | // For extensions, this is the name of the type being extended. It is 195 | // resolved in the same manner as type_name. 196 | optional string extendee = 2; 197 | 198 | // For numeric types, contains the original text representation of the value. 199 | // For booleans, "true" or "false". 200 | // For strings, contains the default text contents (not escaped in any way). 201 | // For bytes, contains the C escaped value. All bytes >= 128 are escaped. 202 | optional string default_value = 7; 203 | 204 | // If set, gives the index of a oneof in the containing type's oneof_decl 205 | // list. This field is a member of that oneof. 206 | optional int32 oneof_index = 9; 207 | 208 | // JSON name of this field. The value is set by protocol compiler. If the 209 | // user has set a "json_name" option on this field, that option's value 210 | // will be used. Otherwise, it's deduced from the field's name by converting 211 | // it to camelCase. 212 | optional string json_name = 10; 213 | 214 | optional FieldOptions options = 8; 215 | 216 | // If true, this is a proto3 "optional". When a proto3 field is optional, it 217 | // tracks presence regardless of field type. 218 | // 219 | // When proto3_optional is true, this field must be belong to a oneof to 220 | // signal to old proto3 clients that presence is tracked for this field. This 221 | // oneof is known as a "synthetic" oneof, and this field must be its sole 222 | // member (each proto3 optional field gets its own synthetic oneof). Synthetic 223 | // oneofs exist in the descriptor only, and do not generate any API. Synthetic 224 | // oneofs must be ordered after all "real" oneofs. 225 | // 226 | // For message fields, proto3_optional doesn't create any semantic change, 227 | // since non-repeated message fields always track presence. However it still 228 | // indicates the semantic detail of whether the user wrote "optional" or not. 229 | // This can be useful for round-tripping the .proto file. For consistency we 230 | // give message fields a synthetic oneof also, even though it is not required 231 | // to track presence. This is especially important because the parser can't 232 | // tell if a field is a message or an enum, so it must always create a 233 | // synthetic oneof. 234 | // 235 | // Proto2 optional fields do not set this flag, because they already indicate 236 | // optional with `LABEL_OPTIONAL`. 237 | optional bool proto3_optional = 17; 238 | } 239 | 240 | // Describes a oneof. 241 | message OneofDescriptorProto { 242 | optional string name = 1; 243 | optional OneofOptions options = 2; 244 | } 245 | 246 | // Describes an enum type. 247 | message EnumDescriptorProto { 248 | optional string name = 1; 249 | 250 | repeated EnumValueDescriptorProto value = 2; 251 | 252 | optional EnumOptions options = 3; 253 | 254 | // Range of reserved numeric values. Reserved values may not be used by 255 | // entries in the same enum. Reserved ranges may not overlap. 256 | // 257 | // Note that this is distinct from DescriptorProto.ReservedRange in that it 258 | // is inclusive such that it can appropriately represent the entire int32 259 | // domain. 260 | message EnumReservedRange { 261 | optional int32 start = 1; // Inclusive. 262 | optional int32 end = 2; // Inclusive. 263 | } 264 | 265 | // Range of reserved numeric values. Reserved numeric values may not be used 266 | // by enum values in the same enum declaration. Reserved ranges may not 267 | // overlap. 268 | repeated EnumReservedRange reserved_range = 4; 269 | 270 | // Reserved enum value names, which may not be reused. A given name may only 271 | // be reserved once. 272 | repeated string reserved_name = 5; 273 | } 274 | 275 | // Describes a value within an enum. 276 | message EnumValueDescriptorProto { 277 | optional string name = 1; 278 | optional int32 number = 2; 279 | 280 | optional EnumValueOptions options = 3; 281 | } 282 | 283 | // Describes a service. 284 | message ServiceDescriptorProto { 285 | optional string name = 1; 286 | repeated MethodDescriptorProto method = 2; 287 | 288 | optional ServiceOptions options = 3; 289 | } 290 | 291 | // Describes a method of a service. 292 | message MethodDescriptorProto { 293 | optional string name = 1; 294 | 295 | // Input and output type names. These are resolved in the same way as 296 | // FieldDescriptorProto.type_name, but must refer to a message type. 297 | optional string input_type = 2; 298 | optional string output_type = 3; 299 | 300 | optional MethodOptions options = 4; 301 | 302 | // Identifies if client streams multiple client messages 303 | optional bool client_streaming = 5 [default = false]; 304 | // Identifies if server streams multiple server messages 305 | optional bool server_streaming = 6 [default = false]; 306 | } 307 | 308 | 309 | // =================================================================== 310 | // Options 311 | 312 | // Each of the definitions above may have "options" attached. These are 313 | // just annotations which may cause code to be generated slightly differently 314 | // or may contain hints for code that manipulates protocol messages. 315 | // 316 | // Clients may define custom options as extensions of the *Options messages. 317 | // These extensions may not yet be known at parsing time, so the parser cannot 318 | // store the values in them. Instead it stores them in a field in the *Options 319 | // message called uninterpreted_option. This field must have the same name 320 | // across all *Options messages. We then use this field to populate the 321 | // extensions when we build a descriptor, at which point all protos have been 322 | // parsed and so all extensions are known. 323 | // 324 | // Extension numbers for custom options may be chosen as follows: 325 | // * For options which will only be used within a single application or 326 | // organization, or for experimental options, use field numbers 50000 327 | // through 99999. It is up to you to ensure that you do not use the 328 | // same number for multiple options. 329 | // * For options which will be published and used publicly by multiple 330 | // independent entities, e-mail protobuf-global-extension-registry@google.com 331 | // to reserve extension numbers. Simply provide your project name (e.g. 332 | // Objective-C plugin) and your project website (if available) -- there's no 333 | // need to explain how you intend to use them. Usually you only need one 334 | // extension number. You can declare multiple options with only one extension 335 | // number by putting them in a sub-message. See the Custom Options section of 336 | // the docs for examples: 337 | // https://developers.google.com/protocol-buffers/docs/proto#options 338 | // If this turns out to be popular, a web service will be set up 339 | // to automatically assign option numbers. 340 | 341 | message FileOptions { 342 | 343 | // Sets the Java package where classes generated from this .proto will be 344 | // placed. By default, the proto package is used, but this is often 345 | // inappropriate because proto packages do not normally start with backwards 346 | // domain names. 347 | optional string java_package = 1; 348 | 349 | 350 | // Controls the name of the wrapper Java class generated for the .proto file. 351 | // That class will always contain the .proto file's getDescriptor() method as 352 | // well as any top-level extensions defined in the .proto file. 353 | // If java_multiple_files is disabled, then all the other classes from the 354 | // .proto file will be nested inside the single wrapper outer class. 355 | optional string java_outer_classname = 8; 356 | 357 | // If enabled, then the Java code generator will generate a separate .java 358 | // file for each top-level message, enum, and service defined in the .proto 359 | // file. Thus, these types will *not* be nested inside the wrapper class 360 | // named by java_outer_classname. However, the wrapper class will still be 361 | // generated to contain the file's getDescriptor() method as well as any 362 | // top-level extensions defined in the file. 363 | optional bool java_multiple_files = 10 [default = false]; 364 | 365 | // This option does nothing. 366 | optional bool java_generate_equals_and_hash = 20 [deprecated=true]; 367 | 368 | // If set true, then the Java2 code generator will generate code that 369 | // throws an exception whenever an attempt is made to assign a non-UTF-8 370 | // byte sequence to a string field. 371 | // Message reflection will do the same. 372 | // However, an extension field still accepts non-UTF-8 byte sequences. 373 | // This option has no effect on when used with the lite runtime. 374 | optional bool java_string_check_utf8 = 27 [default = false]; 375 | 376 | 377 | // Generated classes can be optimized for speed or code size. 378 | enum OptimizeMode { 379 | SPEED = 1; // Generate complete code for parsing, serialization, 380 | // etc. 381 | CODE_SIZE = 2; // Use ReflectionOps to implement these methods. 382 | LITE_RUNTIME = 3; // Generate code using MessageLite and the lite runtime. 383 | } 384 | optional OptimizeMode optimize_for = 9 [default = SPEED]; 385 | 386 | // Sets the Go package where structs generated from this .proto will be 387 | // placed. If omitted, the Go package will be derived from the following: 388 | // - The basename of the package import path, if provided. 389 | // - Otherwise, the package statement in the .proto file, if present. 390 | // - Otherwise, the basename of the .proto file, without extension. 391 | optional string go_package = 11; 392 | 393 | 394 | 395 | 396 | // Should generic services be generated in each language? "Generic" services 397 | // are not specific to any particular RPC system. They are generated by the 398 | // main code generators in each language (without additional plugins). 399 | // Generic services were the only kind of service generation supported by 400 | // early versions of google.protobuf. 401 | // 402 | // Generic services are now considered deprecated in favor of using plugins 403 | // that generate code specific to your particular RPC system. Therefore, 404 | // these default to false. Old code which depends on generic services should 405 | // explicitly set them to true. 406 | optional bool cc_generic_services = 16 [default = false]; 407 | optional bool java_generic_services = 17 [default = false]; 408 | optional bool py_generic_services = 18 [default = false]; 409 | optional bool php_generic_services = 42 [default = false]; 410 | 411 | // Is this file deprecated? 412 | // Depending on the target platform, this can emit Deprecated annotations 413 | // for everything in the file, or it will be completely ignored; in the very 414 | // least, this is a formalization for deprecating files. 415 | optional bool deprecated = 23 [default = false]; 416 | 417 | // Enables the use of arenas for the proto messages in this file. This applies 418 | // only to generated classes for C++. 419 | optional bool cc_enable_arenas = 31 [default = true]; 420 | 421 | 422 | // Sets the objective c class prefix which is prepended to all objective c 423 | // generated classes from this .proto. There is no default. 424 | optional string objc_class_prefix = 36; 425 | 426 | // Namespace for generated classes; defaults to the package. 427 | optional string csharp_namespace = 37; 428 | 429 | // By default Swift generators will take the proto package and CamelCase it 430 | // replacing '.' with underscore and use that to prefix the types/symbols 431 | // defined. When this options is provided, they will use this value instead 432 | // to prefix the types/symbols defined. 433 | optional string swift_prefix = 39; 434 | 435 | // Sets the php class prefix which is prepended to all php generated classes 436 | // from this .proto. Default is empty. 437 | optional string php_class_prefix = 40; 438 | 439 | // Use this option to change the namespace of php generated classes. Default 440 | // is empty. When this option is empty, the package name will be used for 441 | // determining the namespace. 442 | optional string php_namespace = 41; 443 | 444 | // Use this option to change the namespace of php generated metadata classes. 445 | // Default is empty. When this option is empty, the proto file name will be 446 | // used for determining the namespace. 447 | optional string php_metadata_namespace = 44; 448 | 449 | // Use this option to change the package of ruby generated classes. Default 450 | // is empty. When this option is not set, the package name will be used for 451 | // determining the ruby package. 452 | optional string ruby_package = 45; 453 | 454 | 455 | // The parser stores options it doesn't recognize here. 456 | // See the documentation for the "Options" section above. 457 | repeated UninterpretedOption uninterpreted_option = 999; 458 | 459 | // Clients can define custom options in extensions of this message. 460 | // See the documentation for the "Options" section above. 461 | extensions 1000 to max; 462 | 463 | reserved 38; 464 | } 465 | 466 | message MessageOptions { 467 | // Set true to use the old proto1 MessageSet wire format for extensions. 468 | // This is provided for backwards-compatibility with the MessageSet wire 469 | // format. You should not use this for any other reason: It's less 470 | // efficient, has fewer features, and is more complicated. 471 | // 472 | // The message must be defined exactly as follows: 473 | // message Foo { 474 | // option message_set_wire_format = true; 475 | // extensions 4 to max; 476 | // } 477 | // Note that the message cannot have any defined fields; MessageSets only 478 | // have extensions. 479 | // 480 | // All extensions of your type must be singular messages; e.g. they cannot 481 | // be int32s, enums, or repeated messages. 482 | // 483 | // Because this is an option, the above two restrictions are not enforced by 484 | // the protocol compiler. 485 | optional bool message_set_wire_format = 1 [default = false]; 486 | 487 | // Disables the generation of the standard "descriptor()" accessor, which can 488 | // conflict with a field of the same name. This is meant to make migration 489 | // from proto1 easier; new code should avoid fields named "descriptor". 490 | optional bool no_standard_descriptor_accessor = 2 [default = false]; 491 | 492 | // Is this message deprecated? 493 | // Depending on the target platform, this can emit Deprecated annotations 494 | // for the message, or it will be completely ignored; in the very least, 495 | // this is a formalization for deprecating messages. 496 | optional bool deprecated = 3 [default = false]; 497 | 498 | reserved 4, 5, 6; 499 | 500 | // Whether the message is an automatically generated map entry type for the 501 | // maps field. 502 | // 503 | // For maps fields: 504 | // map map_field = 1; 505 | // The parsed descriptor looks like: 506 | // message MapFieldEntry { 507 | // option map_entry = true; 508 | // optional KeyType key = 1; 509 | // optional ValueType value = 2; 510 | // } 511 | // repeated MapFieldEntry map_field = 1; 512 | // 513 | // Implementations may choose not to generate the map_entry=true message, but 514 | // use a native map in the target language to hold the keys and values. 515 | // The reflection APIs in such implementations still need to work as 516 | // if the field is a repeated message field. 517 | // 518 | // NOTE: Do not set the option in .proto files. Always use the maps syntax 519 | // instead. The option should only be implicitly set by the proto compiler 520 | // parser. 521 | optional bool map_entry = 7; 522 | 523 | reserved 8; // javalite_serializable 524 | reserved 9; // javanano_as_lite 525 | 526 | 527 | // The parser stores options it doesn't recognize here. See above. 528 | repeated UninterpretedOption uninterpreted_option = 999; 529 | 530 | // Clients can define custom options in extensions of this message. See above. 531 | extensions 1000 to max; 532 | } 533 | 534 | message FieldOptions { 535 | // The ctype option instructs the C++ code generator to use a different 536 | // representation of the field than it normally would. See the specific 537 | // options below. This option is not yet implemented in the open source 538 | // release -- sorry, we'll try to include it in a future version! 539 | optional CType ctype = 1 [default = STRING]; 540 | enum CType { 541 | // Default mode. 542 | STRING = 0; 543 | 544 | CORD = 1; 545 | 546 | STRING_PIECE = 2; 547 | } 548 | // The packed option can be enabled for repeated primitive fields to enable 549 | // a more efficient representation on the wire. Rather than repeatedly 550 | // writing the tag and type for each element, the entire array is encoded as 551 | // a single length-delimited blob. In proto3, only explicit setting it to 552 | // false will avoid using packed encoding. 553 | optional bool packed = 2; 554 | 555 | // The jstype option determines the JavaScript type used for values of the 556 | // field. The option is permitted only for 64 bit integral and fixed types 557 | // (int64, uint64, sint64, fixed64, sfixed64). A field with jstype JS_STRING 558 | // is represented as JavaScript string, which avoids loss of precision that 559 | // can happen when a large value is converted to a floating point JavaScript. 560 | // Specifying JS_NUMBER for the jstype causes the generated JavaScript code to 561 | // use the JavaScript "number" type. The behavior of the default option 562 | // JS_NORMAL is implementation dependent. 563 | // 564 | // This option is an enum to permit additional types to be added, e.g. 565 | // goog.math.Integer. 566 | optional JSType jstype = 6 [default = JS_NORMAL]; 567 | enum JSType { 568 | // Use the default type. 569 | JS_NORMAL = 0; 570 | 571 | // Use JavaScript strings. 572 | JS_STRING = 1; 573 | 574 | // Use JavaScript numbers. 575 | JS_NUMBER = 2; 576 | } 577 | 578 | // Should this field be parsed lazily? Lazy applies only to message-type 579 | // fields. It means that when the outer message is initially parsed, the 580 | // inner message's contents will not be parsed but instead stored in encoded 581 | // form. The inner message will actually be parsed when it is first accessed. 582 | // 583 | // This is only a hint. Implementations are free to choose whether to use 584 | // eager or lazy parsing regardless of the value of this option. However, 585 | // setting this option true suggests that the protocol author believes that 586 | // using lazy parsing on this field is worth the additional bookkeeping 587 | // overhead typically needed to implement it. 588 | // 589 | // This option does not affect the public interface of any generated code; 590 | // all method signatures remain the same. Furthermore, thread-safety of the 591 | // interface is not affected by this option; const methods remain safe to 592 | // call from multiple threads concurrently, while non-const methods continue 593 | // to require exclusive access. 594 | // 595 | // 596 | // Note that implementations may choose not to check required fields within 597 | // a lazy sub-message. That is, calling IsInitialized() on the outer message 598 | // may return true even if the inner message has missing required fields. 599 | // This is necessary because otherwise the inner message would have to be 600 | // parsed in order to perform the check, defeating the purpose of lazy 601 | // parsing. An implementation which chooses not to check required fields 602 | // must be consistent about it. That is, for any particular sub-message, the 603 | // implementation must either *always* check its required fields, or *never* 604 | // check its required fields, regardless of whether or not the message has 605 | // been parsed. 606 | // 607 | // As of 2021, lazy does no correctness checks on the byte stream during 608 | // parsing. This may lead to crashes if and when an invalid byte stream is 609 | // finally parsed upon access. 610 | // 611 | // TODO(b/211906113): Enable validation on lazy fields. 612 | optional bool lazy = 5 [default = false]; 613 | 614 | // unverified_lazy does no correctness checks on the byte stream. This should 615 | // only be used where lazy with verification is prohibitive for performance 616 | // reasons. 617 | optional bool unverified_lazy = 15 [default = false]; 618 | 619 | // Is this field deprecated? 620 | // Depending on the target platform, this can emit Deprecated annotations 621 | // for accessors, or it will be completely ignored; in the very least, this 622 | // is a formalization for deprecating fields. 623 | optional bool deprecated = 3 [default = false]; 624 | 625 | // For Google-internal migration only. Do not use. 626 | optional bool weak = 10 [default = false]; 627 | 628 | 629 | // The parser stores options it doesn't recognize here. See above. 630 | repeated UninterpretedOption uninterpreted_option = 999; 631 | 632 | // Clients can define custom options in extensions of this message. See above. 633 | extensions 1000 to max; 634 | 635 | reserved 4; // removed jtype 636 | } 637 | 638 | message OneofOptions { 639 | // The parser stores options it doesn't recognize here. See above. 640 | repeated UninterpretedOption uninterpreted_option = 999; 641 | 642 | // Clients can define custom options in extensions of this message. See above. 643 | extensions 1000 to max; 644 | } 645 | 646 | message EnumOptions { 647 | 648 | // Set this option to true to allow mapping different tag names to the same 649 | // value. 650 | optional bool allow_alias = 2; 651 | 652 | // Is this enum deprecated? 653 | // Depending on the target platform, this can emit Deprecated annotations 654 | // for the enum, or it will be completely ignored; in the very least, this 655 | // is a formalization for deprecating enums. 656 | optional bool deprecated = 3 [default = false]; 657 | 658 | reserved 5; // javanano_as_lite 659 | 660 | // The parser stores options it doesn't recognize here. See above. 661 | repeated UninterpretedOption uninterpreted_option = 999; 662 | 663 | // Clients can define custom options in extensions of this message. See above. 664 | extensions 1000 to max; 665 | } 666 | 667 | message EnumValueOptions { 668 | // Is this enum value deprecated? 669 | // Depending on the target platform, this can emit Deprecated annotations 670 | // for the enum value, or it will be completely ignored; in the very least, 671 | // this is a formalization for deprecating enum values. 672 | optional bool deprecated = 1 [default = false]; 673 | 674 | // The parser stores options it doesn't recognize here. See above. 675 | repeated UninterpretedOption uninterpreted_option = 999; 676 | 677 | // Clients can define custom options in extensions of this message. See above. 678 | extensions 1000 to max; 679 | } 680 | 681 | message ServiceOptions { 682 | 683 | // Note: Field numbers 1 through 32 are reserved for Google's internal RPC 684 | // framework. We apologize for hoarding these numbers to ourselves, but 685 | // we were already using them long before we decided to release Protocol 686 | // Buffers. 687 | 688 | // Is this service deprecated? 689 | // Depending on the target platform, this can emit Deprecated annotations 690 | // for the service, or it will be completely ignored; in the very least, 691 | // this is a formalization for deprecating services. 692 | optional bool deprecated = 33 [default = false]; 693 | 694 | // The parser stores options it doesn't recognize here. See above. 695 | repeated UninterpretedOption uninterpreted_option = 999; 696 | 697 | // Clients can define custom options in extensions of this message. See above. 698 | extensions 1000 to max; 699 | } 700 | 701 | message MethodOptions { 702 | 703 | // Note: Field numbers 1 through 32 are reserved for Google's internal RPC 704 | // framework. We apologize for hoarding these numbers to ourselves, but 705 | // we were already using them long before we decided to release Protocol 706 | // Buffers. 707 | 708 | // Is this method deprecated? 709 | // Depending on the target platform, this can emit Deprecated annotations 710 | // for the method, or it will be completely ignored; in the very least, 711 | // this is a formalization for deprecating methods. 712 | optional bool deprecated = 33 [default = false]; 713 | 714 | // Is this method side-effect-free (or safe in HTTP parlance), or idempotent, 715 | // or neither? HTTP based RPC implementation may choose GET verb for safe 716 | // methods, and PUT verb for idempotent methods instead of the default POST. 717 | enum IdempotencyLevel { 718 | IDEMPOTENCY_UNKNOWN = 0; 719 | NO_SIDE_EFFECTS = 1; // implies idempotent 720 | IDEMPOTENT = 2; // idempotent, but may have side effects 721 | } 722 | optional IdempotencyLevel idempotency_level = 34 723 | [default = IDEMPOTENCY_UNKNOWN]; 724 | 725 | // The parser stores options it doesn't recognize here. See above. 726 | repeated UninterpretedOption uninterpreted_option = 999; 727 | 728 | // Clients can define custom options in extensions of this message. See above. 729 | extensions 1000 to max; 730 | } 731 | 732 | 733 | // A message representing a option the parser does not recognize. This only 734 | // appears in options protos created by the compiler::Parser class. 735 | // DescriptorPool resolves these when building Descriptor objects. Therefore, 736 | // options protos in descriptor objects (e.g. returned by Descriptor::options(), 737 | // or produced by Descriptor::CopyTo()) will never have UninterpretedOptions 738 | // in them. 739 | message UninterpretedOption { 740 | // The name of the uninterpreted option. Each string represents a segment in 741 | // a dot-separated name. is_extension is true iff a segment represents an 742 | // extension (denoted with parentheses in options specs in .proto files). 743 | // E.g.,{ ["foo", false], ["bar.baz", true], ["moo", false] } represents 744 | // "foo.(bar.baz).moo". 745 | message NamePart { 746 | required string name_part = 1; 747 | required bool is_extension = 2; 748 | } 749 | repeated NamePart name = 2; 750 | 751 | // The value of the uninterpreted option, in whatever type the tokenizer 752 | // identified it as during parsing. Exactly one of these should be set. 753 | optional string identifier_value = 3; 754 | optional uint64 positive_int_value = 4; 755 | optional int64 negative_int_value = 5; 756 | optional double double_value = 6; 757 | optional bytes string_value = 7; 758 | optional string aggregate_value = 8; 759 | } 760 | 761 | // =================================================================== 762 | // Optional source code info 763 | 764 | // Encapsulates information about the original source file from which a 765 | // FileDescriptorProto was generated. 766 | message SourceCodeInfo { 767 | // A Location identifies a piece of source code in a .proto file which 768 | // corresponds to a particular definition. This information is intended 769 | // to be useful to IDEs, code indexers, documentation generators, and similar 770 | // tools. 771 | // 772 | // For example, say we have a file like: 773 | // message Foo { 774 | // optional string foo = 1; 775 | // } 776 | // Let's look at just the field definition: 777 | // optional string foo = 1; 778 | // ^ ^^ ^^ ^ ^^^ 779 | // a bc de f ghi 780 | // We have the following locations: 781 | // span path represents 782 | // [a,i) [ 4, 0, 2, 0 ] The whole field definition. 783 | // [a,b) [ 4, 0, 2, 0, 4 ] The label (optional). 784 | // [c,d) [ 4, 0, 2, 0, 5 ] The type (string). 785 | // [e,f) [ 4, 0, 2, 0, 1 ] The name (foo). 786 | // [g,h) [ 4, 0, 2, 0, 3 ] The number (1). 787 | // 788 | // Notes: 789 | // - A location may refer to a repeated field itself (i.e. not to any 790 | // particular index within it). This is used whenever a set of elements are 791 | // logically enclosed in a single code segment. For example, an entire 792 | // extend block (possibly containing multiple extension definitions) will 793 | // have an outer location whose path refers to the "extensions" repeated 794 | // field without an index. 795 | // - Multiple locations may have the same path. This happens when a single 796 | // logical declaration is spread out across multiple places. The most 797 | // obvious example is the "extend" block again -- there may be multiple 798 | // extend blocks in the same scope, each of which will have the same path. 799 | // - A location's span is not always a subset of its parent's span. For 800 | // example, the "extendee" of an extension declaration appears at the 801 | // beginning of the "extend" block and is shared by all extensions within 802 | // the block. 803 | // - Just because a location's span is a subset of some other location's span 804 | // does not mean that it is a descendant. For example, a "group" defines 805 | // both a type and a field in a single declaration. Thus, the locations 806 | // corresponding to the type and field and their components will overlap. 807 | // - Code which tries to interpret locations should probably be designed to 808 | // ignore those that it doesn't understand, as more types of locations could 809 | // be recorded in the future. 810 | repeated Location location = 1; 811 | message Location { 812 | // Identifies which part of the FileDescriptorProto was defined at this 813 | // location. 814 | // 815 | // Each element is a field number or an index. They form a path from 816 | // the root FileDescriptorProto to the place where the definition occurs. 817 | // For example, this path: 818 | // [ 4, 3, 2, 7, 1 ] 819 | // refers to: 820 | // file.message_type(3) // 4, 3 821 | // .field(7) // 2, 7 822 | // .name() // 1 823 | // This is because FileDescriptorProto.message_type has field number 4: 824 | // repeated DescriptorProto message_type = 4; 825 | // and DescriptorProto.field has field number 2: 826 | // repeated FieldDescriptorProto field = 2; 827 | // and FieldDescriptorProto.name has field number 1: 828 | // optional string name = 1; 829 | // 830 | // Thus, the above path gives the location of a field name. If we removed 831 | // the last element: 832 | // [ 4, 3, 2, 7 ] 833 | // this path refers to the whole field declaration (from the beginning 834 | // of the label to the terminating semicolon). 835 | repeated int32 path = 1 [packed = true]; 836 | 837 | // Always has exactly three or four elements: start line, start column, 838 | // end line (optional, otherwise assumed same as start line), end column. 839 | // These are packed into a single field for efficiency. Note that line 840 | // and column numbers are zero-based -- typically you will want to add 841 | // 1 to each before displaying to a user. 842 | repeated int32 span = 2 [packed = true]; 843 | 844 | // If this SourceCodeInfo represents a complete declaration, these are any 845 | // comments appearing before and after the declaration which appear to be 846 | // attached to the declaration. 847 | // 848 | // A series of line comments appearing on consecutive lines, with no other 849 | // tokens appearing on those lines, will be treated as a single comment. 850 | // 851 | // leading_detached_comments will keep paragraphs of comments that appear 852 | // before (but not connected to) the current element. Each paragraph, 853 | // separated by empty lines, will be one comment element in the repeated 854 | // field. 855 | // 856 | // Only the comment content is provided; comment markers (e.g. //) are 857 | // stripped out. For block comments, leading whitespace and an asterisk 858 | // will be stripped from the beginning of each line other than the first. 859 | // Newlines are included in the output. 860 | // 861 | // Examples: 862 | // 863 | // optional int32 foo = 1; // Comment attached to foo. 864 | // // Comment attached to bar. 865 | // optional int32 bar = 2; 866 | // 867 | // optional string baz = 3; 868 | // // Comment attached to baz. 869 | // // Another line attached to baz. 870 | // 871 | // // Comment attached to moo. 872 | // // 873 | // // Another line attached to moo. 874 | // optional double moo = 4; 875 | // 876 | // // Detached comment for corge. This is not leading or trailing comments 877 | // // to moo or corge because there are blank lines separating it from 878 | // // both. 879 | // 880 | // // Detached comment for corge paragraph 2. 881 | // 882 | // optional string corge = 5; 883 | // /* Block comment attached 884 | // * to corge. Leading asterisks 885 | // * will be removed. */ 886 | // /* Block comment attached to 887 | // * grault. */ 888 | // optional int32 grault = 6; 889 | // 890 | // // ignored detached comments. 891 | optional string leading_comments = 3; 892 | optional string trailing_comments = 4; 893 | repeated string leading_detached_comments = 6; 894 | } 895 | } 896 | 897 | // Describes the relationship between generated code and its original source 898 | // file. A GeneratedCodeInfo message is associated with only one generated 899 | // source file, but may contain references to different source .proto files. 900 | message GeneratedCodeInfo { 901 | // An Annotation connects some span of text in generated code to an element 902 | // of its generating .proto file. 903 | repeated Annotation annotation = 1; 904 | message Annotation { 905 | // Identifies the element in the original source .proto file. This field 906 | // is formatted the same as SourceCodeInfo.Location.path. 907 | repeated int32 path = 1 [packed = true]; 908 | 909 | // Identifies the filesystem path to the original source .proto. 910 | optional string source_file = 2; 911 | 912 | // Identifies the starting offset in bytes in the generated code 913 | // that relates to the identified object. 914 | optional int32 begin = 3; 915 | 916 | // Identifies the ending offset in bytes in the generated code that 917 | // relates to the identified offset. The end offset should be one past 918 | // the last relevant byte (so the length of the text = end - begin). 919 | optional int32 end = 4; 920 | } 921 | } 922 | -------------------------------------------------------------------------------- /include/google/protobuf/duration.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/durationpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "DurationProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Duration represents a signed, fixed-length span of time represented 44 | // as a count of seconds and fractions of seconds at nanosecond 45 | // resolution. It is independent of any calendar and concepts like "day" 46 | // or "month". It is related to Timestamp in that the difference between 47 | // two Timestamp values is a Duration and it can be added or subtracted 48 | // from a Timestamp. Range is approximately +-10,000 years. 49 | // 50 | // # Examples 51 | // 52 | // Example 1: Compute Duration from two Timestamps in pseudo code. 53 | // 54 | // Timestamp start = ...; 55 | // Timestamp end = ...; 56 | // Duration duration = ...; 57 | // 58 | // duration.seconds = end.seconds - start.seconds; 59 | // duration.nanos = end.nanos - start.nanos; 60 | // 61 | // if (duration.seconds < 0 && duration.nanos > 0) { 62 | // duration.seconds += 1; 63 | // duration.nanos -= 1000000000; 64 | // } else if (duration.seconds > 0 && duration.nanos < 0) { 65 | // duration.seconds -= 1; 66 | // duration.nanos += 1000000000; 67 | // } 68 | // 69 | // Example 2: Compute Timestamp from Timestamp + Duration in pseudo code. 70 | // 71 | // Timestamp start = ...; 72 | // Duration duration = ...; 73 | // Timestamp end = ...; 74 | // 75 | // end.seconds = start.seconds + duration.seconds; 76 | // end.nanos = start.nanos + duration.nanos; 77 | // 78 | // if (end.nanos < 0) { 79 | // end.seconds -= 1; 80 | // end.nanos += 1000000000; 81 | // } else if (end.nanos >= 1000000000) { 82 | // end.seconds += 1; 83 | // end.nanos -= 1000000000; 84 | // } 85 | // 86 | // Example 3: Compute Duration from datetime.timedelta in Python. 87 | // 88 | // td = datetime.timedelta(days=3, minutes=10) 89 | // duration = Duration() 90 | // duration.FromTimedelta(td) 91 | // 92 | // # JSON Mapping 93 | // 94 | // In JSON format, the Duration type is encoded as a string rather than an 95 | // object, where the string ends in the suffix "s" (indicating seconds) and 96 | // is preceded by the number of seconds, with nanoseconds expressed as 97 | // fractional seconds. For example, 3 seconds with 0 nanoseconds should be 98 | // encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should 99 | // be expressed in JSON format as "3.000000001s", and 3 seconds and 1 100 | // microsecond should be expressed in JSON format as "3.000001s". 101 | // 102 | // 103 | message Duration { 104 | // Signed seconds of the span of time. Must be from -315,576,000,000 105 | // to +315,576,000,000 inclusive. Note: these bounds are computed from: 106 | // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years 107 | int64 seconds = 1; 108 | 109 | // Signed fractions of a second at nanosecond resolution of the span 110 | // of time. Durations less than one second are represented with a 0 111 | // `seconds` field and a positive or negative `nanos` field. For durations 112 | // of one second or more, a non-zero value for the `nanos` field must be 113 | // of the same sign as the `seconds` field. Must be from -999,999,999 114 | // to +999,999,999 inclusive. 115 | int32 nanos = 2; 116 | } 117 | -------------------------------------------------------------------------------- /include/google/protobuf/empty.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option go_package = "google.golang.org/protobuf/types/known/emptypb"; 37 | option java_package = "com.google.protobuf"; 38 | option java_outer_classname = "EmptyProto"; 39 | option java_multiple_files = true; 40 | option objc_class_prefix = "GPB"; 41 | option cc_enable_arenas = true; 42 | 43 | // A generic empty message that you can re-use to avoid defining duplicated 44 | // empty messages in your APIs. A typical example is to use it as the request 45 | // or the response type of an API method. For instance: 46 | // 47 | // service Foo { 48 | // rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty); 49 | // } 50 | // 51 | message Empty {} 52 | -------------------------------------------------------------------------------- /include/google/protobuf/field_mask.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "FieldMaskProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb"; 41 | option cc_enable_arenas = true; 42 | 43 | // `FieldMask` represents a set of symbolic field paths, for example: 44 | // 45 | // paths: "f.a" 46 | // paths: "f.b.d" 47 | // 48 | // Here `f` represents a field in some root message, `a` and `b` 49 | // fields in the message found in `f`, and `d` a field found in the 50 | // message in `f.b`. 51 | // 52 | // Field masks are used to specify a subset of fields that should be 53 | // returned by a get operation or modified by an update operation. 54 | // Field masks also have a custom JSON encoding (see below). 55 | // 56 | // # Field Masks in Projections 57 | // 58 | // When used in the context of a projection, a response message or 59 | // sub-message is filtered by the API to only contain those fields as 60 | // specified in the mask. For example, if the mask in the previous 61 | // example is applied to a response message as follows: 62 | // 63 | // f { 64 | // a : 22 65 | // b { 66 | // d : 1 67 | // x : 2 68 | // } 69 | // y : 13 70 | // } 71 | // z: 8 72 | // 73 | // The result will not contain specific values for fields x,y and z 74 | // (their value will be set to the default, and omitted in proto text 75 | // output): 76 | // 77 | // 78 | // f { 79 | // a : 22 80 | // b { 81 | // d : 1 82 | // } 83 | // } 84 | // 85 | // A repeated field is not allowed except at the last position of a 86 | // paths string. 87 | // 88 | // If a FieldMask object is not present in a get operation, the 89 | // operation applies to all fields (as if a FieldMask of all fields 90 | // had been specified). 91 | // 92 | // Note that a field mask does not necessarily apply to the 93 | // top-level response message. In case of a REST get operation, the 94 | // field mask applies directly to the response, but in case of a REST 95 | // list operation, the mask instead applies to each individual message 96 | // in the returned resource list. In case of a REST custom method, 97 | // other definitions may be used. Where the mask applies will be 98 | // clearly documented together with its declaration in the API. In 99 | // any case, the effect on the returned resource/resources is required 100 | // behavior for APIs. 101 | // 102 | // # Field Masks in Update Operations 103 | // 104 | // A field mask in update operations specifies which fields of the 105 | // targeted resource are going to be updated. The API is required 106 | // to only change the values of the fields as specified in the mask 107 | // and leave the others untouched. If a resource is passed in to 108 | // describe the updated values, the API ignores the values of all 109 | // fields not covered by the mask. 110 | // 111 | // If a repeated field is specified for an update operation, new values will 112 | // be appended to the existing repeated field in the target resource. Note that 113 | // a repeated field is only allowed in the last position of a `paths` string. 114 | // 115 | // If a sub-message is specified in the last position of the field mask for an 116 | // update operation, then new value will be merged into the existing sub-message 117 | // in the target resource. 118 | // 119 | // For example, given the target message: 120 | // 121 | // f { 122 | // b { 123 | // d: 1 124 | // x: 2 125 | // } 126 | // c: [1] 127 | // } 128 | // 129 | // And an update message: 130 | // 131 | // f { 132 | // b { 133 | // d: 10 134 | // } 135 | // c: [2] 136 | // } 137 | // 138 | // then if the field mask is: 139 | // 140 | // paths: ["f.b", "f.c"] 141 | // 142 | // then the result will be: 143 | // 144 | // f { 145 | // b { 146 | // d: 10 147 | // x: 2 148 | // } 149 | // c: [1, 2] 150 | // } 151 | // 152 | // An implementation may provide options to override this default behavior for 153 | // repeated and message fields. 154 | // 155 | // In order to reset a field's value to the default, the field must 156 | // be in the mask and set to the default value in the provided resource. 157 | // Hence, in order to reset all fields of a resource, provide a default 158 | // instance of the resource and set all fields in the mask, or do 159 | // not provide a mask as described below. 160 | // 161 | // If a field mask is not present on update, the operation applies to 162 | // all fields (as if a field mask of all fields has been specified). 163 | // Note that in the presence of schema evolution, this may mean that 164 | // fields the client does not know and has therefore not filled into 165 | // the request will be reset to their default. If this is unwanted 166 | // behavior, a specific service may require a client to always specify 167 | // a field mask, producing an error if not. 168 | // 169 | // As with get operations, the location of the resource which 170 | // describes the updated values in the request message depends on the 171 | // operation kind. In any case, the effect of the field mask is 172 | // required to be honored by the API. 173 | // 174 | // ## Considerations for HTTP REST 175 | // 176 | // The HTTP kind of an update operation which uses a field mask must 177 | // be set to PATCH instead of PUT in order to satisfy HTTP semantics 178 | // (PUT must only be used for full updates). 179 | // 180 | // # JSON Encoding of Field Masks 181 | // 182 | // In JSON, a field mask is encoded as a single string where paths are 183 | // separated by a comma. Fields name in each path are converted 184 | // to/from lower-camel naming conventions. 185 | // 186 | // As an example, consider the following message declarations: 187 | // 188 | // message Profile { 189 | // User user = 1; 190 | // Photo photo = 2; 191 | // } 192 | // message User { 193 | // string display_name = 1; 194 | // string address = 2; 195 | // } 196 | // 197 | // In proto a field mask for `Profile` may look as such: 198 | // 199 | // mask { 200 | // paths: "user.display_name" 201 | // paths: "photo" 202 | // } 203 | // 204 | // In JSON, the same mask is represented as below: 205 | // 206 | // { 207 | // mask: "user.displayName,photo" 208 | // } 209 | // 210 | // # Field Masks and Oneof Fields 211 | // 212 | // Field masks treat fields in oneofs just as regular fields. Consider the 213 | // following message: 214 | // 215 | // message SampleMessage { 216 | // oneof test_oneof { 217 | // string name = 4; 218 | // SubMessage sub_message = 9; 219 | // } 220 | // } 221 | // 222 | // The field mask can be: 223 | // 224 | // mask { 225 | // paths: "name" 226 | // } 227 | // 228 | // Or: 229 | // 230 | // mask { 231 | // paths: "sub_message" 232 | // } 233 | // 234 | // Note that oneof type names ("test_oneof" in this case) cannot be used in 235 | // paths. 236 | // 237 | // ## Field Mask Verification 238 | // 239 | // The implementation of any API method which has a FieldMask type field in the 240 | // request should verify the included field paths, and return an 241 | // `INVALID_ARGUMENT` error if any path is unmappable. 242 | message FieldMask { 243 | // The set of field mask paths. 244 | repeated string paths = 1; 245 | } 246 | -------------------------------------------------------------------------------- /include/google/protobuf/source_context.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option java_package = "com.google.protobuf"; 37 | option java_outer_classname = "SourceContextProto"; 38 | option java_multiple_files = true; 39 | option objc_class_prefix = "GPB"; 40 | option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb"; 41 | 42 | // `SourceContext` represents information about the source of a 43 | // protobuf element, like the file in which it is defined. 44 | message SourceContext { 45 | // The path-qualified name of the .proto file that contained the associated 46 | // protobuf element. For example: `"google/protobuf/source_context.proto"`. 47 | string file_name = 1; 48 | } 49 | -------------------------------------------------------------------------------- /include/google/protobuf/struct.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/structpb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "StructProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // `Struct` represents a structured data value, consisting of fields 44 | // which map to dynamically typed values. In some languages, `Struct` 45 | // might be supported by a native representation. For example, in 46 | // scripting languages like JS a struct is represented as an 47 | // object. The details of that representation are described together 48 | // with the proto support for the language. 49 | // 50 | // The JSON representation for `Struct` is JSON object. 51 | message Struct { 52 | // Unordered map of dynamically typed values. 53 | map fields = 1; 54 | } 55 | 56 | // `Value` represents a dynamically typed value which can be either 57 | // null, a number, a string, a boolean, a recursive struct value, or a 58 | // list of values. A producer of value is expected to set one of these 59 | // variants. Absence of any variant indicates an error. 60 | // 61 | // The JSON representation for `Value` is JSON value. 62 | message Value { 63 | // The kind of value. 64 | oneof kind { 65 | // Represents a null value. 66 | NullValue null_value = 1; 67 | // Represents a double value. 68 | double number_value = 2; 69 | // Represents a string value. 70 | string string_value = 3; 71 | // Represents a boolean value. 72 | bool bool_value = 4; 73 | // Represents a structured value. 74 | Struct struct_value = 5; 75 | // Represents a repeated `Value`. 76 | ListValue list_value = 6; 77 | } 78 | } 79 | 80 | // `NullValue` is a singleton enumeration to represent the null value for the 81 | // `Value` type union. 82 | // 83 | // The JSON representation for `NullValue` is JSON `null`. 84 | enum NullValue { 85 | // Null value. 86 | NULL_VALUE = 0; 87 | } 88 | 89 | // `ListValue` is a wrapper around a repeated field of values. 90 | // 91 | // The JSON representation for `ListValue` is JSON array. 92 | message ListValue { 93 | // Repeated field of dynamically typed values. 94 | repeated Value values = 1; 95 | } 96 | -------------------------------------------------------------------------------- /include/google/protobuf/timestamp.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 36 | option cc_enable_arenas = true; 37 | option go_package = "google.golang.org/protobuf/types/known/timestamppb"; 38 | option java_package = "com.google.protobuf"; 39 | option java_outer_classname = "TimestampProto"; 40 | option java_multiple_files = true; 41 | option objc_class_prefix = "GPB"; 42 | 43 | // A Timestamp represents a point in time independent of any time zone or local 44 | // calendar, encoded as a count of seconds and fractions of seconds at 45 | // nanosecond resolution. The count is relative to an epoch at UTC midnight on 46 | // January 1, 1970, in the proleptic Gregorian calendar which extends the 47 | // Gregorian calendar backwards to year one. 48 | // 49 | // All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap 50 | // second table is needed for interpretation, using a [24-hour linear 51 | // smear](https://developers.google.com/time/smear). 52 | // 53 | // The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By 54 | // restricting to that range, we ensure that we can convert to and from [RFC 55 | // 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings. 56 | // 57 | // # Examples 58 | // 59 | // Example 1: Compute Timestamp from POSIX `time()`. 60 | // 61 | // Timestamp timestamp; 62 | // timestamp.set_seconds(time(NULL)); 63 | // timestamp.set_nanos(0); 64 | // 65 | // Example 2: Compute Timestamp from POSIX `gettimeofday()`. 66 | // 67 | // struct timeval tv; 68 | // gettimeofday(&tv, NULL); 69 | // 70 | // Timestamp timestamp; 71 | // timestamp.set_seconds(tv.tv_sec); 72 | // timestamp.set_nanos(tv.tv_usec * 1000); 73 | // 74 | // Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`. 75 | // 76 | // FILETIME ft; 77 | // GetSystemTimeAsFileTime(&ft); 78 | // UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime; 79 | // 80 | // // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z 81 | // // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z. 82 | // Timestamp timestamp; 83 | // timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL)); 84 | // timestamp.set_nanos((INT32) ((ticks % 10000000) * 100)); 85 | // 86 | // Example 4: Compute Timestamp from Java `System.currentTimeMillis()`. 87 | // 88 | // long millis = System.currentTimeMillis(); 89 | // 90 | // Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000) 91 | // .setNanos((int) ((millis % 1000) * 1000000)).build(); 92 | // 93 | // 94 | // Example 5: Compute Timestamp from Java `Instant.now()`. 95 | // 96 | // Instant now = Instant.now(); 97 | // 98 | // Timestamp timestamp = 99 | // Timestamp.newBuilder().setSeconds(now.getEpochSecond()) 100 | // .setNanos(now.getNano()).build(); 101 | // 102 | // 103 | // Example 6: Compute Timestamp from current time in Python. 104 | // 105 | // timestamp = Timestamp() 106 | // timestamp.GetCurrentTime() 107 | // 108 | // # JSON Mapping 109 | // 110 | // In JSON format, the Timestamp type is encoded as a string in the 111 | // [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the 112 | // format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z" 113 | // where {year} is always expressed using four digits while {month}, {day}, 114 | // {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional 115 | // seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution), 116 | // are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone 117 | // is required. A proto3 JSON serializer should always use UTC (as indicated by 118 | // "Z") when printing the Timestamp type and a proto3 JSON parser should be 119 | // able to accept both UTC and other timezones (as indicated by an offset). 120 | // 121 | // For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past 122 | // 01:30 UTC on January 15, 2017. 123 | // 124 | // In JavaScript, one can convert a Date object to this format using the 125 | // standard 126 | // [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString) 127 | // method. In Python, a standard `datetime.datetime` object can be converted 128 | // to this format using 129 | // [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with 130 | // the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use 131 | // the Joda Time's [`ISODateTimeFormat.dateTime()`]( 132 | // http://www.joda.org/joda-time/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime%2D%2D 133 | // ) to obtain a formatter capable of generating timestamps in this format. 134 | // 135 | // 136 | message Timestamp { 137 | // Represents seconds of UTC time since Unix epoch 138 | // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to 139 | // 9999-12-31T23:59:59Z inclusive. 140 | int64 seconds = 1; 141 | 142 | // Non-negative fractions of a second at nanosecond resolution. Negative 143 | // second values with fractions must still have non-negative nanos values 144 | // that count forward in time. Must be from 0 to 999,999,999 145 | // inclusive. 146 | int32 nanos = 2; 147 | } 148 | -------------------------------------------------------------------------------- /include/google/protobuf/type.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | syntax = "proto3"; 32 | 33 | package google.protobuf; 34 | 35 | import "google/protobuf/any.proto"; 36 | import "google/protobuf/source_context.proto"; 37 | 38 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 39 | option cc_enable_arenas = true; 40 | option java_package = "com.google.protobuf"; 41 | option java_outer_classname = "TypeProto"; 42 | option java_multiple_files = true; 43 | option objc_class_prefix = "GPB"; 44 | option go_package = "google.golang.org/protobuf/types/known/typepb"; 45 | 46 | // A protocol buffer message type. 47 | message Type { 48 | // The fully qualified message name. 49 | string name = 1; 50 | // The list of fields. 51 | repeated Field fields = 2; 52 | // The list of types appearing in `oneof` definitions in this type. 53 | repeated string oneofs = 3; 54 | // The protocol buffer options. 55 | repeated Option options = 4; 56 | // The source context. 57 | SourceContext source_context = 5; 58 | // The source syntax. 59 | Syntax syntax = 6; 60 | } 61 | 62 | // A single field of a message type. 63 | message Field { 64 | // Basic field types. 65 | enum Kind { 66 | // Field type unknown. 67 | TYPE_UNKNOWN = 0; 68 | // Field type double. 69 | TYPE_DOUBLE = 1; 70 | // Field type float. 71 | TYPE_FLOAT = 2; 72 | // Field type int64. 73 | TYPE_INT64 = 3; 74 | // Field type uint64. 75 | TYPE_UINT64 = 4; 76 | // Field type int32. 77 | TYPE_INT32 = 5; 78 | // Field type fixed64. 79 | TYPE_FIXED64 = 6; 80 | // Field type fixed32. 81 | TYPE_FIXED32 = 7; 82 | // Field type bool. 83 | TYPE_BOOL = 8; 84 | // Field type string. 85 | TYPE_STRING = 9; 86 | // Field type group. Proto2 syntax only, and deprecated. 87 | TYPE_GROUP = 10; 88 | // Field type message. 89 | TYPE_MESSAGE = 11; 90 | // Field type bytes. 91 | TYPE_BYTES = 12; 92 | // Field type uint32. 93 | TYPE_UINT32 = 13; 94 | // Field type enum. 95 | TYPE_ENUM = 14; 96 | // Field type sfixed32. 97 | TYPE_SFIXED32 = 15; 98 | // Field type sfixed64. 99 | TYPE_SFIXED64 = 16; 100 | // Field type sint32. 101 | TYPE_SINT32 = 17; 102 | // Field type sint64. 103 | TYPE_SINT64 = 18; 104 | } 105 | 106 | // Whether a field is optional, required, or repeated. 107 | enum Cardinality { 108 | // For fields with unknown cardinality. 109 | CARDINALITY_UNKNOWN = 0; 110 | // For optional fields. 111 | CARDINALITY_OPTIONAL = 1; 112 | // For required fields. Proto2 syntax only. 113 | CARDINALITY_REQUIRED = 2; 114 | // For repeated fields. 115 | CARDINALITY_REPEATED = 3; 116 | } 117 | 118 | // The field type. 119 | Kind kind = 1; 120 | // The field cardinality. 121 | Cardinality cardinality = 2; 122 | // The field number. 123 | int32 number = 3; 124 | // The field name. 125 | string name = 4; 126 | // The field type URL, without the scheme, for message or enumeration 127 | // types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`. 128 | string type_url = 6; 129 | // The index of the field type in `Type.oneofs`, for message or enumeration 130 | // types. The first type has index 1; zero means the type is not in the list. 131 | int32 oneof_index = 7; 132 | // Whether to use alternative packed wire representation. 133 | bool packed = 8; 134 | // The protocol buffer options. 135 | repeated Option options = 9; 136 | // The field JSON name. 137 | string json_name = 10; 138 | // The string value of the default value of this field. Proto2 syntax only. 139 | string default_value = 11; 140 | } 141 | 142 | // Enum type definition. 143 | message Enum { 144 | // Enum type name. 145 | string name = 1; 146 | // Enum value definitions. 147 | repeated EnumValue enumvalue = 2; 148 | // Protocol buffer options. 149 | repeated Option options = 3; 150 | // The source context. 151 | SourceContext source_context = 4; 152 | // The source syntax. 153 | Syntax syntax = 5; 154 | } 155 | 156 | // Enum value definition. 157 | message EnumValue { 158 | // Enum value name. 159 | string name = 1; 160 | // Enum value number. 161 | int32 number = 2; 162 | // Protocol buffer options. 163 | repeated Option options = 3; 164 | } 165 | 166 | // A protocol buffer option, which can be attached to a message, field, 167 | // enumeration, etc. 168 | message Option { 169 | // The option's name. For protobuf built-in options (options defined in 170 | // descriptor.proto), this is the short name. For example, `"map_entry"`. 171 | // For custom options, it should be the fully-qualified name. For example, 172 | // `"google.api.http"`. 173 | string name = 1; 174 | // The option's value packed in an Any message. If the value is a primitive, 175 | // the corresponding wrapper type defined in google/protobuf/wrappers.proto 176 | // should be used. If the value is an enum, it should be stored as an int32 177 | // value using the google.protobuf.Int32Value type. 178 | Any value = 2; 179 | } 180 | 181 | // The syntax in which a protocol buffer element is defined. 182 | enum Syntax { 183 | // Syntax `proto2`. 184 | SYNTAX_PROTO2 = 0; 185 | // Syntax `proto3`. 186 | SYNTAX_PROTO3 = 1; 187 | } 188 | -------------------------------------------------------------------------------- /include/google/protobuf/wrappers.proto: -------------------------------------------------------------------------------- 1 | // Protocol Buffers - Google's data interchange format 2 | // Copyright 2008 Google Inc. All rights reserved. 3 | // https://developers.google.com/protocol-buffers/ 4 | // 5 | // Redistribution and use in source and binary forms, with or without 6 | // modification, are permitted provided that the following conditions are 7 | // met: 8 | // 9 | // * Redistributions of source code must retain the above copyright 10 | // notice, this list of conditions and the following disclaimer. 11 | // * Redistributions in binary form must reproduce the above 12 | // copyright notice, this list of conditions and the following disclaimer 13 | // in the documentation and/or other materials provided with the 14 | // distribution. 15 | // * Neither the name of Google Inc. nor the names of its 16 | // contributors may be used to endorse or promote products derived from 17 | // this software without specific prior written permission. 18 | // 19 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | 31 | // Wrappers for primitive (non-message) types. These types are useful 32 | // for embedding primitives in the `google.protobuf.Any` type and for places 33 | // where we need to distinguish between the absence of a primitive 34 | // typed field and its default value. 35 | // 36 | // These wrappers have no meaningful use within repeated fields as they lack 37 | // the ability to detect presence on individual elements. 38 | // These wrappers have no meaningful use within a map or a oneof since 39 | // individual entries of a map or fields of a oneof can already detect presence. 40 | 41 | syntax = "proto3"; 42 | 43 | package google.protobuf; 44 | 45 | option csharp_namespace = "Google.Protobuf.WellKnownTypes"; 46 | option cc_enable_arenas = true; 47 | option go_package = "google.golang.org/protobuf/types/known/wrapperspb"; 48 | option java_package = "com.google.protobuf"; 49 | option java_outer_classname = "WrappersProto"; 50 | option java_multiple_files = true; 51 | option objc_class_prefix = "GPB"; 52 | 53 | // Wrapper message for `double`. 54 | // 55 | // The JSON representation for `DoubleValue` is JSON number. 56 | message DoubleValue { 57 | // The double value. 58 | double value = 1; 59 | } 60 | 61 | // Wrapper message for `float`. 62 | // 63 | // The JSON representation for `FloatValue` is JSON number. 64 | message FloatValue { 65 | // The float value. 66 | float value = 1; 67 | } 68 | 69 | // Wrapper message for `int64`. 70 | // 71 | // The JSON representation for `Int64Value` is JSON string. 72 | message Int64Value { 73 | // The int64 value. 74 | int64 value = 1; 75 | } 76 | 77 | // Wrapper message for `uint64`. 78 | // 79 | // The JSON representation for `UInt64Value` is JSON string. 80 | message UInt64Value { 81 | // The uint64 value. 82 | uint64 value = 1; 83 | } 84 | 85 | // Wrapper message for `int32`. 86 | // 87 | // The JSON representation for `Int32Value` is JSON number. 88 | message Int32Value { 89 | // The int32 value. 90 | int32 value = 1; 91 | } 92 | 93 | // Wrapper message for `uint32`. 94 | // 95 | // The JSON representation for `UInt32Value` is JSON number. 96 | message UInt32Value { 97 | // The uint32 value. 98 | uint32 value = 1; 99 | } 100 | 101 | // Wrapper message for `bool`. 102 | // 103 | // The JSON representation for `BoolValue` is JSON `true` and `false`. 104 | message BoolValue { 105 | // The bool value. 106 | bool value = 1; 107 | } 108 | 109 | // Wrapper message for `string`. 110 | // 111 | // The JSON representation for `StringValue` is JSON string. 112 | message StringValue { 113 | // The string value. 114 | string value = 1; 115 | } 116 | 117 | // Wrapper message for `bytes`. 118 | // 119 | // The JSON representation for `BytesValue` is JSON string. 120 | message BytesValue { 121 | // The bytes value. 122 | bytes value = 1; 123 | } 124 | -------------------------------------------------------------------------------- /include/rustproto.proto: -------------------------------------------------------------------------------- 1 | // Copied from rust-protobuf/protobuf-codegen-pure/src/proto. 2 | syntax = "proto2"; 3 | 4 | import "google/protobuf/descriptor.proto"; 5 | 6 | // see https://github.com/gogo/protobuf/blob/master/gogoproto/gogo.proto 7 | // for the original idea 8 | 9 | // Generated files can be customized using this proto 10 | // or using `Customize` struct when codegen is invoked programmatically. 11 | 12 | package rustproto; 13 | 14 | extend google.protobuf.FileOptions { 15 | // When true, oneof field is generated public 16 | optional bool expose_oneof_all = 17001; 17 | // When true all fields are public, and not accessors generated 18 | optional bool expose_fields_all = 17003; 19 | // When false, `get_`, `set_`, `mut_` etc. accessors are not generated 20 | optional bool generate_accessors_all = 17004; 21 | // When false, `get_` is not generated even if `syntax = "proto2"` 22 | optional bool generate_getter_all = 17005; 23 | // Use `bytes::Bytes` for `bytes` fields 24 | optional bool carllerche_bytes_for_bytes_all = 17011; 25 | // Use `bytes::Bytes` for `string` fields 26 | optional bool carllerche_bytes_for_string_all = 17012; 27 | 28 | // Use `serde_derive` to implement `Serialize` and `Deserialize` 29 | optional bool serde_derive_all = 17030; 30 | // Guard serde annotations with cfg attr. 31 | optional string serde_derive_cfg_all = 17031; 32 | 33 | // When true, will only generate codes that works with lite runtime. 34 | optional bool lite_runtime_all = 17035; 35 | } 36 | 37 | extend google.protobuf.MessageOptions { 38 | // When true, oneof field is generated public 39 | optional bool expose_oneof = 17001; 40 | // When true all fields are public, and not accessors generated 41 | optional bool expose_fields = 17003; 42 | // When false, `get_`, `set_`, `mut_` etc. accessors are not generated 43 | optional bool generate_accessors = 17004; 44 | // When false, `get_` is not generated even if `syntax = "proto2"` 45 | optional bool generate_getter = 17005; 46 | // Use `bytes::Bytes` for `bytes` fields 47 | optional bool carllerche_bytes_for_bytes = 17011; 48 | // Use `bytes::Bytes` for `string` fields 49 | optional bool carllerche_bytes_for_string = 17012; 50 | // Use `serde_derive` to implement `Serialize` and `Deserialize` 51 | optional bool serde_derive = 17030; 52 | // Guard serde annotations with cfg attr. 53 | optional string serde_derive_cfg = 17031; 54 | } 55 | 56 | extend google.protobuf.FieldOptions { 57 | // When true all fields are public, and not accessors generated 58 | optional bool expose_fields_field = 17003; 59 | // When false, `get_`, `set_`, `mut_` etc. accessors are not generated 60 | optional bool generate_accessors_field = 17004; 61 | // When false, `get_` is not generated even if `syntax = "proto2"` 62 | optional bool generate_getter_field = 17005; 63 | // Use `bytes::Bytes` for `bytes` fields 64 | optional bool carllerche_bytes_for_bytes_field = 17011; 65 | // Use `bytes::Bytes` for `string` fields 66 | optional bool carllerche_bytes_for_string_field = 17012; 67 | } 68 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 PingCAP, Inc. 2 | 3 | //! Utility functions for generating Rust code from protobuf specifications. 4 | //! 5 | //! These functions panic liberally, they are designed to be used from build 6 | //! scripts, not in production. 7 | 8 | #[cfg(feature = "prost-codec")] 9 | mod wrapper; 10 | 11 | #[cfg(feature = "protobuf-codec")] 12 | mod protobuf_impl; 13 | 14 | #[cfg(feature = "prost-codec")] 15 | mod prost_impl; 16 | 17 | use bitflags::bitflags; 18 | use regex::Regex; 19 | use std::env; 20 | use std::env::var; 21 | use std::fmt::Write as _; 22 | use std::fs::{self, File}; 23 | use std::io::Write; 24 | use std::path::{Path, PathBuf}; 25 | use std::process::Command; 26 | use std::str::from_utf8; 27 | 28 | // We use system protoc when its version matches, 29 | // otherwise use the protoc from bin which we bundle with the crate. 30 | fn get_protoc() -> String { 31 | // $PROTOC overrides everything; if it isn't a useful version then fail. 32 | if let Ok(s) = var("PROTOC") { 33 | check_protoc_version(&s).expect("PROTOC version not usable"); 34 | return s; 35 | } 36 | 37 | if let Ok(s) = check_protoc_version("protoc") { 38 | return s; 39 | } 40 | 41 | // The bundled protoc should always match the version 42 | #[cfg(windows)] 43 | { 44 | let bin_path = Path::new(env!("CARGO_MANIFEST_DIR")) 45 | .join("bin") 46 | .join("protoc-win32.exe"); 47 | bin_path.display().to_string() 48 | } 49 | 50 | #[cfg(not(windows))] 51 | protobuf_src::protoc().display().to_string() 52 | } 53 | 54 | fn check_protoc_version(protoc: &str) -> Result { 55 | let ver_re = Regex::new(r"([0-9]+)\.([0-9]+)(\.[0-9])?").unwrap(); 56 | let output = Command::new(protoc).arg("--version").output(); 57 | match output { 58 | Ok(o) => { 59 | let caps = ver_re.captures(from_utf8(&o.stdout).unwrap()).unwrap(); 60 | let major = caps.get(1).unwrap().as_str().parse::().unwrap(); 61 | let minor = caps.get(2).unwrap().as_str().parse::().unwrap(); 62 | if (major, minor) >= (3, 1) { 63 | return Ok(protoc.to_owned()); 64 | } 65 | println!("The system `protoc` version mismatch, require >= 3.1.0, got {}.{}.x, fallback to the bundled `protoc`", major, minor); 66 | } 67 | Err(_) => println!("`protoc` not in PATH, try using the bundled protoc"), 68 | }; 69 | 70 | Err(()) 71 | } 72 | 73 | pub struct Builder { 74 | files: Vec, 75 | includes: Vec, 76 | black_list: Vec, 77 | out_dir: String, 78 | #[cfg(feature = "prost-codec")] 79 | wrapper_opts: GenOpt, 80 | package_name: Option, 81 | #[cfg(feature = "grpcio-protobuf-codec")] 82 | re_export_services: bool, 83 | } 84 | 85 | impl Builder { 86 | pub fn new() -> Builder { 87 | Builder { 88 | files: Vec::new(), 89 | includes: vec!["include".to_owned(), "proto".to_owned()], 90 | black_list: vec![ 91 | "protobuf".to_owned(), 92 | "google".to_owned(), 93 | "gogoproto".to_owned(), 94 | ], 95 | out_dir: format!("{}/protos", var("OUT_DIR").expect("No OUT_DIR defined")), 96 | #[cfg(feature = "prost-codec")] 97 | wrapper_opts: GenOpt::all(), 98 | package_name: None, 99 | #[cfg(feature = "grpcio-protobuf-codec")] 100 | re_export_services: true, 101 | } 102 | } 103 | 104 | pub fn include_google_protos(&mut self) -> &mut Self { 105 | let path = format!("{}/include", env!("CARGO_MANIFEST_DIR")); 106 | self.includes.push(path); 107 | self 108 | } 109 | 110 | pub fn generate(&self) { 111 | assert!(!self.files.is_empty(), "No files specified for generation"); 112 | self.prep_out_dir(); 113 | self.generate_files(); 114 | self.generate_mod_file(); 115 | } 116 | 117 | /// This option is only used when generating Prost code. Otherwise, it is 118 | /// silently ignored. 119 | #[cfg(feature = "prost-codec")] 120 | pub fn wrapper_options(&mut self, wrapper_opts: GenOpt) -> &mut Self { 121 | self.wrapper_opts = wrapper_opts; 122 | self 123 | } 124 | 125 | /// Finds proto files to operate on in the `proto_dir` directory. 126 | pub fn search_dir_for_protos(&mut self, proto_dir: &str) -> &mut Self { 127 | self.files = fs::read_dir(proto_dir) 128 | .expect("Couldn't read proto directory") 129 | .filter_map(|e| { 130 | let e = e.expect("Couldn't list file"); 131 | if e.file_type().expect("File broken").is_dir() { 132 | None 133 | } else { 134 | Some(format!("{}/{}", proto_dir, e.file_name().to_string_lossy())) 135 | } 136 | }) 137 | .collect(); 138 | self 139 | } 140 | 141 | pub fn files(&mut self, files: &[T]) -> &mut Self { 142 | self.files = files.iter().map(|t| t.to_string()).collect(); 143 | self 144 | } 145 | 146 | pub fn includes(&mut self, includes: &[T]) -> &mut Self { 147 | self.includes = includes.iter().map(|t| t.to_string()).collect(); 148 | self 149 | } 150 | 151 | pub fn append_include(&mut self, include: impl Into) -> &mut Self { 152 | self.includes.push(include.into()); 153 | self 154 | } 155 | 156 | pub fn black_list(&mut self, black_list: &[T]) -> &mut Self { 157 | self.black_list = black_list.iter().map(|t| t.to_string()).collect(); 158 | self 159 | } 160 | 161 | /// Add the name of an include file to the builder's black list. 162 | /// 163 | /// Files named on the black list are not made modules of the generated 164 | /// program. 165 | pub fn append_to_black_list(&mut self, include: impl Into) -> &mut Self { 166 | self.black_list.push(include.into()); 167 | self 168 | } 169 | 170 | pub fn out_dir(&mut self, out_dir: impl Into) -> &mut Self { 171 | self.out_dir = out_dir.into(); 172 | self 173 | } 174 | 175 | /// If specified, a module with the given name will be generated which re-exports 176 | /// all generated items. 177 | /// 178 | /// This is ignored by Prost, since Prost uses the package names of protocols 179 | /// in any case. 180 | pub fn package_name(&mut self, package_name: impl Into) -> &mut Self { 181 | self.package_name = Some(package_name.into()); 182 | self 183 | } 184 | 185 | /// Whether services defined in separate modules should be re-exported from 186 | /// their corresponding module. Default is `true`. 187 | #[cfg(feature = "grpcio-protobuf-codec")] 188 | pub fn re_export_services(&mut self, re_export_services: bool) -> &mut Self { 189 | self.re_export_services = re_export_services; 190 | self 191 | } 192 | 193 | fn generate_mod_file(&self) { 194 | let mut f = File::create(format!("{}/mod.rs", self.out_dir)).unwrap(); 195 | 196 | let modules = self.list_rs_files().filter_map(|path| { 197 | let name = path.file_stem().unwrap().to_str().unwrap(); 198 | if name.starts_with("wrapper_") 199 | || name == "mod" 200 | || self.black_list.iter().any(|i| name.contains(i)) 201 | { 202 | return None; 203 | } 204 | Some((name.replace('-', "_"), name.to_owned())) 205 | }); 206 | 207 | let mut exports = String::new(); 208 | for (module, file_name) in modules { 209 | if cfg!(feature = "protobuf-codec") { 210 | if self.package_name.is_some() { 211 | writeln!(exports, "pub use super::{}::*;", module).unwrap(); 212 | } else { 213 | writeln!(f, "pub ").unwrap(); 214 | } 215 | writeln!(f, "mod {};", module).unwrap(); 216 | continue; 217 | } 218 | 219 | let mut level = 0; 220 | for part in module.split('.') { 221 | writeln!(f, "pub mod {} {{", part).unwrap(); 222 | level += 1; 223 | } 224 | writeln!(f, "include!(\"{}.rs\");", file_name,).unwrap(); 225 | if Path::new(&format!("{}/wrapper_{}.rs", self.out_dir, file_name)).exists() { 226 | writeln!(f, "include!(\"wrapper_{}.rs\");", file_name,).unwrap(); 227 | } 228 | writeln!(f, "{}", "}\n".repeat(level)).unwrap(); 229 | } 230 | 231 | if !exports.is_empty() { 232 | writeln!( 233 | f, 234 | "pub mod {} {{ {} }}", 235 | self.package_name.as_ref().unwrap(), 236 | exports 237 | ) 238 | .unwrap(); 239 | } 240 | } 241 | 242 | fn prep_out_dir(&self) { 243 | if Path::new(&self.out_dir).exists() { 244 | fs::remove_dir_all(&self.out_dir).unwrap(); 245 | } 246 | fs::create_dir_all(&self.out_dir).unwrap(); 247 | } 248 | 249 | // List all `.rs` files in `self.out_dir`. 250 | fn list_rs_files(&self) -> impl Iterator { 251 | fs::read_dir(&self.out_dir) 252 | .expect("Couldn't read directory") 253 | .filter_map(|e| { 254 | let path = e.expect("Couldn't list file").path(); 255 | if path.extension() == Some(std::ffi::OsStr::new("rs")) { 256 | Some(path) 257 | } else { 258 | None 259 | } 260 | }) 261 | } 262 | } 263 | 264 | impl Default for Builder { 265 | fn default() -> Builder { 266 | Builder::new() 267 | } 268 | } 269 | 270 | bitflags! { 271 | pub struct GenOpt: u32 { 272 | /// Generate implementation for trait `::protobuf::Message`. 273 | const MESSAGE = 0b0000_0001; 274 | /// Generate getters. 275 | const TRIVIAL_GET = 0b0000_0010; 276 | /// Generate setters. 277 | const TRIVIAL_SET = 0b0000_0100; 278 | /// Generate the `new_` constructors. 279 | const NEW = 0b0000_1000; 280 | /// Generate `clear_*` functions. 281 | const CLEAR = 0b0001_0000; 282 | /// Generate `has_*` functions. 283 | const HAS = 0b0010_0000; 284 | /// Generate mutable getters. 285 | const MUT = 0b0100_0000; 286 | /// Generate `take_*` functions. 287 | const TAKE = 0b1000_0000; 288 | /// Except `impl protobuf::Message`. 289 | const NO_MSG = Self::TRIVIAL_GET.bits 290 | | Self::TRIVIAL_SET.bits 291 | | Self::CLEAR.bits 292 | | Self::HAS.bits 293 | | Self::MUT.bits 294 | | Self::TAKE.bits; 295 | /// Except `new_` and `impl protobuf::Message`. 296 | const ACCESSOR = Self::TRIVIAL_GET.bits 297 | | Self::TRIVIAL_SET.bits 298 | | Self::MUT.bits 299 | | Self::TAKE.bits; 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/prost_impl.rs: -------------------------------------------------------------------------------- 1 | use crate::wrapper::WrapperGen; 2 | use crate::{get_protoc, Builder}; 3 | 4 | impl Builder { 5 | pub fn generate_files(&self) { 6 | std::env::set_var("PROTOC", get_protoc()); 7 | 8 | #[cfg(feature = "grpcio-prost-codec")] 9 | { 10 | grpcio_compiler::prost_codegen::compile_protos( 11 | &self.files, 12 | &self.includes, 13 | &self.out_dir, 14 | ) 15 | .unwrap(); 16 | } 17 | #[cfg(not(feature = "grpcio-prost-codec"))] 18 | { 19 | prost_build::Config::new() 20 | .out_dir(&self.out_dir) 21 | .compile_protos(&self.files, &self.includes) 22 | .unwrap(); 23 | } 24 | 25 | self.list_rs_files() 26 | .for_each(|path| WrapperGen::new(path, self.wrapper_opts).write()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/protobuf_impl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 PingCAP, Inc. 2 | 3 | use std::fs::File; 4 | use std::io::{Read, Write}; 5 | use std::path::Path; 6 | use std::process::Command; 7 | 8 | use protobuf::Message; 9 | use regex::Regex; 10 | 11 | use crate::get_protoc; 12 | use crate::Builder; 13 | 14 | impl Builder { 15 | pub fn generate_files(&self) { 16 | let mut cmd = Command::new(get_protoc()); 17 | let desc_file = format!("{}/mod.desc", self.out_dir); 18 | for i in &self.includes { 19 | cmd.arg(format!("-I{}", i)); 20 | } 21 | cmd.arg("--include_imports") 22 | .arg("--include_source_info") 23 | .arg("-o") 24 | .arg(&desc_file); 25 | for f in &self.files { 26 | cmd.arg(f); 27 | } 28 | println!("executing {:?}", cmd); 29 | match cmd.status() { 30 | Ok(e) if e.success() => {} 31 | e => panic!("failed to generate descriptor set files: {:?}", e), 32 | } 33 | 34 | let desc_bytes = std::fs::read(&desc_file).unwrap(); 35 | let mut desc = protobuf::descriptor::FileDescriptorSet::new(); 36 | desc.merge_from_bytes(&desc_bytes).unwrap(); 37 | desc.check_initialized().unwrap(); 38 | 39 | let mut files_to_generate = Vec::new(); 40 | 'outer: for file in &self.files { 41 | for include in &self.includes { 42 | if let Ok(truncated) = Path::new(file).strip_prefix(include) { 43 | files_to_generate.push(format!("{}", truncated.display())); 44 | continue 'outer; 45 | } 46 | } 47 | 48 | panic!( 49 | "file {:?} is not found in includes {:?}", 50 | file, self.includes 51 | ); 52 | } 53 | 54 | protobuf_codegen::gen_and_write( 55 | desc.get_file(), 56 | &files_to_generate, 57 | Path::new(&self.out_dir), 58 | &protobuf_codegen::Customize::default(), 59 | ) 60 | .unwrap(); 61 | self.generate_grpcio(desc.get_file(), &files_to_generate); 62 | self.import_grpcio(); 63 | self.replace_read_unknown_fields(); 64 | } 65 | 66 | /// Convert protobuf files to use the old way of reading protobuf enums. 67 | // FIXME: Remove this once stepancheg/rust-protobuf#233 is resolved. 68 | fn replace_read_unknown_fields(&self) { 69 | let regex = 70 | Regex::new(r"::protobuf::rt::read_proto3_enum_with_unknown_fields_into\(([^,]+), ([^,]+), &mut ([^,]+), [^\)]+\)\?").unwrap(); 71 | self.list_rs_files().for_each(|path| { 72 | let mut text = String::new(); 73 | let mut f = File::open(&path).unwrap(); 74 | f.read_to_string(&mut text) 75 | .expect("Couldn't read source file"); 76 | 77 | // FIXME Rustfmt bug in string literals 78 | #[rustfmt::skip] 79 | let text = { 80 | regex.replace_all( 81 | &text, 82 | "if $1 == ::protobuf::wire_format::WireTypeVarint {\ 83 | $3 = $2.read_enum()?;\ 84 | } else {\ 85 | return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));\ 86 | }", 87 | ) 88 | }; 89 | let mut out = File::create(&path).unwrap(); 90 | out.write_all(text.as_bytes()) 91 | .expect("Could not write source file"); 92 | }); 93 | } 94 | 95 | #[cfg(feature = "grpcio-protobuf-codec")] 96 | fn import_grpcio(&self) { 97 | use std::collections::BTreeMap; 98 | use std::fs::OpenOptions; 99 | 100 | if !self.re_export_services { 101 | return; 102 | } 103 | 104 | // TODO should be behind an option 105 | let paths: BTreeMap<_, _> = self 106 | .list_rs_files() 107 | .map(|path| (path.file_stem().unwrap().to_str().unwrap().to_owned(), path)) 108 | .collect(); 109 | for (name, path) in &paths { 110 | if name.starts_with("wrapper_") 111 | || *name == "mod" 112 | || name.ends_with("_grpc") 113 | || !paths.contains_key(&*format!("{}_grpc", name)) 114 | { 115 | continue; 116 | } 117 | 118 | let mut out = OpenOptions::new() 119 | .append(true) 120 | .open(&path) 121 | .expect("Couldn't open source file"); 122 | writeln!(out, "pub use super::{}_grpc::*;", name).expect("Could not write source file"); 123 | } 124 | } 125 | 126 | #[cfg(not(feature = "grpcio-protobuf-codec"))] 127 | fn import_grpcio(&self) {} 128 | 129 | #[cfg(feature = "grpcio-protobuf-codec")] 130 | fn generate_grpcio( 131 | &self, 132 | desc: &[protobuf::descriptor::FileDescriptorProto], 133 | files_to_generate: &[String], 134 | ) { 135 | let output_dir = std::path::Path::new(&self.out_dir); 136 | let results = grpcio_compiler::codegen::gen(desc, &files_to_generate); 137 | for res in results { 138 | let out_file = output_dir.join(&res.name); 139 | let mut f = std::fs::File::create(&out_file).unwrap(); 140 | f.write_all(&res.content).unwrap(); 141 | } 142 | } 143 | 144 | #[cfg(not(feature = "grpcio-protobuf-codec"))] 145 | fn generate_grpcio(&self, _: &[protobuf::descriptor::FileDescriptorProto], _: &[String]) {} 146 | } 147 | -------------------------------------------------------------------------------- /src/wrapper.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 PingCAP, Inc. 2 | 3 | use std::fs::{self, File}; 4 | use std::io::{self, BufWriter, Write}; 5 | use std::path::PathBuf; 6 | 7 | use proc_macro2::Span; 8 | use quote::ToTokens; 9 | use syn::{ 10 | Attribute, GenericArgument, Ident, Item, ItemEnum, ItemStruct, Meta, NestedMeta, PathArguments, 11 | Token, Type, TypePath, 12 | }; 13 | 14 | use crate::GenOpt; 15 | 16 | pub struct WrapperGen { 17 | input: String, 18 | input_file: PathBuf, 19 | gen_opt: GenOpt, 20 | } 21 | 22 | impl WrapperGen { 23 | pub fn new(file_name: PathBuf, gen_opt: GenOpt) -> WrapperGen { 24 | let input = String::from_utf8( 25 | fs::read(&file_name).unwrap_or_else(|_| panic!("Could not read {:?}", file_name)), 26 | ) 27 | .expect("File not utf8"); 28 | WrapperGen { 29 | input, 30 | gen_opt, 31 | input_file: file_name, 32 | } 33 | } 34 | 35 | pub fn write(&self) { 36 | let mut path = self.input_file.clone(); 37 | path.set_file_name(format!( 38 | "wrapper_{}", 39 | path.file_name().unwrap().to_str().unwrap() 40 | )); 41 | let mut out = BufWriter::new(File::create(&path).expect("Could not create file")); 42 | self.generate(&mut out).expect("Error generating code"); 43 | } 44 | 45 | fn generate(&self, buf: &mut W) -> Result<(), io::Error> 46 | where 47 | W: Write, 48 | { 49 | let file = ::syn::parse_file(&self.input).expect("Could not parse file"); 50 | writeln!(buf, "// Generated file, please don't edit manually.\n")?; 51 | generate_from_items(&file.items, self.gen_opt, "", buf) 52 | } 53 | } 54 | 55 | fn generate_from_items( 56 | items: &[Item], 57 | gen_opt: GenOpt, 58 | prefix: &str, 59 | buf: &mut W, 60 | ) -> Result<(), io::Error> 61 | where 62 | W: Write, 63 | { 64 | for item in items { 65 | if let Item::Struct(item) = item { 66 | if is_message(&item.attrs) { 67 | generate_struct(item, gen_opt, prefix, buf)?; 68 | } 69 | } else if let Item::Enum(item) = item { 70 | if is_enum(&item.attrs) { 71 | generate_enum(item, prefix, buf)?; 72 | } 73 | } else if let Item::Mod(m) = item { 74 | if let Some(ref content) = m.content { 75 | let prefix = format!("{}{}::", prefix, m.ident); 76 | generate_from_items(&content.1, gen_opt, &prefix, buf)?; 77 | } 78 | } 79 | } 80 | Ok(()) 81 | } 82 | 83 | fn generate_struct( 84 | item: &ItemStruct, 85 | gen_opt: GenOpt, 86 | prefix: &str, 87 | buf: &mut W, 88 | ) -> Result<(), io::Error> 89 | where 90 | W: Write, 91 | { 92 | writeln!(buf, "impl {}{} {{", prefix, item.ident)?; 93 | if gen_opt.contains(GenOpt::NEW) { 94 | generate_new(&item.ident, prefix, buf)?; 95 | } 96 | generate_default_ref(&item.ident, prefix, gen_opt, buf)?; 97 | item.fields 98 | .iter() 99 | .filter_map(|f| { 100 | f.ident 101 | .as_ref() 102 | .map(|i| (i, &f.ty, FieldKind::from_attrs(&f.attrs, prefix))) 103 | }) 104 | .filter_map(|(n, t, (k, deprecated))| k.methods(t, n, deprecated)) 105 | .map(|m| m.write_methods(buf, gen_opt)) 106 | .collect::, _>>()?; 107 | writeln!(buf, "}}")?; 108 | if gen_opt.contains(GenOpt::MESSAGE) { 109 | generate_message_trait(&item.ident, prefix, buf)?; 110 | } 111 | Ok(()) 112 | } 113 | 114 | fn generate_enum(item: &ItemEnum, prefix: &str, buf: &mut W) -> Result<(), io::Error> 115 | where 116 | W: Write, 117 | { 118 | writeln!(buf, "impl {}{} {{", prefix, item.ident)?; 119 | writeln!(buf, "pub fn values() -> &'static [Self] {{")?; 120 | writeln!( 121 | buf, 122 | "static VALUES: &'static [{}{}] = &[", 123 | prefix, item.ident 124 | )?; 125 | for v in &item.variants { 126 | writeln!(buf, "{}{}::{},", prefix, item.ident, v.ident)?; 127 | } 128 | writeln!(buf, "];\nVALUES\n}}")?; 129 | writeln!(buf, "}}") 130 | } 131 | 132 | fn generate_new(name: &Ident, prefix: &str, buf: &mut W) -> Result<(), io::Error> 133 | where 134 | W: Write, 135 | { 136 | writeln!( 137 | buf, 138 | "pub fn new_() -> {}{} {{ ::std::default::Default::default() }}", 139 | prefix, name, 140 | ) 141 | } 142 | 143 | fn generate_default_ref( 144 | name: &Ident, 145 | prefix: &str, 146 | gen_opt: GenOpt, 147 | buf: &mut W, 148 | ) -> Result<(), io::Error> 149 | where 150 | W: Write, 151 | { 152 | if gen_opt.contains(GenOpt::MESSAGE) { 153 | writeln!( 154 | buf, 155 | "#[inline] pub fn default_ref() -> &'static Self {{ ::protobuf::Message::default_instance() }}", 156 | ) 157 | } else { 158 | writeln!( 159 | buf, 160 | "#[inline] pub fn default_ref() -> &'static Self {{ 161 | ::lazy_static::lazy_static! {{ 162 | static ref INSTANCE: {0}{1} = {0}{1}::default(); 163 | }} 164 | &*INSTANCE 165 | }}", 166 | prefix, name, 167 | ) 168 | } 169 | } 170 | 171 | fn generate_message_trait(name: &Ident, prefix: &str, buf: &mut W) -> Result<(), io::Error> 172 | where 173 | W: Write, 174 | { 175 | write!(buf, "impl ::protobuf::Clear for {}{} {{", prefix, name)?; 176 | writeln!( 177 | buf, 178 | "fn clear(&mut self) {{ ::prost::Message::clear(self); }}", 179 | )?; 180 | writeln!(buf, "}}")?; 181 | 182 | write!(buf, "impl ::protobuf::Message for {}{} {{", prefix, name)?; 183 | writeln!( 184 | buf, 185 | "fn compute_size(&self) -> u32 {{ ::prost::Message::encoded_len(self) as u32 }}", 186 | )?; 187 | writeln!( 188 | buf, 189 | "fn get_cached_size(&self) -> u32 {{ ::prost::Message::encoded_len(self) as u32 }}", 190 | )?; 191 | writeln!( 192 | buf, 193 | "fn as_any(&self) -> &dyn ::std::any::Any {{ self as &dyn ::std::any::Any }}", 194 | )?; 195 | writeln!( 196 | buf, 197 | "fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {{ Self::descriptor_static() }}", 198 | )?; 199 | writeln!(buf, "fn new() -> Self {{ Self::default() }}",)?; 200 | writeln!( 201 | buf, 202 | "fn default_instance() -> &'static {}{} {{ 203 | ::lazy_static::lazy_static! {{ 204 | static ref INSTANCE: {0}{1} = {0}{1}::default(); 205 | }} 206 | &*INSTANCE 207 | }}", 208 | prefix, name, 209 | )?; 210 | // The only way for this to be false is if there are `required` fields, but 211 | // afaict, we never use that feature. In any case rust-protobuf plans to 212 | // always return `true` in 3.0. 213 | writeln!(buf, "fn is_initialized(&self) -> bool {{ true }}",)?; 214 | writeln!( 215 | buf, 216 | "fn write_to_with_cached_sizes(&self, _os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {{ unimplemented!(); }}", 217 | )?; 218 | writeln!( 219 | buf, 220 | "fn merge_from(&mut self, _is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {{ unimplemented!(); }}", 221 | )?; 222 | writeln!( 223 | buf, 224 | "fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {{ unimplemented!(); }}", 225 | )?; 226 | writeln!( 227 | buf, 228 | "fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {{ unimplemented!(); }}", 229 | )?; 230 | writeln!( 231 | buf, 232 | "fn write_to_bytes(&self) -> ::protobuf::ProtobufResult> {{ 233 | let mut buf = Vec::new(); 234 | if ::prost::Message::encode(self, &mut buf).is_err() {{ 235 | return Err(::protobuf::ProtobufError::WireError(::protobuf::error::WireError::Other)); 236 | }} 237 | Ok(buf) 238 | }}" 239 | )?; 240 | writeln!( 241 | buf, 242 | "fn merge_from_bytes(&mut self, bytes: &[u8]) -> ::protobuf::ProtobufResult<()> {{ 243 | if ::prost::Message::merge(self, bytes).is_err() {{ 244 | return Err(::protobuf::ProtobufError::WireError(::protobuf::error::WireError::Other)); 245 | }} 246 | Ok(()) 247 | }}" 248 | )?; 249 | writeln!(buf, "}}") 250 | } 251 | 252 | const INT_TYPES: [&str; 4] = ["int32", "int64", "uint32", "uint64"]; 253 | 254 | #[derive(Clone, Eq, PartialEq, Debug, Ord, PartialOrd)] 255 | enum FieldKind { 256 | Optional(Box), 257 | Repeated { 258 | // A module prefix of a repeated message. 259 | prefix: String, 260 | }, 261 | Message, 262 | Int, 263 | Float, 264 | Bool, 265 | Bytes, 266 | String, 267 | OneOf(String), 268 | Enumeration(String), 269 | Map, 270 | // Fixed are not handled. 271 | } 272 | 273 | impl FieldKind { 274 | fn from_attrs(attrs: &[Attribute], prefix: &str) -> (FieldKind, bool) { 275 | let mut deprecated = false; 276 | 277 | for a in attrs { 278 | // condition: in prost generated code, `[deprecated]` appears before `[prost(..)]` 279 | deprecated = deprecated || a.path.is_ident("deprecated"); 280 | if a.path.is_ident("prost") { 281 | if let Ok(Meta::List(list)) = a.parse_meta() { 282 | let mut kinds = list 283 | .nested 284 | .iter() 285 | .filter_map(|item| { 286 | if let NestedMeta::Meta(Meta::Path(id)) = item { 287 | if id.is_ident("optional") { 288 | Some(FieldKind::Optional(Box::new(FieldKind::Message))) 289 | } else if id.is_ident("message") { 290 | Some(FieldKind::Message) 291 | } else if id.is_ident("repeated") { 292 | Some(FieldKind::Repeated { 293 | prefix: prefix.to_owned(), 294 | }) 295 | } else if id.is_ident("bytes") { 296 | Some(FieldKind::Bytes) 297 | } else if id.is_ident("string") { 298 | Some(FieldKind::String) 299 | } else if id.is_ident("bool") { 300 | Some(FieldKind::Bool) 301 | } else if id.is_ident("float") || id.is_ident("double") { 302 | Some(FieldKind::Float) 303 | } else if let Some(id) = id.get_ident() { 304 | if INT_TYPES.contains(&id.to_string().as_str()) { 305 | Some(FieldKind::Int) 306 | } else { 307 | None 308 | } 309 | } else { 310 | None 311 | } 312 | } else if let NestedMeta::Meta(Meta::NameValue(mnv)) = item { 313 | let value = mnv.lit.clone().into_token_stream().to_string(); 314 | // Trim leading and trailing `"` and add prefix. 315 | let value = format!("{}{}", prefix, &value[1..value.len() - 1]); 316 | if mnv.path.is_ident("bytes") { 317 | Some(FieldKind::Bytes) 318 | } else if mnv.path.is_ident("enumeration") { 319 | Some(FieldKind::Enumeration(value)) 320 | } else if mnv.path.is_ident("oneof") { 321 | Some(FieldKind::OneOf(value)) 322 | } else if mnv.path.is_ident("map") { 323 | Some(FieldKind::Map) 324 | } else { 325 | None 326 | } 327 | } else { 328 | None 329 | } 330 | }) 331 | .collect::>(); 332 | kinds.sort(); 333 | if !kinds.is_empty() { 334 | let mut iter = kinds.into_iter(); 335 | let mut result = iter.next().unwrap(); 336 | // If the type is an optional, keep looking to find the underlying type. 337 | if let FieldKind::Optional(_) = result { 338 | result = FieldKind::Optional(Box::new(iter.next().unwrap())); 339 | } 340 | return (result, deprecated); 341 | } 342 | } 343 | } 344 | } 345 | unreachable!("Unknown field kind"); 346 | } 347 | 348 | fn methods(&self, ty: &Type, ident: &Ident, deprecated: bool) -> Option { 349 | let mut result = FieldMethods::new(ty, ident, deprecated); 350 | match self { 351 | FieldKind::Optional(fk) => { 352 | let unwrapped_type = unwrap_type(ty, "Option"); 353 | let unboxed_type = unwrap_type(&unwrapped_type, "Box"); 354 | let nested_methods = fk.methods(&unwrapped_type, ident, deprecated).unwrap(); 355 | let unwrapped_type = unwrapped_type.into_token_stream().to_string(); 356 | let unboxed_type = unboxed_type.into_token_stream().to_string(); 357 | 358 | result.override_ty = Some(match nested_methods.override_ty { 359 | Some(t) => t, 360 | None => unwrapped_type.clone(), 361 | }); 362 | result.ref_ty = nested_methods.ref_ty; 363 | result.enum_set = nested_methods.enum_set; 364 | result.has = true; 365 | result.clear = Some("::std::option::Option::None".to_owned()); 366 | result.set = Some(match &**fk { 367 | FieldKind::Enumeration(_) => "::std::option::Option::Some(v as i32)".to_owned(), 368 | _ => "::std::option::Option::Some(v)".to_owned(), 369 | }); 370 | 371 | let as_ref = match &result.ref_ty { 372 | RefType::Ref | RefType::Deref(_) => { 373 | let unwrapped_type = match &**fk { 374 | FieldKind::Bytes | FieldKind::Repeated { .. } => "::std::vec::Vec", 375 | _ => &unwrapped_type, 376 | }; 377 | result.mt = MethodKind::Custom(format!( 378 | "if self.{}.is_none() {{ 379 | self.{0} = ::std::option::Option::Some({1}::default()); 380 | }} 381 | self.{0}.as_mut().unwrap()", 382 | result.name, 383 | type_in_expr_context(unwrapped_type), 384 | )); 385 | ".as_ref()" 386 | } 387 | RefType::Copy => "", 388 | }; 389 | 390 | let init_val = match &**fk { 391 | FieldKind::Message => { 392 | result.take = Some(format!( 393 | "self.{}.take().unwrap_or_else({}::default)", 394 | result.name, 395 | type_in_expr_context(&unwrapped_type), 396 | )); 397 | format!("{}::default_ref()", type_in_expr_context(&unboxed_type)) 398 | } 399 | FieldKind::Bytes => { 400 | result.take = Some(format!( 401 | "self.{}.take().unwrap_or_else(::std::vec::Vec::new)", 402 | result.name, 403 | )); 404 | "&[]".to_owned() 405 | } 406 | FieldKind::String => { 407 | result.take = Some(format!( 408 | "self.{}.take().unwrap_or_else(::std::string::String::new)", 409 | result.name, 410 | )); 411 | "\"\"".to_owned() 412 | } 413 | FieldKind::Int | FieldKind::Enumeration(_) => "0".to_owned(), 414 | FieldKind::Float => "0.".to_owned(), 415 | FieldKind::Bool => "false".to_owned(), 416 | _ => unimplemented!(), 417 | }; 418 | 419 | result.get = Some(match &**fk { 420 | FieldKind::Enumeration(t) => format!( 421 | "match self.{} {{ 422 | Some(v) => match {}::from_i32(v) {{\ 423 | Some(e) => e, 424 | None => panic!(\"Unknown enum variant: {{}}\", v), 425 | }}, 426 | None => {}::default(), 427 | }}", 428 | result.name, 429 | type_in_expr_context(t), 430 | t, 431 | ), 432 | _ => format!( 433 | "match self.{}{} {{ 434 | Some(v) => v, 435 | None => {}, 436 | }}", 437 | result.name, as_ref, init_val, 438 | ), 439 | }); 440 | } 441 | FieldKind::Message => { 442 | let unboxed_type = unwrap_type(ty, "Box"); 443 | if ty != &unboxed_type { 444 | result.ref_ty = RefType::Deref(unboxed_type.into_token_stream().to_string()); 445 | } 446 | } 447 | FieldKind::Int => { 448 | result.ref_ty = RefType::Copy; 449 | result.clear = Some("0".to_owned()); 450 | } 451 | FieldKind::Float => { 452 | result.ref_ty = RefType::Copy; 453 | result.clear = Some("0.".to_owned()); 454 | } 455 | FieldKind::Bool => { 456 | result.ref_ty = RefType::Copy; 457 | result.clear = Some("false".to_owned()); 458 | } 459 | FieldKind::Repeated { prefix } => { 460 | result.mt = MethodKind::Standard; 461 | result.take = Some(format!( 462 | "::std::mem::replace(&mut self.{}, ::std::vec::Vec::new())", 463 | result.name 464 | )); 465 | let mut unwrapped_type: &str = 466 | &unwrap_type(ty, "Vec").into_token_stream().to_string(); 467 | 468 | // The point of the prefix is to account for nesting of modules. However, it turns out 469 | // that unwrapped_type may start with `super` so if we just smoosh the two together we 470 | // get an invalid type. So the following small nightmare of code pops a suffix of 471 | // prefix for every `super`, while there are both `super`s and segments of the prefix. 472 | let mut segments: Vec<_> = if ["bool", "u32", "i32", "u64", "i32", "f32", "f64"] 473 | .contains(&unwrapped_type) 474 | { 475 | // A built-in type should never be prefixed. 476 | Vec::new() 477 | } else { 478 | prefix.split("::").collect() 479 | }; 480 | while let Some(s) = segments.pop() { 481 | if s.is_empty() { 482 | continue; 483 | } 484 | if !unwrapped_type.starts_with("super ::") { 485 | segments.push(s); 486 | break; 487 | } 488 | unwrapped_type = &unwrapped_type[8..] 489 | } 490 | let mut prefix = segments.join("::"); 491 | if !prefix.is_empty() { 492 | prefix += "::" 493 | } 494 | 495 | result.ref_ty = RefType::Deref(format!("[{}{}]", prefix, unwrapped_type)); 496 | result.override_ty = Some(format!("::std::vec::Vec<{}{}>", prefix, unwrapped_type)); 497 | } 498 | FieldKind::Bytes => { 499 | result.ref_ty = RefType::Deref("[u8]".to_owned()); 500 | result.mt = MethodKind::Standard; 501 | result.take = Some(format!( 502 | "::std::mem::replace(&mut self.{}, Default::default())", 503 | result.name 504 | )); 505 | } 506 | FieldKind::String => { 507 | result.ref_ty = RefType::Deref("str".to_owned()); 508 | result.mt = MethodKind::Standard; 509 | result.take = Some(format!( 510 | "::std::mem::replace(&mut self.{}, Default::default())", 511 | result.name 512 | )); 513 | } 514 | FieldKind::Enumeration(enum_type) => { 515 | result.override_ty = Some(enum_type.clone()); 516 | result.ref_ty = RefType::Copy; 517 | result.clear = Some("0".to_owned()); 518 | result.set = Some("v as i32".to_owned()); 519 | result.enum_set = true; 520 | result.get = Some(format!( 521 | "match {}::from_i32(self.{}) {{\ 522 | Some(e) => e, 523 | None => panic!(\"Unknown enum variant: {{}}\", self.{1}), 524 | }}", 525 | type_in_expr_context(enum_type), 526 | result.name, 527 | )); 528 | } 529 | FieldKind::Map => { 530 | result.mt = MethodKind::Standard; 531 | } 532 | // There's only a few `oneof`s and they are a bit complex, so easier to 533 | // handle manually. 534 | FieldKind::OneOf(_) => return None, 535 | } 536 | 537 | Some(result) 538 | } 539 | } 540 | 541 | fn unwrap_type(ty: &Type, type_ctor: &str) -> Type { 542 | match ty { 543 | Type::Path(p) => { 544 | let seg = p.path.segments.iter().last().unwrap(); 545 | if seg.ident == type_ctor { 546 | match &seg.arguments { 547 | PathArguments::AngleBracketed(args) => match &args.args[0] { 548 | GenericArgument::Type(ty) => ty.clone(), 549 | _ => unreachable!(), 550 | }, 551 | _ => unreachable!(), 552 | } 553 | } else { 554 | ty.clone() 555 | } 556 | } 557 | _ => unreachable!(), 558 | } 559 | } 560 | 561 | struct FieldMethods { 562 | ty: String, 563 | ref_ty: RefType, 564 | override_ty: Option, 565 | name: Ident, 566 | unesc_base: String, 567 | has: bool, 568 | // None = delegate to field's `clear` 569 | // Some = default value 570 | clear: Option, 571 | // None = set to `v` 572 | // Some = expression to set. 573 | set: Option, 574 | enum_set: bool, 575 | // Some = custom getter expression. 576 | get: Option, 577 | mt: MethodKind, 578 | take: Option, 579 | deprecated: bool, 580 | } 581 | 582 | impl FieldMethods { 583 | fn new(ty: &Type, ident: &Ident, deprecated: bool) -> FieldMethods { 584 | let mut unesc_base = ident.to_string(); 585 | if unesc_base.starts_with("r#") { 586 | unesc_base = unesc_base[2..].to_owned(); 587 | } 588 | FieldMethods { 589 | ty: ty.clone().into_token_stream().to_string(), 590 | ref_ty: RefType::Ref, 591 | override_ty: None, 592 | name: ident.clone(), 593 | unesc_base, 594 | has: false, 595 | clear: None, 596 | set: None, 597 | enum_set: false, 598 | get: None, 599 | mt: MethodKind::None, 600 | take: None, 601 | deprecated, 602 | } 603 | } 604 | 605 | fn write_methods(&self, buf: &mut W, gen_opt: GenOpt) -> Result<(), io::Error> 606 | where 607 | W: Write, 608 | { 609 | let deprecated = if self.deprecated { 610 | "#[allow(deprecated)] " 611 | } else { 612 | "" 613 | }; 614 | // has_* 615 | if self.has && gen_opt.contains(GenOpt::HAS) { 616 | writeln!( 617 | buf, 618 | "{}#[inline] pub fn has_{}(&self) -> bool {{ self.{}.is_some() }}", 619 | deprecated, self.unesc_base, self.name 620 | )?; 621 | } 622 | let ty = match &self.override_ty { 623 | Some(s) => s.clone(), 624 | None => self.ty.clone(), 625 | }; 626 | let ref_ty = match &self.ref_ty { 627 | RefType::Copy => ty.clone(), 628 | RefType::Ref => format!("&{}", ty), 629 | RefType::Deref(s) => format!("&{}", s), 630 | }; 631 | // clear_* 632 | if gen_opt.contains(GenOpt::CLEAR) { 633 | match &self.clear { 634 | Some(s) => writeln!( 635 | buf, 636 | "{}#[inline] pub fn clear_{}(&mut self) {{ self.{} = {} }}", 637 | deprecated, self.unesc_base, self.name, s 638 | )?, 639 | None => writeln!( 640 | buf, 641 | "{}#[inline] pub fn clear_{}(&mut self) {{ self.{}.clear(); }}", 642 | deprecated, self.unesc_base, self.name 643 | )?, 644 | } 645 | } 646 | // set_* 647 | match &self.set { 648 | Some(s) if !self.enum_set => writeln!( 649 | buf, 650 | "{}#[inline] pub fn set_{}(&mut self, v: {}) {{ self.{} = {}; }}", 651 | deprecated, self.unesc_base, ty, self.name, s 652 | )?, 653 | None if gen_opt.contains(GenOpt::TRIVIAL_SET) => writeln!( 654 | buf, 655 | "{}#[inline] pub fn set_{}(&mut self, v: {}) {{ self.{} = v; }}", 656 | deprecated, self.unesc_base, ty, self.name 657 | )?, 658 | _ => {} 659 | } 660 | // get_* 661 | match &self.get { 662 | Some(s) => writeln!( 663 | buf, 664 | "{}#[inline] pub fn get_{}(&self) -> {} {{ {} }}", 665 | deprecated, self.unesc_base, ref_ty, s 666 | )?, 667 | None => { 668 | if gen_opt.contains(GenOpt::TRIVIAL_GET) { 669 | let rf = match &self.ref_ty { 670 | RefType::Copy => "", 671 | _ => "&", 672 | }; 673 | writeln!( 674 | buf, 675 | "{}#[inline] pub fn get_{}(&self) -> {} {{ {}self.{} }}", 676 | deprecated, self.unesc_base, ref_ty, rf, self.name 677 | )? 678 | } 679 | } 680 | } 681 | // mut_* 682 | if gen_opt.contains(GenOpt::MUT) { 683 | match &self.mt { 684 | MethodKind::Standard => { 685 | writeln!( 686 | buf, 687 | "{}#[inline] pub fn mut_{}(&mut self) -> &mut {} {{ &mut self.{} }}", 688 | deprecated, self.unesc_base, ty, self.name 689 | )?; 690 | } 691 | MethodKind::Custom(s) => { 692 | writeln!( 693 | buf, 694 | "{}#[inline] pub fn mut_{}(&mut self) -> &mut {} {{ {} }} ", 695 | deprecated, self.unesc_base, ty, s 696 | )?; 697 | } 698 | MethodKind::None => {} 699 | } 700 | } 701 | 702 | // take_* 703 | if gen_opt.contains(GenOpt::TAKE) { 704 | if let Some(s) = &self.take { 705 | writeln!( 706 | buf, 707 | "{}#[inline] pub fn take_{}(&mut self) -> {} {{ {} }}", 708 | deprecated, self.unesc_base, ty, s 709 | )?; 710 | } 711 | } 712 | 713 | Ok(()) 714 | } 715 | } 716 | 717 | enum RefType { 718 | Copy, 719 | Ref, 720 | Deref(String), 721 | } 722 | 723 | enum MethodKind { 724 | None, 725 | Standard, 726 | Custom(String), 727 | } 728 | 729 | fn is_message(attrs: &[Attribute]) -> bool { 730 | for a in attrs { 731 | if a.path.is_ident("derive") { 732 | let tts = a.tokens.to_string(); 733 | if tts.contains(":: Message") { 734 | return true; 735 | } 736 | } 737 | } 738 | false 739 | } 740 | 741 | fn is_enum(attrs: &[Attribute]) -> bool { 742 | for a in attrs { 743 | if a.path.is_ident("derive") { 744 | let tts = a.tokens.to_string(); 745 | if tts.contains("Enumeration") { 746 | return true; 747 | } 748 | } 749 | } 750 | false 751 | } 752 | 753 | // When a generic type is used in expression context, it might need to be adjusted. 754 | // For example, `Box` becomes `Box::` 755 | fn type_in_expr_context(s: &str) -> String { 756 | let mut parsed: TypePath = syn::parse_str(s).expect("Not a type?"); 757 | let last_segment = parsed.path.segments.last_mut().unwrap(); 758 | if !last_segment.arguments.is_empty() { 759 | if let PathArguments::AngleBracketed(ref mut a) = last_segment.arguments { 760 | if a.colon2_token == None { 761 | a.colon2_token = Some(Token![::](Span::call_site())); 762 | } 763 | } 764 | } 765 | parsed.to_token_stream().to_string() 766 | } 767 | 768 | #[cfg(test)] 769 | mod test { 770 | use super::*; 771 | 772 | #[test] 773 | fn test_type_in_expr_context() { 774 | assert_eq!("T", type_in_expr_context("T")); 775 | assert_eq!( 776 | ":: foo :: bar :: Vec :: < Baz >", 777 | type_in_expr_context("::foo::bar::Vec") 778 | ); 779 | assert_eq!( 780 | ":: foo :: bar :: Vec :: < Box < Baz > >", 781 | type_in_expr_context("::foo::bar::Vec::>") 782 | ); 783 | assert_eq!( 784 | ":: foo :: bar :: Vec :: < Box < Baz > >", 785 | type_in_expr_context("::foo::bar::Vec>") 786 | ); 787 | } 788 | } 789 | -------------------------------------------------------------------------------- /tests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tests" 3 | version = "0.1.0" 4 | authors = ["Neil Shen "] 5 | edition = "2018" 6 | publish = false 7 | build = "build.rs" 8 | 9 | [features] 10 | protobuf-codec = ["protobuf-build/grpcio-protobuf-codec"] 11 | prost-codec = ["protobuf-build/grpcio-prost-codec"] 12 | 13 | [dependencies] 14 | protobuf = "2" 15 | prost = "0.11" 16 | prost-derive = "0.11" 17 | lazy_static = "1.4" 18 | 19 | [build-dependencies] 20 | protobuf-build = { path = "../", default-features = false } 21 | -------------------------------------------------------------------------------- /tests/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 PingCAP, Inc. 2 | 3 | use protobuf_build::Builder; 4 | 5 | fn main() { 6 | Builder::new().search_dir_for_protos("proto").generate() 7 | } 8 | -------------------------------------------------------------------------------- /tests/proto/nested.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package nested; 3 | 4 | message Event { 5 | enum LogType { 6 | UNKNOWN = 0; 7 | } 8 | 9 | message Row { 10 | LogType type = 3; 11 | 12 | enum OpType { 13 | UNKNOWN = 0; 14 | } 15 | OpType op_type = 4; 16 | } 17 | 18 | message Entries { 19 | repeated Row entries = 1; 20 | } 21 | 22 | oneof event { 23 | Entries entries = 3; 24 | } 25 | } 26 | 27 | message NoopEvent { 28 | repeated Event events = 1; 29 | } 30 | -------------------------------------------------------------------------------- /tests/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 PingCAP, Inc. 2 | 3 | #[allow(dead_code)] 4 | #[allow(unknown_lints)] 5 | #[allow(clippy::all)] 6 | #[allow(renamed_and_removed_lints)] 7 | #[allow(bare_trait_objects)] 8 | 9 | mod protos { 10 | include!(concat!(env!("OUT_DIR"), "/protos/mod.rs")); 11 | } 12 | --------------------------------------------------------------------------------