Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can .proto files' fields start at zero?

.proto examples all seem to start numbering their fields at one.

e.g. https://developers.google.com/protocol-buffers/docs/proto#simple

message SearchRequest {
  required string query = 1;
  optional int32 page_number = 2;
  optional int32 result_per_page = 3;
}

If zero can be used, it will make some messages one or more bytes smaller (i.e. those with a one or more field numbers of 16).

As the key is simply a varint encoding of (fieldnum << 3 | fieldtype) I can't immediately see why zero shouldn't be used.

Is there a reason for not starting the field numbering at zero?

like image 365
fadedbee Avatar asked Nov 11 '14 14:11

fadedbee


People also ask

Can Protobuf fields be null?

Protobuf treats strings as primitive types and therefore they can not be null. Instead of checking if the string is not null use standard libraries, like apache commons, to check if the string is not blank. This is clear that the value will be inserted if the value is not blank.

Does order matter in Protobuf?

Field numbers may be declared in any order in a . proto file. The order chosen has no effect on how the messages are serialized. When a message is serialized, there is no guaranteed order for how its known or unknown fields will be written.

Are all fields optional in Proto3?

Proto3 Fields marked optional will track presence like proto2, while fields without any label (known as "singular fields"), will continue to omit presence information. The optional keyword was chosen to minimize differences with proto2. Unfortunately, for the current descriptor protos and Descriptor API (as of 3.11.


2 Answers

One very immediate reason is that zero field numbers are rejected by protoc:

test.proto:2:28: Field numbers must be positive integers.

As to why Protocol Buffers has been designed this way, I can only guess. One nice consequence of this is that a message full of zeros will be detected as invalid. It can also be used to indicate "no field" internally as a return value in protocol buffers implementation.

like image 185
jpa Avatar answered Nov 20 '22 05:11

jpa


Assigning Tags

As you can see, each field in the message definition has a unique numbered tag. These tags are used to identify your fields in the message binary format, and should not be changed once your message type is in use. Note that tags with values in the range 1 through 15 take one byte to encode, including the identifying number and the field's type (you can find out more about this in Protocol Buffer Encoding). Tags in the range 16 through 2047 take two bytes. So you should reserve the tags 1 through 15 for very frequently occurring message elements. Remember to leave some room for frequently occurring elements that might be added in the future.

The smallest tag number you can specify is 1, and the largest is 229-1, or 536,870,911. You also cannot use the numbers 19000 through 19999 (FieldDescriptor::kFirstReservedNumber through FieldDescriptor::kLastReservedNumber), as they are reserved for the Protocol Buffers implementation - the protocol buffer compiler will complain if you use one of these reserved numbers in your .proto. Similarly, you cannot use any previously reserved tags.

https://developers.google.com/protocol-buffers/docs/proto

Just like the document says, 0 can't be detected.

like image 40
Lee Lam Avatar answered Nov 20 '22 04:11

Lee Lam