diff --git a/pkgs/jni/CHANGELOG.md b/pkgs/jni/CHANGELOG.md index 7186b632d8..5d61684eff 100644 --- a/pkgs/jni/CHANGELOG.md +++ b/pkgs/jni/CHANGELOG.md @@ -1,6 +1,12 @@ ## 0.9.0-wip -- No changes yet. +- **Breaking Change** + ([#1004](https://github.com/dart-lang/native/issues/1004)): Changed the return + type `operator []` of `JArray` to `int` instead of `String`. Similarly, + change the argument type of `operator []=` to accept `int`. +- Added `getRange` method to `JArray` of primitive types that returns a + `TypedData` list depending on the kind of the array. +- Improved the performance of `JArray`'s `setRange` and `operator []=`. ## 0.8.0 diff --git a/pkgs/jni/lib/src/jarray.dart b/pkgs/jni/lib/src/jarray.dart index 3404ceb495..ea368adf85 100644 --- a/pkgs/jni/lib/src/jarray.dart +++ b/pkgs/jni/lib/src/jarray.dart @@ -5,6 +5,7 @@ // ignore_for_file: unnecessary_cast, overridden_fields import 'dart:ffi'; +import 'dart:typed_data'; import 'package:collection/collection.dart'; import 'package:ffi/ffi.dart'; @@ -131,16 +132,26 @@ class JArray extends JObject { extension NativeArray on JArray { void _allocate( - int size, + int byteCount, void Function(Pointer ptr) use, ) { using((arena) { - final ptr = arena.allocate(size); + final ptr = arena.allocate(byteCount); use(ptr); }, malloc); } } +extension on Allocator { + Pointer? get _nativeFree { + return switch (this) { + malloc => malloc.nativeFree, + calloc => calloc.nativeFree, + _ => null, + }; + } +} + extension BoolArray on JArray { bool operator [](int index) { return _elementAt(index, JniCallType.booleanType).boolean; @@ -148,22 +159,30 @@ extension BoolArray on JArray { void operator []=(int index, bool value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value ? 1 : 0; - Jni.env.SetBooleanArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors + .setBooleanArrayElement(reference.pointer, index, value ? 1 : 0); + } + + Uint8List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator + .allocate(sizeOf() * rangeLength); + Jni.env + .GetBooleanArrayRegion(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 size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { + final rangeLength = end - start; + final it = iterable.skip(skipCount).take(rangeLength); + _allocate(sizeOf() * rangeLength, (ptr) { it.forEachIndexed((index, element) { ptr[index] = element ? 1 : 0; }); - Jni.env.SetBooleanArrayRegion(reference.pointer, start, size, ptr); + Jni.env.SetBooleanArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -175,51 +194,61 @@ extension ByteArray on JArray { void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetByteArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setByteArrayElement(reference.pointer, index, value).check(); + } + + 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); } void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { RangeError.checkValidRange(start, end, length); - final size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetByteArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetByteArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } +/// `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 { - String operator [](int index) { - return String.fromCharCode( - _elementAt(index, JniCallType.charType).char, - ); + int operator [](int index) { + return _elementAt(index, JniCallType.charType).char; } - void operator []=(int index, String value) { + void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value.codeUnits.first; - Jni.env.SetCharArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setCharArrayElement(reference.pointer, index, value).check(); + } + + 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, + void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { RangeError.checkValidRange(start, end, length); - final size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element.codeUnits.first; - }); - Jni.env.SetCharArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetCharArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -231,22 +260,26 @@ extension ShortArray on JArray { void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetShortArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setShortArrayElement(reference.pointer, index, value).check(); + } + + 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 size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetShortArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetShortArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -258,22 +291,26 @@ extension IntArray on JArray { void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetIntArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setIntArrayElement(reference.pointer, index, value).check(); + } + + 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); } void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { RangeError.checkValidRange(start, end, length); - final size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetIntArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetIntArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -285,22 +322,26 @@ extension LongArray on JArray { void operator []=(int index, int value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetLongArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setLongArrayElement(reference.pointer, index, value).check(); + } + + Int64List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator(rangeLength); + Jni.env.GetLongArrayRegion(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 size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetLongArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetLongArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -312,22 +353,26 @@ extension FloatArray on JArray { void operator []=(int index, double value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetFloatArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors.setFloatArrayElement(reference.pointer, index, value).check(); + } + + Float32List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator(rangeLength); + Jni.env.GetFloatArrayRegion(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 size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetFloatArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetFloatArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -339,22 +384,28 @@ extension DoubleArray on JArray { void operator []=(int index, double value) { RangeError.checkValidIndex(index, this); - _allocate(sizeOf(), (ptr) { - ptr.value = value; - Jni.env.SetDoubleArrayRegion(reference.pointer, index, 1, ptr); - }); + Jni.accessors + .setDoubleArrayElement(reference.pointer, index, value) + .check(); + } + + Float64List getRange(int start, int end, {Allocator allocator = malloc}) { + RangeError.checkValidRange(start, end, length); + final rangeLength = end - start; + final buffer = allocator(rangeLength); + Jni.env.GetDoubleArrayRegion(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 size = end - start; - final it = iterable.skip(skipCount).take(size); - _allocate(sizeOf() * size, (ptr) { - it.forEachIndexed((index, element) { - ptr[index] = element; - }); - Jni.env.SetDoubleArrayRegion(reference.pointer, start, size, ptr); + final rangeLength = end - start; + _allocate(sizeOf() * rangeLength, (ptr) { + ptr + .asTypedList(rangeLength) + .setRange(0, rangeLength, iterable, skipCount); + Jni.env.SetDoubleArrayRegion(reference.pointer, start, rangeLength, ptr); }); } } @@ -373,8 +424,8 @@ extension ObjectArray on JArray { void setRange(int start, int end, Iterable iterable, [int skipCount = 0]) { RangeError.checkValidRange(start, end, length); - final size = end - start; - final it = iterable.skip(skipCount).take(size); + final rangeLength = end - start; + final it = iterable.skip(skipCount).take(rangeLength); it.forEachIndexed((index, element) { this[index] = element; }); diff --git a/pkgs/jni/lib/src/third_party/global_env_extensions.dart b/pkgs/jni/lib/src/third_party/global_env_extensions.dart index 2a909ec712..a878f5a2b7 100644 --- a/pkgs/jni/lib/src/third_party/global_env_extensions.dart +++ b/pkgs/jni/lib/src/third_party/global_env_extensions.dart @@ -1491,6 +1491,49 @@ class JniAccessors { JniResult getArrayElement(JArrayPtr array, int index, int type) => _getArrayElement(array, index, type); + late final _setBooleanArrayElement = ptr.ref.setBooleanArrayElement + .asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setBooleanArrayElement(JArrayPtr array, int index, int value) => + _setBooleanArrayElement(array, index, value); + + late final _setByteArrayElement = ptr.ref.setByteArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setByteArrayElement(JArrayPtr array, int index, int value) => + _setByteArrayElement(array, index, value); + + late final _setShortArrayElement = ptr.ref.setShortArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setShortArrayElement(JArrayPtr array, int index, int value) => + _setShortArrayElement(array, index, value); + + late final _setCharArrayElement = ptr.ref.setCharArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setCharArrayElement(JArrayPtr array, int index, int value) => + _setCharArrayElement(array, index, value); + + late final _setIntArrayElement = ptr.ref.setIntArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setIntArrayElement(JArrayPtr array, int index, int value) => + _setIntArrayElement(array, index, value); + + late final _setLongArrayElement = ptr.ref.setLongArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, int value)>(); + JThrowablePtr setLongArrayElement(JArrayPtr array, int index, int value) => + _setLongArrayElement(array, index, value); + + late final _setFloatArrayElement = ptr.ref.setFloatArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, double value)>(); + JThrowablePtr setFloatArrayElement( + JArrayPtr array, int index, double value) => + _setFloatArrayElement(array, index, value); + + late final _setDoubleArrayElement = ptr.ref.setDoubleArrayElement.asFunction< + JThrowablePtr Function(JArrayPtr array, int index, double value)>(); + JThrowablePtr setDoubleArrayElement( + JArrayPtr array, int index, double value) => + _setDoubleArrayElement(array, index, value); + late final _callMethod = ptr.ref.callMethod.asFunction< JniResult Function(JObjectPtr obj, JMethodIDPtr methodID, int callType, ffi.Pointer args)>(); diff --git a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart index a575c812f6..2c81d990ce 100644 --- a/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart +++ b/pkgs/jni/lib/src/third_party/jni_bindings_generated.dart @@ -442,6 +442,54 @@ final class JniAccessorsStruct extends ffi.Struct { JniResult Function(JArrayPtr array, ffi.Int index, ffi.Int type)>> getArrayElement; + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JBooleanMarker value)>> + setBooleanArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JByteMarker value)>> + setByteArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JShortMarker value)>> + setShortArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JCharMarker value)>> + setCharArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JIntMarker value)>> + setIntArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JLongMarker value)>> + setLongArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JFloatMarker value)>> + setFloatArrayElement; + + external ffi.Pointer< + ffi.NativeFunction< + JThrowablePtr Function( + JArrayPtr array, ffi.Int index, JDoubleMarker value)>> + setDoubleArrayElement; + external ffi.Pointer< ffi.NativeFunction< JniResult Function(JObjectPtr obj, JMethodIDPtr methodID, diff --git a/pkgs/jni/src/dartjni.c b/pkgs/jni/src/dartjni.c index 0c2bff26e3..0213a4f46d 100644 --- a/pkgs/jni/src/dartjni.c +++ b/pkgs/jni/src/dartjni.c @@ -517,6 +517,62 @@ JniResult getArrayElement(jarray array, int index, int type) { return jniResult; } +jthrowable setBooleanArrayElement(jarray array, int index, jboolean value) { + attach_thread(); + (*jniEnv)->SetBooleanArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setByteArrayElement(jarray array, int index, jbyte value) { + attach_thread(); + (*jniEnv)->SetByteArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setShortArrayElement(jarray array, int index, jshort value) { + attach_thread(); + (*jniEnv)->SetShortArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setCharArrayElement(jarray array, int index, jchar value) { + attach_thread(); + (*jniEnv)->SetCharArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setIntArrayElement(jarray array, int index, jint value) { + attach_thread(); + (*jniEnv)->SetIntArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setLongArrayElement(jarray array, int index, jlong value) { + attach_thread(); + (*jniEnv)->SetLongArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setFloatArrayElement(jarray array, int index, jfloat value) { + attach_thread(); + (*jniEnv)->SetFloatArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + +jthrowable setDoubleArrayElement(jarray array, int index, jdouble value) { + attach_thread(); + (*jniEnv)->SetDoubleArrayRegion(jniEnv, array, index, 1, &value); + jthrowable exception = check_exception(); + return exception; +} + JniExceptionDetails getExceptionDetails(jthrowable exception) { JniExceptionDetails details; details.message = (*jniEnv)->CallObjectMethod( @@ -552,6 +608,14 @@ JniAccessorsStruct accessors = { .newPrimitiveArray = newPrimitiveArray, .newObjectArray = newObjectArray, .getArrayElement = getArrayElement, + .setBooleanArrayElement = setBooleanArrayElement, + .setByteArrayElement = setByteArrayElement, + .setShortArrayElement = setShortArrayElement, + .setCharArrayElement = setCharArrayElement, + .setIntArrayElement = setIntArrayElement, + .setLongArrayElement = setLongArrayElement, + .setFloatArrayElement = setFloatArrayElement, + .setDoubleArrayElement = setDoubleArrayElement, .callMethod = callMethod, .callStaticMethod = callStaticMethod, .getField = getField, diff --git a/pkgs/jni/src/dartjni.h b/pkgs/jni/src/dartjni.h index f834d1577b..4ba8badb2e 100644 --- a/pkgs/jni/src/dartjni.h +++ b/pkgs/jni/src/dartjni.h @@ -228,6 +228,14 @@ typedef struct JniAccessorsStruct { jclass elementClass, jobject initialElement); JniResult (*getArrayElement)(jarray array, int index, int type); + jthrowable (*setBooleanArrayElement)(jarray array, int index, jboolean value); + jthrowable (*setByteArrayElement)(jarray array, int index, jbyte value); + jthrowable (*setShortArrayElement)(jarray array, int index, jshort value); + jthrowable (*setCharArrayElement)(jarray array, int index, jchar value); + jthrowable (*setIntArrayElement)(jarray array, int index, jint value); + jthrowable (*setLongArrayElement)(jarray array, int index, jlong value); + jthrowable (*setFloatArrayElement)(jarray array, int index, jfloat value); + jthrowable (*setDoubleArrayElement)(jarray array, int index, jdouble value); JniResult (*callMethod)(jobject obj, jmethodID methodID, int callType, @@ -343,29 +351,6 @@ static inline jobject to_global_ref(jobject ref) { return g; } -// These functions are useful for C+Dart bindings, and not required for pure dart bindings. - -FFI_PLUGIN_EXPORT JniContext* GetJniContextPtr(); - -/// For use by jni_gen's generated code -/// don't use these. - -// these 2 fn ptr vars will be defined by generated code library -extern JniContext* (*context_getter)(void); -extern JNIEnv* (*env_getter)(void); - -// this function will be exported by generated code library -// it will set above 2 variables. -FFI_PLUGIN_EXPORT void setJniGetters(struct JniContext* (*cg)(void), - JNIEnv* (*eg)(void)); - -static inline void load_env() { - if (jniEnv == NULL) { - jni = context_getter(); - jniEnv = env_getter(); - } -} - static inline jthrowable check_exception() { jthrowable exception = (*jniEnv)->ExceptionOccurred(jniEnv); if (exception != NULL) (*jniEnv)->ExceptionClear(jniEnv); diff --git a/pkgs/jni/test/jarray_test.dart b/pkgs/jni/test/jarray_test.dart index fd4d119068..233ff5d9d0 100644 --- a/pkgs/jni/test/jarray_test.dart +++ b/pkgs/jni/test/jarray_test.dart @@ -2,6 +2,7 @@ // 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:io'; import 'package:jni/jni.dart'; @@ -29,6 +30,17 @@ void run({required TestRunnerCallback testRunner}) { expect(array[0], true); expect(array[1], false); expect(array[2], false); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 0); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [false, true, true, true], 1); expect(array[0], true); expect(array[1], true); @@ -48,24 +60,35 @@ void run({required TestRunnerCallback testRunner}) { using((arena) { final array = JArray(jchar.type, 3)..releasedBy(arena); expect(array.length, 3); - array[0] = 'ح'; - array[1] = '2'; - array[2] = '3'; - expect(array[0], 'ح'); - expect(array[1], '2'); - expect(array[2], '3'); - array.setRange(0, 3, ['4', '5', '6', '7'], 1); - expect(array[0], '5'); - expect(array[1], '6'); - expect(array[2], '7'); + array[0] = 1; + array[1] = 2; + array[2] = 3 + 256 * 256 * 5; // Truncates the input. + expect(array[0], 1); + expect(array[1], 2); + expect(array[2], 3); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 2); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); + array.setRange(0, 3, [4, 5, 6, 7], 1); + expect(array[0], 5); + expect(array[1], 6); + expect(array[2], 7); expect(() { final _ = array[-1]; }, throwsRangeError); expect(() { - array[-1] = '4'; + array[-1] = 4; }, throwsRangeError); expect(() { - array[3] = '4'; + array[3] = 4; }, throwsRangeError); }); }); @@ -75,10 +98,21 @@ void run({required TestRunnerCallback testRunner}) { expect(array.length, 3); array[0] = 1; array[1] = 2; - array[2] = 3 + 256 * 5; // truncates the input; + array[2] = 3 + 256 * 5; // Truncates the input.; expect(array[0], 1); expect(array[1], 2); expect(array[2], 3); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 2); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], 5); expect(array[1], 6); @@ -100,10 +134,21 @@ void run({required TestRunnerCallback testRunner}) { expect(array.length, 3); array[0] = 1; array[1] = 2; - array[2] = 3 + 256 * 256 * 5; // truncates the input + array[2] = 3 + 256 * 256 * 5; // Truncates the input. expect(array[0], 1); expect(array[1], 2); expect(array[2], 3); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 2); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], 5); expect(array[1], 6); @@ -125,10 +170,21 @@ void run({required TestRunnerCallback testRunner}) { expect(array.length, 3); array[0] = 1; array[1] = 2; - array[2] = 3 + 256 * 256 * 256 * 256 * 5; // truncates the input + array[2] = 3 + 256 * 256 * 256 * 256 * 5; // Truncates the input. expect(array[0], 1); expect(array[1], 2); expect(array[2], 3); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 2); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], 5); expect(array[1], 6); @@ -154,6 +210,17 @@ void run({required TestRunnerCallback testRunner}) { expect(array[0], 1); expect(array[1], 2); expect(array[2], 3 + 256 * 256 * 256 * 256 * 5); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], 1); + expect(firstTwo[1], 2); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], 5); expect(array[1], 6); @@ -180,6 +247,17 @@ void run({required TestRunnerCallback testRunner}) { expect(array[0], closeTo(0.5, epsilon)); expect(array[1], closeTo(2, epsilon)); expect(array[2], closeTo(3, epsilon)); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], closeTo(0.5, epsilon)); + expect(firstTwo[1], closeTo(2, epsilon)); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], closeTo(5, epsilon)); expect(array[1], closeTo(6, epsilon)); @@ -205,6 +283,17 @@ void run({required TestRunnerCallback testRunner}) { expect(array[0], closeTo(0.5, epsilon)); expect(array[1], closeTo(2, epsilon)); expect(array[2], closeTo(3, epsilon)); + final firstTwo = array.getRange(0, 2); + expect(firstTwo.length, 2); + expect(firstTwo.elementSizeInBytes, sizeOf()); + expect(firstTwo[0], closeTo(0.5, epsilon)); + expect(firstTwo[1], closeTo(2, epsilon)); + expect(() { + array.getRange(0, 4); + }, throwsRangeError); + expect(() { + array.setRange(0, 4, []); + }, throwsRangeError); array.setRange(0, 3, [4, 5, 6, 7], 1); expect(array[0], closeTo(5, epsilon)); expect(array[1], closeTo(6, epsilon));