forked from uber/prototool
-
Notifications
You must be signed in to change notification settings - Fork 0
/
uber1.proto
286 lines (233 loc) · 9.3 KB
/
uber1.proto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
// Protobuf Uber V1 Style Guide
//
// This is the default style enforced with lint.
//
// There are places in this style guide that reference line places, i.e. the
// first line is always the syntax line, however for demonstration purposes,
// this is violated so we can comment on such style choices here.
// Tab style is two spaces.
// Comments are always //, not /**/.
// The first line is always the syntax line. If there is a license header,
// this comes first, then a newline, then the syntax line.
//
// Syntax should always be "proto3".
syntax = "proto3";
// Next is the package.
package style.uber;
// Next are the package options.
// There is one newline between the package declaration and package options.
// Package options should be alphabetized.
// The below java and golang options are always specified.
// The java options match https://cloud.google.com/apis/design/file_structure
// The go package is always $(basename PACKAGE)pb.
// Do not use the "long-form" package name with a directory path.
option go_package = "uberpb";
// java_multiple_files is always true.
option java_multiple_files = true;
// java_outer_classname is the CamelCased file name without the extension, followed by Proto.
option java_outer_classname = "Uber1Proto";
// The java package is always com.PACKAGE.
option java_package = "com.style.uber";
// Imports come next.
// There is one newline between the package/options and imports.
// Import lines have no newlines between them.
// The imports should be alphabetized.
import "dep/dep.proto";
// Google's well-known types should be directly imported from
// "google/protobuf" as shown.
import "google/protobuf/timestamp.proto";
// Next come the definitions.
// There is one newline between the package options and the definitions.
// The preferred ordering is enums, messages, services.
// IMPORTANT
// 1. All enums have their name as a prefix to all values.
// 2. All enums have a zero value with suffix _INVALID.
// 3. Enums optionally have a one value with suffix _UNSET to denote a
// purposefully unset value, but if you think you will need to denote an
// actually null value over the wire, set this, as _INVALID is not a valid
// value to check against.
// (1) is necessary for C++ scoping rules, (2) is good for golang zero values.
// We prefer _INVALID instead of _NONE or _UNSET as it carries no intention.
// I.e. A programmer would not intentionally set the enum value to _INVALID.
// See FooType as an example.
//
// A longer explanation:
//
// Protocol buffers (v3+ to be specific) does not expose the concept of set vs.
// unset integral fields (of which enums are), as a result it is possible to
// create a empty version of a message and accidentally creating the impression
// that an enum value was set by the caller. This can lead to hard to find bugs
// where 'default' values (the 0 value enum option) is being set without the
// caller knowingly doing so. You may be thinking - but it is super useful to
// just be able to assume my default enum option, just like I want a field
// called count to default to 0 without setting it explicitly. The thing is,
// ENUMs are not integers, they are just represented as them in the proto
// description. Take for example the following enum:
//
// enum Shape {
// SHAPE_CIRCLE = 0;
// SHAPE_RECTANGLE = 1;
// }
//
// In this case a consumer of this proto message might forget to set any Shape
// fields that exist, and as a result the default value of 'Circle' will be
// assumed, this is dangerous and creates hard to track down bugs.
//
// The 1 numbered enum should be used for UNSET when this semantic is
// desired {ENUM_TYPE}_UNSET = 1.
//
// Following similar logic to our INVALID case, we don't want information in
// messages to be implied, we want signal to be stated with intention. If you
// have a case where you want UNSET to be a semantic concept then this value
// must be explicitly set. For example:
//
// enum TrafficLight {
// TRAFFIC_LIGHT_INVALID = 0;
// TRAFFIC_LIGHT_UNSET = 1;
// TRAFFIC_LIGHT_GREEN = 2;
// TRAFFIC_LIGHT_YELLOW = 3;
// TRAFFIC_LIGHT_RED = 4;
// }
//
// It's tempting to use UNSET as a default value, but then again we risk the
// case of a user forgetting to set the value and it being interpreted as the
// intentional value 'UNSET'. For consistency across our protos if UNSET is
// a semantic value of your enum, it should be field value 1.
// FooType is a foo type, and wants to tell you what type of Foo it is.
enum FooType {
// There should be no spaces between comments and values.
// _NONE and _UNSET values should not have comments.
FOO_TYPE_INVALID = 0;
FOO_TYPE_UNSET = 1;
// FOO_TYPE_BALLOON is a balloon that foo likes.
FOO_TYPE_BALLOON = 2;
FOO_TYPE_TREE = 3;
}
// Foo is a foo, it goes around the world and talks to bars.
message Foo {
// If there is a type enum associated with a message, the name of the
// field should be "type", as is shown here, and it uses tag 1.
// Type is the type of Foo.
FooType type = 1;
// https://developers.google.com/protocol-buffers/docs/proto3#scalar
// Use the "right" primitive type for the situation, regardless
// of generated code in the particular target language.
// For example, use uint32 for ports, not int32, uint64, int64, etc.
// Note underscore, not CamelCase.
// https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
double why_are_we_using_doubles = 2;
// See, micros!
//
// Here an sint32 is used instead of int32 as this has a high probability
// of having a negative value, and 32 bits instead of 64 as by definition
// this will never exceed 32 bits.
sint32 latitude_micros = 3;
sint32 longitude_micros = 4;
// Ids should be strings. Sometimes there are cases where repos have
// had wrapper message types for ids, but it ends up providing not much
// if any value in practice, and causes a lot of code uncleanliness when
// developing.
string bar_id = 5;
style.uber.dep.Dep dep = 6;
google.protobuf.Timestamp timestamp = 7;
}
// Nesting messages and enums is allowed, except for request/response
// messages (see below).
// For example, this appropriate in cases where the inner message
// has no meaning or purpose outside the scope of the outer message.
// NOTE: This affects the names of generated types and may add a great
// amount of verbosity.
// Perform this at your own discretion.
// In this example, Bar has an embedded type, and an ID.
// Bar is a bar that a Foo can talk to.
message Bar {
// Note the fully-qualified prefix BAR_TYPE_.
// Type is the type of Bar.
enum Type {
BAR_TYPE_INVALID = 0;
BAR_TYPE_UNSET = 1;
BAR_TYPE_REMOTE_CONTROL = 2;
BAR_TYPE_FAN = 3;
}
// Type always uses the first tag.
Type type = 1;
// An ID field for a message should be the first tag, UNLESS
// there is a type field, in which case it is the second tag.
string id = 2;
// Repeated fields use plural case.
// Traditionally for Protobuf, repeated fields actually used singular
// case, but this ends up being more confusing and few actually did this
// in practice.
repeated string planet_ids = 3;
}
// Planet is a planet.
message Planet {
string id = 1;
string name = 2;
}
// Galaxy is a galaxy.
message Galaxy {
string id = 1;
string name = 2;
}
// Quasar is a quasar.
message Quasar {
string id = 1;
string name = 2;
}
// ShowingOffBuiltInFieldOptions shows off built in field options.
message ShowingOffBuiltInFieldOptions {
// Fields that are deprecated should be marked as such.
//
// Deprecated is used instead of removing the field and setting the field
// as reserved because we want to disallow reusing field names, for JSON
// compatibility. By keeping the field and marking it as deprecated, we
// make it impossible to reuse either the field tag or field name.
//
// Note the space on either side of the =.
string foo = 1 [deprecated = true];
}
// IMPORTANT: Each individual method needs it's own request and response message,
// even if the message is empty. This for backwards compatibility.
//
// Message names are METHODRequest and METHODResponse.
// This applies to streaming RPC methods as well.
//
// Do not nest enums or other messages in the request or response messages.
message SendFooRequest {
Foo foo = 1;
}
// Note no newline after opening bracket if the message is empty.
message SendFooResponse {}
message GetPlanetRequest {
string planet_id = 1;
}
message GetPlanetResponse {
Planet planet = 1;
}
message StreamGalaxiesRequest {}
message StreamGalaxiesResponse {
Galaxy galaxy = 1;
}
message StreamQuasarsRequest {
Quasar quasar = 1;
}
message StreamQuasarsResponse {
repeated Quasar quasars = 1;
}
// Services should end in Service.
// Use ; to terminate the method definition if there are no RPC options,
// {} if there are RPC options.
// HelloService is the hello service.
service HelloService {
// Requests and Responses should always match the rpc name.
// rpc NAME(NAMERequest) returns (NAMEResponse);
// SendFoo sends a foo.
rpc SendFoo(SendFooRequest) returns (SendFooResponse);
// GetPlanet gets a planet.
rpc GetPlanet(GetPlanetRequest) returns (GetPlanetResponse);
// StreamGalaxies streams galaxies.
rpc StreamGalaxies(StreamGalaxiesRequest) returns (stream StreamGalaxiesResponse);
// StreamQuasars streams quasars.
rpc StreamQuasars(stream StreamQuasarsRequest) returns (StreamQuasarsResponse);
}