1*1b3f573fSAndroid Build Coastguard Worker# Application note: Field presence 2*1b3f573fSAndroid Build Coastguard Worker 3*1b3f573fSAndroid Build Coastguard WorkerThis application note explains the various presence tracking disciplines for protobuf fields. It also explains the behaviour of explicit presence tracking for singular proto3 fields with basic types. 4*1b3f573fSAndroid Build Coastguard Worker 5*1b3f573fSAndroid Build Coastguard Worker## Background 6*1b3f573fSAndroid Build Coastguard Worker 7*1b3f573fSAndroid Build Coastguard Worker_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set. 8*1b3f573fSAndroid Build Coastguard Worker 9*1b3f573fSAndroid Build Coastguard WorkerHistorically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this feature is enabled by default as release 3.15). 10*1b3f573fSAndroid Build Coastguard Worker 11*1b3f573fSAndroid Build Coastguard Worker### Presence disciplines 12*1b3f573fSAndroid Build Coastguard Worker 13*1b3f573fSAndroid Build Coastguard Worker_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead. 14*1b3f573fSAndroid Build Coastguard Worker 15*1b3f573fSAndroid Build Coastguard Worker### Presence in _tag-value stream_ (wire format) serialization 16*1b3f573fSAndroid Build Coastguard Worker 17*1b3f573fSAndroid Build Coastguard WorkerThe wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values. 18*1b3f573fSAndroid Build Coastguard Worker 19*1b3f573fSAndroid Build Coastguard WorkerThe generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatible across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages: 20*1b3f573fSAndroid Build Coastguard Worker 21*1b3f573fSAndroid Build Coastguard Worker- When serializing, fields with _no presence_ are not serialized if they contain their default value. 22*1b3f573fSAndroid Build Coastguard Worker - For numeric types, the default is 0. 23*1b3f573fSAndroid Build Coastguard Worker - For enums, the default is the zero-valued enumerator. 24*1b3f573fSAndroid Build Coastguard Worker - For strings, bytes, and repeated fields, the default is the zero-length value. 25*1b3f573fSAndroid Build Coastguard Worker - For messages, the default is the language-specific null value. 26*1b3f573fSAndroid Build Coastguard Worker- "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip. 27*1b3f573fSAndroid Build Coastguard Worker- When deserializing, duplicate field values may be handled in different ways depending on the field definition. 28*1b3f573fSAndroid Build Coastguard Worker - Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.) 29*1b3f573fSAndroid Build Coastguard Worker - Duplicate `optional` field values follow the rule that "the last one wins." 30*1b3f573fSAndroid Build Coastguard Worker- `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule. 31*1b3f573fSAndroid Build Coastguard Worker- Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized. 32*1b3f573fSAndroid Build Coastguard Worker 33*1b3f573fSAndroid Build Coastguard Worker### Presence in _named-field mapping_ formats 34*1b3f573fSAndroid Build Coastguard Worker 35*1b3f573fSAndroid Build Coastguard WorkerProtobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON. 36*1b3f573fSAndroid Build Coastguard Worker 37*1b3f573fSAndroid Build Coastguard WorkerThese formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present. 38*1b3f573fSAndroid Build Coastguard Worker 39*1b3f573fSAndroid Build Coastguard WorkerJSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat. 40*1b3f573fSAndroid Build Coastguard Worker 41*1b3f573fSAndroid Build Coastguard Worker- Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields. 42*1b3f573fSAndroid Build Coastguard Worker- JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats: 43*1b3f573fSAndroid Build Coastguard Worker - JSON defines a `null` value, which may be used to represent a _defined but not-present field_. 44*1b3f573fSAndroid Build Coastguard Worker - Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list). 45*1b3f573fSAndroid Build Coastguard Worker- Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule. 46*1b3f573fSAndroid Build Coastguard Worker - In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat. 47*1b3f573fSAndroid Build Coastguard Worker - However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered. 48*1b3f573fSAndroid Build Coastguard Worker 49*1b3f573fSAndroid Build Coastguard WorkerIn theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs. 50*1b3f573fSAndroid Build Coastguard Worker 51*1b3f573fSAndroid Build Coastguard Worker### Presence in proto2 APIs 52*1b3f573fSAndroid Build Coastguard Worker 53*1b3f573fSAndroid Build Coastguard WorkerThis table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection): 54*1b3f573fSAndroid Build Coastguard Worker 55*1b3f573fSAndroid Build Coastguard WorkerField type | Explicit Presence 56*1b3f573fSAndroid Build Coastguard Worker-------------------------------------------- | ----------------- 57*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | ✔️ 58*1b3f573fSAndroid Build Coastguard WorkerSingular enum | ✔️ 59*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes | ✔️ 60*1b3f573fSAndroid Build Coastguard WorkerSingular message | ✔️ 61*1b3f573fSAndroid Build Coastguard WorkerRepeated | 62*1b3f573fSAndroid Build Coastguard WorkerOneofs | ✔️ 63*1b3f573fSAndroid Build Coastguard WorkerMaps | 64*1b3f573fSAndroid Build Coastguard Worker 65*1b3f573fSAndroid Build Coastguard WorkerSingular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation. 66*1b3f573fSAndroid Build Coastguard Worker 67*1b3f573fSAndroid Build Coastguard WorkerSimilar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`: 68*1b3f573fSAndroid Build Coastguard Worker 69*1b3f573fSAndroid Build Coastguard Worker```protobuf 70*1b3f573fSAndroid Build Coastguard Workeroneof foo { 71*1b3f573fSAndroid Build Coastguard Worker int32 a = 1; 72*1b3f573fSAndroid Build Coastguard Worker float b = 2; 73*1b3f573fSAndroid Build Coastguard Worker} 74*1b3f573fSAndroid Build Coastguard Worker``` 75*1b3f573fSAndroid Build Coastguard Worker 76*1b3f573fSAndroid Build Coastguard WorkerDepending on the target language, the generated API would generally include several methods: 77*1b3f573fSAndroid Build Coastguard Worker 78*1b3f573fSAndroid Build Coastguard Worker- A hazzer for the oneof: `has_foo` 79*1b3f573fSAndroid Build Coastguard Worker- A _oneof case_ method: `foo` 80*1b3f573fSAndroid Build Coastguard Worker- Hazzers for the members: `has_a`, `has_b` 81*1b3f573fSAndroid Build Coastguard Worker- Getters for the members: `a`, `b` 82*1b3f573fSAndroid Build Coastguard Worker 83*1b3f573fSAndroid Build Coastguard WorkerRepeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field. 84*1b3f573fSAndroid Build Coastguard Worker 85*1b3f573fSAndroid Build Coastguard Worker### Presence in proto3 APIs 86*1b3f573fSAndroid Build Coastguard Worker 87*1b3f573fSAndroid Build Coastguard WorkerThis table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection): 88*1b3f573fSAndroid Build Coastguard Worker 89*1b3f573fSAndroid Build Coastguard WorkerField type | `optional` | Explicit Presence 90*1b3f573fSAndroid Build Coastguard Worker-------------------------------------------- | ---------- | ----------------- 91*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | No | 92*1b3f573fSAndroid Build Coastguard WorkerSingular enum | No | 93*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes | No | 94*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | Yes | ✔️ 95*1b3f573fSAndroid Build Coastguard WorkerSingular enum | Yes | ✔️ 96*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes | Yes | ✔️ 97*1b3f573fSAndroid Build Coastguard WorkerSingular message | Yes | ✔️ 98*1b3f573fSAndroid Build Coastguard WorkerSingular message | No | ✔️ 99*1b3f573fSAndroid Build Coastguard WorkerRepeated | N/A | 100*1b3f573fSAndroid Build Coastguard WorkerOneofs | N/A | ✔️ 101*1b3f573fSAndroid Build Coastguard WorkerMaps | N/A | 102*1b3f573fSAndroid Build Coastguard Worker 103*1b3f573fSAndroid Build Coastguard WorkerSimilar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs. 104*1b3f573fSAndroid Build Coastguard Worker 105*1b3f573fSAndroid Build Coastguard WorkerUnder the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value. 106*1b3f573fSAndroid Build Coastguard Worker 107*1b3f573fSAndroid Build Coastguard WorkerThe default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_. 108*1b3f573fSAndroid Build Coastguard Worker 109*1b3f573fSAndroid Build Coastguard Worker## Semantic differences 110*1b3f573fSAndroid Build Coastguard Worker 111*1b3f573fSAndroid Build Coastguard WorkerThe _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type: 112*1b3f573fSAndroid Build Coastguard Worker 113*1b3f573fSAndroid Build Coastguard Worker- _No presence_ discipline: 114*1b3f573fSAndroid Build Coastguard Worker - Default values are not serialized. 115*1b3f573fSAndroid Build Coastguard Worker - Default values are _not_ merged-from. 116*1b3f573fSAndroid Build Coastguard Worker - To "clear" a field, it is set to its default value. 117*1b3f573fSAndroid Build Coastguard Worker - The default value may mean: 118*1b3f573fSAndroid Build Coastguard Worker - the field was explicitly set to its default value, which is valid in the application-specific domain of values; 119*1b3f573fSAndroid Build Coastguard Worker - the field was notionally "cleared" by setting its default; or 120*1b3f573fSAndroid Build Coastguard Worker - the field was never set. 121*1b3f573fSAndroid Build Coastguard Worker- _Explicit presence_ discipline: 122*1b3f573fSAndroid Build Coastguard Worker - Explicitly set values are always serialized, including default values. 123*1b3f573fSAndroid Build Coastguard Worker - Un-set fields are never merged-from. 124*1b3f573fSAndroid Build Coastguard Worker - Explicitly set fields -- including default values -- _are_ merged-from. 125*1b3f573fSAndroid Build Coastguard Worker - A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared). 126*1b3f573fSAndroid Build Coastguard Worker - A generated `clear_foo` method must be used to clear (i.e., un-set) the value. 127*1b3f573fSAndroid Build Coastguard Worker 128*1b3f573fSAndroid Build Coastguard Worker### Considerations for merging 129*1b3f573fSAndroid Build Coastguard Worker 130*1b3f573fSAndroid Build Coastguard WorkerUnder the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, similar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message. 131*1b3f573fSAndroid Build Coastguard Worker 132*1b3f573fSAndroid Build Coastguard WorkerThe difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from. 133*1b3f573fSAndroid Build Coastguard Worker 134*1b3f573fSAndroid Build Coastguard WorkerUpdating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target. 135*1b3f573fSAndroid Build Coastguard Worker 136*1b3f573fSAndroid Build Coastguard Worker### Considerations for change-compatibility 137*1b3f573fSAndroid Build Coastguard Worker 138*1b3f573fSAndroid Build Coastguard WorkerChanging a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value: 139*1b3f573fSAndroid Build Coastguard Worker 140*1b3f573fSAndroid Build Coastguard Worker- The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set. 141*1b3f573fSAndroid Build Coastguard Worker- The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value. 142*1b3f573fSAndroid Build Coastguard Worker 143*1b3f573fSAndroid Build Coastguard WorkerThis change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition. 144*1b3f573fSAndroid Build Coastguard Worker 145*1b3f573fSAndroid Build Coastguard WorkerClient A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`: 146*1b3f573fSAndroid Build Coastguard Worker 147*1b3f573fSAndroid Build Coastguard Worker```protobuf 148*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 149*1b3f573fSAndroid Build Coastguard Workermessage Msg { 150*1b3f573fSAndroid Build Coastguard Worker optional int32 foo = 1; 151*1b3f573fSAndroid Build Coastguard Worker} 152*1b3f573fSAndroid Build Coastguard Worker``` 153*1b3f573fSAndroid Build Coastguard Worker 154*1b3f573fSAndroid Build Coastguard WorkerClient B uses a definition of the same message, except that it follows the _no presence_ discipline: 155*1b3f573fSAndroid Build Coastguard Worker 156*1b3f573fSAndroid Build Coastguard Worker```protobuf 157*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 158*1b3f573fSAndroid Build Coastguard Workermessage Msg { 159*1b3f573fSAndroid Build Coastguard Worker int32 foo = 1; 160*1b3f573fSAndroid Build Coastguard Worker} 161*1b3f573fSAndroid Build Coastguard Worker``` 162*1b3f573fSAndroid Build Coastguard Worker 163*1b3f573fSAndroid Build Coastguard WorkerNow, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing: 164*1b3f573fSAndroid Build Coastguard Worker 165*1b3f573fSAndroid Build Coastguard Worker```protobuf 166*1b3f573fSAndroid Build Coastguard Worker// Client A: 167*1b3f573fSAndroid Build Coastguard WorkerMsg m_a; 168*1b3f573fSAndroid Build Coastguard Workerm_a.set_foo(1); // non-default value 169*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo()); // OK 170*1b3f573fSAndroid Build Coastguard WorkerSend(m_a.SerializeAsString()); // to client B 171*1b3f573fSAndroid Build Coastguard Worker 172*1b3f573fSAndroid Build Coastguard Worker// Client B: 173*1b3f573fSAndroid Build Coastguard WorkerMsg m_b; 174*1b3f573fSAndroid Build Coastguard Workerm_b.ParseFromString(Receive()); // from client A 175*1b3f573fSAndroid Build Coastguard Workerassert(m_b.foo() == 1); // OK 176*1b3f573fSAndroid Build Coastguard WorkerSend(m_b.SerializeAsString()); // to client A 177*1b3f573fSAndroid Build Coastguard Worker 178*1b3f573fSAndroid Build Coastguard Worker// Client A: 179*1b3f573fSAndroid Build Coastguard Workerm_a.ParseFromString(Receive()); // from client B 180*1b3f573fSAndroid Build Coastguard Workerassert(m_a.foo() == 1); // OK 181*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo()); // OK 182*1b3f573fSAndroid Build Coastguard Workerm_a.set_foo(0); // default value 183*1b3f573fSAndroid Build Coastguard WorkerSend(m_a.SerializeAsString()); // to client B 184*1b3f573fSAndroid Build Coastguard Worker 185*1b3f573fSAndroid Build Coastguard Worker// Client B: 186*1b3f573fSAndroid Build Coastguard WorkerMsg m_b; 187*1b3f573fSAndroid Build Coastguard Workerm_b.ParseFromString(Receive()); // from client A 188*1b3f573fSAndroid Build Coastguard Workerassert(m_b.foo() == 0); // OK 189*1b3f573fSAndroid Build Coastguard WorkerSend(m_b.SerializeAsString()); // to client A 190*1b3f573fSAndroid Build Coastguard Worker 191*1b3f573fSAndroid Build Coastguard Worker// Client A: 192*1b3f573fSAndroid Build Coastguard Workerm_a.ParseFromString(Receive()); // from client B 193*1b3f573fSAndroid Build Coastguard Workerassert(m_a.foo() == 0); // OK 194*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo()); // FAIL 195*1b3f573fSAndroid Build Coastguard Worker``` 196*1b3f573fSAndroid Build Coastguard Worker 197*1b3f573fSAndroid Build Coastguard WorkerIf client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case. 198*1b3f573fSAndroid Build Coastguard Worker 199*1b3f573fSAndroid Build Coastguard Worker## How to enable _explicit presence_ in proto3 200*1b3f573fSAndroid Build Coastguard Worker 201*1b3f573fSAndroid Build Coastguard WorkerThese are the general steps to use field tracking support for proto3: 202*1b3f573fSAndroid Build Coastguard Worker 203*1b3f573fSAndroid Build Coastguard Worker1. Add an `optional` field to a `.proto` file. 204*1b3f573fSAndroid Build Coastguard Worker1. Run `protoc` (at least v3.15, or v3.12 using `--experimental_allow_proto3_optional` flag). 205*1b3f573fSAndroid Build Coastguard Worker1. Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values. 206*1b3f573fSAndroid Build Coastguard Worker 207*1b3f573fSAndroid Build Coastguard Worker### `.proto` file changes 208*1b3f573fSAndroid Build Coastguard Worker 209*1b3f573fSAndroid Build Coastguard WorkerThis is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics: 210*1b3f573fSAndroid Build Coastguard Worker 211*1b3f573fSAndroid Build Coastguard Worker```protobuf 212*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 213*1b3f573fSAndroid Build Coastguard Workerpackage example; 214*1b3f573fSAndroid Build Coastguard Worker 215*1b3f573fSAndroid Build Coastguard Workermessage MyMessage { 216*1b3f573fSAndroid Build Coastguard Worker // No presence: 217*1b3f573fSAndroid Build Coastguard Worker int32 not_tracked = 1; 218*1b3f573fSAndroid Build Coastguard Worker 219*1b3f573fSAndroid Build Coastguard Worker // Explicit presence: 220*1b3f573fSAndroid Build Coastguard Worker optional int32 tracked = 2; 221*1b3f573fSAndroid Build Coastguard Worker} 222*1b3f573fSAndroid Build Coastguard Worker``` 223*1b3f573fSAndroid Build Coastguard Worker 224*1b3f573fSAndroid Build Coastguard Worker### `protoc` invocation 225*1b3f573fSAndroid Build Coastguard Worker 226*1b3f573fSAndroid Build Coastguard WorkerPresence tracking for proto3 messages is enabled by default [since v3.15.0](https://github.com/protocolbuffers/protobuf/releases/tag/v3.15.0) release, formerly up until [v3.12.0](https://github.com/protocolbuffers/protobuf/releases/tag/v3.12.0) the `--experimental_allow_proto3_optional` flag was required when using presence tracking with protoc. 227*1b3f573fSAndroid Build Coastguard Worker 228*1b3f573fSAndroid Build Coastguard Worker### Using the generated code 229*1b3f573fSAndroid Build Coastguard Worker 230*1b3f573fSAndroid Build Coastguard WorkerThe generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file. 231*1b3f573fSAndroid Build Coastguard Worker 232*1b3f573fSAndroid Build Coastguard WorkerThis is the definition used in the "no presence" examples below: 233*1b3f573fSAndroid Build Coastguard Worker 234*1b3f573fSAndroid Build Coastguard Worker```protobuf 235*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 236*1b3f573fSAndroid Build Coastguard Workerpackage example; 237*1b3f573fSAndroid Build Coastguard Workermessage Msg { 238*1b3f573fSAndroid Build Coastguard Worker int32 foo = 1; 239*1b3f573fSAndroid Build Coastguard Worker} 240*1b3f573fSAndroid Build Coastguard Worker``` 241*1b3f573fSAndroid Build Coastguard Worker 242*1b3f573fSAndroid Build Coastguard WorkerThis is the definition used in the "explicit presence" examples below: 243*1b3f573fSAndroid Build Coastguard Worker 244*1b3f573fSAndroid Build Coastguard Worker```protobuf 245*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3"; 246*1b3f573fSAndroid Build Coastguard Workerpackage example; 247*1b3f573fSAndroid Build Coastguard Workermessage Msg { 248*1b3f573fSAndroid Build Coastguard Worker optional int32 foo = 1; 249*1b3f573fSAndroid Build Coastguard Worker} 250*1b3f573fSAndroid Build Coastguard Worker``` 251*1b3f573fSAndroid Build Coastguard Worker 252*1b3f573fSAndroid Build Coastguard WorkerIn the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents. 253*1b3f573fSAndroid Build Coastguard Worker 254*1b3f573fSAndroid Build Coastguard Worker#### C++ example 255*1b3f573fSAndroid Build Coastguard Worker 256*1b3f573fSAndroid Build Coastguard WorkerNo presence: 257*1b3f573fSAndroid Build Coastguard Worker 258*1b3f573fSAndroid Build Coastguard Worker```C++ 259*1b3f573fSAndroid Build Coastguard WorkerMsg m = GetProto(); 260*1b3f573fSAndroid Build Coastguard Workerif (m.foo() != 0) { 261*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 262*1b3f573fSAndroid Build Coastguard Worker m.set_foo(0); 263*1b3f573fSAndroid Build Coastguard Worker} else { 264*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 265*1b3f573fSAndroid Build Coastguard Worker m.set_foo(1); 266*1b3f573fSAndroid Build Coastguard Worker} 267*1b3f573fSAndroid Build Coastguard Worker``` 268*1b3f573fSAndroid Build Coastguard Worker 269*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 270*1b3f573fSAndroid Build Coastguard Worker 271*1b3f573fSAndroid Build Coastguard Worker```C++ 272*1b3f573fSAndroid Build Coastguard WorkerMsg m = GetProto(); 273*1b3f573fSAndroid Build Coastguard Workerif (m.has_foo()) { 274*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 275*1b3f573fSAndroid Build Coastguard Worker m.clear_foo(); 276*1b3f573fSAndroid Build Coastguard Worker} else { 277*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 278*1b3f573fSAndroid Build Coastguard Worker m.set_foo(1); 279*1b3f573fSAndroid Build Coastguard Worker} 280*1b3f573fSAndroid Build Coastguard Worker``` 281*1b3f573fSAndroid Build Coastguard Worker 282*1b3f573fSAndroid Build Coastguard Worker#### C# example 283*1b3f573fSAndroid Build Coastguard Worker 284*1b3f573fSAndroid Build Coastguard WorkerNo presence: 285*1b3f573fSAndroid Build Coastguard Worker 286*1b3f573fSAndroid Build Coastguard Worker```C# 287*1b3f573fSAndroid Build Coastguard Workervar m = GetProto(); 288*1b3f573fSAndroid Build Coastguard Workerif (m.Foo != 0) { 289*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 290*1b3f573fSAndroid Build Coastguard Worker m.Foo = 0; 291*1b3f573fSAndroid Build Coastguard Worker} else { 292*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 293*1b3f573fSAndroid Build Coastguard Worker m.Foo = 1; 294*1b3f573fSAndroid Build Coastguard Worker} 295*1b3f573fSAndroid Build Coastguard Worker``` 296*1b3f573fSAndroid Build Coastguard Worker 297*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 298*1b3f573fSAndroid Build Coastguard Worker 299*1b3f573fSAndroid Build Coastguard Worker```C# 300*1b3f573fSAndroid Build Coastguard Workervar m = GetProto(); 301*1b3f573fSAndroid Build Coastguard Workerif (m.HasFoo) { 302*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 303*1b3f573fSAndroid Build Coastguard Worker m.ClearFoo(); 304*1b3f573fSAndroid Build Coastguard Worker} else { 305*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 306*1b3f573fSAndroid Build Coastguard Worker m.Foo = 1; 307*1b3f573fSAndroid Build Coastguard Worker} 308*1b3f573fSAndroid Build Coastguard Worker``` 309*1b3f573fSAndroid Build Coastguard Worker 310*1b3f573fSAndroid Build Coastguard Worker#### Go example 311*1b3f573fSAndroid Build Coastguard Worker 312*1b3f573fSAndroid Build Coastguard WorkerNo presence: 313*1b3f573fSAndroid Build Coastguard Worker 314*1b3f573fSAndroid Build Coastguard Worker```go 315*1b3f573fSAndroid Build Coastguard Workerm := GetProto() 316*1b3f573fSAndroid Build Coastguard Workerif m.Foo != 0 { 317*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 318*1b3f573fSAndroid Build Coastguard Worker m.Foo = 0 319*1b3f573fSAndroid Build Coastguard Worker} else { 320*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 321*1b3f573fSAndroid Build Coastguard Worker m.Foo = 1 322*1b3f573fSAndroid Build Coastguard Worker} 323*1b3f573fSAndroid Build Coastguard Worker``` 324*1b3f573fSAndroid Build Coastguard Worker 325*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 326*1b3f573fSAndroid Build Coastguard Worker 327*1b3f573fSAndroid Build Coastguard Worker```go 328*1b3f573fSAndroid Build Coastguard Workerm := GetProto() 329*1b3f573fSAndroid Build Coastguard Workerif m.Foo != nil { 330*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 331*1b3f573fSAndroid Build Coastguard Worker m.Foo = nil 332*1b3f573fSAndroid Build Coastguard Worker} else { 333*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 334*1b3f573fSAndroid Build Coastguard Worker m.Foo = proto.Int32(1) 335*1b3f573fSAndroid Build Coastguard Worker} 336*1b3f573fSAndroid Build Coastguard Worker``` 337*1b3f573fSAndroid Build Coastguard Worker 338*1b3f573fSAndroid Build Coastguard Worker#### Java example 339*1b3f573fSAndroid Build Coastguard Worker 340*1b3f573fSAndroid Build Coastguard WorkerThese examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type. 341*1b3f573fSAndroid Build Coastguard Worker 342*1b3f573fSAndroid Build Coastguard WorkerNo presence: 343*1b3f573fSAndroid Build Coastguard Worker 344*1b3f573fSAndroid Build Coastguard Worker```java 345*1b3f573fSAndroid Build Coastguard WorkerMsg.Builder m = GetProto().toBuilder(); 346*1b3f573fSAndroid Build Coastguard Workerif (m.getFoo() != 0) { 347*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 348*1b3f573fSAndroid Build Coastguard Worker m.setFoo(0); 349*1b3f573fSAndroid Build Coastguard Worker} else { 350*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 351*1b3f573fSAndroid Build Coastguard Worker m.setFoo(1); 352*1b3f573fSAndroid Build Coastguard Worker} 353*1b3f573fSAndroid Build Coastguard Worker``` 354*1b3f573fSAndroid Build Coastguard Worker 355*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 356*1b3f573fSAndroid Build Coastguard Worker 357*1b3f573fSAndroid Build Coastguard Worker```java 358*1b3f573fSAndroid Build Coastguard WorkerMsg.Builder m = GetProto().toBuilder(); 359*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) { 360*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 361*1b3f573fSAndroid Build Coastguard Worker m.clearFoo() 362*1b3f573fSAndroid Build Coastguard Worker} else { 363*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 364*1b3f573fSAndroid Build Coastguard Worker m.setFoo(1); 365*1b3f573fSAndroid Build Coastguard Worker} 366*1b3f573fSAndroid Build Coastguard Worker``` 367*1b3f573fSAndroid Build Coastguard Worker 368*1b3f573fSAndroid Build Coastguard Worker#### Python example 369*1b3f573fSAndroid Build Coastguard Worker 370*1b3f573fSAndroid Build Coastguard WorkerNo presence: 371*1b3f573fSAndroid Build Coastguard Worker 372*1b3f573fSAndroid Build Coastguard Worker```python 373*1b3f573fSAndroid Build Coastguard Workerm = example.Msg() 374*1b3f573fSAndroid Build Coastguard Workerif m.foo != 0: 375*1b3f573fSAndroid Build Coastguard Worker # "Clear" the field: 376*1b3f573fSAndroid Build Coastguard Worker m.foo = 0 377*1b3f573fSAndroid Build Coastguard Workerelse: 378*1b3f573fSAndroid Build Coastguard Worker # Default value: field may not have been present. 379*1b3f573fSAndroid Build Coastguard Worker m.foo = 1 380*1b3f573fSAndroid Build Coastguard Worker``` 381*1b3f573fSAndroid Build Coastguard Worker 382*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 383*1b3f573fSAndroid Build Coastguard Worker 384*1b3f573fSAndroid Build Coastguard Worker```python 385*1b3f573fSAndroid Build Coastguard Workerm = example.Msg() 386*1b3f573fSAndroid Build Coastguard Workerif m.HasField('foo'): 387*1b3f573fSAndroid Build Coastguard Worker # Clear the field: 388*1b3f573fSAndroid Build Coastguard Worker m.ClearField('foo') 389*1b3f573fSAndroid Build Coastguard Workerelse: 390*1b3f573fSAndroid Build Coastguard Worker # Field is not present, so set it. 391*1b3f573fSAndroid Build Coastguard Worker m.foo = 1 392*1b3f573fSAndroid Build Coastguard Worker``` 393*1b3f573fSAndroid Build Coastguard Worker 394*1b3f573fSAndroid Build Coastguard Worker#### Ruby example 395*1b3f573fSAndroid Build Coastguard Worker 396*1b3f573fSAndroid Build Coastguard WorkerNo presence: 397*1b3f573fSAndroid Build Coastguard Worker 398*1b3f573fSAndroid Build Coastguard Worker```ruby 399*1b3f573fSAndroid Build Coastguard Workerm = Msg.new 400*1b3f573fSAndroid Build Coastguard Workerif m.foo != 0 401*1b3f573fSAndroid Build Coastguard Worker # "Clear" the field: 402*1b3f573fSAndroid Build Coastguard Worker m.foo = 0 403*1b3f573fSAndroid Build Coastguard Workerelse 404*1b3f573fSAndroid Build Coastguard Worker # Default value: field may not have been present. 405*1b3f573fSAndroid Build Coastguard Worker m.foo = 1 406*1b3f573fSAndroid Build Coastguard Workerend 407*1b3f573fSAndroid Build Coastguard Worker``` 408*1b3f573fSAndroid Build Coastguard Worker 409*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 410*1b3f573fSAndroid Build Coastguard Worker 411*1b3f573fSAndroid Build Coastguard Worker```ruby 412*1b3f573fSAndroid Build Coastguard Workerm = Msg.new 413*1b3f573fSAndroid Build Coastguard Workerif m.has_foo? 414*1b3f573fSAndroid Build Coastguard Worker # Clear the field: 415*1b3f573fSAndroid Build Coastguard Worker m.clear_foo 416*1b3f573fSAndroid Build Coastguard Workerelse 417*1b3f573fSAndroid Build Coastguard Worker # Field is not present, so set it. 418*1b3f573fSAndroid Build Coastguard Worker m.foo = 1 419*1b3f573fSAndroid Build Coastguard Workerend 420*1b3f573fSAndroid Build Coastguard Worker``` 421*1b3f573fSAndroid Build Coastguard Worker 422*1b3f573fSAndroid Build Coastguard Worker#### Javascript example 423*1b3f573fSAndroid Build Coastguard Worker 424*1b3f573fSAndroid Build Coastguard WorkerNo presence: 425*1b3f573fSAndroid Build Coastguard Worker 426*1b3f573fSAndroid Build Coastguard Worker```js 427*1b3f573fSAndroid Build Coastguard Workervar m = new Msg(); 428*1b3f573fSAndroid Build Coastguard Workerif (m.getFoo() != 0) { 429*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 430*1b3f573fSAndroid Build Coastguard Worker m.setFoo(0); 431*1b3f573fSAndroid Build Coastguard Worker} else { 432*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 433*1b3f573fSAndroid Build Coastguard Worker m.setFoo(1); 434*1b3f573fSAndroid Build Coastguard Worker} 435*1b3f573fSAndroid Build Coastguard Worker``` 436*1b3f573fSAndroid Build Coastguard Worker 437*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 438*1b3f573fSAndroid Build Coastguard Worker 439*1b3f573fSAndroid Build Coastguard Worker```js 440*1b3f573fSAndroid Build Coastguard Workervar m = new Msg(); 441*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) { 442*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 443*1b3f573fSAndroid Build Coastguard Worker m.clearFoo() 444*1b3f573fSAndroid Build Coastguard Worker} else { 445*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 446*1b3f573fSAndroid Build Coastguard Worker m.setFoo(1); 447*1b3f573fSAndroid Build Coastguard Worker} 448*1b3f573fSAndroid Build Coastguard Worker``` 449*1b3f573fSAndroid Build Coastguard Worker 450*1b3f573fSAndroid Build Coastguard Worker#### Objective C example 451*1b3f573fSAndroid Build Coastguard Worker 452*1b3f573fSAndroid Build Coastguard WorkerNo presence: 453*1b3f573fSAndroid Build Coastguard Worker 454*1b3f573fSAndroid Build Coastguard Worker```Objective-C 455*1b3f573fSAndroid Build Coastguard WorkerMsg *m = [[Msg alloc] init]; 456*1b3f573fSAndroid Build Coastguard Workerif (m.foo != 0) { 457*1b3f573fSAndroid Build Coastguard Worker // "Clear" the field: 458*1b3f573fSAndroid Build Coastguard Worker m.foo = 0; 459*1b3f573fSAndroid Build Coastguard Worker} else { 460*1b3f573fSAndroid Build Coastguard Worker // Default value: field may not have been present. 461*1b3f573fSAndroid Build Coastguard Worker m.foo = 1; 462*1b3f573fSAndroid Build Coastguard Worker} 463*1b3f573fSAndroid Build Coastguard Worker``` 464*1b3f573fSAndroid Build Coastguard Worker 465*1b3f573fSAndroid Build Coastguard WorkerExplicit presence: 466*1b3f573fSAndroid Build Coastguard Worker 467*1b3f573fSAndroid Build Coastguard Worker```Objective-C 468*1b3f573fSAndroid Build Coastguard WorkerMsg *m = [[Msg alloc] init]; 469*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) { 470*1b3f573fSAndroid Build Coastguard Worker // Clear the field: 471*1b3f573fSAndroid Build Coastguard Worker [m clearFoo]; 472*1b3f573fSAndroid Build Coastguard Worker} else { 473*1b3f573fSAndroid Build Coastguard Worker // Field is not present, so set it. 474*1b3f573fSAndroid Build Coastguard Worker [m setFoo:1]; 475*1b3f573fSAndroid Build Coastguard Worker} 476*1b3f573fSAndroid Build Coastguard Worker``` 477