Skip to content

Commit 2e928d7

Browse files
authored
[pigeon] Moves all codec logic to singular custom codec (flutter#6600)
[pigeon] Moves all codec logic to singular custom codec. Also fixes a few small codec related bugs that have cropped up over time. fixes flutter#147454 fixes flutter#147127 fixes flutter#147587 fixes flutter#148065
1 parent 027c7d0 commit 2e928d7

File tree

90 files changed

+4712
-4841
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

90 files changed

+4712
-4841
lines changed

packages/pigeon/CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
## 20.0.0
2+
3+
* Moves all codec logic to single custom codec per file.
4+
* **Breaking Change** Limits the number of total custom types to 126.
5+
* If more than 126 custom types are needed, consider breaking up your definition files.
6+
* Fixes bug that prevented collection subtypes from being added properly.
7+
* [swift] Adds `@unchecked Sendable` to codec method.
8+
* [objc] [cpp] Fixes bug that prevented setting custom header import path.
9+
110
## 19.0.2
211

312
* [kotlin] Adds the `@JvmOverloads` to the `HostApi` setUp method. This prevents the calling Java code from having to provide an empty `String` as Kotlin provides it by default

packages/pigeon/example/app/android/app/src/main/java/io/flutter/plugins/Messages.java

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ ArrayList<Object> toList() {
181181
ArrayList<Object> toListResult = new ArrayList<Object>(4);
182182
toListResult.add(name);
183183
toListResult.add(description);
184-
toListResult.add(code == null ? null : code.index);
184+
toListResult.add(code);
185185
toListResult.add(data);
186186
return toListResult;
187187
}
@@ -193,13 +193,45 @@ ArrayList<Object> toList() {
193193
Object description = __pigeon_list.get(1);
194194
pigeonResult.setDescription((String) description);
195195
Object code = __pigeon_list.get(2);
196-
pigeonResult.setCode(Code.values()[(int) code]);
196+
pigeonResult.setCode((Code) code);
197197
Object data = __pigeon_list.get(3);
198198
pigeonResult.setData((Map<String, String>) data);
199199
return pigeonResult;
200200
}
201201
}
202202

203+
private static class PigeonCodec extends StandardMessageCodec {
204+
public static final PigeonCodec INSTANCE = new PigeonCodec();
205+
206+
private PigeonCodec() {}
207+
208+
@Override
209+
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
210+
switch (type) {
211+
case (byte) 129:
212+
return MessageData.fromList((ArrayList<Object>) readValue(buffer));
213+
case (byte) 130:
214+
Object value = readValue(buffer);
215+
return value == null ? null : Code.values()[(int) value];
216+
default:
217+
return super.readValueOfType(type, buffer);
218+
}
219+
}
220+
221+
@Override
222+
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
223+
if (value instanceof MessageData) {
224+
stream.write(129);
225+
writeValue(stream, ((MessageData) value).toList());
226+
} else if (value instanceof Code) {
227+
stream.write(130);
228+
writeValue(stream, value == null ? null : ((Code) value).index);
229+
} else {
230+
super.writeValue(stream, value);
231+
}
232+
}
233+
}
234+
203235
/** Asynchronous error handling return type for non-nullable API method returns. */
204236
public interface Result<T> {
205237
/** Success case callback method for handling returns. */
@@ -224,33 +256,6 @@ public interface VoidResult {
224256
/** Failure case callback method for handling errors. */
225257
void error(@NonNull Throwable error);
226258
}
227-
228-
private static class ExampleHostApiCodec extends StandardMessageCodec {
229-
public static final ExampleHostApiCodec INSTANCE = new ExampleHostApiCodec();
230-
231-
private ExampleHostApiCodec() {}
232-
233-
@Override
234-
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
235-
switch (type) {
236-
case (byte) 128:
237-
return MessageData.fromList((ArrayList<Object>) readValue(buffer));
238-
default:
239-
return super.readValueOfType(type, buffer);
240-
}
241-
}
242-
243-
@Override
244-
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
245-
if (value instanceof MessageData) {
246-
stream.write(128);
247-
writeValue(stream, ((MessageData) value).toList());
248-
} else {
249-
super.writeValue(stream, value);
250-
}
251-
}
252-
}
253-
254259
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
255260
public interface ExampleHostApi {
256261

@@ -264,7 +269,7 @@ public interface ExampleHostApi {
264269

265270
/** The codec used by ExampleHostApi. */
266271
static @NonNull MessageCodec<Object> getCodec() {
267-
return ExampleHostApiCodec.INSTANCE;
272+
return PigeonCodec.INSTANCE;
268273
}
269274
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
270275
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) {
@@ -382,7 +387,7 @@ public MessageFlutterApi(
382387
/** Public interface for sending reply. */
383388
/** The codec used by MessageFlutterApi. */
384389
static @NonNull MessageCodec<Object> getCodec() {
385-
return new StandardMessageCodec();
390+
return PigeonCodec.INSTANCE;
386391
}
387392

388393
public void flutterMethod(@Nullable String aStringArg, @NonNull Result<String> result) {

packages/pigeon/example/app/android/app/src/main/kotlin/dev/flutter/pigeon_example_app/Messages.g.kt

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -69,38 +69,45 @@ data class MessageData(
6969
fun fromList(__pigeon_list: List<Any?>): MessageData {
7070
val name = __pigeon_list[0] as String?
7171
val description = __pigeon_list[1] as String?
72-
val code = Code.ofRaw(__pigeon_list[2] as Int)!!
72+
val code = __pigeon_list[2] as Code
7373
val data = __pigeon_list[3] as Map<String?, String?>
7474
return MessageData(name, description, code, data)
7575
}
7676
}
7777

7878
fun toList(): List<Any?> {
79-
return listOf<Any?>(
79+
return listOf(
8080
name,
8181
description,
82-
code.raw,
82+
code,
8383
data,
8484
)
8585
}
8686
}
8787

88-
private object ExampleHostApiCodec : StandardMessageCodec() {
88+
private object MessagesPigeonCodec : StandardMessageCodec() {
8989
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
9090
return when (type) {
91-
128.toByte() -> {
91+
129.toByte() -> {
9292
return (readValue(buffer) as? List<Any?>)?.let { MessageData.fromList(it) }
9393
}
94+
130.toByte() -> {
95+
return (readValue(buffer) as Int?)?.let { Code.ofRaw(it) }
96+
}
9497
else -> super.readValueOfType(type, buffer)
9598
}
9699
}
97100

98101
override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
99102
when (value) {
100103
is MessageData -> {
101-
stream.write(128)
104+
stream.write(129)
102105
writeValue(stream, value.toList())
103106
}
107+
is Code -> {
108+
stream.write(130)
109+
writeValue(stream, value.raw)
110+
}
104111
else -> super.writeValue(stream, value)
105112
}
106113
}
@@ -116,7 +123,7 @@ interface ExampleHostApi {
116123

117124
companion object {
118125
/** The codec used by ExampleHostApi. */
119-
val codec: MessageCodec<Any?> by lazy { ExampleHostApiCodec }
126+
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
120127
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
121128
@JvmOverloads
122129
fun setUp(
@@ -136,7 +143,7 @@ interface ExampleHostApi {
136143
channel.setMessageHandler { _, reply ->
137144
val wrapped: List<Any?> =
138145
try {
139-
listOf<Any?>(api.getHostLanguage())
146+
listOf(api.getHostLanguage())
140147
} catch (exception: Throwable) {
141148
wrapError(exception)
142149
}
@@ -159,7 +166,7 @@ interface ExampleHostApi {
159166
val bArg = args[1].let { num -> if (num is Int) num.toLong() else num as Long }
160167
val wrapped: List<Any?> =
161168
try {
162-
listOf<Any?>(api.add(aArg, bArg))
169+
listOf(api.add(aArg, bArg))
163170
} catch (exception: Throwable) {
164171
wrapError(exception)
165172
}
@@ -203,7 +210,7 @@ class MessageFlutterApi(
203210
) {
204211
companion object {
205212
/** The codec used by MessageFlutterApi. */
206-
val codec: MessageCodec<Any?> by lazy { StandardMessageCodec() }
213+
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
207214
}
208215

209216
fun flutterMethod(aStringArg: String?, callback: (Result<String>) -> Unit) {

packages/pigeon/example/app/ios/Runner/Messages.g.swift

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ struct MessageData {
8989
static func fromList(_ __pigeon_list: [Any?]) -> MessageData? {
9090
let name: String? = nilOrValue(__pigeon_list[0])
9191
let description: String? = nilOrValue(__pigeon_list[1])
92-
let code = Code(rawValue: __pigeon_list[2] as! Int)!
92+
let code = __pigeon_list[2] as! Code
9393
let data = __pigeon_list[3] as! [String?: String?]
9494

9595
return MessageData(
@@ -103,46 +103,55 @@ struct MessageData {
103103
return [
104104
name,
105105
description,
106-
code.rawValue,
106+
code,
107107
data,
108108
]
109109
}
110110
}
111-
112-
private class ExampleHostApiCodecReader: FlutterStandardReader {
111+
private class MessagesPigeonCodecReader: FlutterStandardReader {
113112
override func readValue(ofType type: UInt8) -> Any? {
114113
switch type {
115-
case 128:
114+
case 129:
116115
return MessageData.fromList(self.readValue() as! [Any?])
116+
case 130:
117+
var enumResult: Code? = nil
118+
let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int)
119+
if let enumResultAsInt = enumResultAsInt {
120+
enumResult = Code(rawValue: enumResultAsInt)
121+
}
122+
return enumResult
117123
default:
118124
return super.readValue(ofType: type)
119125
}
120126
}
121127
}
122128

123-
private class ExampleHostApiCodecWriter: FlutterStandardWriter {
129+
private class MessagesPigeonCodecWriter: FlutterStandardWriter {
124130
override func writeValue(_ value: Any) {
125131
if let value = value as? MessageData {
126-
super.writeByte(128)
132+
super.writeByte(129)
127133
super.writeValue(value.toList())
134+
} else if let value = value as? Code {
135+
super.writeByte(130)
136+
super.writeValue(value.rawValue)
128137
} else {
129138
super.writeValue(value)
130139
}
131140
}
132141
}
133142

134-
private class ExampleHostApiCodecReaderWriter: FlutterStandardReaderWriter {
143+
private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
135144
override func reader(with data: Data) -> FlutterStandardReader {
136-
return ExampleHostApiCodecReader(data: data)
145+
return MessagesPigeonCodecReader(data: data)
137146
}
138147

139148
override func writer(with data: NSMutableData) -> FlutterStandardWriter {
140-
return ExampleHostApiCodecWriter(data: data)
149+
return MessagesPigeonCodecWriter(data: data)
141150
}
142151
}
143152

144-
class ExampleHostApiCodec: FlutterStandardMessageCodec {
145-
static let shared = ExampleHostApiCodec(readerWriter: ExampleHostApiCodecReaderWriter())
153+
class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
154+
static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter())
146155
}
147156

148157
/// Generated protocol from Pigeon that represents a handler of messages from Flutter.
@@ -154,8 +163,7 @@ protocol ExampleHostApi {
154163

155164
/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
156165
class ExampleHostApiSetup {
157-
/// The codec used by ExampleHostApi.
158-
static var codec: FlutterStandardMessageCodec { ExampleHostApiCodec.shared }
166+
static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared }
159167
/// Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`.
160168
static func setUp(
161169
binaryMessenger: FlutterBinaryMessenger, api: ExampleHostApi?, messageChannelSuffix: String = ""
@@ -228,12 +236,16 @@ class MessageFlutterApi: MessageFlutterApiProtocol {
228236
self.binaryMessenger = binaryMessenger
229237
self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
230238
}
239+
var codec: MessagesPigeonCodec {
240+
return MessagesPigeonCodec.shared
241+
}
231242
func flutterMethod(
232243
aString aStringArg: String?, completion: @escaping (Result<String, PigeonError>) -> Void
233244
) {
234245
let channelName: String =
235246
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod\(messageChannelSuffix)"
236-
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger)
247+
let channel = FlutterBasicMessageChannel(
248+
name: channelName, binaryMessenger: binaryMessenger, codec: codec)
237249
channel.sendMessage([aStringArg] as [Any?]) { response in
238250
guard let listResponse = response as? [Any?] else {
239251
completion(.failure(createConnectionError(withChannelName: channelName)))

packages/pigeon/example/app/lib/src/messages.g.dart

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class MessageData {
5454
return <Object?>[
5555
name,
5656
description,
57-
code.index,
57+
code,
5858
data,
5959
];
6060
}
@@ -64,19 +64,22 @@ class MessageData {
6464
return MessageData(
6565
name: result[0] as String?,
6666
description: result[1] as String?,
67-
code: Code.values[result[2]! as int],
67+
code: result[2]! as Code,
6868
data: (result[3] as Map<Object?, Object?>?)!.cast<String?, String?>(),
6969
);
7070
}
7171
}
7272

73-
class _ExampleHostApiCodec extends StandardMessageCodec {
74-
const _ExampleHostApiCodec();
73+
class _PigeonCodec extends StandardMessageCodec {
74+
const _PigeonCodec();
7575
@override
7676
void writeValue(WriteBuffer buffer, Object? value) {
7777
if (value is MessageData) {
78-
buffer.putUint8(128);
78+
buffer.putUint8(129);
7979
writeValue(buffer, value.encode());
80+
} else if (value is Code) {
81+
buffer.putUint8(130);
82+
writeValue(buffer, value.index);
8083
} else {
8184
super.writeValue(buffer, value);
8285
}
@@ -85,8 +88,11 @@ class _ExampleHostApiCodec extends StandardMessageCodec {
8588
@override
8689
Object? readValueOfType(int type, ReadBuffer buffer) {
8790
switch (type) {
88-
case 128:
91+
case 129:
8992
return MessageData.decode(readValue(buffer)!);
93+
case 130:
94+
final int? value = readValue(buffer) as int?;
95+
return value == null ? null : Code.values[value];
9096
default:
9197
return super.readValueOfType(type, buffer);
9298
}
@@ -104,8 +110,7 @@ class ExampleHostApi {
104110
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
105111
final BinaryMessenger? __pigeon_binaryMessenger;
106112

107-
static const MessageCodec<Object?> pigeonChannelCodec =
108-
_ExampleHostApiCodec();
113+
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
109114

110115
final String __pigeon_messageChannelSuffix;
111116

@@ -198,8 +203,7 @@ class ExampleHostApi {
198203
}
199204

200205
abstract class MessageFlutterApi {
201-
static const MessageCodec<Object?> pigeonChannelCodec =
202-
StandardMessageCodec();
206+
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();
203207

204208
String flutterMethod(String? aString);
205209

0 commit comments

Comments
 (0)