0
# Extension Field Access
1
2
Operator overloads for intuitive extension field access on extendable messages and builders, providing get, set, and contains operations with full type safety.
3
4
## Capabilities
5
6
### Setting Extension Values
7
8
Sets the current value of a protocol buffer extension in a message builder.
9
10
```kotlin { .api }
11
/**
12
* Sets the current value of the proto extension in this builder
13
* @param extension the extension field to set
14
* @param value the value to set for the extension
15
*/
16
operator fun <
17
M : GeneratedMessage.ExtendableMessage<M>,
18
B : GeneratedMessage.ExtendableBuilder<M, B>,
19
T : Any
20
> B.set(extension: ExtensionLite<M, T>, value: T)
21
```
22
23
**Usage Example:**
24
25
```kotlin
26
import com.google.protobuf.kotlin.set
27
// Assuming you have generated message classes with extensions
28
29
val builder = MyExtendableMessage.newBuilder()
30
31
// Set extension value using bracket notation
32
builder[myStringExtension] = "Hello, Extensions!"
33
builder[myIntExtension] = 42
34
builder[myBoolExtension] = true
35
36
val message = builder.build()
37
```
38
39
### Getting Extension Values
40
41
Gets the current value of a protocol buffer extension from a message or builder.
42
43
```kotlin { .api }
44
/**
45
* Gets the current value of the proto extension
46
* @param extension the extension field to get
47
* @return the current value of the extension
48
*/
49
operator fun <
50
M : GeneratedMessage.ExtendableMessage<M>,
51
MorBT : GeneratedMessage.ExtendableMessageOrBuilder<M>,
52
T : Any
53
> MorBT.get(extension: ExtensionLite<M, T>): T
54
```
55
56
**Usage Example:**
57
58
```kotlin
59
import com.google.protobuf.kotlin.get
60
61
// From a built message
62
val message: MyExtendableMessage = // ... some message with extensions
63
val stringValue = message[myStringExtension]
64
val intValue = message[myIntExtension]
65
val boolValue = message[myBoolExtension]
66
67
// From a builder
68
val builder = MyExtendableMessage.newBuilder()
69
builder[myStringExtension] = "test"
70
val currentValue = builder[myStringExtension] // "test"
71
```
72
73
### Checking Extension Presence
74
75
Returns true if the specified extension is set on a message or builder.
76
77
```kotlin { .api }
78
/**
79
* Returns true if the specified extension is set on this builder
80
* @param extension the extension field to check
81
* @return true if the extension is set, false otherwise
82
*/
83
operator fun <
84
M : GeneratedMessage.ExtendableMessage<M>,
85
MorBT : GeneratedMessage.ExtendableMessageOrBuilder<M>
86
> MorBT.contains(extension: ExtensionLite<M, *>): Boolean
87
```
88
89
**Usage Example:**
90
91
```kotlin
92
import com.google.protobuf.kotlin.contains
93
94
val message: MyExtendableMessage = // ... some message
95
val builder = MyExtendableMessage.newBuilder()
96
97
// Check if extension is set
98
if (myStringExtension in message) {
99
println("String extension is set: ${message[myStringExtension]}")
100
} else {
101
println("String extension is not set")
102
}
103
104
// Check before accessing to avoid exceptions
105
if (myOptionalExtension in builder) {
106
val value = builder[myOptionalExtension]
107
// Use value safely
108
}
109
```
110
111
## Complete Usage Patterns
112
113
### Working with Extension Fields
114
115
```kotlin
116
import com.google.protobuf.kotlin.*
117
118
fun configureMessage(builder: MyExtendableMessage.Builder) {
119
// Set various extension types
120
builder[userNameExtension] = "john_doe"
121
builder[userAgeExtension] = 25
122
builder[isActiveExtension] = true
123
builder[scoresExtension] = listOf(95, 87, 92)
124
125
// Check what's been set
126
if (userNameExtension in builder) {
127
println("Username: ${builder[userNameExtension]}")
128
}
129
130
if (userAgeExtension in builder) {
131
println("Age: ${builder[userAgeExtension]}")
132
}
133
}
134
135
fun processMessage(message: MyExtendableMessage) {
136
// Safely access extensions
137
val username = if (userNameExtension in message) {
138
message[userNameExtension]
139
} else {
140
"unknown"
141
}
142
143
val age = if (userAgeExtension in message) {
144
message[userAgeExtension]
145
} else {
146
0
147
}
148
149
println("Processing user: $username (age: $age)")
150
}
151
```
152
153
### Extension Field Validation
154
155
```kotlin
156
import com.google.protobuf.kotlin.*
157
158
fun validateExtensions(message: MyExtendableMessage): List<String> {
159
val errors = mutableListOf<String>()
160
161
if (requiredNameExtension !in message) {
162
errors.add("Required name extension is missing")
163
}
164
165
if (emailExtension in message) {
166
val email = message[emailExtension]
167
if (!email.contains("@")) {
168
errors.add("Invalid email format: $email")
169
}
170
}
171
172
if (ageExtension in message) {
173
val age = message[ageExtension]
174
if (age < 0 || age > 150) {
175
errors.add("Invalid age: $age")
176
}
177
}
178
179
return errors
180
}
181
```
182
183
### Builder Pattern with Extensions
184
185
```kotlin
186
import com.google.protobuf.kotlin.*
187
188
class MessageBuilder {
189
private val builder = MyExtendableMessage.newBuilder()
190
191
fun withName(name: String): MessageBuilder {
192
builder[nameExtension] = name
193
return this
194
}
195
196
fun withAge(age: Int): MessageBuilder {
197
builder[ageExtension] = age
198
return this
199
}
200
201
fun withEmail(email: String): MessageBuilder {
202
builder[emailExtension] = email
203
return this
204
}
205
206
fun build(): MyExtendableMessage {
207
// Validation before building
208
require(nameExtension in builder) { "Name is required" }
209
require(ageExtension in builder) { "Age is required" }
210
211
return builder.build()
212
}
213
}
214
215
// Usage
216
val message = MessageBuilder()
217
.withName("Alice")
218
.withAge(30)
219
.withEmail("alice@example.com")
220
.build()
221
```
222
223
### Copying Extensions Between Messages
224
225
```kotlin
226
import com.google.protobuf.kotlin.*
227
228
fun copyExtensions(
229
source: MyExtendableMessage,
230
target: MyExtendableMessage.Builder
231
) {
232
// Copy all known extensions
233
val extensionsToCheck = listOf(
234
nameExtension,
235
ageExtension,
236
emailExtension,
237
isActiveExtension
238
)
239
240
extensionsToCheck.forEach { extension ->
241
if (extension in source) {
242
target[extension] = source[extension]
243
}
244
}
245
}
246
247
// Usage
248
val originalMessage: MyExtendableMessage = // ... some message
249
val newBuilder = MyExtendableMessage.newBuilder()
250
251
copyExtensions(originalMessage, newBuilder)
252
val copiedMessage = newBuilder.build()
253
```
254
255
## Types
256
257
```kotlin { .api }
258
// Imported from Java protobuf library
259
import com.google.protobuf.ExtensionLite
260
import com.google.protobuf.GeneratedMessage.ExtendableMessage
261
import com.google.protobuf.GeneratedMessage.ExtendableBuilder
262
import com.google.protobuf.GeneratedMessage.ExtendableMessageOrBuilder
263
```
264
265
## Notes
266
267
- These operator functions provide Kotlin-idiomatic access to protocol buffer extensions
268
- The `set` operator works only on builders, not on immutable messages
269
- The `get` and `contains` operators work on both messages and builders
270
- Extension fields must be defined in your `.proto` files and generated by the protocol buffer compiler
271
- Type safety is maintained through generic constraints - you cannot assign the wrong type to an extension field
272
- Always check with `contains` (using `in` operator) before accessing optional extensions to avoid exceptions
273
- These operators are commonly used in DSL builders and when working with protocol buffer messages that support extensions