diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md index 7faae37d9..6de5b92dd 100644 --- a/pkgs/jni/CHANGELOG.md +++ b/pkgs/jni/CHANGELOG.md @@ -1,5 +1,14 @@ ## 0.13.0-wip +- **Breaking Change**: Separated primitive arrays from object arrays. + Previously, a primitive array like an array of bytes was typed + `JArray`. Now `JArray` only accepts `JObject`s as types and + primitive arrays like arrays of bytes have their own types such as + `JByteArray`. + + This enables all arrays to implement `Iterable` which makes it possible to use + them in a for-loop or use methods such as `map` on them. + - Added nullable type classes for all Java objects. ## 0.12.2 diff --git a/pkgs/jni/lib/_internal.dart b/pkgs/jni/lib/_internal.dart index 768be191f..9b5ce9aad 100644 --- a/pkgs/jni/lib/_internal.dart +++ b/pkgs/jni/lib/_internal.dart @@ -34,7 +34,6 @@ export 'src/method_invocation.dart'; export 'src/types.dart' show JAccessible, - JArrayElementType, JCallable, JConstructable, JObjType, diff --git a/pkgs/jni/lib/jni.dart b/pkgs/jni/lib/jni.dart index cb069dc21..2ebe0c375 100644 --- a/pkgs/jni/lib/jni.dart +++ b/pkgs/jni/lib/jni.dart @@ -63,6 +63,7 @@ library; export 'package:ffi/ffi.dart' show Arena, using; export 'src/errors.dart'; +export 'src/jarray.dart'; export 'src/jimplementer.dart'; export 'src/jni.dart' hide ProtectedJniExtensions, StringMethodsForJni; export 'src/jobject.dart'; @@ -75,7 +76,6 @@ export 'src/third_party/generated_bindings.dart' export 'src/types.dart' hide JAccessible, - JArrayElementType, JCallable, JConstructable, JObjType, diff --git a/pkgs/jni/lib/src/jarray.dart b/pkgs/jni/lib/src/jarray.dart index 60dca97c1..f3eea8cb8 100644 --- a/pkgs/jni/lib/src/jarray.dart +++ b/pkgs/jni/lib/src/jarray.dart @@ -4,11 +4,22 @@ // ignore_for_file: unnecessary_cast, overridden_fields -part of 'types.dart'; +import 'dart:ffi'; +import 'dart:typed_data'; -final class JArrayNullableType extends JObjType?> { +import 'package:ffi/ffi.dart'; +import 'package:meta/meta.dart'; + +import 'jni.dart'; +import 'jobject.dart'; +import 'jreference.dart'; +import 'third_party/generated_bindings.dart'; +import 'types.dart'; + +final class JArrayNullableType + extends JObjType?> { @internal - final JArrayElementType elementType; + final JObjType elementType; @internal const JArrayNullableType(this.elementType); @@ -20,7 +31,7 @@ final class JArrayNullableType extends JObjType?> { @internal @override JArray? fromReference(JReference reference) => - reference.isNull ? null : JArray.fromReference(elementType, reference); + reference.isNull ? null : JArray.fromReference(elementType, reference); @internal @override @@ -45,9 +56,9 @@ final class JArrayNullableType extends JObjType?> { } } -final class JArrayType extends JObjType> { +final class JArrayType extends JObjType> { @internal - final JArrayElementType elementType; + final JObjType elementType; @internal const JArrayType(this.elementType); @@ -59,7 +70,7 @@ final class JArrayType extends JObjType> { @internal @override JArray fromReference(JReference reference) => - JArray.fromReference(elementType, reference); + JArray.fromReference(elementType, reference); @internal @override @@ -84,26 +95,26 @@ final class JArrayType extends JObjType> { } } -class JArray extends JObject { +class JArray extends JObject with Iterable { @internal - final JArrayElementType elementType; + final JObjType elementType; @internal @override final JArrayType $type; /// The type which includes information such as the signature of this class. - static JArrayType type(JArrayElementType innerType) => - JArrayType(innerType); + static JArrayType type(JObjType innerType) => + JArrayType(innerType); /// The type which includes information such as the signature of this class. - static JArrayNullableType nullableType( - JArrayElementType innerType) => - JArrayNullableType(innerType); + static JArrayNullableType nullableType( + JObjType innerType) => + JArrayNullableType(innerType); /// Construct a new [JArray] with [reference] as its underlying reference. JArray.fromReference(this.elementType, JReference reference) - : $type = type(elementType), + : $type = type(elementType), super.fromReference(reference); /// Creates a [JArray] of the given length from the given [elementType]. @@ -111,15 +122,31 @@ class JArray extends JObject { /// The [length] must be a non-negative integer. /// For objects, [elementType] must be a nullable type as this constructor /// initializes all elements with `null`. - factory JArray(JArrayElementType elementType, int length) { + factory JArray(JObjType elementType, int length) { RangeError.checkNotNegative(length); - if (elementType is JObjType && - !(elementType as JObjType).isNullable) { + if (!elementType.isNullable) { throw StateError('Element type of JArray must be nullable when ' 'all elements with null\n\n' 'Try using .nullableType instead'); } - return elementType._newArray(length); + return _newArray(elementType, length); + } + + static JArray<$E> _newArray<$E extends JObject?>( + JObjType<$E> elementType, int length, + [$E? fill]) { + final classRef = elementType.jClass.reference; + final fillRef = fill?.reference ?? jNullReference; + final array = JArray<$E>.fromReference( + elementType, + JGlobalReference(Jni.env.NewObjectArray( + length, + classRef.pointer, + fillRef.pointer, + )), + ); + classRef.release(); + return array; } /// Creates a [JArray] of the given length with [fill] at each position. @@ -129,29 +156,88 @@ class JArray extends JObject { {JObjType<$E>? E}) { RangeError.checkNotNegative(length); E ??= fill.$type as JObjType<$E>; - return E._newArray(length, fill); + return _newArray<$E>(E, length, fill); } - int? _length; - /// The number of elements in this array. - int get length { - return _length ??= Jni.env.GetArrayLength(reference.pointer); + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + E elementAt(int index) { + RangeError.checkValidIndex(index, this); + final pointer = Jni.env.GetObjectArrayElement(reference.pointer, index); + if (pointer == nullptr) { + return null as E; + } + return (elementType as JObjType) + .fromReference(JGlobalReference(pointer)); + } + + E operator [](int index) { + return elementAt(index); + } + + void operator []=(int index, E value) { + RangeError.checkValidIndex(index, this); + final valueRef = value?.reference ?? jNullReference; + Jni.env.SetObjectArrayElement(reference.pointer, index, valueRef.pointer); + } + + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final it = iterable.skip(skipCount).take(rangeLength); + for (final (index, element) in it.indexed) { + this[index] = element; + } } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension NativeArray on JArray { - void _allocate( - int byteCount, - void Function(Pointer ptr) use, - ) { - using((arena) { - final ptr = arena.allocate(byteCount); - use(ptr); - }, malloc); +class _JArrayIterator implements Iterator { + final Iterable _iterable; + final int _length; + int _index; + E? _current; + + _JArrayIterator(Iterable iterable) + : _iterable = iterable, + _length = iterable.length, + _index = 0; + + @override + E get current => _current as E; + + @override + @pragma('vm:prefer-inline') + bool moveNext() { + final length = _iterable.length; + if (_length != length) { + throw ConcurrentModificationError(_iterable); + } + if (_index >= length) { + _current = null; + return false; + } + _current = _iterable.elementAt(_index); + _index++; + return true; } } +void _allocate( + int byteCount, + void Function(Pointer ptr) use, +) { + using((arena) { + final ptr = arena.allocate(byteCount); + use(ptr); + }, malloc); +} + extension on Allocator { Pointer? get _nativeFree { return switch (this) { @@ -162,12 +248,117 @@ extension on Allocator { } } -extension BoolArray on JArray { - bool operator [](int index) { +final class JBooleanArrayNullableType extends JObjType { + @internal + const JBooleanArrayNullableType(); + + @internal + @override + String get signature => '[Z'; + + @internal + @override + JBooleanArray? fromReference(JReference reference) => + reference.isNull ? null : JBooleanArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JBooleanArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JBooleanArrayNullableType && + other is JBooleanArrayNullableType; + } +} + +final class JBooleanArrayType extends JObjType { + @internal + const JBooleanArrayType(); + + @internal + @override + String get signature => '[Z'; + + @internal + @override + JBooleanArray fromReference(JReference reference) => + JBooleanArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => + const JBooleanArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JBooleanArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JBooleanArrayType && other is JBooleanArrayType; + } +} + +class JBooleanArray extends JObject with Iterable { + @internal + @override + final JBooleanArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JBooleanArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JBooleanArrayNullableType(); + + /// Construct a new [JBooleanArray] with [reference] as its underlying + /// reference. + JBooleanArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JBooleanArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JBooleanArray(int length) { + RangeError.checkNotNegative(length); + return JBooleanArray.fromReference( + JGlobalReference(Jni.env.NewBooleanArray(length)), + ); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + bool elementAt(int index) { RangeError.checkValidIndex(index, this); return Jni.env.GetBooleanArrayElement(reference.pointer, index); } + bool operator [](int index) { + return elementAt(index); + } + void operator []=(int index, bool value) { RangeError.checkValidIndex(index, this); Jni.env.SetBooleanArrayElement(reference.pointer, index, value); @@ -193,92 +384,130 @@ extension BoolArray on JArray { Jni.env.SetBooleanArrayRegion(reference.pointer, start, rangeLength, ptr); }); } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension ByteArray on JArray { - int operator [](int index) { - RangeError.checkValidIndex(index, this); - return Jni.env.GetByteArrayElement(reference.pointer, index); - } +final class JByteArrayNullableType extends JObjType { + @internal + const JByteArrayNullableType(); - void operator []=(int index, int value) { - RangeError.checkValidIndex(index, this); - Jni.env.SetByteArrayElement(reference.pointer, index, value); - } + @internal + @override + String get signature => '[B'; - Int8List getRange(int start, int end, {Allocator allocator = malloc}) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; - final buffer = allocator(rangeLength); - Jni.env.GetByteArrayRegion(reference.pointer, start, rangeLength, buffer); - return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); - } + @internal + @override + JByteArray? fromReference(JReference reference) => + reference.isNull ? null : JByteArray.fromReference(reference); - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; - _allocate(sizeOf() * rangeLength, (ptr) { - ptr - .asTypedList(rangeLength) - .setRange(0, rangeLength, iterable, skipCount); - Jni.env.SetByteArrayRegion(reference.pointer, start, rangeLength, ptr); - }); + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JByteArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JByteArrayNullableType && + other is JByteArrayNullableType; } } -/// `JArray` is a 16-bit integer array. -/// -/// Due to variable length encoding, the number of code units is not equal to -/// the number of characters. -extension CharArray on JArray { - int operator [](int index) { - RangeError.checkValidIndex(index, this); - return Jni.env.GetCharArrayElement(reference.pointer, index); - } +final class JByteArrayType extends JObjType { + @internal + const JByteArrayType(); - void operator []=(int index, int value) { - RangeError.checkValidIndex(index, this); - Jni.env.SetCharArrayElement(reference.pointer, index, value); + @internal + @override + String get signature => '[B'; + + @internal + @override + JByteArray fromReference(JReference reference) => + JByteArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JByteArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JByteArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JByteArrayType && other is JByteArrayType; } +} - Uint16List getRange(int start, int end, {Allocator allocator = malloc}) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; - final buffer = allocator(rangeLength); - Jni.env.GetCharArrayRegion(reference.pointer, start, rangeLength, buffer); - return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); +class JByteArray extends JObject with Iterable { + @internal + @override + final JByteArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JByteArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JByteArrayNullableType(); + + /// Construct a new [JByteArray] with [reference] as its underlying + /// reference. + JByteArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JByteArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JByteArray(int length) { + RangeError.checkNotNegative(length); + return JByteArray.fromReference( + JGlobalReference(Jni.env.NewByteArray(length))); } - void setRange(int start, int end, Iterable iterable, - [int skipCount = 0]) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; - _allocate(sizeOf() * rangeLength, (ptr) { - ptr - .asTypedList(rangeLength) - .setRange(0, rangeLength, iterable, skipCount); - Jni.env.SetCharArrayRegion(reference.pointer, start, rangeLength, ptr); - }); + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + int elementAt(int index) { + RangeError.checkValidIndex(index, this); + return Jni.env.GetByteArrayElement(reference.pointer, index); } -} -extension ShortArray on JArray { int operator [](int index) { - RangeError.checkValidIndex(index, this); - return Jni.env.GetShortArrayElement(reference.pointer, index); + return elementAt(index); } void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - Jni.env.SetShortArrayElement(reference.pointer, index, value); + Jni.env.SetByteArrayElement(reference.pointer, index, value); } - Int16List getRange(int start, int end, {Allocator allocator = malloc}) { + Int8List getRange(int start, int end, {Allocator allocator = malloc}) { RangeError.checkValidRange(start, end, length); final rangeLength = end - start; - final buffer = allocator(rangeLength); - Jni.env.GetShortArrayRegion(reference.pointer, start, rangeLength, buffer); + final buffer = allocator(rangeLength); + Jni.env.GetByteArrayRegion(reference.pointer, start, rangeLength, buffer); return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); } @@ -286,29 +515,415 @@ extension ShortArray on JArray { [int skipCount = 0]) { RangeError.checkValidRange(start, end, length); final rangeLength = end - start; - _allocate(sizeOf() * rangeLength, (ptr) { + _allocate(sizeOf() * rangeLength, (ptr) { ptr .asTypedList(rangeLength) .setRange(0, rangeLength, iterable, skipCount); - Jni.env.SetShortArrayRegion(reference.pointer, start, rangeLength, ptr); + Jni.env.SetByteArrayRegion(reference.pointer, start, rangeLength, ptr); }); } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension IntArray on JArray { - int operator [](int index) { - RangeError.checkValidIndex(index, this); - return Jni.env.GetIntArrayElement(reference.pointer, index); - } +final class JCharArrayNullableType extends JObjType { + @internal + const JCharArrayNullableType(); - void operator []=(int index, int value) { - RangeError.checkValidIndex(index, this); - Jni.env.SetIntArrayElement(reference.pointer, index, value); - } + @internal + @override + String get signature => '[C'; - Int32List getRange(int start, int end, {Allocator allocator = malloc}) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; + @internal + @override + JCharArray? fromReference(JReference reference) => + reference.isNull ? null : JCharArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JCharArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JCharArrayNullableType && + other is JCharArrayNullableType; + } +} + +final class JCharArrayType extends JObjType { + @internal + const JCharArrayType(); + + @internal + @override + String get signature => '[C'; + + @internal + @override + JCharArray fromReference(JReference reference) => + JCharArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JCharArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JCharArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JCharArrayType && other is JCharArrayType; + } +} + +/// `JCharArray` is a 16-bit integer array. +/// +/// Due to variable length encoding, the number of code units is not equal to +/// the number of characters. +class JCharArray extends JObject with Iterable { + @internal + @override + final JCharArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JCharArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JCharArrayNullableType(); + + /// Construct a new [JCharArray] with [reference] as its underlying + /// reference. + JCharArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JCharArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JCharArray(int length) { + RangeError.checkNotNegative(length); + return JCharArray.fromReference( + JGlobalReference(Jni.env.NewCharArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + int elementAt(int index) { + RangeError.checkValidIndex(index, this); + return Jni.env.GetCharArrayElement(reference.pointer, index); + } + + int operator [](int index) { + return elementAt(index); + } + + void operator []=(int index, int value) { + RangeError.checkValidIndex(index, this); + Jni.env.SetCharArrayElement(reference.pointer, index, value); + } + + Uint16List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator(rangeLength); + Jni.env.GetCharArrayRegion(reference.pointer, start, rangeLength, buffer); + return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); + } + + void setRange(int start, int end, Iterable iterable, + [int skipCount = 0]) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetCharArrayRegion(reference.pointer, start, rangeLength, ptr); + }); + } + + @override + Iterator get iterator => _JArrayIterator(this); +} + +final class JShortArrayNullableType extends JObjType { + @internal + const JShortArrayNullableType(); + + @internal + @override + String get signature => '[S'; + + @internal + @override + JShortArray? fromReference(JReference reference) => + reference.isNull ? null : JShortArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JShortArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JShortArrayNullableType && + other is JShortArrayNullableType; + } +} + +final class JShortArrayType extends JObjType { + @internal + const JShortArrayType(); + + @internal + @override + String get signature => '[S'; + + @internal + @override + JShortArray fromReference(JReference reference) => + JShortArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JShortArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JShortArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JShortArrayType && other is JShortArrayType; + } +} + +class JShortArray extends JObject with Iterable { + @internal + @override + final JShortArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JShortArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JShortArrayNullableType(); + + /// Construct a new [JShortArray] with [reference] as its underlying + /// reference. + JShortArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JShortArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JShortArray(int length) { + RangeError.checkNotNegative(length); + return JShortArray.fromReference( + JGlobalReference(Jni.env.NewShortArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + int elementAt(int index) { + RangeError.checkValidIndex(index, this); + return Jni.env.GetShortArrayElement(reference.pointer, index); + } + + int operator [](int index) { + return elementAt(index); + } + + void operator []=(int index, int value) { + RangeError.checkValidIndex(index, this); + Jni.env.SetShortArrayElement(reference.pointer, index, value); + } + + Int16List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator(rangeLength); + Jni.env.GetShortArrayRegion(reference.pointer, start, rangeLength, buffer); + return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); + } + + void setRange(int start, int end, Iterable iterable, + [int skipCount = 0]) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetShortArrayRegion(reference.pointer, start, rangeLength, ptr); + }); + } + + @override + Iterator get iterator => _JArrayIterator(this); +} + +final class JIntArrayNullableType extends JObjType { + @internal + const JIntArrayNullableType(); + + @internal + @override + String get signature => '[I'; + + @internal + @override + JIntArray? fromReference(JReference reference) => + reference.isNull ? null : JIntArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JIntArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JIntArrayNullableType && + other is JIntArrayNullableType; + } +} + +final class JIntArrayType extends JObjType { + @internal + const JIntArrayType(); + + @internal + @override + String get signature => '[I'; + + @internal + @override + JIntArray fromReference(JReference reference) => + JIntArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JIntArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JIntArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JIntArrayType && other is JIntArrayType; + } +} + +class JIntArray extends JObject with Iterable { + @internal + @override + final JIntArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JIntArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JIntArrayNullableType(); + + /// Construct a new [JIntArray] with [reference] as its underlying + /// reference. + JIntArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JIntArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JIntArray(int length) { + RangeError.checkNotNegative(length); + return JIntArray.fromReference( + JGlobalReference(Jni.env.NewIntArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + int elementAt(int index) { + RangeError.checkValidIndex(index, this); + return Jni.env.GetIntArrayElement(reference.pointer, index); + } + + int operator [](int index) { + return elementAt(index); + } + + void operator []=(int index, int value) { + RangeError.checkValidIndex(index, this); + Jni.env.SetIntArrayElement(reference.pointer, index, value); + } + + Int32List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; final buffer = allocator(rangeLength); Jni.env.GetIntArrayRegion(reference.pointer, start, rangeLength, buffer); return buffer.asTypedList(rangeLength, finalizer: allocator._nativeFree); @@ -325,14 +940,120 @@ extension IntArray on JArray { Jni.env.SetIntArrayRegion(reference.pointer, start, rangeLength, ptr); }); } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension LongArray on JArray { - int operator [](int index) { +final class JLongArrayNullableType extends JObjType { + @internal + const JLongArrayNullableType(); + + @internal + @override + String get signature => '[J'; + + @internal + @override + JLongArray? fromReference(JReference reference) => + reference.isNull ? null : JLongArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JLongArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JLongArrayNullableType && + other is JLongArrayNullableType; + } +} + +final class JLongArrayType extends JObjType { + @internal + const JLongArrayType(); + + @internal + @override + String get signature => '[J'; + + @internal + @override + JLongArray fromReference(JReference reference) => + JLongArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JLongArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JLongArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JLongArrayType && other is JLongArrayType; + } +} + +class JLongArray extends JObject with Iterable { + @internal + @override + final JLongArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JLongArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JLongArrayNullableType(); + + /// Construct a new [JLongArray] with [reference] as its underlying + /// reference. + JLongArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JLongArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JLongArray(int length) { + RangeError.checkNotNegative(length); + return JLongArray.fromReference( + JGlobalReference(Jni.env.NewLongArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + int elementAt(int index) { RangeError.checkValidIndex(index, this); return Jni.env.GetLongArrayElement(reference.pointer, index); } + int operator [](int index) { + return elementAt(index); + } + void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); Jni.env.SetLongArrayElement(reference.pointer, index, value); @@ -357,14 +1078,120 @@ extension LongArray on JArray { Jni.env.SetLongArrayRegion(reference.pointer, start, rangeLength, ptr); }); } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension FloatArray on JArray { - double operator [](int index) { +final class JFloatArrayNullableType extends JObjType { + @internal + const JFloatArrayNullableType(); + + @internal + @override + String get signature => '[F'; + + @internal + @override + JFloatArray? fromReference(JReference reference) => + reference.isNull ? null : JFloatArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JFloatArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JFloatArrayNullableType && + other is JFloatArrayNullableType; + } +} + +final class JFloatArrayType extends JObjType { + @internal + const JFloatArrayType(); + + @internal + @override + String get signature => '[F'; + + @internal + @override + JFloatArray fromReference(JReference reference) => + JFloatArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JFloatArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JFloatArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JFloatArrayType && other is JFloatArrayType; + } +} + +class JFloatArray extends JObject with Iterable { + @internal + @override + final JFloatArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JFloatArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JFloatArrayNullableType(); + + /// Construct a new [JFloatArray] with [reference] as its underlying + /// reference. + JFloatArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JFloatArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JFloatArray(int length) { + RangeError.checkNotNegative(length); + return JFloatArray.fromReference( + JGlobalReference(Jni.env.NewFloatArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + double elementAt(int index) { RangeError.checkValidIndex(index, this); return Jni.env.GetFloatArrayElement(reference.pointer, index); } + double operator [](int index) { + return elementAt(index); + } + void operator []=(int index, double value) { RangeError.checkValidIndex(index, this); Jni.env.SetFloatArrayElement(reference.pointer, index, value); @@ -389,14 +1216,120 @@ extension FloatArray on JArray { Jni.env.SetFloatArrayRegion(reference.pointer, start, rangeLength, ptr); }); } + + @override + Iterator get iterator => _JArrayIterator(this); } -extension DoubleArray on JArray { - double operator [](int index) { +final class JDoubleArrayNullableType extends JObjType { + @internal + const JDoubleArrayNullableType(); + + @internal + @override + String get signature => '[D'; + + @internal + @override + JDoubleArray? fromReference(JReference reference) => + reference.isNull ? null : JDoubleArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectNullableType(); + + @internal + @override + JObjType get nullableType => this; + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JDoubleArrayNullableType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JDoubleArrayNullableType && + other is JDoubleArrayNullableType; + } +} + +final class JDoubleArrayType extends JObjType { + @internal + const JDoubleArrayType(); + + @internal + @override + String get signature => '[D'; + + @internal + @override + JDoubleArray fromReference(JReference reference) => + JDoubleArray.fromReference(reference); + + @internal + @override + JObjType get superType => const JObjectType(); + + @internal + @override + JObjType get nullableType => const JDoubleArrayNullableType(); + + @internal + @override + final int superCount = 1; + + @override + int get hashCode => (JDoubleArrayType).hashCode; + + @override + bool operator ==(Object other) { + return other.runtimeType == JDoubleArrayType && other is JDoubleArrayType; + } +} + +class JDoubleArray extends JObject with Iterable { + @internal + @override + final JDoubleArrayType $type; + + /// The type which includes information such as the signature of this class. + static const type = JDoubleArrayType(); + + /// The type which includes information such as the signature of this class. + static const nullableType = JDoubleArrayNullableType(); + + /// Construct a new [JDoubleArray] with [reference] as its underlying + /// reference. + JDoubleArray.fromReference(super.reference) + : $type = type, + super.fromReference(); + + /// Creates a [JDoubleArray] of the given [length]. + /// + /// The [length] must be a non-negative integer. + factory JDoubleArray(int length) { + RangeError.checkNotNegative(length); + return JDoubleArray.fromReference( + JGlobalReference(Jni.env.NewDoubleArray(length))); + } + + /// The number of elements in this array. + @override + late final length = Jni.env.GetArrayLength(reference.pointer); + + @override + double elementAt(int index) { RangeError.checkValidIndex(index, this); return Jni.env.GetDoubleArrayElement(reference.pointer, index); } + double operator [](int index) { + return elementAt(index); + } + void operator []=(int index, double value) { RangeError.checkValidIndex(index, this); Jni.env.SetDoubleArrayElement(reference.pointer, index, value); @@ -421,31 +1354,7 @@ extension DoubleArray on JArray { Jni.env.SetDoubleArrayRegion(reference.pointer, start, rangeLength, ptr); }); } -} - -extension ObjectArray on JArray { - T operator [](int index) { - RangeError.checkValidIndex(index, this); - final pointer = Jni.env.GetObjectArrayElement(reference.pointer, index); - if (pointer == nullptr) { - return null as T; - } - return (elementType as JObjType) - .fromReference(JGlobalReference(pointer)); - } - - void operator []=(int index, T value) { - RangeError.checkValidIndex(index, this); - final valueRef = value?.reference ?? jNullReference; - Jni.env.SetObjectArrayElement(reference.pointer, index, valueRef.pointer); - } - void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { - RangeError.checkValidRange(start, end, length); - final rangeLength = end - start; - final it = iterable.skip(skipCount).take(rangeLength); - for (final (index, element) in it.indexed) { - this[index] = element; - } - } + @override + Iterator get iterator => _JArrayIterator(this); } diff --git a/pkgs/jni/lib/src/jprimitives.dart b/pkgs/jni/lib/src/jprimitives.dart index 7e0997120..c63210e96 100644 --- a/pkgs/jni/lib/src/jprimitives.dart +++ b/pkgs/jni/lib/src/jprimitives.dart @@ -15,10 +15,7 @@ abstract final class jbyte extends JPrimitive { } final class jbyteType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jbyteType(); @@ -57,14 +54,6 @@ final class jbyteType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, int val) { return Jni.env.SetStaticByteField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewByteArray(length)), - ); - } } abstract final class jboolean extends JPrimitive { @@ -72,10 +61,7 @@ abstract final class jboolean extends JPrimitive { } final class jbooleanType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jbooleanType(); @@ -114,14 +100,6 @@ final class jbooleanType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, bool val) { return Jni.env.SetStaticBooleanField(clazz, fieldID, val ? 1 : 0); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewBooleanArray(length)), - ); - } } abstract final class jchar extends JPrimitive { @@ -129,10 +107,7 @@ abstract final class jchar extends JPrimitive { } final class jcharType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jcharType(); @@ -171,14 +146,6 @@ final class jcharType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, int val) { return Jni.env.SetStaticCharField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewCharArray(length)), - ); - } } abstract final class jshort extends JPrimitive { @@ -186,10 +153,7 @@ abstract final class jshort extends JPrimitive { } final class jshortType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jshortType(); @@ -228,14 +192,6 @@ final class jshortType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, int val) { return Jni.env.SetStaticShortField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewShortArray(length)), - ); - } } abstract final class jint extends JPrimitive { @@ -243,7 +199,7 @@ abstract final class jint extends JPrimitive { } final class jintType extends JType - with JCallable, JAccessible, JArrayElementType { + with JCallable, JAccessible { @internal const jintType(); @@ -281,14 +237,6 @@ final class jintType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, int val) { return Jni.env.SetStaticIntField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewIntArray(length)), - ); - } } abstract final class jlong extends JPrimitive { @@ -296,10 +244,7 @@ abstract final class jlong extends JPrimitive { } final class jlongType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jlongType(); @@ -337,14 +282,6 @@ final class jlongType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, int val) { return Jni.env.SetStaticLongField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewLongArray(length)), - ); - } } abstract final class jfloat extends JPrimitive { @@ -352,10 +289,7 @@ abstract final class jfloat extends JPrimitive { } final class jfloatType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jfloatType(); @@ -394,14 +328,6 @@ final class jfloatType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, double val) { return Jni.env.SetStaticFloatField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewFloatArray(length)), - ); - } } abstract final class jdouble extends JPrimitive { @@ -409,10 +335,7 @@ abstract final class jdouble extends JPrimitive { } final class jdoubleType extends JType - with - JCallable, - JAccessible, - JArrayElementType { + with JCallable, JAccessible { @internal const jdoubleType(); @@ -451,14 +374,6 @@ final class jdoubleType extends JType void _staticSet(JClassPtr clazz, JFieldIDPtr fieldID, double val) { return Jni.env.SetStaticDoubleField(clazz, fieldID, val); } - - @override - JArray _newArray(int length) { - return JArray.fromReference( - this, - JGlobalReference(Jni.env.NewDoubleArray(length)), - ); - } } abstract final class jvoid extends JPrimitive { diff --git a/pkgs/jni/lib/src/method_invocation.dart b/pkgs/jni/lib/src/method_invocation.dart index 9c42237d9..8c1f47170 100644 --- a/pkgs/jni/lib/src/method_invocation.dart +++ b/pkgs/jni/lib/src/method_invocation.dart @@ -6,11 +6,11 @@ import 'dart:ffi'; import 'package:meta/meta.dart' show internal; +import 'jarray.dart'; import 'jobject.dart'; import 'jreference.dart'; import 'lang/jstring.dart'; import 'third_party/generated_bindings.dart'; -import 'types.dart'; @internal class MethodInvocation { diff --git a/pkgs/jni/lib/src/nio/jbyte_buffer.dart b/pkgs/jni/lib/src/nio/jbyte_buffer.dart index b0154d68c..5251c5c6a 100644 --- a/pkgs/jni/lib/src/nio/jbyte_buffer.dart +++ b/pkgs/jni/lib/src/nio/jbyte_buffer.dart @@ -7,6 +7,7 @@ import 'dart:typed_data'; import 'package:meta/meta.dart' show internal; +import '../jarray.dart'; import '../jni.dart'; import '../jobject.dart'; import '../jreference.dart'; @@ -184,7 +185,7 @@ class JByteBuffer extends JBuffer { /// modifications to the buffer will cause the array to be modified /// and vice versa. static JByteBuffer wrap( - JArray array, [ + JByteArray array, [ int? offset, int? length, ]) { @@ -268,8 +269,8 @@ class JByteBuffer extends JBuffer { static final _arrayId = _class.instanceMethodId(r'array', r'()[B'); @override - JArray get array { - return _arrayId(this, const JArrayType(jbyteType()), [])!; + JByteArray get array { + return _arrayId(this, JByteArray.type, [])!; } void _ensureIsDirect() { diff --git a/pkgs/jni/lib/src/types.dart b/pkgs/jni/lib/src/types.dart index 5b0bf2781..466e825b8 100644 --- a/pkgs/jni/lib/src/types.dart +++ b/pkgs/jni/lib/src/types.dart @@ -2,9 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -import 'dart:ffi'; -import 'dart:typed_data'; - import 'package:ffi/ffi.dart'; import '../_internal.dart'; @@ -13,7 +10,6 @@ import 'jobject.dart'; import 'jvalues.dart'; import 'third_party/generated_bindings.dart'; -part 'jarray.dart'; part 'jclass.dart'; part 'jprimitives.dart'; @@ -49,12 +45,6 @@ mixin JAccessible on JType { void _instanceSet(JObjectPtr obj, JFieldIDPtr fieldID, DartT val); } -/// Able to be the type of array elements. -@internal -mixin JArrayElementType on JType { - JArray _newArray(int length); -} - /// Only used for jnigen. /// /// Makes constructing objects easier inside the generated bindings by allowing @@ -80,11 +70,7 @@ final class _ReferenceType extends JType @internal abstract class JObjType extends JType - with - JCallable, - JConstructable, - JAccessible, - JArrayElementType { + with JCallable, JConstructable, JAccessible { /// Number of super types. Distance to the root type. int get superCount; @@ -147,22 +133,6 @@ abstract class JObjType extends JType final valRef = val?.reference ?? jNullReference; Jni.env.SetStaticObjectField(clazz, fieldID, valRef.pointer); } - - @override - JArray _newArray(int length, [T? fill]) { - final classRef = jClass.reference; - final fillRef = fill?.reference ?? jNullReference; - final array = JArray.fromReference( - this, - JGlobalReference(Jni.env.NewObjectArray( - length, - classRef.pointer, - fillRef.pointer, - )), - ); - classRef.release(); - return array; - } } /// Lowest common ancestor of two types in the inheritance tree. diff --git a/pkgs/jni/test/jarray_test.dart b/pkgs/jni/test/jarray_test.dart index d62184562..d64b7353a 100644 --- a/pkgs/jni/test/jarray_test.dart +++ b/pkgs/jni/test/jarray_test.dart @@ -22,7 +22,13 @@ void main() { void run({required TestRunnerCallback testRunner}) { testRunner('Java boolean array', () { using((arena) { - final array = JArray(jboolean.type, 3)..releasedBy(arena); + final array = JBooleanArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = true; array[1] = false; @@ -58,7 +64,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java char array', () { using((arena) { - final array = JArray(jchar.type, 3)..releasedBy(arena); + final array = JCharArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 1; array[1] = 2; @@ -94,7 +106,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java byte array', () { using((arena) { - final array = JArray(jbyte.type, 3)..releasedBy(arena); + final array = JByteArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 1; array[1] = 2; @@ -130,7 +148,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java short array', () { using((arena) { - final array = JArray(jshort.type, 3)..releasedBy(arena); + final array = JShortArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 1; array[1] = 2; @@ -166,7 +190,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java int array', () { using((arena) { - final array = JArray(jint.type, 3)..releasedBy(arena); + final array = JIntArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 1; array[1] = 2; @@ -202,7 +232,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java long array', () { using((arena) { - final array = JArray(jlong.type, 3)..releasedBy(arena); + final array = JLongArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 1; array[1] = 2; @@ -239,7 +275,13 @@ void run({required TestRunnerCallback testRunner}) { const epsilon = 1e-6; testRunner('Java float array', () { using((arena) { - final array = JArray(jfloat.type, 3)..releasedBy(arena); + final array = JFloatArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 0.5; array[1] = 2; @@ -275,7 +317,13 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java double array', () { using((arena) { - final array = JArray(jdouble.type, 3)..releasedBy(arena); + final array = JDoubleArray(3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 0.5; array[1] = 2; @@ -312,6 +360,12 @@ void run({required TestRunnerCallback testRunner}) { testRunner('Java string array', () { using((arena) { final array = JArray(JString.nullableType, 3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); array[0] = 'حس'.toJString()..releasedBy(arena); array[1] = '\$'.toJString()..releasedBy(arena); @@ -347,6 +401,12 @@ void run({required TestRunnerCallback testRunner}) { testRunner('Java object array', () { using((arena) { final array = JArray(JObject.nullableType, 3)..releasedBy(arena); + var counter = 0; + for (final element in array) { + expect(element, array[counter]); + ++counter; + } + expect(counter, array.length); expect(array.length, 3); expect(array[0], isNull); expect(array[1], isNull); @@ -355,12 +415,11 @@ void run({required TestRunnerCallback testRunner}) { }); testRunner('Java 2d array', () { using((arena) { - final array = JArray(jint.type, 3)..releasedBy(arena); + final array = JIntArray(3)..releasedBy(arena); array[0] = 1; array[1] = 2; array[2] = 3; - final twoDimArray = JArray(JArray.nullableType(jint.type), 3) - ..releasedBy(arena); + final twoDimArray = JArray(JIntArray.nullableType, 3)..releasedBy(arena); expect(twoDimArray.length, 3); twoDimArray[0] = array; twoDimArray[1] = array; diff --git a/pkgs/jni/test/jbyte_buffer_test.dart b/pkgs/jni/test/jbyte_buffer_test.dart index a26126d73..666479dcb 100644 --- a/pkgs/jni/test/jbyte_buffer_test.dart +++ b/pkgs/jni/test/jbyte_buffer_test.dart @@ -32,7 +32,7 @@ void run({required TestRunnerCallback testRunner}) { testRunner('wrap whole array', () { using((arena) { - final array = JArray(jbyte.type, 3)..releasedBy(arena); + final array = JByteArray(3)..releasedBy(arena); array[0] = 1; array[1] = 2; array[2] = 3; @@ -43,7 +43,7 @@ void run({required TestRunnerCallback testRunner}) { testRunner('wrap partial array', () { using((arena) { - final array = JArray(jbyte.type, 3)..releasedBy(arena); + final array = JByteArray(3)..releasedBy(arena); array[0] = 1; array[1] = 2; array[2] = 3; diff --git a/pkgs/jni/test/type_test.dart b/pkgs/jni/test/type_test.dart index 333945946..2182281ac 100644 --- a/pkgs/jni/test/type_test.dart +++ b/pkgs/jni/test/type_test.dart @@ -4,7 +4,6 @@ import 'package:jni/_internal.dart'; import 'package:jni/jni.dart'; -import 'package:jni/src/types.dart'; import 'package:test/test.dart'; import 'test_util/test_util.dart'; @@ -452,7 +451,7 @@ void run({required TestRunnerCallback testRunner}) { expect(lowestCommonSuperType([JString.type]), JString.type); expect(lowestCommonSuperType([JObject.type, JObject.type]), JObject.type); expect(lowestCommonSuperType([JString.type, JString.type]), JString.type); - expect(lowestCommonSuperType([JString.type, JArray.type(jlong.type)]), + expect(lowestCommonSuperType([JString.type, JArray.type(JString.type)]), JObject.type); }); @@ -490,10 +489,10 @@ void run({required TestRunnerCallback testRunner}) { using((arena) { expect( lowestCommonSuperType([ - JArray.type(jint.type), - JArray.type(jint.type), + JIntArray.type, + JIntArray.type, ]), - JArray.type(jint.type), + JIntArray.type, ); expect( lowestCommonSuperType([ @@ -505,7 +504,7 @@ void run({required TestRunnerCallback testRunner}) { expect( lowestCommonSuperType([ JArray.type(JObject.type), - JArray.type(jint.type), + JIntArray.type, ]), JObject.type, ); diff --git a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart index 0a3c445e2..4e10e9804 100644 --- a/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart +++ b/pkgs/jnigen/example/pdfbox_plugin/lib/src/third_party/org/apache/pdfbox/pdmodel/PDDocument.dart @@ -1565,7 +1565,7 @@ class PDDocument extends jni$_.JObject { ///@throws InvalidPasswordException If the PDF required a non-empty password. ///@throws IOException In case of a reading or parsing error. static PDDocument? load$12( - jni$_.JArray? input, + jni$_.JByteArray? input, ) { final _$input = input?.reference ?? jni$_.jNullReference; return _load$12(_class.reference.pointer, _id_load$12 as jni$_.JMethodIDPtr, @@ -1605,7 +1605,7 @@ class PDDocument extends jni$_.JObject { ///@throws InvalidPasswordException If the password is incorrect. ///@throws IOException In case of a reading or parsing error. static PDDocument? load$13( - jni$_.JArray? input, + jni$_.JByteArray? input, jni$_.JString? password, ) { final _$input = input?.reference ?? jni$_.jNullReference; @@ -1653,7 +1653,7 @@ class PDDocument extends jni$_.JObject { ///@throws InvalidPasswordException If the password is incorrect. ///@throws IOException In case of a reading or parsing error. static PDDocument? load$14( - jni$_.JArray? input, + jni$_.JByteArray? input, jni$_.JString? password, jni$_.JObject? keyStore, jni$_.JString? alias, @@ -1713,7 +1713,7 @@ class PDDocument extends jni$_.JObject { ///@throws InvalidPasswordException If the password is incorrect. ///@throws IOException In case of a reading or parsing error. static PDDocument? load$15( - jni$_.JArray? input, + jni$_.JByteArray? input, jni$_.JString? password, jni$_.JObject? keyStore, jni$_.JString? alias, diff --git a/pkgs/jnigen/lib/src/bindings/dart_generator.dart b/pkgs/jnigen/lib/src/bindings/dart_generator.dart index afa9d7363..56c88d772 100644 --- a/pkgs/jnigen/lib/src/bindings/dart_generator.dart +++ b/pkgs/jnigen/lib/src/bindings/dart_generator.dart @@ -733,6 +733,9 @@ class _TypeGenerator extends TypeVisitor { includeNullability: true, arrayType: true, ); + if (innerType.kind == Kind.primitive) { + return '$_jni.J${innerType.accept(typeGenerator)}Array$nullable'; + } return '$_jArray<${innerType.accept(typeGenerator)}>$nullable'; } @@ -785,7 +788,7 @@ class _TypeGenerator extends TypeVisitor { @override String visitPrimitiveType(PrimitiveType node) { if (arrayType) { - return '$_jni.j${node.name}'; + return node.name.capitalize(); } return node.dartType; } @@ -886,6 +889,12 @@ class _TypeClassGenerator extends TypeVisitor<_TypeClass> { final ifConst = innerTypeClass.canBeConst && isConst ? 'const ' : ''; final type = includeNullability && node.isNullable ? 'NullableType' : 'Type'; + if (node.elementType.kind == Kind.primitive) { + return _TypeClass( + '$ifConst$_jni.J${innerType}Array$type()', + innerTypeClass.canBeConst, + ); + } return _TypeClass( '$ifConst$_jArray$type<$innerType>(${innerTypeClass.name})', innerTypeClass.canBeConst, diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart index 71d30a020..65477c199 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonFactory.dart @@ -1953,7 +1953,7 @@ class JsonFactory extends jni$_.JObject { /// the contents of given byte array. ///@since 2.1 jsonparser$_.JsonParser? createParser$4( - jni$_.JArray? data, + jni$_.JByteArray? data, ) { final _$data = data?.reference ?? jni$_.jNullReference; return _createParser$4(reference.pointer, @@ -1992,7 +1992,7 @@ class JsonFactory extends jni$_.JObject { ///@param len Length of contents to parse within buffer ///@since 2.1 jsonparser$_.JsonParser? createParser$5( - jni$_.JArray? data, + jni$_.JByteArray? data, int offset, int len, ) { @@ -2062,7 +2062,7 @@ class JsonFactory extends jni$_.JObject { /// contents of given char array. ///@since 2.4 jsonparser$_.JsonParser? createParser$7( - jni$_.JArray? content, + jni$_.JCharArray? content, ) { final _$content = content?.reference ?? jni$_.jNullReference; return _createParser$7(reference.pointer, @@ -2097,7 +2097,7 @@ class JsonFactory extends jni$_.JObject { /// Method for constructing parser for parsing contents of given char array. ///@since 2.4 jsonparser$_.JsonParser? createParser$8( - jni$_.JArray? content, + jni$_.JCharArray? content, int offset, int len, ) { @@ -2653,7 +2653,7 @@ class JsonFactory extends jni$_.JObject { ///@throws JsonParseException if parser initialization fails due to content decoding problem ///@deprecated Since 2.2, use \#createParser(byte[]) instead. jsonparser$_.JsonParser? createJsonParser$4( - jni$_.JArray? data, + jni$_.JByteArray? data, ) { final _$data = data?.reference ?? jni$_.jNullReference; return _createJsonParser$4(reference.pointer, @@ -2695,7 +2695,7 @@ class JsonFactory extends jni$_.JObject { ///@throws JsonParseException if parser initialization fails due to content decoding problem ///@deprecated Since 2.2, use \#createParser(byte[],int,int) instead. jsonparser$_.JsonParser? createJsonParser$5( - jni$_.JArray? data, + jni$_.JByteArray? data, int offset, int len, ) { diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart index d4cf58115..3f5e313c1 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonParser.dart @@ -643,7 +643,7 @@ class JsonParser extends jni$_.JObject { ///@param charset Character encoding for (lazily) decoding payload ///@since 2.8 void setRequestPayloadOnError$1( - jni$_.JArray? payload, + jni$_.JByteArray? payload, jni$_.JString? charset, ) { final _$payload = payload?.reference ?? jni$_.jNullReference; @@ -2780,11 +2780,10 @@ class JsonParser extends jni$_.JObject { /// at offset 0, and not necessarily until the end of buffer) ///@throws IOException for low-level read issues, or /// JsonParseException for decoding problems - jni$_.JArray? getTextCharacters() { + jni$_.JCharArray? getTextCharacters() { return _getTextCharacters( reference.pointer, _id_getTextCharacters as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jcharType())); + .object(const jni$_.JCharArrayNullableType()); } static final _id_getTextLength = _class.instanceMethodId( @@ -3432,14 +3431,13 @@ class JsonParser extends jni$_.JObject { ///@return Decoded binary data ///@throws IOException for low-level read issues, or /// JsonParseException for decoding problems - jni$_.JArray? getBinaryValue( + jni$_.JByteArray? getBinaryValue( jni$_.JObject? bv, ) { final _$bv = bv?.reference ?? jni$_.jNullReference; return _getBinaryValue(reference.pointer, _id_getBinaryValue as jni$_.JMethodIDPtr, _$bv.pointer) - .object?>( - const jni$_.JArrayNullableType(jni$_.jbyteType())); + .object(const jni$_.JByteArrayNullableType()); } static final _id_getBinaryValue$1 = _class.instanceMethodId( @@ -3468,11 +3466,10 @@ class JsonParser extends jni$_.JObject { ///@return Decoded binary data ///@throws IOException for low-level read issues, or /// JsonParseException for decoding problems - jni$_.JArray? getBinaryValue$1() { + jni$_.JByteArray? getBinaryValue$1() { return _getBinaryValue$1( reference.pointer, _id_getBinaryValue$1 as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jbyteType())); + .object(const jni$_.JByteArrayNullableType()); } static final _id_readBinaryValue = _class.instanceMethodId( diff --git a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart index 88f09cde7..45e61549d 100644 --- a/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart +++ b/pkgs/jnigen/test/jackson_core_test/third_party/bindings/com/fasterxml/jackson/core/JsonToken.dart @@ -191,11 +191,10 @@ class JsonToken extends jni$_.JObject { /// from: `public final char[] asCharArray()` /// The returned object must be released after use, by calling the [release] method. - jni$_.JArray? asCharArray() { + jni$_.JCharArray? asCharArray() { return _asCharArray( reference.pointer, _id_asCharArray as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jcharType())); + .object(const jni$_.JCharArrayNullableType()); } static final _id_asByteArray = _class.instanceMethodId( @@ -217,11 +216,10 @@ class JsonToken extends jni$_.JObject { /// from: `public final byte[] asByteArray()` /// The returned object must be released after use, by calling the [release] method. - jni$_.JArray? asByteArray() { + jni$_.JByteArray? asByteArray() { return _asByteArray( reference.pointer, _id_asByteArray as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jbyteType())); + .object(const jni$_.JByteArrayNullableType()); } static final _id_isNumeric = _class.instanceMethodId( diff --git a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart index c51518b81..0e7178234 100644 --- a/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart +++ b/pkgs/jnigen/test/simple_package_test/bindings/simple_package.dart @@ -1452,7 +1452,7 @@ class Example extends jni$_.JObject { void methodWithSeveralParams<$T extends jni$_.JObject?>( int c, jni$_.JString? string, - jni$_.JArray? is$, + jni$_.JIntArray? is$, $T? charSequence, jni$_.JList<$T?>? list, jni$_.JMap? map, { @@ -1691,10 +1691,9 @@ class Example extends jni$_.JObject { /// from: `static public int[] getArr()` /// The returned object must be released after use, by calling the [release] method. - static jni$_.JArray? getArr() { + static jni$_.JIntArray? getArr() { return _getArr(_class.reference.pointer, _id_getArr as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jintType())); + .object(const jni$_.JIntArrayNullableType()); } static final _id_addAll = _class.staticMethodId( @@ -1715,7 +1714,7 @@ class Example extends jni$_.JObject { /// from: `static public int addAll(int[] is)` static int addAll( - jni$_.JArray? is$, + jni$_.JIntArray? is$, ) { final _$is$ = is$?.reference ?? jni$_.jNullReference; return _addAll(_class.reference.pointer, _id_addAll as jni$_.JMethodIDPtr, @@ -2177,11 +2176,10 @@ class Exceptions extends jni$_.JObject { /// from: `static public int[] staticIntArrayMethod()` /// The returned object must be released after use, by calling the [release] method. - static jni$_.JArray? staticIntArrayMethod() { + static jni$_.JIntArray? staticIntArrayMethod() { return _staticIntArrayMethod(_class.reference.pointer, _id_staticIntArrayMethod as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jintType())); + .object(const jni$_.JIntArrayNullableType()); } static final _id_objectMethod = _class.instanceMethodId( @@ -2278,11 +2276,10 @@ class Exceptions extends jni$_.JObject { /// from: `public int[] intArrayMethod()` /// The returned object must be released after use, by calling the [release] method. - jni$_.JArray? intArrayMethod() { + jni$_.JIntArray? intArrayMethod() { return _intArrayMethod( reference.pointer, _id_intArrayMethod as jni$_.JMethodIDPtr) - .object?>( - const jni$_.JArrayNullableType(jni$_.jintType())); + .object(const jni$_.JIntArrayNullableType()); } static final _id_throwNullPointerException = _class.instanceMethodId(