Reading — step 1 of 5
Read
~1 min readSchema & Encoding
Field Encoding
Each field encoded as: tag (varint) + value.
Tag combines field number + wire type:
tag = (field_number << 3) | wire_type
Wire types:
- 0: varint (int32, int64, uint32, uint64, bool, enum).
- 1: 64-bit fixed (fixed64, sfixed64, double).
- 2: length-delimited (string, bytes, embedded message, packed repeated).
- 5: 32-bit fixed (fixed32, sfixed32, float).
- 3: start group (deprecated, was for proto2).
- 4: end group (deprecated).
Examples:
int32 age = 2; age = 30:
- Tag: (2 << 3) | 0 = 0x10 =
10. - Value: 30 =
1e. - Bytes:
10 1e.
string name = 1; name = "Alice":
- Tag: (1 << 3) | 2 = 0x0A =
0a. - Length: 5 =
05. - Value:
Alice=41 6c 69 63 65. - Bytes:
0a 05 41 6c 69 63 65.
Embedded message:
- Same as string (wire type 2).
- Length-prefixed bytes contain serialized inner message.
Repeated fields (proto3):
- Default for scalars: packed = single tag + length + concatenated values.
- For messages: separate tag per element.
Default values:
- Skipped during encoding (proto3).
- 0 for numbers, "" for strings, false for bools, empty for arrays.
- On decode: missing fields stay at default.
Unknown fields:
- Decoder encounters tag for field it doesn't know.
- Preserved as raw bytes (forward compatibility).
- Re-emitted on serialize (so old code can pass through new fields).
Field ordering: technically unspecified but standard is by tag number.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…