Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
86 commits
Select commit Hold shift + click to select a range
b9b0b5e
kotlin jni impementation
tarrinneal Oct 30, 2025
e599d1e
analyzer
tarrinneal Oct 30, 2025
726975d
test fixes w jetski
tarrinneal Oct 30, 2025
f636cdb
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Nov 6, 2025
72a305e
remove future code
tarrinneal Nov 7, 2025
4e59659
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Nov 11, 2025
e22c55a
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Nov 11, 2025
3f0be1d
Merge remote-tracking branch 'origin/Frillback' into Kamyshin
tarrinneal Jan 20, 2026
0d09615
minor cleanup
tarrinneal Jan 21, 2026
e0f23a9
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Jan 21, 2026
025376c
omit types
tarrinneal Jan 22, 2026
aa01700
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Jan 22, 2026
6a0df05
format
tarrinneal Jan 22, 2026
022ed51
flutter api
tarrinneal Feb 11, 2026
43f2e5a
fix swift optional bug
tarrinneal Feb 12, 2026
5fd46e8
add nullable tests and more sync tests
tarrinneal Feb 12, 2026
a0c56ab
flutter api async methods
tarrinneal Feb 24, 2026
2c252ae
error handling and tests
tarrinneal Feb 25, 2026
5072a47
basic thread tests
tarrinneal Feb 25, 2026
b0cd2ec
fix swftFunction
tarrinneal Feb 26, 2026
38bd37e
add back tests for named/optional params
tarrinneal Feb 26, 2026
850cb2e
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Feb 26, 2026
9bb4bc5
fix const gen adapter classes
tarrinneal Feb 26, 2026
0c7ef63
performance improvements to typedData and isEquals
tarrinneal Feb 27, 2026
110ab70
stuff that I'm going to move to a different branch
tarrinneal Feb 28, 2026
82065a8
Improve efficiency in some methods
tarrinneal Feb 28, 2026
9861c00
analyze this
tarrinneal Feb 28, 2026
11daedd
format
tarrinneal Mar 2, 2026
e197fc0
less repeating, and less listing
tarrinneal Mar 3, 2026
cbf4096
allow individual class types to not have colliding hashes
tarrinneal Mar 3, 2026
935aa47
improve deep equals for non-collections
tarrinneal Mar 3, 2026
4e9541f
allowing for NaN or other cases where identical is better
tarrinneal Mar 3, 2026
f30b44c
more tests, add other languages, unify behavior across platforms
tarrinneal Mar 3, 2026
08a79f3
first pass at gobject
tarrinneal Mar 3, 2026
8cb51ac
Merge branch 'main' of https://github.com/flutter/packages into effic
tarrinneal Mar 3, 2026
ddc41c2
analyze
tarrinneal Mar 3, 2026
4ad3636
delete random extra files
tarrinneal Mar 3, 2026
0a08ef5
fix kotlin generator change that broke unit test
tarrinneal Mar 3, 2026
5855b23
fix broken gobject and cpp code
tarrinneal Mar 4, 2026
f99e64a
more bugs on languages I can't compile locally
tarrinneal Mar 4, 2026
101fb0f
last few issues I hope
tarrinneal Mar 4, 2026
7309d17
not being able to run things locally sucks
tarrinneal Mar 4, 2026
24d0f23
bigobj
tarrinneal Mar 4, 2026
21ad393
consolidate tests
tarrinneal Mar 4, 2026
94a58c8
revert project files
tarrinneal Mar 4, 2026
3fdd987
More consistency across languages
tarrinneal Mar 4, 2026
b920f50
revert -0.0 changes
tarrinneal Mar 4, 2026
7df481e
gen example
tarrinneal Mar 5, 2026
25021e7
Merge branch 'main' of https://github.com/flutter/packages into effic
tarrinneal Mar 5, 2026
4cbfdcd
memecmp
tarrinneal Mar 5, 2026
8c75a36
re-normalize -0.0 in hash methods to create consistent behavior acros…
tarrinneal Mar 5, 2026
655229c
finish tests
tarrinneal Mar 5, 2026
80d8bbc
lints and reverting of accidentally pushed files
tarrinneal Mar 5, 2026
a57dd6f
hopeful test fix
tarrinneal Mar 5, 2026
4ded545
delete file that shouldn't ever have existed
tarrinneal Mar 5, 2026
8698cb5
more tests and windows method rework
tarrinneal Mar 5, 2026
7355a96
bug fixes and more robust map==
tarrinneal Mar 5, 2026
45d8207
fix linix
tarrinneal Mar 5, 2026
ad236e7
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Mar 5, 2026
97b8e8c
one last linux fix
tarrinneal Mar 5, 2026
38cffb2
nits and nats
tarrinneal Mar 6, 2026
ff33669
jnigen config yaml -> dart
tarrinneal Mar 10, 2026
a2a80b5
dentist has been busy today
tarrinneal Mar 11, 2026
b5b4506
Merge branch 'main' of https://github.com/flutter/packages into effic
tarrinneal Mar 11, 2026
1305a1d
fix std::map hash
tarrinneal Mar 11, 2026
a5ce9cc
even more better
tarrinneal Mar 11, 2026
6d92541
Merge branch 'main' of https://github.com/flutter/packages into effic
tarrinneal Mar 11, 2026
eba918b
revert dumb change
tarrinneal Mar 11, 2026
8d55afd
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Mar 11, 2026
5097bdc
namespace
tarrinneal Mar 11, 2026
0a5adee
Triple checked methods
tarrinneal Mar 12, 2026
a3e5531
update to jnigen 16, with some manual changes
tarrinneal Mar 17, 2026
51d7b7c
jni error handling
tarrinneal Mar 18, 2026
9ca1762
remove dead code
tarrinneal Mar 18, 2026
69c20d2
Adds prefixing for classes that will have collisions within the same …
tarrinneal Mar 19, 2026
214299f
remove similar methods and fix datatype methods to avoid poorly shape…
tarrinneal Mar 19, 2026
393c5c8
lock ffi hash
tarrinneal Mar 19, 2026
18f5c23
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Mar 19, 2026
7b8e9ec
reorg ni classes, remove duplicated error handling code
tarrinneal Mar 20, 2026
944a09a
Merge branch 'main' of https://github.com/flutter/packages into Kamyshin
tarrinneal Mar 20, 2026
d4d8f92
fix spm build issues
tarrinneal Mar 20, 2026
88bade6
revert swift messenger changes
tarrinneal Mar 20, 2026
4c90953
revert unintentional proxy api changes
tarrinneal Mar 20, 2026
a5a1593
remove incidental changes and crusty stuff
tarrinneal Mar 20, 2026
09d3960
Merge branch 'effic' into Kamyshin and move some files around
tarrinneal Mar 24, 2026
b9f0e4d
revert command changes and format, add license, update allowed deps
tarrinneal Mar 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ analyzer:
# Ignore generated files
- '**/*.pb.dart'
- '**/*.g.dart'
- '**/*.gen.jni.dart'
- '**/*.gen.ffi.dart'
- '**/*.mocks.dart' # Mockito @GenerateMocks

linter:
Expand Down
6 changes: 6 additions & 0 deletions packages/pigeon/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 26.3.0

* Optimizes and improves data class equality and hashing.
* Changes hashing and equality methods to behave consistently across platforms.
* Adds equality methods to previously unsupported languages.

## 26.2.3

* Produces a helpful error message when a method return type is missing or an
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,171 @@
import java.lang.annotation.Target;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/** Generated class from Pigeon. */
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression", "serial"})
public class Messages {
static boolean pigeonDoubleEquals(double a, double b) {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (a == 0.0 ? 0.0 : a) == (b == 0.0 ? 0.0 : b) || (Double.isNaN(a) && Double.isNaN(b));
}

static boolean pigeonFloatEquals(float a, float b) {
// Normalize -0.0 to 0.0 and handle NaN equality.
return (a == 0.0f ? 0.0f : a) == (b == 0.0f ? 0.0f : b) || (Float.isNaN(a) && Float.isNaN(b));
}

static int pigeonDoubleHashCode(double d) {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
if (d == 0.0) {
d = 0.0;
}
long bits = Double.doubleToLongBits(d);
return (int) (bits ^ (bits >>> 32));
}

static int pigeonFloatHashCode(float f) {
// Normalize -0.0 to 0.0 and handle NaN to ensure consistent hash codes.
if (f == 0.0f) {
f = 0.0f;
}
return Float.floatToIntBits(f);
}

static boolean pigeonDeepEquals(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
if (a instanceof byte[] && b instanceof byte[]) {
return Arrays.equals((byte[]) a, (byte[]) b);
}
if (a instanceof int[] && b instanceof int[]) {
return Arrays.equals((int[]) a, (int[]) b);
}
if (a instanceof long[] && b instanceof long[]) {
return Arrays.equals((long[]) a, (long[]) b);
}
if (a instanceof double[] && b instanceof double[]) {
double[] da = (double[]) a;
double[] db = (double[]) b;
if (da.length != db.length) {
return false;
}
for (int i = 0; i < da.length; i++) {
if (!pigeonDoubleEquals(da[i], db[i])) {
return false;
}
}
return true;
}
if (a instanceof List && b instanceof List) {
List<?> listA = (List<?>) a;
List<?> listB = (List<?>) b;
if (listA.size() != listB.size()) {
return false;
}
for (int i = 0; i < listA.size(); i++) {
if (!pigeonDeepEquals(listA.get(i), listB.get(i))) {
return false;
}
}
return true;
}
if (a instanceof Map && b instanceof Map) {
Map<?, ?> mapA = (Map<?, ?>) a;
Map<?, ?> mapB = (Map<?, ?>) b;
if (mapA.size() != mapB.size()) {
return false;
}
for (Map.Entry<?, ?> entryA : mapA.entrySet()) {
Object keyA = entryA.getKey();
Object valueA = entryA.getValue();
boolean found = false;
for (Map.Entry<?, ?> entryB : mapB.entrySet()) {
Object keyB = entryB.getKey();
if (pigeonDeepEquals(keyA, keyB)) {
Object valueB = entryB.getValue();
if (pigeonDeepEquals(valueA, valueB)) {
found = true;
break;
} else {
return false;
}
}
}
if (!found) {
return false;
}
}
return true;
}
Comment on lines +99 to +126

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The deep equality check for Map instances has a time complexity of O(n^2) due to the nested loops used for comparison. This could lead to significant performance degradation for large maps.

A more performant approach should be considered. For example, if the keys' hashCode and equals methods are consistent with pigeonDeepEquals, you could iterate through one map's entries and perform lookups on the second map, which would be much faster. If that's not a safe assumption, an alternative to the nested loop would be to build a mutable copy of one map's entries and remove them as they are matched. This would reduce the complexity from O(n^2) to O(n) on average, at the cost of higher memory usage.

if (a instanceof Double && b instanceof Double) {
return pigeonDoubleEquals((double) a, (double) b);
}
if (a instanceof Float && b instanceof Float) {
return pigeonFloatEquals((float) a, (float) b);
}
return a.equals(b);
}

static int pigeonDeepHashCode(Object value) {
if (value == null) {
return 0;
}
if (value instanceof byte[]) {
return Arrays.hashCode((byte[]) value);
}
if (value instanceof int[]) {
return Arrays.hashCode((int[]) value);
}
if (value instanceof long[]) {
return Arrays.hashCode((long[]) value);
}
if (value instanceof double[]) {
double[] da = (double[]) value;
int result = 1;
for (double d : da) {
result = 31 * result + pigeonDoubleHashCode(d);
}
return result;
}
if (value instanceof List) {
int result = 1;
for (Object item : (List<?>) value) {
result = 31 * result + pigeonDeepHashCode(item);
}
return result;
}
if (value instanceof Map) {
int result = 0;
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
result +=
((pigeonDeepHashCode(entry.getKey()) * 31) ^ pigeonDeepHashCode(entry.getValue()));
}
return result;
}
if (value instanceof Object[]) {
int result = 1;
for (Object item : (Object[]) value) {
result = 31 * result + pigeonDeepHashCode(item);
}
return result;
}
if (value instanceof Double) {
return pigeonDoubleHashCode((double) value);
}
if (value instanceof Float) {
return pigeonFloatHashCode((float) value);
}
return value.hashCode();
}

/** Error class for passing custom error details to Flutter via a thrown PlatformException. */
public static class FlutterError extends RuntimeException {
Expand Down Expand Up @@ -142,15 +299,16 @@ public boolean equals(Object o) {
return false;
}
MessageData that = (MessageData) o;
return Objects.equals(name, that.name)
&& Objects.equals(description, that.description)
&& code.equals(that.code)
&& data.equals(that.data);
return pigeonDeepEquals(name, that.name)
&& pigeonDeepEquals(description, that.description)
&& pigeonDeepEquals(code, that.code)
&& pigeonDeepEquals(data, that.data);
}

@Override
public int hashCode() {
return Objects.hash(name, description, code, data);
Object[] fields = new Object[] {getClass(), name, description, code, data};
return pigeonDeepHashCode(fields);
}

public static final class Builder {
Expand Down
Loading
Loading