22

Enums are not allowed to be used as keys in map. PaxType here is an enum and not allowed to be used as key.

enum PaxType {
    ADULT = 0 ;
    CHILD = 1 ;
    INFANT = 2 ;
}

message FlightData {
    map<PaxType, FareType> fareType = 1;
}
Vivek Sinha
  • 1,591
  • 3
  • 15
  • 23

3 Answers3

31

This is disallowed because it doesn't play well with proto3 open enum semantics. For example, in Java, if you have a Map, the key can only be one of the defined values. If you happen to receive an enum key value from a remote client/server that's not in the defined value set, it can't be put in the Map. This limitation forces us to either drop map entries with unknown enum keys (which is against proto3 open enum semantics), or disallow enum as map keys all together.

for reference: https://groups.google.com/forum/#!topic/protobuf/ikeldBe60eI

Vivek Sinha
  • 1,591
  • 3
  • 15
  • 23
  • It seems that this could still work in proto2 though. Even in proto3 with a bit more work. In particular, proto3 could define a special Map type called `OpenEnumMap` or some such thing. Then `flightData` in the example above would have two methods: `getFlightData()` which uses a closed-world assumption and doesn't have any unrecognized keys, and also `getOpenEnumFlightData()` which would have a slightly more awkard API (map keys would be arbitrary integers rather than enums) but would serve those who need to handle unknown enums. – Mark VY Jun 30 '22 at 16:59
7

Define your own map entry type such as:

enum MyEnum {
  FOO = 0;
  BAR = 1;
  BAZ = 2;
}

message MapEntry {
  MyEnum type = 1;
  int32 count = 2;
}

message MyMessage {
  repeated MapEntry counts = 1;
}

You won't get the exact semantics or behavior of a map, such as duplicate entries with the same keys being reduced to the last-received value, but you'll get the same compatibility benefits and the same general utility.

C. McKinnon
  • 259
  • 3
  • 5
0

As Vivek Sinha already said is it not allowed to use Enums as keys in maps. However you can use a list and populate it in the same order you define your enum. For example when you program a game that uses bioms and you want to have a mapping from a biom type to the number of existing bioms in the world. This could be accomplished as follows:

enum BiomType {
    PLACEHOLDER = 0;
    FOREST = 1;
    DESERT = 2;
}

message Map {
    repeated int32 biom_distribution = 1;
}

When you populate the biom_distribution list you have to keep the order of elements in the enum (BiomType in this case).

F.M.F.
  • 1,929
  • 3
  • 23
  • 42