xref: /aosp_15_r20/external/protobuf/docs/implementing_proto3_presence.md (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
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