1*1b3f573fSAndroid Build Coastguard Worker# How To Implement Field Presence for Proto3 2*1b3f573fSAndroid Build Coastguard Worker 3*1b3f573fSAndroid Build Coastguard WorkerProtobuf release 3.12 adds experimental support for `optional` fields in 4*1b3f573fSAndroid Build Coastguard Workerproto3. Proto3 optional fields track presence like in proto2. For background 5*1b3f573fSAndroid Build Coastguard Workerinformation about what presence tracking means, please see 6*1b3f573fSAndroid Build Coastguard Worker[docs/field_presence](field_presence.md). 7*1b3f573fSAndroid Build Coastguard Worker 8*1b3f573fSAndroid Build Coastguard Worker## Document Summary 9*1b3f573fSAndroid Build Coastguard Worker 10*1b3f573fSAndroid Build Coastguard WorkerThis document is targeted at developers who own or maintain protobuf code 11*1b3f573fSAndroid Build Coastguard Workergenerators. All code generators will need to be updated to support proto3 12*1b3f573fSAndroid Build Coastguard Workeroptional fields. First-party code generators developed by Google are being 13*1b3f573fSAndroid Build Coastguard Workerupdated already. However third-party code generators will need to be updated 14*1b3f573fSAndroid Build Coastguard Workerindependently by their authors. This includes: 15*1b3f573fSAndroid Build Coastguard Worker 16*1b3f573fSAndroid Build Coastguard Worker- implementations of Protocol Buffers for other languages. 17*1b3f573fSAndroid Build Coastguard Worker- alternate implementations of Protocol Buffers that target specialized use 18*1b3f573fSAndroid Build Coastguard Worker cases. 19*1b3f573fSAndroid Build Coastguard Worker- RPC code generators that create generated APIs for service calls. 20*1b3f573fSAndroid Build Coastguard Worker- code generators that implement some utility code on top of protobuf generated 21*1b3f573fSAndroid Build Coastguard Worker classes. 22*1b3f573fSAndroid Build Coastguard Worker 23*1b3f573fSAndroid Build Coastguard WorkerWhile this document speaks in terms of "code generators", these same principles 24*1b3f573fSAndroid Build Coastguard Workerapply to implementations that dynamically generate a protocol buffer API "on the 25*1b3f573fSAndroid Build Coastguard Workerfly", directly from a descriptor, in languages that support this kind of usage. 26*1b3f573fSAndroid Build Coastguard Worker 27*1b3f573fSAndroid Build Coastguard Worker## Background 28*1b3f573fSAndroid Build Coastguard Worker 29*1b3f573fSAndroid Build Coastguard WorkerPresence tracking was added to proto3 in response to user feedback, both from 30*1b3f573fSAndroid Build Coastguard Workerinside Google and [from open-source 31*1b3f573fSAndroid Build Coastguard Workerusers](https://github.com/protocolbuffers/protobuf/issues/1606). The [proto3 32*1b3f573fSAndroid Build Coastguard Workerwrapper 33*1b3f573fSAndroid Build Coastguard Workertypes](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/wrappers.proto) 34*1b3f573fSAndroid Build Coastguard Workerwere previously the only supported presence mechanism for proto3. Users have 35*1b3f573fSAndroid Build Coastguard Workerpointed to both efficiency and usability issues with the wrapper types. 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard WorkerPresence in proto3 uses exactly the same syntax and semantics as in proto2. 38*1b3f573fSAndroid Build Coastguard WorkerProto3 Fields marked `optional` will track presence like proto2, while fields 39*1b3f573fSAndroid Build Coastguard Workerwithout any label (known as "singular fields"), will continue to omit presence 40*1b3f573fSAndroid Build Coastguard Workerinformation. The `optional` keyword was chosen to minimize differences with 41*1b3f573fSAndroid Build Coastguard Workerproto2. 42*1b3f573fSAndroid Build Coastguard Worker 43*1b3f573fSAndroid Build Coastguard WorkerUnfortunately, for the current descriptor protos and `Descriptor` API (as of 44*1b3f573fSAndroid Build Coastguard Worker3.11.4) it is not possible to use the same representation as proto2. Proto3 45*1b3f573fSAndroid Build Coastguard Workerdescriptors already use `LABEL_OPTIONAL` for proto3 singular fields, which do 46*1b3f573fSAndroid Build Coastguard Workernot track presence. There is a lot of existing code that reflects over proto3 47*1b3f573fSAndroid Build Coastguard Workerprotos and assumes that `LABEL_OPTIONAL` in proto3 means "no presence." Changing 48*1b3f573fSAndroid Build Coastguard Workerthe semantics now would be risky, since old software would likely drop proto3 49*1b3f573fSAndroid Build Coastguard Workerpresence information, which would be a data loss bug. 50*1b3f573fSAndroid Build Coastguard Worker 51*1b3f573fSAndroid Build Coastguard WorkerTo minimize this risk we chose a descriptor representation that is semantically 52*1b3f573fSAndroid Build Coastguard Workercompatible with existing proto3 reflection. Every proto3 optional field is 53*1b3f573fSAndroid Build Coastguard Workerplaced into a one-field `oneof`. We call this a "synthetic" oneof, as it was not 54*1b3f573fSAndroid Build Coastguard Workerpresent in the source `.proto` file. 55*1b3f573fSAndroid Build Coastguard Worker 56*1b3f573fSAndroid Build Coastguard WorkerSince oneof fields in proto3 already track presence, existing proto3 57*1b3f573fSAndroid Build Coastguard Workerreflection-based algorithms should correctly preserve presence for proto3 58*1b3f573fSAndroid Build Coastguard Workeroptional fields with no code changes. For example, the JSON and TextFormat 59*1b3f573fSAndroid Build Coastguard Workerparsers/serializers in C++ and Java did not require any changes to support 60*1b3f573fSAndroid Build Coastguard Workerproto3 presence. This is the major benefit of synthetic oneofs. 61*1b3f573fSAndroid Build Coastguard Worker 62*1b3f573fSAndroid Build Coastguard WorkerThis design does leave some cruft in descriptors. Synthetic oneofs are a 63*1b3f573fSAndroid Build Coastguard Workercompatibility measure that we can hopefully clean up in the future. For now 64*1b3f573fSAndroid Build Coastguard Workerthough, it is important to preserve them across different descriptor formats and 65*1b3f573fSAndroid Build Coastguard WorkerAPIs. It is never safe to drop synthetic oneofs from a proto schema. Code 66*1b3f573fSAndroid Build Coastguard Workergenerators can (and should) skip synthetic oneofs when generating a user-facing 67*1b3f573fSAndroid Build Coastguard WorkerAPI or user-facing documentation. But for any schema representation that is 68*1b3f573fSAndroid Build Coastguard Workerconsumed programmatically, it is important to keep the synthetic oneofs around. 69*1b3f573fSAndroid Build Coastguard Worker 70*1b3f573fSAndroid Build Coastguard WorkerIn APIs it can be helpful to offer separate accessors that refer to "real" 71*1b3f573fSAndroid Build Coastguard Workeroneofs (see [API Changes](#api-changes) below). This is a convenient way to omit 72*1b3f573fSAndroid Build Coastguard Workersynthetic oneofs in code generators. 73*1b3f573fSAndroid Build Coastguard Worker 74*1b3f573fSAndroid Build Coastguard Worker## Updating a Code Generator 75*1b3f573fSAndroid Build Coastguard Worker 76*1b3f573fSAndroid Build Coastguard WorkerWhen a user adds an `optional` field to proto3, this is internally rewritten as 77*1b3f573fSAndroid Build Coastguard Workera one-field oneof, for backward-compatibility with reflection-based algorithms: 78*1b3f573fSAndroid Build Coastguard Worker 79*1b3f573fSAndroid Build Coastguard Worker```protobuf 80*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 81*1b3f573fSAndroid Build Coastguard Worker 82*1b3f573fSAndroid Build Coastguard Workermessage Foo { 83*1b3f573fSAndroid Build Coastguard Worker // Experimental feature, not generally supported yet! 84*1b3f573fSAndroid Build Coastguard Worker optional int32 foo = 1; 85*1b3f573fSAndroid Build Coastguard Worker 86*1b3f573fSAndroid Build Coastguard Worker // Internally rewritten to: 87*1b3f573fSAndroid Build Coastguard Worker // oneof _foo { 88*1b3f573fSAndroid Build Coastguard Worker // int32 foo = 1 [proto3_optional=true]; 89*1b3f573fSAndroid Build Coastguard Worker // } 90*1b3f573fSAndroid Build Coastguard Worker // 91*1b3f573fSAndroid Build Coastguard Worker // We call _foo a "synthetic" oneof, since it was not created by the user. 92*1b3f573fSAndroid Build Coastguard Worker} 93*1b3f573fSAndroid Build Coastguard Worker``` 94*1b3f573fSAndroid Build Coastguard Worker 95*1b3f573fSAndroid Build Coastguard WorkerAs a result, the main two goals when updating a code generator are: 96*1b3f573fSAndroid Build Coastguard Worker 97*1b3f573fSAndroid Build Coastguard Worker1. Give `optional` fields like `foo` normal field presence, as described in 98*1b3f573fSAndroid Build Coastguard Worker [docs/field_presence](field_presence.md) If your implementation already 99*1b3f573fSAndroid Build Coastguard Worker supports proto2, a proto3 `optional` field should use exactly the same API 100*1b3f573fSAndroid Build Coastguard Worker and internal implementation as proto2 `optional`. 101*1b3f573fSAndroid Build Coastguard Worker2. Avoid generating any oneof-based accessors for the synthetic oneof. Its only 102*1b3f573fSAndroid Build Coastguard Worker purpose is to make reflection-based algorithms work properly if they are 103*1b3f573fSAndroid Build Coastguard Worker not aware of proto3 presence. The synthetic oneof should not appear anywhere 104*1b3f573fSAndroid Build Coastguard Worker in the generated API. 105*1b3f573fSAndroid Build Coastguard Worker 106*1b3f573fSAndroid Build Coastguard Worker### Satisfying the Experimental Check 107*1b3f573fSAndroid Build Coastguard Worker 108*1b3f573fSAndroid Build Coastguard WorkerIf you try to run `protoc` on a file with proto3 `optional` fields, you will get 109*1b3f573fSAndroid Build Coastguard Workeran error because the feature is still experimental: 110*1b3f573fSAndroid Build Coastguard Worker 111*1b3f573fSAndroid Build Coastguard Worker``` 112*1b3f573fSAndroid Build Coastguard Worker$ cat test.proto 113*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 114*1b3f573fSAndroid Build Coastguard Worker 115*1b3f573fSAndroid Build Coastguard Workermessage Foo { 116*1b3f573fSAndroid Build Coastguard Worker // Experimental feature, not generally supported yet! 117*1b3f573fSAndroid Build Coastguard Worker optional int32 a = 1; 118*1b3f573fSAndroid Build Coastguard Worker} 119*1b3f573fSAndroid Build Coastguard Worker$ protoc --cpp_out=. test.proto 120*1b3f573fSAndroid Build Coastguard Workertest.proto: This file contains proto3 optional fields, but --experimental_allow_proto3_optional was not set. 121*1b3f573fSAndroid Build Coastguard Worker``` 122*1b3f573fSAndroid Build Coastguard Worker 123*1b3f573fSAndroid Build Coastguard WorkerThere are two options for getting around this error: 124*1b3f573fSAndroid Build Coastguard Worker 125*1b3f573fSAndroid Build Coastguard Worker1. Pass `--experimental_allow_proto3_optional` to protoc. 126*1b3f573fSAndroid Build Coastguard Worker2. Make your filename (or a directory name) contain the string 127*1b3f573fSAndroid Build Coastguard Worker `test_proto3_optional`. This indicates that the proto file is specifically 128*1b3f573fSAndroid Build Coastguard Worker for testing proto3 optional support, so the check is suppressed. 129*1b3f573fSAndroid Build Coastguard Worker 130*1b3f573fSAndroid Build Coastguard WorkerThese options are demonstrated below: 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard Worker``` 133*1b3f573fSAndroid Build Coastguard Worker# One option: 134*1b3f573fSAndroid Build Coastguard Worker$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional 135*1b3f573fSAndroid Build Coastguard Worker 136*1b3f573fSAndroid Build Coastguard Worker# Another option: 137*1b3f573fSAndroid Build Coastguard Worker$ cp test.proto test_proto3_optional.proto 138*1b3f573fSAndroid Build Coastguard Worker$ ./src/protoc test_proto3_optional.proto --cpp_out=. 139*1b3f573fSAndroid Build Coastguard Worker$ 140*1b3f573fSAndroid Build Coastguard Worker``` 141*1b3f573fSAndroid Build Coastguard Worker 142*1b3f573fSAndroid Build Coastguard WorkerThe experimental check will be removed in a future release, once we are ready 143*1b3f573fSAndroid Build Coastguard Workerto make this feature generally available. Ideally this will happen for the 3.13 144*1b3f573fSAndroid Build Coastguard Workerrelease of protobuf, sometime in mid-2020, but there is not a specific date set 145*1b3f573fSAndroid Build Coastguard Workerfor this yet. Some of the timing will depend on feedback we get from the 146*1b3f573fSAndroid Build Coastguard Workercommunity, so if you have questions or concerns please get in touch via a 147*1b3f573fSAndroid Build Coastguard WorkerGitHub issue. 148*1b3f573fSAndroid Build Coastguard Worker 149*1b3f573fSAndroid Build Coastguard Worker### Signaling That Your Code Generator Supports Proto3 Optional 150*1b3f573fSAndroid Build Coastguard Worker 151*1b3f573fSAndroid Build Coastguard WorkerIf you now try to invoke your own code generator with the test proto, you will 152*1b3f573fSAndroid Build Coastguard Workerrun into a different error: 153*1b3f573fSAndroid Build Coastguard Worker 154*1b3f573fSAndroid Build Coastguard Worker``` 155*1b3f573fSAndroid Build Coastguard Worker$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. 156*1b3f573fSAndroid Build Coastguard Workertest_proto3_optional.proto: is a proto3 file that contains optional fields, but 157*1b3f573fSAndroid Build Coastguard Workercode generator --my_codegen_out hasn't been updated to support optional fields in 158*1b3f573fSAndroid Build Coastguard Workerproto3. Please ask the owner of this code generator to support proto3 optional. 159*1b3f573fSAndroid Build Coastguard Worker``` 160*1b3f573fSAndroid Build Coastguard Worker 161*1b3f573fSAndroid Build Coastguard WorkerThis check exists to make sure that code generators get a chance to update 162*1b3f573fSAndroid Build Coastguard Workerbefore they are used with proto3 `optional` fields. Without this check an old 163*1b3f573fSAndroid Build Coastguard Workercode generator might emit obsolete generated APIs (like accessors for a 164*1b3f573fSAndroid Build Coastguard Workersynthetic oneof) and users could start depending on these. That would create 165*1b3f573fSAndroid Build Coastguard Workera legacy migration burden once a code generator actually implements the feature. 166*1b3f573fSAndroid Build Coastguard Worker 167*1b3f573fSAndroid Build Coastguard WorkerTo signal that your code generator supports `optional` fields in proto3, you 168*1b3f573fSAndroid Build Coastguard Workerneed to tell `protoc` what features you support. The method for doing this 169*1b3f573fSAndroid Build Coastguard Workerdepends on whether you are using the C++ 170*1b3f573fSAndroid Build Coastguard Worker`google::protobuf::compiler::CodeGenerator` 171*1b3f573fSAndroid Build Coastguard Workerframework or not. 172*1b3f573fSAndroid Build Coastguard Worker 173*1b3f573fSAndroid Build Coastguard WorkerIf you are using the CodeGenerator framework: 174*1b3f573fSAndroid Build Coastguard Worker 175*1b3f573fSAndroid Build Coastguard Worker```c++ 176*1b3f573fSAndroid Build Coastguard Workerclass MyCodeGenerator : public google::protobuf::compiler::CodeGenerator { 177*1b3f573fSAndroid Build Coastguard Worker // Add this method. 178*1b3f573fSAndroid Build Coastguard Worker uint64_t GetSupportedFeatures() const override { 179*1b3f573fSAndroid Build Coastguard Worker // Indicate that this code generator supports proto3 optional fields. 180*1b3f573fSAndroid Build Coastguard Worker // (Note: don't release your code generator with this flag set until you 181*1b3f573fSAndroid Build Coastguard Worker // have actually added and tested your proto3 support!) 182*1b3f573fSAndroid Build Coastguard Worker return FEATURE_PROTO3_OPTIONAL; 183*1b3f573fSAndroid Build Coastguard Worker } 184*1b3f573fSAndroid Build Coastguard Worker} 185*1b3f573fSAndroid Build Coastguard Worker``` 186*1b3f573fSAndroid Build Coastguard Worker 187*1b3f573fSAndroid Build Coastguard WorkerIf you are generating code using raw `CodeGeneratorRequest` and 188*1b3f573fSAndroid Build Coastguard Worker`CodeGeneratorResponse` messages from `plugin.proto`, the change will be very 189*1b3f573fSAndroid Build Coastguard Workersimilar: 190*1b3f573fSAndroid Build Coastguard Worker 191*1b3f573fSAndroid Build Coastguard Worker```c++ 192*1b3f573fSAndroid Build Coastguard Workervoid GenerateResponse() { 193*1b3f573fSAndroid Build Coastguard Worker CodeGeneratorResponse response; 194*1b3f573fSAndroid Build Coastguard Worker response.set_supported_features(CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL); 195*1b3f573fSAndroid Build Coastguard Worker 196*1b3f573fSAndroid Build Coastguard Worker // Generate code... 197*1b3f573fSAndroid Build Coastguard Worker} 198*1b3f573fSAndroid Build Coastguard Worker``` 199*1b3f573fSAndroid Build Coastguard Worker 200*1b3f573fSAndroid Build Coastguard WorkerOnce you have added this, you should now be able to successfully use your code 201*1b3f573fSAndroid Build Coastguard Workergenerator to generate a file containing proto3 optional fields: 202*1b3f573fSAndroid Build Coastguard Worker 203*1b3f573fSAndroid Build Coastguard Worker``` 204*1b3f573fSAndroid Build Coastguard Worker$ ./src/protoc test_proto3_optional.proto --my_codegen_out=. 205*1b3f573fSAndroid Build Coastguard Worker``` 206*1b3f573fSAndroid Build Coastguard Worker 207*1b3f573fSAndroid Build Coastguard Worker### Updating Your Code Generator 208*1b3f573fSAndroid Build Coastguard Worker 209*1b3f573fSAndroid Build Coastguard WorkerNow to actually add support for proto3 optional to your code generator. The goal 210*1b3f573fSAndroid Build Coastguard Workeris to recognize proto3 optional fields as optional, and suppress any output from 211*1b3f573fSAndroid Build Coastguard Workersynthetic oneofs. 212*1b3f573fSAndroid Build Coastguard Worker 213*1b3f573fSAndroid Build Coastguard WorkerIf your code generator does not currently support proto2, you will need to 214*1b3f573fSAndroid Build Coastguard Workerdesign an API and implementation for supporting presence in scalar fields. 215*1b3f573fSAndroid Build Coastguard WorkerGenerally this means: 216*1b3f573fSAndroid Build Coastguard Worker 217*1b3f573fSAndroid Build Coastguard Worker- allocating a bit inside the generated class to represent whether a given field 218*1b3f573fSAndroid Build Coastguard Worker is present or not. 219*1b3f573fSAndroid Build Coastguard Worker- exposing a `has_foo()` method for each field to return the value of this bit. 220*1b3f573fSAndroid Build Coastguard Worker- make the parser set this bit when a value is parsed from the wire. 221*1b3f573fSAndroid Build Coastguard Worker- make the serializer test this bit to decide whether to serialize. 222*1b3f573fSAndroid Build Coastguard Worker 223*1b3f573fSAndroid Build Coastguard WorkerIf your code generator already supports proto2, then most of your work is 224*1b3f573fSAndroid Build Coastguard Workeralready done. All you need to do is make sure that proto3 optional fields have 225*1b3f573fSAndroid Build Coastguard Workerexactly the same API and behave in exactly the same way as proto2 optional 226*1b3f573fSAndroid Build Coastguard Workerfields. 227*1b3f573fSAndroid Build Coastguard Worker 228*1b3f573fSAndroid Build Coastguard WorkerFrom experience updating several of Google's code generators, most of the 229*1b3f573fSAndroid Build Coastguard Workerupdates that are required fall into one of several patterns. Here we will show 230*1b3f573fSAndroid Build Coastguard Workerthe patterns in terms of the C++ CodeGenerator framework. If you are using 231*1b3f573fSAndroid Build Coastguard Worker`CodeGeneratorRequest` and `CodeGeneratorReply` directly, you can translate the 232*1b3f573fSAndroid Build Coastguard WorkerC++ examples to your own language, referencing the C++ implementation of these 233*1b3f573fSAndroid Build Coastguard Workermethods where required. 234*1b3f573fSAndroid Build Coastguard Worker 235*1b3f573fSAndroid Build Coastguard Worker#### To test whether a field should have presence 236*1b3f573fSAndroid Build Coastguard Worker 237*1b3f573fSAndroid Build Coastguard WorkerOld: 238*1b3f573fSAndroid Build Coastguard Worker 239*1b3f573fSAndroid Build Coastguard Worker```c++ 240*1b3f573fSAndroid Build Coastguard Workerbool MessageHasPresence(const google::protobuf::Descriptor* message) { 241*1b3f573fSAndroid Build Coastguard Worker return message->file()->syntax() == 242*1b3f573fSAndroid Build Coastguard Worker google::protobuf::FileDescriptor::SYNTAX_PROTO2; 243*1b3f573fSAndroid Build Coastguard Worker} 244*1b3f573fSAndroid Build Coastguard Worker``` 245*1b3f573fSAndroid Build Coastguard Worker 246*1b3f573fSAndroid Build Coastguard WorkerNew: 247*1b3f573fSAndroid Build Coastguard Worker 248*1b3f573fSAndroid Build Coastguard Worker```c++ 249*1b3f573fSAndroid Build Coastguard Worker// Presence is no longer a property of a message, it's a property of individual 250*1b3f573fSAndroid Build Coastguard Worker// fields. 251*1b3f573fSAndroid Build Coastguard Workerbool FieldHasPresence(const google::protobuf::FieldDescriptor* field) { 252*1b3f573fSAndroid Build Coastguard Worker return field->has_presence(); 253*1b3f573fSAndroid Build Coastguard Worker // Note, the above will return true for fields in a oneof. 254*1b3f573fSAndroid Build Coastguard Worker // If you want to filter out oneof fields, write this instead: 255*1b3f573fSAndroid Build Coastguard Worker // return field->has_presence && !field->real_containing_oneof() 256*1b3f573fSAndroid Build Coastguard Worker} 257*1b3f573fSAndroid Build Coastguard Worker``` 258*1b3f573fSAndroid Build Coastguard Worker 259*1b3f573fSAndroid Build Coastguard Worker#### To test whether a field is a member of a oneof 260*1b3f573fSAndroid Build Coastguard Worker 261*1b3f573fSAndroid Build Coastguard WorkerOld: 262*1b3f573fSAndroid Build Coastguard Worker 263*1b3f573fSAndroid Build Coastguard Worker```c++ 264*1b3f573fSAndroid Build Coastguard Workerbool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) { 265*1b3f573fSAndroid Build Coastguard Worker return field->containing_oneof() != nullptr; 266*1b3f573fSAndroid Build Coastguard Worker} 267*1b3f573fSAndroid Build Coastguard Worker``` 268*1b3f573fSAndroid Build Coastguard Worker 269*1b3f573fSAndroid Build Coastguard WorkerNew: 270*1b3f573fSAndroid Build Coastguard Worker 271*1b3f573fSAndroid Build Coastguard Worker```c++ 272*1b3f573fSAndroid Build Coastguard Workerbool FieldIsInOneof(const google::protobuf::FieldDescriptor* field) { 273*1b3f573fSAndroid Build Coastguard Worker // real_containing_oneof() returns nullptr for synthetic oneofs. 274*1b3f573fSAndroid Build Coastguard Worker return field->real_containing_oneof() != nullptr; 275*1b3f573fSAndroid Build Coastguard Worker} 276*1b3f573fSAndroid Build Coastguard Worker``` 277*1b3f573fSAndroid Build Coastguard Worker 278*1b3f573fSAndroid Build Coastguard Worker#### To iterate over all oneofs 279*1b3f573fSAndroid Build Coastguard Worker 280*1b3f573fSAndroid Build Coastguard WorkerOld: 281*1b3f573fSAndroid Build Coastguard Worker 282*1b3f573fSAndroid Build Coastguard Worker```c++ 283*1b3f573fSAndroid Build Coastguard Workerbool IterateOverOneofs(const google::protobuf::Descriptor* message) { 284*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < message->oneof_decl_count(); i++) { 285*1b3f573fSAndroid Build Coastguard Worker const google::protobuf::OneofDescriptor* oneof = message->oneof(i); 286*1b3f573fSAndroid Build Coastguard Worker // ... 287*1b3f573fSAndroid Build Coastguard Worker } 288*1b3f573fSAndroid Build Coastguard Worker} 289*1b3f573fSAndroid Build Coastguard Worker``` 290*1b3f573fSAndroid Build Coastguard Worker 291*1b3f573fSAndroid Build Coastguard WorkerNew: 292*1b3f573fSAndroid Build Coastguard Worker 293*1b3f573fSAndroid Build Coastguard Worker```c++ 294*1b3f573fSAndroid Build Coastguard Workerbool IterateOverOneofs(const google::protobuf::Descriptor* message) { 295*1b3f573fSAndroid Build Coastguard Worker // Real oneofs are always first, and real_oneof_decl_count() will return the 296*1b3f573fSAndroid Build Coastguard Worker // total number of oneofs, excluding synthetic oneofs. 297*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < message->real_oneof_decl_count(); i++) { 298*1b3f573fSAndroid Build Coastguard Worker const google::protobuf::OneofDescriptor* oneof = message->oneof(i); 299*1b3f573fSAndroid Build Coastguard Worker // ... 300*1b3f573fSAndroid Build Coastguard Worker } 301*1b3f573fSAndroid Build Coastguard Worker} 302*1b3f573fSAndroid Build Coastguard Worker``` 303*1b3f573fSAndroid Build Coastguard Worker 304*1b3f573fSAndroid Build Coastguard Worker## Updating Reflection 305*1b3f573fSAndroid Build Coastguard Worker 306*1b3f573fSAndroid Build Coastguard WorkerIf your implementation offers reflection, there are a few other changes to make: 307*1b3f573fSAndroid Build Coastguard Worker 308*1b3f573fSAndroid Build Coastguard Worker### API Changes 309*1b3f573fSAndroid Build Coastguard Worker 310*1b3f573fSAndroid Build Coastguard WorkerThe API for reflecting over fields and oneofs should make the following changes. 311*1b3f573fSAndroid Build Coastguard WorkerThese match the changes implemented in C++ reflection. 312*1b3f573fSAndroid Build Coastguard Worker 313*1b3f573fSAndroid Build Coastguard Worker1. Add a `FieldDescriptor::has_presence()` method returning `bool` 314*1b3f573fSAndroid Build Coastguard Worker (adjusted to your language's naming convention). This should return true 315*1b3f573fSAndroid Build Coastguard Worker for all fields that have explicit presence, as documented in 316*1b3f573fSAndroid Build Coastguard Worker [docs/field_presence](field_presence.md). In particular, this includes 317*1b3f573fSAndroid Build Coastguard Worker fields in a oneof, proto2 scalar fields, and proto3 `optional` fields. 318*1b3f573fSAndroid Build Coastguard Worker This accessor will allow users to query what fields have presence without 319*1b3f573fSAndroid Build Coastguard Worker thinking about the difference between proto2 and proto3. 320*1b3f573fSAndroid Build Coastguard Worker2. As a corollary of (1), please do *not* expose an accessor for the 321*1b3f573fSAndroid Build Coastguard Worker `FieldDescriptorProto.proto3_optional` field. We want to avoid having 322*1b3f573fSAndroid Build Coastguard Worker users implement any proto2/proto3-specific logic. Users should use the 323*1b3f573fSAndroid Build Coastguard Worker `has_presence()` function instead. 324*1b3f573fSAndroid Build Coastguard Worker3. You may also wish to add a `FieldDescriptor::has_optional_keyword()` method 325*1b3f573fSAndroid Build Coastguard Worker returning `bool`, which indicates whether the `optional` keyword is present. 326*1b3f573fSAndroid Build Coastguard Worker Message fields will always return `true` for `has_presence()`, so this method 327*1b3f573fSAndroid Build Coastguard Worker can allow a user to know whether the user wrote `optional` or not. It can 328*1b3f573fSAndroid Build Coastguard Worker occasionally be useful to have this information, even though it does not 329*1b3f573fSAndroid Build Coastguard Worker change the presence semantics of the field. 330*1b3f573fSAndroid Build Coastguard Worker4. If your reflection API may be used for a code generator, you may wish to 331*1b3f573fSAndroid Build Coastguard Worker implement methods to help users tell the difference between real and 332*1b3f573fSAndroid Build Coastguard Worker synthetic oneofs. In particular: 333*1b3f573fSAndroid Build Coastguard Worker - `OneofDescriptor::is_synthetic()`: returns true if this is a synthetic 334*1b3f573fSAndroid Build Coastguard Worker oneof. 335*1b3f573fSAndroid Build Coastguard Worker - `FieldDescriptor::real_containing_oneof()`: like `containing_oneof()`, 336*1b3f573fSAndroid Build Coastguard Worker but returns `nullptr` if the oneof is synthetic. 337*1b3f573fSAndroid Build Coastguard Worker - `Descriptor::real_oneof_decl_count()`: like `oneof_decl_count()`, but 338*1b3f573fSAndroid Build Coastguard Worker returns the number of real oneofs only. 339*1b3f573fSAndroid Build Coastguard Worker 340*1b3f573fSAndroid Build Coastguard Worker### Implementation Changes 341*1b3f573fSAndroid Build Coastguard Worker 342*1b3f573fSAndroid Build Coastguard WorkerProto3 `optional` fields and synthetic oneofs must work correctly when 343*1b3f573fSAndroid Build Coastguard Workerreflected on. Specifically: 344*1b3f573fSAndroid Build Coastguard Worker 345*1b3f573fSAndroid Build Coastguard Worker1. Reflection for synthetic oneofs should work properly. Even though synthetic 346*1b3f573fSAndroid Build Coastguard Worker oneofs do not really exist in the message, you can still make reflection work 347*1b3f573fSAndroid Build Coastguard Worker as if they did. In particular, you can make a method like 348*1b3f573fSAndroid Build Coastguard Worker `Reflection::HasOneof()` or `Reflection::GetOneofFieldDescriptor()` look at 349*1b3f573fSAndroid Build Coastguard Worker the hasbit to determine if the oneof is present or not. 350*1b3f573fSAndroid Build Coastguard Worker2. Reflection for proto3 optional fields should work properly. For example, a 351*1b3f573fSAndroid Build Coastguard Worker method like `Reflection::HasField()` should know to look for the hasbit for a 352*1b3f573fSAndroid Build Coastguard Worker proto3 `optional` field. It should not be fooled by the synthetic oneof into 353*1b3f573fSAndroid Build Coastguard Worker thinking that there is a `case` member for the oneof. 354*1b3f573fSAndroid Build Coastguard Worker 355*1b3f573fSAndroid Build Coastguard WorkerOnce you have updated reflection to work properly with proto3 `optional` and 356*1b3f573fSAndroid Build Coastguard Workersynthetic oneofs, any code that *uses* your reflection interface should work 357*1b3f573fSAndroid Build Coastguard Workerproperly with no changes. This is the benefit of using synthetic oneofs. 358*1b3f573fSAndroid Build Coastguard Worker 359*1b3f573fSAndroid Build Coastguard WorkerIn particular, if you have a reflection-based implementation of protobuf text 360*1b3f573fSAndroid Build Coastguard Workerformat or JSON, it should properly support proto3 optional fields without any 361*1b3f573fSAndroid Build Coastguard Workerchanges to the code. The fields will look like they all belong to a one-field 362*1b3f573fSAndroid Build Coastguard Workeroneof, and existing proto3 reflection code should know how to test presence for 363*1b3f573fSAndroid Build Coastguard Workerfields in a oneof. 364*1b3f573fSAndroid Build Coastguard Worker 365*1b3f573fSAndroid Build Coastguard WorkerSo the best way to test your reflection changes is to try round-tripping a 366*1b3f573fSAndroid Build Coastguard Workermessage through text format, JSON, or some other reflection-based parser and 367*1b3f573fSAndroid Build Coastguard Workerserializer, if you have one. 368*1b3f573fSAndroid Build Coastguard Worker 369*1b3f573fSAndroid Build Coastguard Worker### Validating Descriptors 370*1b3f573fSAndroid Build Coastguard Worker 371*1b3f573fSAndroid Build Coastguard WorkerIf your reflection implementation supports loading descriptors at runtime, 372*1b3f573fSAndroid Build Coastguard Workeryou must verify that all synthetic oneofs are ordered after all "real" oneofs. 373*1b3f573fSAndroid Build Coastguard Worker 374*1b3f573fSAndroid Build Coastguard WorkerHere is the code that implements this validation step in C++, for inspiration: 375*1b3f573fSAndroid Build Coastguard Worker 376*1b3f573fSAndroid Build Coastguard Worker```c++ 377*1b3f573fSAndroid Build Coastguard Worker // Validation that runs for each message. 378*1b3f573fSAndroid Build Coastguard Worker // Synthetic oneofs must be last. 379*1b3f573fSAndroid Build Coastguard Worker int first_synthetic = -1; 380*1b3f573fSAndroid Build Coastguard Worker for (int i = 0; i < message->oneof_decl_count(); i++) { 381*1b3f573fSAndroid Build Coastguard Worker const OneofDescriptor* oneof = message->oneof_decl(i); 382*1b3f573fSAndroid Build Coastguard Worker if (oneof->is_synthetic()) { 383*1b3f573fSAndroid Build Coastguard Worker if (first_synthetic == -1) { 384*1b3f573fSAndroid Build Coastguard Worker first_synthetic = i; 385*1b3f573fSAndroid Build Coastguard Worker } 386*1b3f573fSAndroid Build Coastguard Worker } else { 387*1b3f573fSAndroid Build Coastguard Worker if (first_synthetic != -1) { 388*1b3f573fSAndroid Build Coastguard Worker AddError(message->full_name(), proto.oneof_decl(i), 389*1b3f573fSAndroid Build Coastguard Worker DescriptorPool::ErrorCollector::OTHER, 390*1b3f573fSAndroid Build Coastguard Worker "Synthetic oneofs must be after all other oneofs"); 391*1b3f573fSAndroid Build Coastguard Worker } 392*1b3f573fSAndroid Build Coastguard Worker } 393*1b3f573fSAndroid Build Coastguard Worker } 394*1b3f573fSAndroid Build Coastguard Worker 395*1b3f573fSAndroid Build Coastguard Worker if (first_synthetic == -1) { 396*1b3f573fSAndroid Build Coastguard Worker message->real_oneof_decl_count_ = message->oneof_decl_count_; 397*1b3f573fSAndroid Build Coastguard Worker } else { 398*1b3f573fSAndroid Build Coastguard Worker message->real_oneof_decl_count_ = first_synthetic; 399*1b3f573fSAndroid Build Coastguard Worker } 400*1b3f573fSAndroid Build Coastguard Worker``` 401