Every field in a Protobuf message starts with a tag. That tag is the only reason the decoder knows which field it's looking at and how to read the bytes that follow.
Tag Composition
A tag is a single Varint that combines two pieces of information:
- Field Number (bits 3 through N)
- Wire Type (the bottom 3 bits)
The formula for the tag value is (field_number << 3) | wire_type. Small field numbers fit in a single byte. Larger ones, 16 and above, spill into additional bytes under the same continuation rule varints always follow.
A tag packs two facts into a single number, the field number and the wire type. The lowest three bits hold the wire type. Everything above them holds the field number.
One number, two parts
Encoded as a varint
Further Reading
- Tip of the week #9: Some numbers are more equal than others
The tag math on this page, taken further: number ranges, reserved blocks, and rationing single-byte tags.
Next
Wire Types
The Protobuf wire types: VARINT, I64, LEN, and I32, what each one carries, and how length-delimited encoding wraps strings, bytes, and sub-messages.