15 June 2026 — Compiler
Traits, not types
A field is not an int. It is a width, an endianness, a signedness, and sometimes an implied decimal place. Modeling those independently is why the compiler can target five languages without special cases.
Open Markets Initiative · 5 min read
A field is not an int.
That sounds like pedantry until you try to generate a parser for thirty venues.
A four-byte price on one feed is big-endian with two implied decimal places. On
another it is little-endian with four. On a third it is four ASCII digits. All
three would be typed int32 by a naive model, and all three need different code.
Decompose the field
Rather than a closed set of types, every field in the binary model carries a set of traits, each answering one question independently:
- Size — how many bytes on the wire
- Endian — byte order, where it applies
- Signedness — whether the high bit is magnitude or sign
- DecimalPlaces — the implied divisor for fixed-point values
- Timestamp — the epoch and unit, when the field is temporal
- Memory — how the value should be held once decoded
A field's generated code depends entirely on which traits it has. Nothing else about it matters. The generator does not branch on the venue, the protocol, or the message; it branches on traits.
Why this beats an enum of types
The type-enum approach fails in a specific and predictable way: every new venue
introduces a combination nobody anticipated, and the enum grows a member.
Int32BigEndianTwoDecimals becomes Int32BigEndianFourDecimals becomes
Uint64LittleEndianNanosSinceMidnight, and the switch statement in every
generator grows with it.
Traits are combinatorial instead of enumerated. Six independent traits describe a space that no enum could cover by hand, and adding a venue that uses an unusual combination requires no generator changes at all — the combination is already expressible.
The load-bearing constraint
Traits only work if they stay orthogonal. The moment a trait's meaning depends on another trait's value, the model has smuggled a type back in and the combinatorial property is gone.
This is the rule that gets tested most often, usually by a venue doing something genuinely strange. The answer is almost always a new trait rather than a special case in an existing one — a new question that can be asked of every field, including the ones that answer "not applicable."
Runtime rules
Traits describe fields that are fixed at compile time. Variable-length structures — repeating groups, optional blocks, payloads sized by an earlier field — are modeled separately as rules carrying dependencies: a count, a size, or a payload reference pointing at another element in the tree.
Those dependencies survive compilation and become the actual control flow in the generated parser. A repeating group is a loop because the model says it has a Count dependency, not because someone wrote a loop.