Upgrading protobuf from version 2 to 3 – incompatible with protobuf default values

Turns out there is a way to find out if a default value is actually missing or not (thanks to some friends at google for this answer):

message Record {
  uint32 fileno = 1;               
  uint64 pos = 2;                  
  uint64 bmsPos = 3; 
  oneof scanMode_present {
    uint32 scanMode = 4;
  }
  uint32 version = 5; // set to >= 3 for protobuf 3 
}

The generate code has additional methods to detect if oneof fields are set, using the getXXXcase() method:

int scanMode = proto.getScanMode();
boolean isMissing = proto.getScanModePresentCase() == Record.ScanModePresentCase.SCANMODEPRESENT_NOT_SET;
if (isMissing) {
  boolean isProto3 = proto.getVersion() >= 3;
  scanMode = (isProto3) ? 0 : 9999;
}
  • Note that the name of the oneof is arbitrary, i have adopted the convention fieldname_present.
  • The oneof doesnt add anything to the wire format, so it stays compatible with the proto-2 messages.
  • You can add the version info anywhere that makes sense, i put it in the Record message for this example.

With this ‘trick’, i have upgraded to proto-3 with backwards compatibility with non-standard proto-2 default values.

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)