Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pigeon] Moves all codec logic to singular custom codec #6600

Open
wants to merge 43 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
1f2f1f2
add custom codecs
tarrinneal May 6, 2024
932f4f5
fixes bug with headerIncludePath
tarrinneal May 6, 2024
2c80cd7
reorder classes
tarrinneal May 6, 2024
b71a901
Merge branch 'customcodecs' of github.com:tarrinneal/packages into cu…
tarrinneal May 6, 2024
ecb4928
unwrap enums
tarrinneal May 7, 2024
6d69557
wrap case
tarrinneal May 7, 2024
36b86ab
fi unit test
tarrinneal May 8, 2024
f49f1c4
not optional
tarrinneal May 9, 2024
988fad9
comment out failing tests
tarrinneal May 9, 2024
6f78b2f
gen
tarrinneal May 10, 2024
fad35c8
fix kotlin test
tarrinneal May 10, 2024
63f9054
fix c++ and add comments to test files
tarrinneal May 13, 2024
7f47b01
Merge branch 'customcodecs' of github.com:tarrinneal/packages into cu…
tarrinneal May 13, 2024
fa1c0ab
add proxy api changes
tarrinneal May 14, 2024
fea5b9c
fix flutter tests and update generate tool
tarrinneal May 14, 2024
81b0d7d
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal May 14, 2024
7a050dd
update tools
tarrinneal May 14, 2024
cb64c0a
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal May 15, 2024
3800d0e
fix unit tests, and re-add enum tests
tarrinneal May 16, 2024
c7b548b
remove extra test classes
tarrinneal May 16, 2024
6fdadac
update version (assuming other pr lands first)
tarrinneal May 16, 2024
22f7c25
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal May 16, 2024
ed47982
cleanup
tarrinneal May 16, 2024
3dc6c60
remove future work comments
tarrinneal May 16, 2024
eb06884
update error message
tarrinneal May 16, 2024
5c5084b
typo
tarrinneal May 17, 2024
6ddf333
Add test to prevent duplicate entries in Kotlin generator
bc-lee May 18, 2024
7cc9be6
Merge pull request #1 from bc-lee/feature/test-duplicate-entries
tarrinneal May 20, 2024
d16b00b
fix test analyze
tarrinneal May 20, 2024
2c883ca
nits
tarrinneal May 29, 2024
a7113f0
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal May 29, 2024
3393bb8
fix objc import bug
tarrinneal May 29, 2024
426d668
fix bugs I added in nits
tarrinneal May 30, 2024
9f9bc6d
fix unit test
tarrinneal May 30, 2024
a4583be
fix to/from json bug with headerIncludePath
tarrinneal May 30, 2024
e5d340e
test
tarrinneal May 30, 2024
abe92f7
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal May 30, 2024
9d89b85
Sendable
tarrinneal May 30, 2024
b12e6c2
gen
tarrinneal May 30, 2024
0a1b900
add test for nested class list
tarrinneal May 31, 2024
860dd39
nits
tarrinneal May 31, 2024
abf088a
fix nit fix for fixed nit fix fix
tarrinneal May 31, 2024
a4fa5b0
Merge branch 'main' of github.com:flutter/packages into customcodecs
tarrinneal Jun 4, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 9 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
## 20.0.0

* Moves all codec logic to single custom codec per file.
* **Breaking Change** Limits the number of total custom types to 126.
tarrinneal marked this conversation as resolved.
Show resolved Hide resolved
* If more than 126 custom types are needed, consider breaking up your definition files.
* Fixes bug that prevented collection subtypes from being added properly.
* [swift] Adds `@unchecked Sendable` to codec method.
* [objc] [cpp] Fixes bug that prevented setting custom header import path.

## 19.0.2

* [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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ ArrayList<Object> toList() {
ArrayList<Object> toListResult = new ArrayList<Object>(4);
toListResult.add(name);
toListResult.add(description);
toListResult.add(code == null ? null : code.index);
toListResult.add(code);
toListResult.add(data);
return toListResult;
}
Expand All @@ -193,13 +193,45 @@ ArrayList<Object> toList() {
Object description = __pigeon_list.get(1);
pigeonResult.setDescription((String) description);
Object code = __pigeon_list.get(2);
pigeonResult.setCode(Code.values()[(int) code]);
pigeonResult.setCode((Code) code);
Object data = __pigeon_list.get(3);
pigeonResult.setData((Map<String, String>) data);
return pigeonResult;
}
}

private static class PigeonCodec extends StandardMessageCodec {
public static final PigeonCodec INSTANCE = new PigeonCodec();

private PigeonCodec() {}

@Override
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
switch (type) {
case (byte) 129:
return MessageData.fromList((ArrayList<Object>) readValue(buffer));
case (byte) 130:
Object value = readValue(buffer);
return value == null ? null : Code.values()[(int) value];
default:
return super.readValueOfType(type, buffer);
}
}

@Override
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
if (value instanceof MessageData) {
stream.write(129);
writeValue(stream, ((MessageData) value).toList());
} else if (value instanceof Code) {
stream.write(130);
writeValue(stream, value == null ? null : ((Code) value).index);
} else {
super.writeValue(stream, value);
}
}
}

/** Asynchronous error handling return type for non-nullable API method returns. */
public interface Result<T> {
/** Success case callback method for handling returns. */
Expand All @@ -224,33 +256,6 @@ public interface VoidResult {
/** Failure case callback method for handling errors. */
void error(@NonNull Throwable error);
}

private static class ExampleHostApiCodec extends StandardMessageCodec {
public static final ExampleHostApiCodec INSTANCE = new ExampleHostApiCodec();

private ExampleHostApiCodec() {}

@Override
protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
switch (type) {
case (byte) 128:
return MessageData.fromList((ArrayList<Object>) readValue(buffer));
default:
return super.readValueOfType(type, buffer);
}
}

@Override
protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
if (value instanceof MessageData) {
stream.write(128);
writeValue(stream, ((MessageData) value).toList());
} else {
super.writeValue(stream, value);
}
}
}

/** Generated interface from Pigeon that represents a handler of messages from Flutter. */
public interface ExampleHostApi {

Expand All @@ -264,7 +269,7 @@ public interface ExampleHostApi {

/** The codec used by ExampleHostApi. */
static @NonNull MessageCodec<Object> getCodec() {
return ExampleHostApiCodec.INSTANCE;
return PigeonCodec.INSTANCE;
}
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
static void setUp(@NonNull BinaryMessenger binaryMessenger, @Nullable ExampleHostApi api) {
Expand Down Expand Up @@ -382,7 +387,7 @@ public MessageFlutterApi(
/** Public interface for sending reply. */
/** The codec used by MessageFlutterApi. */
static @NonNull MessageCodec<Object> getCodec() {
return new StandardMessageCodec();
return PigeonCodec.INSTANCE;
}

public void flutterMethod(@Nullable String aStringArg, @NonNull Result<String> result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,38 +69,45 @@ data class MessageData(
fun fromList(__pigeon_list: List<Any?>): MessageData {
val name = __pigeon_list[0] as String?
val description = __pigeon_list[1] as String?
val code = Code.ofRaw(__pigeon_list[2] as Int)!!
val code = __pigeon_list[2] as Code
val data = __pigeon_list[3] as Map<String?, String?>
return MessageData(name, description, code, data)
}
}

fun toList(): List<Any?> {
return listOf<Any?>(
return listOf(
name,
description,
code.raw,
code,
data,
)
}
}

private object ExampleHostApiCodec : StandardMessageCodec() {
private object MessagesPigeonCodec : StandardMessageCodec() {
override fun readValueOfType(type: Byte, buffer: ByteBuffer): Any? {
return when (type) {
128.toByte() -> {
129.toByte() -> {
return (readValue(buffer) as? List<Any?>)?.let { MessageData.fromList(it) }
}
130.toByte() -> {
return (readValue(buffer) as Int?)?.let { Code.ofRaw(it) }
}
else -> super.readValueOfType(type, buffer)
}
}

override fun writeValue(stream: ByteArrayOutputStream, value: Any?) {
when (value) {
is MessageData -> {
stream.write(128)
stream.write(129)
writeValue(stream, value.toList())
}
is Code -> {
stream.write(130)
writeValue(stream, value.raw)
}
else -> super.writeValue(stream, value)
}
}
Expand All @@ -116,7 +123,7 @@ interface ExampleHostApi {

companion object {
/** The codec used by ExampleHostApi. */
val codec: MessageCodec<Any?> by lazy { ExampleHostApiCodec }
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
/** Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`. */
@JvmOverloads
fun setUp(
Expand All @@ -136,7 +143,7 @@ interface ExampleHostApi {
channel.setMessageHandler { _, reply ->
val wrapped: List<Any?> =
try {
listOf<Any?>(api.getHostLanguage())
listOf(api.getHostLanguage())
} catch (exception: Throwable) {
wrapError(exception)
}
Expand All @@ -159,7 +166,7 @@ interface ExampleHostApi {
val bArg = args[1].let { num -> if (num is Int) num.toLong() else num as Long }
val wrapped: List<Any?> =
try {
listOf<Any?>(api.add(aArg, bArg))
listOf(api.add(aArg, bArg))
} catch (exception: Throwable) {
wrapError(exception)
}
Expand Down Expand Up @@ -203,7 +210,7 @@ class MessageFlutterApi(
) {
companion object {
/** The codec used by MessageFlutterApi. */
val codec: MessageCodec<Any?> by lazy { StandardMessageCodec() }
val codec: MessageCodec<Any?> by lazy { MessagesPigeonCodec }
}

fun flutterMethod(aStringArg: String?, callback: (Result<String>) -> Unit) {
Expand Down
42 changes: 27 additions & 15 deletions packages/pigeon/example/app/ios/Runner/Messages.g.swift
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ struct MessageData {
static func fromList(_ __pigeon_list: [Any?]) -> MessageData? {
let name: String? = nilOrValue(__pigeon_list[0])
let description: String? = nilOrValue(__pigeon_list[1])
let code = Code(rawValue: __pigeon_list[2] as! Int)!
let code = __pigeon_list[2] as! Code
let data = __pigeon_list[3] as! [String?: String?]

return MessageData(
Expand All @@ -103,46 +103,55 @@ struct MessageData {
return [
name,
description,
code.rawValue,
code,
data,
]
}
}

private class ExampleHostApiCodecReader: FlutterStandardReader {
private class MessagesPigeonCodecReader: FlutterStandardReader {
override func readValue(ofType type: UInt8) -> Any? {
switch type {
case 128:
case 129:
return MessageData.fromList(self.readValue() as! [Any?])
case 130:
var enumResult: Code? = nil
let enumResultAsInt: Int? = nilOrValue(self.readValue() as? Int)
if let enumResultAsInt = enumResultAsInt {
enumResult = Code(rawValue: enumResultAsInt)
}
return enumResult
default:
return super.readValue(ofType: type)
}
}
}

private class ExampleHostApiCodecWriter: FlutterStandardWriter {
private class MessagesPigeonCodecWriter: FlutterStandardWriter {
override func writeValue(_ value: Any) {
if let value = value as? MessageData {
super.writeByte(128)
super.writeByte(129)
super.writeValue(value.toList())
} else if let value = value as? Code {
super.writeByte(130)
super.writeValue(value.rawValue)
} else {
super.writeValue(value)
}
}
}

private class ExampleHostApiCodecReaderWriter: FlutterStandardReaderWriter {
private class MessagesPigeonCodecReaderWriter: FlutterStandardReaderWriter {
override func reader(with data: Data) -> FlutterStandardReader {
return ExampleHostApiCodecReader(data: data)
return MessagesPigeonCodecReader(data: data)
}

override func writer(with data: NSMutableData) -> FlutterStandardWriter {
return ExampleHostApiCodecWriter(data: data)
return MessagesPigeonCodecWriter(data: data)
}
}

class ExampleHostApiCodec: FlutterStandardMessageCodec {
static let shared = ExampleHostApiCodec(readerWriter: ExampleHostApiCodecReaderWriter())
class MessagesPigeonCodec: FlutterStandardMessageCodec, @unchecked Sendable {
static let shared = MessagesPigeonCodec(readerWriter: MessagesPigeonCodecReaderWriter())
}

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

/// Generated setup class from Pigeon to handle messages through the `binaryMessenger`.
class ExampleHostApiSetup {
/// The codec used by ExampleHostApi.
static var codec: FlutterStandardMessageCodec { ExampleHostApiCodec.shared }
static var codec: FlutterStandardMessageCodec { MessagesPigeonCodec.shared }
/// Sets up an instance of `ExampleHostApi` to handle messages through the `binaryMessenger`.
static func setUp(
binaryMessenger: FlutterBinaryMessenger, api: ExampleHostApi?, messageChannelSuffix: String = ""
Expand Down Expand Up @@ -228,12 +236,16 @@ class MessageFlutterApi: MessageFlutterApiProtocol {
self.binaryMessenger = binaryMessenger
self.messageChannelSuffix = messageChannelSuffix.count > 0 ? ".\(messageChannelSuffix)" : ""
}
var codec: MessagesPigeonCodec {
return MessagesPigeonCodec.shared
}
func flutterMethod(
aString aStringArg: String?, completion: @escaping (Result<String, PigeonError>) -> Void
) {
let channelName: String =
"dev.flutter.pigeon.pigeon_example_package.MessageFlutterApi.flutterMethod\(messageChannelSuffix)"
let channel = FlutterBasicMessageChannel(name: channelName, binaryMessenger: binaryMessenger)
let channel = FlutterBasicMessageChannel(
name: channelName, binaryMessenger: binaryMessenger, codec: codec)
channel.sendMessage([aStringArg] as [Any?]) { response in
guard let listResponse = response as? [Any?] else {
completion(.failure(createConnectionError(withChannelName: channelName)))
Expand Down
24 changes: 14 additions & 10 deletions packages/pigeon/example/app/lib/src/messages.g.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class MessageData {
return <Object?>[
name,
description,
code.index,
code,
data,
];
}
Expand All @@ -64,19 +64,22 @@ class MessageData {
return MessageData(
name: result[0] as String?,
description: result[1] as String?,
code: Code.values[result[2]! as int],
code: result[2]! as Code,
data: (result[3] as Map<Object?, Object?>?)!.cast<String?, String?>(),
);
}
}

class _ExampleHostApiCodec extends StandardMessageCodec {
const _ExampleHostApiCodec();
class _PigeonCodec extends StandardMessageCodec {
const _PigeonCodec();
@override
void writeValue(WriteBuffer buffer, Object? value) {
if (value is MessageData) {
buffer.putUint8(128);
buffer.putUint8(129);
writeValue(buffer, value.encode());
} else if (value is Code) {
buffer.putUint8(130);
writeValue(buffer, value.index);
} else {
super.writeValue(buffer, value);
}
Expand All @@ -85,8 +88,11 @@ class _ExampleHostApiCodec extends StandardMessageCodec {
@override
Object? readValueOfType(int type, ReadBuffer buffer) {
switch (type) {
case 128:
case 129:
return MessageData.decode(readValue(buffer)!);
case 130:
final int? value = readValue(buffer) as int?;
return value == null ? null : Code.values[value];
default:
return super.readValueOfType(type, buffer);
}
Expand All @@ -104,8 +110,7 @@ class ExampleHostApi {
messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
final BinaryMessenger? __pigeon_binaryMessenger;

static const MessageCodec<Object?> pigeonChannelCodec =
_ExampleHostApiCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();

final String __pigeon_messageChannelSuffix;

Expand Down Expand Up @@ -198,8 +203,7 @@ class ExampleHostApi {
}

abstract class MessageFlutterApi {
static const MessageCodec<Object?> pigeonChannelCodec =
StandardMessageCodec();
static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();

String flutterMethod(String? aString);

Expand Down