Repository navigation
fix: map fields with enum values, and default values in map entries - #1022
jasperpotts wants to merge 2 commits into
Conversation
The model stores a map's enum values as their protobuf ordinals, as Map<K, Integer>, and the writers write them as ordinals, but the parser and the JSON codec treated them as enum constants, so a map<K, SomeEnum> field did not compile. The parser now keeps the ordinal, so unrecognized values round-trip, and the JSON codec converts between ordinals and enum names. Map entries also skipped an enum value of 0, where protoc, and PBJ for every other value type, writes both key and value. The enum writers and size methods get a skipDefault overload, used for map entries. Fixes #1019 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jasper Potts <1466205+jasperpotts@users.noreply.github.com>
…does Map entries hold both a key and a value, and protoc writes both even when one is a default. PBJ already did for every value type except enums, fixed in the previous commit, and float and double, whose writers skipped 0 and -0.0. writeFloat, writeDouble, sizeOfFloat and sizeOfDouble get skipDefault overloads, used for map entries, so the bytes match protoc's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jasper Potts <1466205+jasperpotts@users.noreply.github.com>
|
Hash and serialization impact This PR changes the bytes written for some messages, and so any hash computed over them. A map entry whose value is a default enum ( This does not affect any Hiero HAPI protobufs. None of the 399 🤖 Generated with Claude Code |
Description
Fixes #1019: generated code did not compile for a map whose values are an enum, such as
map<int32, SomeEnum>.Performance: no change; this is a correctness fix (compile error for enum map values, and protoc-compatible default values in map entries).
Also makes map entries with a default enum,
floatordoublevalue write that value, as protoc does. This includes-0.0, so it fixes #1020 for map values only (see below).Enum map values (#1019)
The model already declares these maps as
Map<K, Integer>, holding the values' protobuf ordinals, and the writers already write them as ordinals. Only the parser and the JSON codec treated the values as enum constants. This PR makes them agree with the model rather than changing the model's API:intand stored as its ordinal. Unrecognized values, such as one from a newer schema, are kept, and they round-trip byte for byte.fromProtobufOrdinal(v).protoName()), and parses names back to ordinals (fromString(...).protoOrdinal()). This matches how singular enum fields are handled in JSON.MapField.isEntryValue(Field)identifies a map entry's synthetic value field for the parser.Default values in map entries
A map entry holds both a key and a value, and protoc writes both even when one is a default. PBJ already did this for int, bool, string and bytes values, but skipped enum values of 0 and
float/doublevalues of0.0and-0.0. So PBJ's bytes differed from protoc's, although they parse to the same map.ProtoWriterTools.writeEnumProtoOrdinal,sizeOfEnum,writeFloat,writeDouble,sizeOfFloatandsizeOfDoublegetskipDefaultoverloads, as doProtoArrayWriterTools.writeEnumProtoOrdinal,writeFloatandwriteDouble.measureRecordandprotobufSize()generators passfalsefor map entries.#1020 outside maps
This PR does not change singular, repeated or wrapper (
FloatValue,DoubleValue) fields. They still skip-0.0, becausevalue == 0is true for it. Fixing those means comparing bit patterns, as protoc does. To keepequals/hashCodeconsistent with the bytes written, generatedequalsandhashCodewould also need to compare floats by bits. That changes the wire format of-0.0values and model equality, so it is left for a separate decision.Tests
MessageWithEnumMapsandMessageWithFloatingPointMapsinmap.proto. Their generated tests compare PBJ against protoc byte for byte and round-trip through JSON.MapEnumValueTest:protobufSize();MapFloatingPointValueTest:0.0,-0.0,NaNand other values in float and double maps produce protoc's bytes from every writer and size method. The0.0and-0.0cases fail without this change.ProtoWriterToolsTestcovers the newskipDefaultoverloads.buildand the full integrationbuildpass (164,008 tests).Related
This lets the reverse writer's fallback for maps of enums in #1003 be tested.
🤖 Generated with Claude Code