A message is a list of fields, and the same field number can appear in it more than once, in any place. These rules say what a reader makes of that, and of fields it does not know or that are not there at all.
Field order
Fields may come in any order, and parsers must accept that. Writers usually write them in field-number order (every ONNX file examined for this site is), but nothing requires it. The elements of a repeated field may be interleaved with other fields; their order relative to each other is kept.
The last value wins
When a field that is not repeated and is not a message (a number, a string or bytes)
appears more than once, the last one wins. Field 1 written as 08 01 08 02
reads as 2.
Messages merge
When a message field that is not repeated appears more than once, the parts are merged, as if the second were applied over the first with MergeFrom: scalars in the later part replace earlier ones, nested messages merge in turn and repeated fields are joined. So two encoded messages written one after the other parse as their merge. The documentation: “Parsing the concatenation of two encoded messages is equivalent to parsing each separately and calling MergeFrom.”
That is also why a file holding several messages needs a delimiter between them; see several messages in one file.
Unknown fields
A field number that the reader’s schema does not have is an unknown field. The reader skips it by its wire type, and current Protocol Buffers libraries keep it and write it out again when the message is saved (“Proto3 messages preserve unknown fields”). This is what lets an old program pass on fields added by a newer schema.
The schema formats in the explorer are stricter: a field number their schema does not have makes them turn the file down, and the file is shown here, read without a schema, instead.
Missing fields and default values
A field that is not set is not written. A reader gives it its default: 0, false, an empty string or empty bytes, the first enum value, or an empty message.
- In proto3, a scalar field without the
optionalkeyword is not written either when it holds its default, so a missing field and a zero look the same. Message fields always record whether they are set. - In proto2, a set field is written even when it holds its default. ONNX’s
schema is proto2: its test file for an empty optional value writes
10 00, field 2 (elem_type) set to 0.
The same message, different bytes
Serialisation is not guaranteed to give the same bytes across library versions, or even between calls: map entries in particular may come in any order. Do not compare encoded bytes to decide whether two messages are equal; parse them and compare the messages.