diff --git a/lib/src/web/bindings.dart b/lib/src/web/bindings.dart deleted file mode 100644 index d4a1b76..0000000 --- a/lib/src/web/bindings.dart +++ /dev/null @@ -1,188 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:indexed_db'; -import 'dart:js'; - -import 'package:isar/isar.dart'; -import 'package:js/js.dart'; -import 'package:js/js_util.dart'; - -@JS('JSON.stringify') -external String stringify(dynamic value); - -@JS('indexedDB.cmp') -external int idbCmp(dynamic value1, dynamic value2); - -@JS('Object.keys') -external List objectKeys(dynamic obj); - -Map jsMapToDart(Object obj) { - final keys = objectKeys(obj); - final map = {}; - for (final key in keys) { - map[key] = getProperty(obj, key); - } - return map; -} - -@JS('Promise') -class Promise {} - -extension PromiseX on Promise { - Future wait() => promiseToFuture(this); -} - -@JS('openIsar') -external Promise openIsarJs( - String name, - List schemas, - bool relaxedDurability, -); - -@JS('IsarTxn') -class IsarTxnJs { - external Promise commit(); - - external void abort(); - - external bool get write; -} - -@JS('IsarInstance') -class IsarInstanceJs { - external IsarTxnJs beginTxn(bool write); - - external IsarCollectionJs getCollection(String name); - - external Promise close(bool deleteFromDisk); -} - -typedef ChangeCallbackJs = void Function(); - -typedef ObjectChangeCallbackJs = void Function(Object? object); - -typedef QueryChangeCallbackJs = void Function(List results); - -typedef StopWatchingJs = JsFunction; - -@JS('IsarCollection') -class IsarCollectionJs { - external IsarLinkJs getLink(String name); - - external Promise getAll(IsarTxnJs txn, List ids); - - external Promise getAllByIndex( - IsarTxnJs txn, - String indexName, - List> values, - ); - - external Promise putAll(IsarTxnJs txn, List objects); - - external Promise deleteAll(IsarTxnJs txn, List ids); - - external Promise deleteAllByIndex( - IsarTxnJs txn, - String indexName, - List keys, - ); - - external Promise clear(IsarTxnJs txn); - - external StopWatchingJs watchLazy(ChangeCallbackJs callback); - - external StopWatchingJs watchObject(Id id, ObjectChangeCallbackJs callback); - - external StopWatchingJs watchQuery( - QueryJs query, - QueryChangeCallbackJs callback, - ); - - external StopWatchingJs watchQueryLazy( - QueryJs query, - ChangeCallbackJs callback, - ); -} - -@JS('IsarLink') -class IsarLinkJs { - external Promise update( - IsarTxnJs txn, - bool backlink, - Id id, - List addedTargets, - List deletedTargets, - ); - - external Promise clear(IsarTxnJs txn, Id id, bool backlink); -} - -@JS('IdWhereClause') -@anonymous -class IdWhereClauseJs { - external KeyRange? range; -} - -@JS('IndexWhereClause') -@anonymous -class IndexWhereClauseJs { - external String indexName; - external KeyRange? range; -} - -@JS('LinkWhereClause') -@anonymous -class LinkWhereClauseJs { - external String linkCollection; - external String linkName; - external bool backlink; - external Id id; -} - -@JS('Function') -class FilterJs { - external FilterJs(String id, String obj, String method); -} - -@JS('Function') -class SortCmpJs { - external SortCmpJs(String a, String b, String method); -} - -@JS('Function') -class DistinctValueJs { - external DistinctValueJs(String obj, String method); -} - -@JS('IsarQuery') -class QueryJs { - external QueryJs( - IsarCollectionJs collection, - List whereClauses, - bool whereDistinct, - bool whereAscending, - FilterJs? filter, - SortCmpJs? sortCmp, - DistinctValueJs? distinctValue, - int? offset, - int? limit, - ); - - external Promise findFirst(IsarTxnJs txn); - - external Promise findAll(IsarTxnJs txn); - - external Promise deleteFirst(IsarTxnJs txn); - - external Promise deleteAll(IsarTxnJs txn); - - external Promise min(IsarTxnJs txn, String propertyName); - - external Promise max(IsarTxnJs txn, String propertyName); - - external Promise sum(IsarTxnJs txn, String propertyName); - - external Promise average(IsarTxnJs txn, String propertyName); - - external Promise count(IsarTxnJs txn); -} diff --git a/lib/src/web/isar_collection_impl.dart b/lib/src/web/isar_collection_impl.dart deleted file mode 100644 index d89ad69..0000000 --- a/lib/src/web/isar_collection_impl.dart +++ /dev/null @@ -1,266 +0,0 @@ -// ignore_for_file: public_member_api_docs, invalid_use_of_protected_member - -import 'dart:async'; -import 'dart:convert'; -import 'dart:js'; -import 'dart:js_util'; -import 'dart:typed_data'; - -import 'package:isar/isar.dart'; -import 'package:isar/src/web/bindings.dart'; -import 'package:isar/src/web/isar_impl.dart'; -import 'package:isar/src/web/isar_reader_impl.dart'; -import 'package:isar/src/web/isar_web.dart'; -import 'package:isar/src/web/isar_writer_impl.dart'; -import 'package:isar/src/web/query_build.dart'; -import 'package:meta/dart2js.dart'; - -class IsarCollectionImpl extends IsarCollection { - IsarCollectionImpl({ - required this.isar, - required this.native, - required this.schema, - }); - - @override - final IsarImpl isar; - final IsarCollectionJs native; - - @override - final CollectionSchema schema; - - @override - String get name => schema.name; - - late final _offsets = isar.offsets[OBJ]!; - - @tryInline - OBJ deserializeObject(Object object) { - final id = getProperty(object, idName); - final reader = IsarReaderImpl(object); - return schema.deserialize(id, reader, _offsets, isar.offsets); - } - - @tryInline - List deserializeObjects(dynamic objects) { - final list = objects as List; - final results = []; - for (final object in list) { - results.add(object is Object ? deserializeObject(object) : null); - } - return results; - } - - @override - Future> getAll(List ids) { - return isar.getTxn(false, (IsarTxnJs txn) async { - final objects = await native.getAll(txn, ids).wait>(); - return deserializeObjects(objects); - }); - } - - @override - Future> getAllByIndex(String indexName, List keys) { - return isar.getTxn(false, (IsarTxnJs txn) async { - final objects = await native - .getAllByIndex(txn, indexName, keys) - .wait>(); - return deserializeObjects(objects); - }); - } - - @override - List getAllSync(List ids) => unsupportedOnWeb(); - - @override - List getAllByIndexSync(String indexName, List keys) => - unsupportedOnWeb(); - - @override - Future> putAll(List objects) { - return putAllByIndex(null, objects); - } - - @override - List putAllSync(List objects, {bool saveLinks = true}) => - unsupportedOnWeb(); - - @override - Future> putAllByIndex(String? indexName, List objects) { - return isar.getTxn(true, (IsarTxnJs txn) async { - final serialized = []; - for (final object in objects) { - final jsObj = newObject(); - final writer = IsarWriterImpl(jsObj); - schema.serialize(object, writer, _offsets, isar.offsets); - setProperty(jsObj, idName, schema.getId(object)); - serialized.add(jsObj); - } - final ids = await native.putAll(txn, serialized).wait>(); - for (var i = 0; i < objects.length; i++) { - final object = objects[i]; - final id = ids[i] as Id; - schema.attach(this, id, object); - } - - return ids.cast().toList(); - }); - } - - @override - List putAllByIndexSync( - String indexName, - List objects, { - bool saveLinks = true, - }) => - unsupportedOnWeb(); - - @override - Future deleteAll(List ids) async { - await isar.getTxn(true, (IsarTxnJs txn) { - return native.deleteAll(txn, ids).wait(); - }); - return ids.length; - } - - @override - Future deleteAllByIndex(String indexName, List keys) { - return isar.getTxn(true, (IsarTxnJs txn) { - return native.deleteAllByIndex(txn, indexName, keys).wait(); - }); - } - - @override - int deleteAllSync(List ids) => unsupportedOnWeb(); - - @override - int deleteAllByIndexSync(String indexName, List keys) => - unsupportedOnWeb(); - - @override - Future clear() { - return isar.getTxn(true, (IsarTxnJs txn) { - return native.clear(txn).wait(); - }); - } - - @override - void clearSync() => unsupportedOnWeb(); - - @override - Future importJson(List> json) { - return isar.getTxn(true, (IsarTxnJs txn) async { - await native.putAll(txn, json.map(jsify).toList()).wait(); - }); - } - - @override - Future importJsonRaw(Uint8List jsonBytes) { - final json = jsonDecode(const Utf8Decoder().convert(jsonBytes)) as List; - return importJson(json.cast()); - } - - @override - void importJsonSync(List> json) => unsupportedOnWeb(); - - @override - void importJsonRawSync(Uint8List jsonBytes) => unsupportedOnWeb(); - - @override - Future count() => where().count(); - - @override - int countSync() => unsupportedOnWeb(); - - @override - Future getSize({ - bool includeIndexes = false, - bool includeLinks = false, - }) => - unsupportedOnWeb(); - - @override - int getSizeSync({ - bool includeIndexes = false, - bool includeLinks = false, - }) => - unsupportedOnWeb(); - - @override - Stream watchLazy({bool fireImmediately = false}) { - JsFunction? stop; - final controller = StreamController( - onCancel: () { - stop?.apply([]); - }, - ); - - final void Function() callback = allowInterop(() => controller.add(null)); - stop = native.watchLazy(callback); - - return controller.stream; - } - - @override - Stream watchObject( - Id id, { - bool fireImmediately = false, - bool deserialize = true, - }) { - JsFunction? stop; - final controller = StreamController( - onCancel: () { - stop?.apply([]); - }, - ); - - final Null Function(Object? obj) callback = allowInterop((Object? obj) { - final object = deserialize && obj != null ? deserializeObject(obj) : null; - controller.add(object); - }); - stop = native.watchObject(id, callback); - - return controller.stream; - } - - @override - Stream watchObjectLazy(Id id, {bool fireImmediately = false}) => - watchObject(id, deserialize: false); - - @override - Query buildQuery({ - List whereClauses = const [], - bool whereDistinct = false, - Sort whereSort = Sort.asc, - FilterOperation? filter, - List sortBy = const [], - List distinctBy = const [], - int? offset, - int? limit, - String? property, - }) { - return buildWebQuery( - this, - whereClauses, - whereDistinct, - whereSort, - filter, - sortBy, - distinctBy, - offset, - limit, - property, - ); - } - - @override - Future verify(List objects) => unsupportedOnWeb(); - - @override - Future verifyLink( - String linkName, - List sourceIds, - List targetIds, - ) => - unsupportedOnWeb(); -} diff --git a/lib/src/web/isar_impl.dart b/lib/src/web/isar_impl.dart deleted file mode 100644 index 5c0efb4..0000000 --- a/lib/src/web/isar_impl.dart +++ /dev/null @@ -1,135 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:async'; -import 'dart:html'; - -import 'package:isar/isar.dart'; - -import 'package:isar/src/web/bindings.dart'; -import 'package:isar/src/web/isar_web.dart'; - -const Symbol _zoneTxn = #zoneTxn; - -class IsarImpl extends Isar { - IsarImpl(super.name, this.instance); - - final IsarInstanceJs instance; - final offsets = >{}; - final List> _activeAsyncTxns = []; - - @override - final String? directory = null; - - void requireNotInTxn() { - if (Zone.current[_zoneTxn] != null) { - throw IsarError( - 'Cannot perform this operation from within an active transaction.', - ); - } - } - - Future _txn( - bool write, - bool silent, - Future Function() callback, - ) async { - requireOpen(); - requireNotInTxn(); - - final completer = Completer(); - _activeAsyncTxns.add(completer.future); - - final txn = instance.beginTxn(write); - - final zone = Zone.current.fork( - zoneValues: {_zoneTxn: txn}, - ); - - T result; - try { - result = await zone.run(callback); - await txn.commit().wait(); - } catch (e) { - txn.abort(); - if (e is DomException) { - if (e.name == DomException.CONSTRAINT) { - throw IsarUniqueViolationError(); - } else { - throw IsarError('${e.name}: ${e.message}'); - } - } else { - rethrow; - } - } finally { - completer.complete(); - _activeAsyncTxns.remove(completer.future); - } - - return result; - } - - @override - Future txn(Future Function() callback) { - return _txn(false, false, callback); - } - - @override - Future writeTxn(Future Function() callback, {bool silent = false}) { - return _txn(true, silent, callback); - } - - @override - T txnSync(T Function() callback) => unsupportedOnWeb(); - - @override - T writeTxnSync(T Function() callback, {bool silent = false}) => - unsupportedOnWeb(); - - Future getTxn(bool write, Future Function(IsarTxnJs txn) callback) { - final currentTxn = Zone.current[_zoneTxn] as IsarTxnJs?; - if (currentTxn != null) { - if (write && !currentTxn.write) { - throw IsarError( - 'Operation cannot be performed within a read transaction.', - ); - } - return callback(currentTxn); - } else if (!write) { - return _txn(false, false, () { - return callback(Zone.current[_zoneTxn] as IsarTxnJs); - }); - } else { - throw IsarError('Write operations require an explicit transaction.'); - } - } - - @override - Future getSize({ - bool includeIndexes = false, - bool includeLinks = false, - }) => - unsupportedOnWeb(); - - @override - int getSizeSync({ - bool includeIndexes = false, - bool includeLinks = false, - }) => - unsupportedOnWeb(); - - @override - Future copyToFile(String targetPath) => unsupportedOnWeb(); - - @override - Future close({bool deleteFromDisk = false}) async { - requireOpen(); - requireNotInTxn(); - await Future.wait(_activeAsyncTxns); - await super.close(); - await instance.close(deleteFromDisk).wait(); - return true; - } - - @override - Future verify() => unsupportedOnWeb(); -} diff --git a/lib/src/web/isar_link_impl.dart b/lib/src/web/isar_link_impl.dart deleted file mode 100644 index 6efa9c1..0000000 --- a/lib/src/web/isar_link_impl.dart +++ /dev/null @@ -1,75 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'package:isar/isar.dart'; -import 'package:isar/src/common/isar_link_base_impl.dart'; -import 'package:isar/src/common/isar_link_common.dart'; -import 'package:isar/src/common/isar_links_common.dart'; -import 'package:isar/src/web/bindings.dart'; -import 'package:isar/src/web/isar_collection_impl.dart'; -import 'package:isar/src/web/isar_web.dart'; - -mixin IsarLinkBaseMixin on IsarLinkBaseImpl { - @override - IsarCollectionImpl get sourceCollection => - super.sourceCollection as IsarCollectionImpl; - - @override - IsarCollectionImpl get targetCollection => - super.targetCollection as IsarCollectionImpl; - - @override - late final Id Function(OBJ) getId = targetCollection.schema.getId; - - late final String? backlinkLinkName = - sourceCollection.schema.link(linkName).linkName; - - late final IsarLinkJs jsLink = backlinkLinkName != null - ? targetCollection.native.getLink(backlinkLinkName!) - : sourceCollection.native.getLink(linkName); - - @override - Future update({ - Iterable link = const [], - Iterable unlink = const [], - bool reset = false, - }) { - final linkList = link.toList(); - final unlinkList = unlink.toList(); - - final containingId = requireAttached(); - final backlink = backlinkLinkName != null; - - final linkIds = List.filled(linkList.length, 0); - for (var i = 0; i < linkList.length; i++) { - linkIds[i] = requireGetId(linkList[i]); - } - - final unlinkIds = List.filled(unlinkList.length, 0); - for (var i = 0; i < unlinkList.length; i++) { - unlinkIds[i] = requireGetId(unlinkList[i]); - } - - return targetCollection.isar.getTxn(true, (IsarTxnJs txn) async { - if (reset) { - await jsLink.clear(txn, containingId, backlink).wait(); - } - return jsLink - .update(txn, backlink, containingId, linkIds, unlinkIds) - .wait(); - }); - } - - @override - void updateSync({ - Iterable link = const [], - Iterable unlink = const [], - bool reset = false, - }) => - unsupportedOnWeb(); -} - -class IsarLinkImpl extends IsarLinkCommon - with IsarLinkBaseMixin {} - -class IsarLinksImpl extends IsarLinksCommon - with IsarLinkBaseMixin {} diff --git a/lib/src/web/isar_reader_impl.dart b/lib/src/web/isar_reader_impl.dart deleted file mode 100644 index fac7e8b..0000000 --- a/lib/src/web/isar_reader_impl.dart +++ /dev/null @@ -1,347 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'package:isar/isar.dart'; -import 'package:js/js_util.dart'; -import 'package:meta/dart2js.dart'; - -const nullNumber = double.negativeInfinity; -const idName = '_id'; -final nullDate = DateTime.fromMillisecondsSinceEpoch(0); - -class IsarReaderImpl implements IsarReader { - IsarReaderImpl(this.object); - - final Object object; - - @tryInline - @override - bool readBool(int offset) { - final value = getProperty(object, offset); - return value == 1; - } - - @tryInline - @override - bool? readBoolOrNull(int offset) { - final value = getProperty(object, offset); - return value == 0 - ? false - : value == 1 - ? true - : null; - } - - @tryInline - @override - int readByte(int offset) { - final value = getProperty(object, offset); - return value is int ? value : nullNumber as int; - } - - @tryInline - @override - int? readByteOrNull(int offset) { - final value = getProperty(object, offset); - return value is int && value != nullNumber ? value : null; - } - - @tryInline - @override - int readInt(int offset) { - final value = getProperty(object, offset); - return value is int ? value : nullNumber as int; - } - - @tryInline - @override - int? readIntOrNull(int offset) { - final value = getProperty(object, offset); - return value is int && value != nullNumber ? value : null; - } - - @tryInline - @override - double readFloat(int offset) { - final value = getProperty(object, offset); - return value is double ? value : nullNumber; - } - - @tryInline - @override - double? readFloatOrNull(int offset) { - final value = getProperty(object, offset); - return value is double && value != nullNumber ? value : null; - } - - @tryInline - @override - int readLong(int offset) { - final value = getProperty(object, offset); - return value is int ? value : nullNumber as int; - } - - @tryInline - @override - int? readLongOrNull(int offset) { - final value = getProperty(object, offset); - return value is int && value != nullNumber ? value : null; - } - - @tryInline - @override - double readDouble(int offset) { - final value = getProperty(object, offset); - return value is double && value != nullNumber ? value : nullNumber; - } - - @tryInline - @override - double? readDoubleOrNull(int offset) { - final value = getProperty(object, offset); - return value is double && value != nullNumber ? value : null; - } - - @tryInline - @override - DateTime readDateTime(int offset) { - final value = getProperty(object, offset); - return value is int && value != nullNumber - ? DateTime.fromMillisecondsSinceEpoch(value, isUtc: true).toLocal() - : nullDate; - } - - @tryInline - @override - DateTime? readDateTimeOrNull(int offset) { - final value = getProperty(object, offset); - return value is int && value != nullNumber - ? DateTime.fromMillisecondsSinceEpoch(value, isUtc: true).toLocal() - : null; - } - - @tryInline - @override - String readString(int offset) { - final value = getProperty(object, offset); - return value is String ? value : ''; - } - - @tryInline - @override - String? readStringOrNull(int offset) { - final value = getProperty(object, offset); - return value is String ? value : null; - } - - @tryInline - @override - T? readObjectOrNull( - int offset, - Deserialize deserialize, - Map> allOffsets, - ) { - final value = getProperty(object, offset); - if (value is Object) { - final reader = IsarReaderImpl(value); - return deserialize(0, reader, allOffsets[T]!, allOffsets); - } else { - return null; - } - } - - @tryInline - @override - List? readBoolList(int offset) { - final value = getProperty(object, offset); - return value is List ? value.map((e) => e == 1).toList() : null; - } - - @tryInline - @override - List? readBoolOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value - .map( - (e) => e == 0 - ? false - : e == 1 - ? true - : null, - ) - .toList() - : null; - } - - @tryInline - @override - List? readByteList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is int ? e : nullNumber as int).toList() - : null; - } - - @tryInline - @override - List? readIntList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is int ? e : nullNumber as int).toList() - : null; - } - - @tryInline - @override - List? readIntOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is int && e != nullNumber ? e : null).toList() - : null; - } - - @tryInline - @override - List? readFloatList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is double ? e : nullNumber).toList() - : null; - } - - @tryInline - @override - List? readFloatOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is double && e != nullNumber ? e : null).toList() - : null; - } - - @tryInline - @override - List? readLongList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is int ? e : nullNumber as int).toList() - : null; - } - - @tryInline - @override - List? readLongOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is int && e != nullNumber ? e : null).toList() - : null; - } - - @tryInline - @override - List? readDoubleList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is double ? e : nullNumber).toList() - : null; - } - - @tryInline - @override - List? readDoubleOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is double && e != nullNumber ? e : null).toList() - : null; - } - - @tryInline - @override - List? readDateTimeList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value - .map( - (e) => e is int && e != nullNumber - ? DateTime.fromMillisecondsSinceEpoch(e, isUtc: true) - .toLocal() - : nullDate, - ) - .toList() - : null; - } - - @tryInline - @override - List? readDateTimeOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value - .map( - (e) => e is int && e != nullNumber - ? DateTime.fromMillisecondsSinceEpoch(e, isUtc: true) - .toLocal() - : null, - ) - .toList() - : null; - } - - @tryInline - @override - List? readStringList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is String ? e : '').toList() - : null; - } - - @tryInline - @override - List? readStringOrNullList(int offset) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) => e is String ? e : null).toList() - : null; - } - - @tryInline - @override - List? readObjectList( - int offset, - Deserialize deserialize, - Map> allOffsets, - T defaultValue, - ) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) { - if (e is Object) { - final reader = IsarReaderImpl(e); - return deserialize(0, reader, allOffsets[T]!, allOffsets); - } else { - return defaultValue; - } - }).toList() - : null; - } - - @tryInline - @override - List? readObjectOrNullList( - int offset, - Deserialize deserialize, - Map> allOffsets, - ) { - final value = getProperty(object, offset); - return value is List - ? value.map((e) { - if (e is Object) { - final reader = IsarReaderImpl(e); - return deserialize(0, reader, allOffsets[T]!, allOffsets); - } else { - return null; - } - }).toList() - : null; - } -} diff --git a/lib/src/web/isar_web.dart b/lib/src/web/isar_web.dart deleted file mode 100644 index 0cff278..0000000 --- a/lib/src/web/isar_web.dart +++ /dev/null @@ -1,48 +0,0 @@ -// ignore_for_file: unused_field, public_member_api_docs - -import 'dart:async'; - -import 'package:isar/isar.dart'; -import 'package:meta/meta.dart'; - -/// @nodoc -@protected -const Id isarMinId = -9007199254740990; - -/// @nodoc -@protected -const Id isarMaxId = 9007199254740991; - -/// @nodoc -@protected -const Id isarAutoIncrementId = -9007199254740991; - -/// @nodoc -Never unsupportedOnWeb() { - throw UnsupportedError('This operation is not supported for Isar web'); -} - -class _WebAbi { - static const androidArm = null as dynamic; - static const androidArm64 = null as dynamic; - static const androidIA32 = null as dynamic; - static const androidX64 = null as dynamic; - static const iosArm64 = null as dynamic; - static const iosX64 = null as dynamic; - static const linuxArm64 = null as dynamic; - static const linuxX64 = null as dynamic; - static const macosArm64 = null as dynamic; - static const macosX64 = null as dynamic; - static const windowsArm64 = null as dynamic; - static const windowsX64 = null as dynamic; -} - -/// @nodoc -@protected -typedef IsarAbi = _WebAbi; - -FutureOr initializeCoreBinary({ - Map libraries = const {}, - bool download = false, -}) => - unsupportedOnWeb(); diff --git a/lib/src/web/isar_writer_impl.dart b/lib/src/web/isar_writer_impl.dart deleted file mode 100644 index a4a65ca..0000000 --- a/lib/src/web/isar_writer_impl.dart +++ /dev/null @@ -1,171 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'package:isar/isar.dart'; -import 'package:isar/src/web/isar_reader_impl.dart'; -import 'package:js/js_util.dart'; -import 'package:meta/dart2js.dart'; - -class IsarWriterImpl implements IsarWriter { - IsarWriterImpl(this.object); - - final Object object; - - @tryInline - @override - void writeBool(int offset, bool? value) { - final number = value == true - ? 1 - : value == false - ? 0 - : nullNumber; - setProperty(object, offset, number); - } - - @tryInline - @override - void writeByte(int offset, int value) { - setProperty(object, offset, value); - } - - @tryInline - @override - void writeInt(int offset, int? value) { - setProperty(object, offset, value ?? nullNumber); - } - - @tryInline - @override - void writeFloat(int offset, double? value) { - setProperty(object, offset, value ?? nullNumber); - } - - @tryInline - @override - void writeLong(int offset, int? value) { - setProperty(object, offset, value ?? nullNumber); - } - - @tryInline - @override - void writeDouble(int offset, double? value) { - setProperty(object, offset, value ?? nullNumber); - } - - @tryInline - @override - void writeDateTime(int offset, DateTime? value) { - setProperty( - object, - offset, - value?.toUtc().millisecondsSinceEpoch ?? nullNumber, - ); - } - - @tryInline - @override - void writeString(int offset, String? value) { - setProperty(object, offset, value ?? nullNumber); - } - - @tryInline - @override - void writeObject( - int offset, - Map> allOffsets, - Serialize serialize, - T? value, - ) { - if (value != null) { - final object = newObject(); - final writer = IsarWriterImpl(object); - serialize(value, writer, allOffsets[T]!, allOffsets); - setProperty(this.object, offset, object); - } - } - - @tryInline - @override - void writeByteList(int offset, List? values) { - setProperty(object, offset, values ?? nullNumber); - } - - @tryInline - @override - void writeBoolList(int offset, List? values) { - final list = values - ?.map( - (e) => e == false - ? 0 - : e == true - ? 1 - : nullNumber, - ) - .toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeIntList(int offset, List? values) { - final list = values?.map((e) => e ?? nullNumber).toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeFloatList(int offset, List? values) { - final list = values?.map((e) => e ?? nullNumber).toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeLongList(int offset, List? values) { - final list = values?.map((e) => e ?? nullNumber).toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeDoubleList(int offset, List? values) { - final list = values?.map((e) => e ?? nullNumber).toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeDateTimeList(int offset, List? values) { - final list = values - ?.map((e) => e?.toUtc().millisecondsSinceEpoch ?? nullNumber) - .toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeStringList(int offset, List? values) { - final list = values?.map((e) => e ?? nullNumber).toList(); - setProperty(object, offset, list ?? nullNumber); - } - - @tryInline - @override - void writeObjectList( - int offset, - Map> allOffsets, - Serialize serialize, - List? values, - ) { - if (values != null) { - final list = values.map((e) { - if (e != null) { - final object = newObject(); - final writer = IsarWriterImpl(object); - serialize(e, writer, allOffsets[T]!, allOffsets); - return object; - } - }).toList(); - setProperty(object, offset, list); - } - } -} diff --git a/lib/src/web/open.dart b/lib/src/web/open.dart deleted file mode 100644 index 5e50791..0000000 --- a/lib/src/web/open.dart +++ /dev/null @@ -1,82 +0,0 @@ -// ignore_for_file: public_member_api_docs, invalid_use_of_protected_member - -import 'dart:html'; -//import 'dart:js_util'; - -import 'package:isar/isar.dart'; -/*import 'package:isar/src/common/schemas.dart'; - -import 'package:isar/src/web/bindings.dart'; -import 'package:isar/src/web/isar_collection_impl.dart'; -import 'package:isar/src/web/isar_impl.dart';*/ -import 'package:isar/src/web/isar_web.dart'; -import 'package:meta/meta.dart'; - -bool _loaded = false; -Future initializeIsarWeb([String? jsUrl]) async { - if (_loaded) { - return; - } - _loaded = true; - - final script = ScriptElement(); - script.type = 'text/javascript'; - // ignore: unsafe_html - script.src = 'https://unpkg.com/isar@${Isar.version}/dist/index.js'; - script.async = true; - document.head!.append(script); - await script.onLoad.first.timeout( - const Duration(seconds: 30), - onTimeout: () { - throw IsarError('Failed to load Isar'); - }, - ); -} - -@visibleForTesting -void doNotInitializeIsarWeb() { - _loaded = true; -} - -Future openIsar({ - required List> schemas, - String? directory, - required String name, - required int maxSizeMiB, - required bool relaxedDurability, - CompactCondition? compactOnLaunch, -}) async { - throw IsarError('Please use Isar 2.5.0 if you need web support. ' - 'A 3.x version with web support will be released soon.'); - /*await initializeIsarWeb(); - final schemasJson = getSchemas(schemas).map((e) => e.toJson()); - final schemasJs = jsify(schemasJson.toList()) as List; - final instance = await openIsarJs(name, schemasJs, relaxedDurability) - .wait(); - final isar = IsarImpl(name, instance); - final cols = >{}; - for (final schema in schemas) { - final col = instance.getCollection(schema.name); - schema.toCollection(() { - schema as CollectionSchema; - cols[OBJ] = IsarCollectionImpl( - isar: isar, - native: col, - schema: schema, - ); - }); - } - - isar.attachCollections(cols); - return isar;*/ -} - -Isar openIsarSync({ - required List> schemas, - String? directory, - required String name, - required int maxSizeMiB, - required bool relaxedDurability, - CompactCondition? compactOnLaunch, -}) => - unsupportedOnWeb(); diff --git a/lib/src/web/query_build.dart b/lib/src/web/query_build.dart deleted file mode 100644 index 89ff6dc..0000000 --- a/lib/src/web/query_build.dart +++ /dev/null @@ -1,375 +0,0 @@ -// ignore_for_file: public_member_api_docs, invalid_use_of_protected_member - -import 'dart:indexed_db'; - -import 'package:isar/isar.dart'; - -import 'package:isar/src/web/bindings.dart'; -import 'package:isar/src/web/isar_collection_impl.dart'; -import 'package:isar/src/web/isar_web.dart'; -import 'package:isar/src/web/query_impl.dart'; - -Query buildWebQuery( - IsarCollectionImpl col, - List whereClauses, - bool whereDistinct, - Sort whereSort, - FilterOperation? filter, - List sortBy, - List distinctBy, - int? offset, - int? limit, - String? property, -) { - final whereClausesJs = whereClauses.map((wc) { - if (wc is IdWhereClause) { - return _buildIdWhereClause(wc); - } else if (wc is IndexWhereClause) { - return _buildIndexWhereClause(col.schema, wc); - } else { - return _buildLinkWhereClause(col, wc as LinkWhereClause); - } - }).toList(); - - final filterJs = filter != null ? _buildFilter(col.schema, filter) : null; - final sortJs = sortBy.isNotEmpty ? _buildSort(sortBy) : null; - final distinctJs = distinctBy.isNotEmpty ? _buildDistinct(distinctBy) : null; - - final queryJs = QueryJs( - col.native, - whereClausesJs, - whereDistinct, - whereSort == Sort.asc, - filterJs, - sortJs, - distinctJs, - offset, - limit, - ); - - QueryDeserialize deserialize; - //if (property == null) { - deserialize = col.deserializeObject as T Function(Object); - /*} else { - deserialize = (jsObj) => col.schema.deserializeProp(jsObj, property) as T; - }*/ - - return QueryImpl(col, queryJs, deserialize, property); -} - -dynamic _valueToJs(dynamic value) { - if (value == null) { - return double.negativeInfinity; - } else if (value == true) { - return 1; - } else if (value == false) { - return 0; - } else if (value is DateTime) { - return value.toUtc().millisecondsSinceEpoch; - } else if (value is List) { - return value.map(_valueToJs).toList(); - } else { - return value; - } -} - -IdWhereClauseJs _buildIdWhereClause(IdWhereClause wc) { - return IdWhereClauseJs() - ..range = _buildKeyRange( - wc.lower, - wc.upper, - wc.includeLower, - wc.includeUpper, - ); -} - -IndexWhereClauseJs _buildIndexWhereClause( - CollectionSchema schema, - IndexWhereClause wc, -) { - final index = schema.index(wc.indexName); - - final lower = wc.lower?.toList(); - final upper = wc.upper?.toList(); - if (upper != null) { - while (index.properties.length > upper.length) { - upper.add([]); - } - } - - dynamic lowerUnwrapped = wc.lower; - if (index.properties.length == 1 && lower != null) { - lowerUnwrapped = lower.isNotEmpty ? lower[0] : null; - } - - dynamic upperUnwrapped = upper; - if (index.properties.length == 1 && upper != null) { - upperUnwrapped = upper.isNotEmpty ? upper[0] : double.infinity; - } - - return IndexWhereClauseJs() - ..indexName = wc.indexName - ..range = _buildKeyRange( - wc.lower != null ? _valueToJs(lowerUnwrapped) : null, - wc.upper != null ? _valueToJs(upperUnwrapped) : null, - wc.includeLower, - wc.includeUpper, - ); -} - -LinkWhereClauseJs _buildLinkWhereClause( - IsarCollectionImpl col, - LinkWhereClause wc, -) { - // ignore: unused_local_variable - final linkCol = col.isar.getCollectionByNameInternal(wc.linkCollection)! - as IsarCollectionImpl; - //final backlinkLinkName = linkCol.schema.backlinkLinkNames[wc.linkName]; - return LinkWhereClauseJs() - ..linkCollection = wc.linkCollection - //..linkName = backlinkLinkName ?? wc.linkName - //..backlink = backlinkLinkName != null - ..id = wc.id; -} - -KeyRange? _buildKeyRange( - dynamic lower, - dynamic upper, - bool includeLower, - bool includeUpper, -) { - if (lower != null) { - if (upper != null) { - final boundsEqual = idbCmp(lower, upper) == 0; - if (boundsEqual) { - if (includeLower && includeUpper) { - return KeyRange.only(lower); - } else { - // empty range - return KeyRange.upperBound(double.negativeInfinity, true); - } - } - - return KeyRange.bound( - lower, - upper, - !includeLower, - !includeUpper, - ); - } else { - return KeyRange.lowerBound(lower, !includeLower); - } - } else if (upper != null) { - return KeyRange.upperBound(upper, !includeUpper); - } - return null; -} - -FilterJs? _buildFilter( - CollectionSchema schema, - FilterOperation filter, -) { - final filterStr = _buildFilterOperation(schema, filter); - if (filterStr != null) { - return FilterJs('id', 'obj', 'return $filterStr'); - } else { - return null; - } -} - -String? _buildFilterOperation( - CollectionSchema schema, - FilterOperation filter, -) { - if (filter is FilterGroup) { - return _buildFilterGroup(schema, filter); - } else if (filter is LinkFilter) { - unsupportedOnWeb(); - } else if (filter is FilterCondition) { - return _buildCondition(schema, filter); - } else { - return null; - } -} - -String? _buildFilterGroup(CollectionSchema schema, FilterGroup group) { - final builtConditions = group.filters - .map((op) => _buildFilterOperation(schema, op)) - .where((e) => e != null) - .toList(); - - if (builtConditions.isEmpty) { - return null; - } - - if (group.type == FilterGroupType.not) { - return '!(${builtConditions[0]})'; - } else if (builtConditions.length == 1) { - return builtConditions[0]; - } else if (group.type == FilterGroupType.xor) { - final conditions = builtConditions.join(','); - return 'IsarQuery.xor($conditions)'; - } else { - final op = group.type == FilterGroupType.or ? '||' : '&&'; - final condition = builtConditions.join(op); - return '($condition)'; - } -} - -String _buildCondition( - CollectionSchema schema, - FilterCondition condition, -) { - dynamic _prepareFilterValue(dynamic value) { - if (value == null) { - return null; - } else if (value is String) { - return stringify(value); - } else { - return _valueToJs(value); - } - } - - final isListOp = condition.type != FilterConditionType.isNull && - condition.type != FilterConditionType.listLength && - schema.property(condition.property).type.isList; - final accessor = - condition.property == schema.idName ? 'id' : 'obj.${condition.property}'; - final variable = isListOp ? 'e' : accessor; - - final cond = _buildConditionInternal( - conditionType: condition.type, - variable: variable, - val1: _prepareFilterValue(condition.value1), - include1: condition.include1, - val2: _prepareFilterValue(condition.value2), - include2: condition.include2, - caseSensitive: condition.caseSensitive, - ); - - if (isListOp) { - return '(Array.isArray($accessor) && $accessor.some(e => $cond))'; - } else { - return cond; - } -} - -String _buildConditionInternal({ - required FilterConditionType conditionType, - required String variable, - required Object? val1, - required bool include1, - required Object? val2, - required bool include2, - required bool caseSensitive, -}) { - final isNull = '($variable == null || $variable === -Infinity)'; - switch (conditionType) { - case FilterConditionType.equalTo: - if (val1 == null) { - return isNull; - } else if (val1 is String && !caseSensitive) { - return '$variable?.toLowerCase() === ${val1.toLowerCase()}'; - } else { - return '$variable === $val1'; - } - case FilterConditionType.between: - final val = val1 ?? val2; - final lowerOp = include1 ? '>=' : '>'; - final upperOp = include2 ? '<=' : '<'; - if (val == null) { - return isNull; - } else if ((val1 is String?) && (val2 is String?) && !caseSensitive) { - final lower = val1?.toLowerCase() ?? '-Infinity'; - final upper = val2?.toLowerCase() ?? '-Infinity'; - final variableLc = '$variable?.toLowerCase() ?? -Infinity'; - final lowerCond = 'indexedDB.cmp($variableLc, $lower) $lowerOp 0'; - final upperCond = 'indexedDB.cmp($variableLc, $upper) $upperOp 0'; - return '($lowerCond && $upperCond)'; - } else { - final lowerCond = - 'indexedDB.cmp($variable, ${val1 ?? '-Infinity'}) $lowerOp 0'; - final upperCond = - 'indexedDB.cmp($variable, ${val2 ?? '-Infinity'}) $upperOp 0'; - return '($lowerCond && $upperCond)'; - } - case FilterConditionType.lessThan: - if (val1 == null) { - if (include1) { - return isNull; - } else { - return 'false'; - } - } else { - final op = include1 ? '<=' : '<'; - if (val1 is String && !caseSensitive) { - return 'indexedDB.cmp($variable?.toLowerCase() ?? ' - '-Infinity, ${val1.toLowerCase()}) $op 0'; - } else { - return 'indexedDB.cmp($variable, $val1) $op 0'; - } - } - case FilterConditionType.greaterThan: - if (val1 == null) { - if (include1) { - return 'true'; - } else { - return '!$isNull'; - } - } else { - final op = include1 ? '>=' : '>'; - if (val1 is String && !caseSensitive) { - return 'indexedDB.cmp($variable?.toLowerCase() ?? ' - '-Infinity, ${val1.toLowerCase()}) $op 0'; - } else { - return 'indexedDB.cmp($variable, $val1) $op 0'; - } - } - case FilterConditionType.startsWith: - case FilterConditionType.endsWith: - case FilterConditionType.contains: - final op = conditionType == FilterConditionType.startsWith - ? 'startsWith' - : conditionType == FilterConditionType.endsWith - ? 'endsWith' - : 'includes'; - if (val1 is String) { - final isString = 'typeof $variable == "string"'; - if (!caseSensitive) { - return '($isString && $variable.toLowerCase() ' - '.$op(${val1.toLowerCase()}))'; - } else { - return '($isString && $variable.$op($val1))'; - } - } else { - throw IsarError('Unsupported type for condition'); - } - case FilterConditionType.matches: - throw UnimplementedError(); - case FilterConditionType.isNull: - return isNull; - // ignore: no_default_cases - default: - throw UnimplementedError(); - } -} - -SortCmpJs _buildSort(List properties) { - final sort = properties.map((e) { - final op = e.sort == Sort.asc ? '' : '-'; - return '${op}indexedDB.cmp(a.${e.property} ?? "-Infinity", b.${e.property} ' - '?? "-Infinity")'; - }).join('||'); - return SortCmpJs('a', 'b', 'return $sort'); -} - -DistinctValueJs _buildDistinct(List properties) { - final distinct = properties.map((e) { - if (e.caseSensitive == false) { - return 'obj.${e.property}?.toLowerCase() ?? "-Infinity"'; - } else { - return 'obj.${e.property}?.toString() ?? "-Infinity"'; - } - }).join('+'); - return DistinctValueJs('obj', 'return $distinct'); -} diff --git a/lib/src/web/query_impl.dart b/lib/src/web/query_impl.dart deleted file mode 100644 index e2bfc15..0000000 --- a/lib/src/web/query_impl.dart +++ /dev/null @@ -1,180 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'dart:async'; -import 'dart:convert'; -import 'dart:js'; -import 'dart:typed_data'; - -import 'package:isar/isar.dart'; -import 'package:isar/src/web/bindings.dart'; - -import 'package:isar/src/web/isar_collection_impl.dart'; -import 'package:isar/src/web/isar_web.dart'; - -typedef QueryDeserialize = T Function(Object); - -class QueryImpl extends Query { - QueryImpl(this.col, this.queryJs, this.deserialize, this.propertyName); - final IsarCollectionImpl col; - final QueryJs queryJs; - final QueryDeserialize deserialize; - final String? propertyName; - - @override - Isar get isar => col.isar; - - @override - Future findFirst() { - return col.isar.getTxn(false, (IsarTxnJs txn) async { - final result = await queryJs.findFirst(txn).wait(); - if (result == null) { - return null; - } - return deserialize(result); - }); - } - - @override - T? findFirstSync() => unsupportedOnWeb(); - - @override - Future> findAll() { - return col.isar.getTxn(false, (IsarTxnJs txn) async { - final result = await queryJs.findAll(txn).wait>(); - return result.map((e) => deserialize(e as Object)).toList(); - }); - } - - @override - List findAllSync() => unsupportedOnWeb(); - - @override - Future aggregate(AggregationOp op) { - return col.isar.getTxn(false, (IsarTxnJs txn) async { - final property = propertyName ?? col.schema.idName; - - num? result; - switch (op) { - case AggregationOp.min: - result = await queryJs.min(txn, property).wait(); - break; - case AggregationOp.max: - result = await queryJs.max(txn, property).wait(); - break; - case AggregationOp.sum: - result = await queryJs.sum(txn, property).wait(); - break; - case AggregationOp.average: - result = await queryJs.average(txn, property).wait(); - break; - case AggregationOp.count: - result = await queryJs.count(txn).wait(); - break; - // ignore: no_default_cases - default: - throw UnimplementedError(); - } - - if (result == null) { - return null; - } - - if (R == DateTime) { - return DateTime.fromMillisecondsSinceEpoch(result.toInt()).toLocal() - as R; - } else if (R == int) { - return result.toInt() as R; - } else if (R == double) { - return result.toDouble() as R; - } else { - return null; - } - }); - } - - @override - R? aggregateSync(AggregationOp op) => unsupportedOnWeb(); - - @override - Future deleteFirst() { - return col.isar.getTxn(true, (IsarTxnJs txn) { - return queryJs.deleteFirst(txn).wait(); - }); - } - - @override - bool deleteFirstSync() => unsupportedOnWeb(); - - @override - Future deleteAll() { - return col.isar.getTxn(true, (IsarTxnJs txn) { - return queryJs.deleteAll(txn).wait(); - }); - } - - @override - int deleteAllSync() => unsupportedOnWeb(); - - @override - Stream> watch({bool fireImmediately = false}) { - JsFunction? stop; - final controller = StreamController>( - onCancel: () { - stop?.apply([]); - }, - ); - - if (fireImmediately) { - findAll().then(controller.add); - } - - final Null Function(List results) callback = - allowInterop((List results) { - controller.add(results.map((e) => deserialize(e as Object)).toList()); - }); - stop = col.native.watchQuery(queryJs, callback); - - return controller.stream; - } - - @override - Stream watchLazy({bool fireImmediately = false}) { - JsFunction? stop; - final controller = StreamController( - onCancel: () { - stop?.apply([]); - }, - ); - - final Null Function() callback = allowInterop(() { - controller.add(null); - }); - stop = col.native.watchQueryLazy(queryJs, callback); - - return controller.stream; - } - - @override - Future exportJsonRaw(R Function(Uint8List) callback) async { - return col.isar.getTxn(false, (IsarTxnJs txn) async { - final result = await queryJs.findAll(txn).wait(); - final jsonStr = stringify(result); - return callback(const Utf8Encoder().convert(jsonStr)); - }); - } - - @override - Future>> exportJson() { - return col.isar.getTxn(false, (IsarTxnJs txn) async { - final result = await queryJs.findAll(txn).wait>(); - return result.map((e) => jsMapToDart(e as Object)).toList(); - }); - } - - @override - R exportJsonRawSync(R Function(Uint8List) callback) => unsupportedOnWeb(); - - @override - List> exportJsonSync({bool primitiveNull = true}) => - unsupportedOnWeb(); -} diff --git a/lib/src/web/split_words.dart b/lib/src/web/split_words.dart deleted file mode 100644 index fa29ddd..0000000 --- a/lib/src/web/split_words.dart +++ /dev/null @@ -1,5 +0,0 @@ -// ignore_for_file: public_member_api_docs - -import 'package:isar/src/web/isar_web.dart'; - -List isarSplitWords(String input) => unsupportedOnWeb(); diff --git a/test/isar_reader_writer_test.dart b/test/isar_reader_writer_test.dart deleted file mode 100644 index 5fc83de..0000000 --- a/test/isar_reader_writer_test.dart +++ /dev/null @@ -1,287 +0,0 @@ -@TestOn('vm') - -// ignore_for_file: constant_identifier_names - -import 'dart:convert'; -import 'dart:io'; -import 'dart:typed_data'; - -import 'package:isar/isar.dart'; -import 'package:isar/src/native/isar_core.dart'; -import 'package:isar/src/native/isar_reader_impl.dart'; -import 'package:isar/src/native/isar_writer_impl.dart'; -import 'package:test/test.dart'; - -void main() { - group('Golden Binary', () { - late final json = - File('../isar_core/tests/binary_golden.json').readAsStringSync(); - late final tests = (jsonDecode(json) as List) - .map((e) => BinaryTest.fromJson(e as Map)) - .toList(); - - test('IsarReader', () { - var t = 0; - for (final test in tests) { - final reader = IsarReaderImpl(Uint8List.fromList(test.bytes)); - var offset = 2; - for (var i = 0; i < test.types.length; i++) { - final type = test.types[i]; - final nullableValue = type.read(reader, offset, true); - expect(nullableValue, test.values[i], reason: '${test.types} $t'); - - final nonNullableValue = type.read(reader, offset, false); - _expectIgnoreNull(nonNullableValue, test.values[i], type); - offset += type.size; - } - t++; - } - }); - - test('IsarWriter', () { - for (final test in tests) { - final buffer = Uint8List(10000); - final size = - test.types.fold(0, (sum, type) => sum + type.size) + 2; - - final bufferView = buffer.buffer.asUint8List(0, test.bytes.length); - final writer = IsarWriterImpl(bufferView, size); - var offset = 2; - for (var i = 0; i < test.types.length; i++) { - final type = test.types[i]; - final value = test.values[i]; - type.write(writer, offset, value); - offset += type.size; - } - - expect(buffer.sublist(0, test.bytes.length), test.bytes); - } - }); - }); -} - -enum Type { - Bool(1, false, _readBool, _writeBool), - Byte(1, 0, _readByte, _writeByte), - Int(4, nullInt, _readInt, _writeInt), - Float(4, nullFloat, _readFloat, _writeFloat), - Long(8, nullLong, _readLong, _writeLong), - Double(8, nullDouble, _readDouble, _writeDouble), - String(3, '', _readString, _writeString), - BoolList(3, false, _readBoolList, _writeBoolList), - ByteList(3, 0, _readByteList, _writeByteList), - IntList(3, nullInt, _readIntList, _writeIntList), - FloatList(3, nullFloat, _readFloatList, _writeFloatList), - LongList(3, nullLong, _readLongList, _writeLongList), - DoubleList(3, nullDouble, _readDoubleList, _writeDoubleList), - StringList(3, '', _readStringList, _writeStringList); - - const Type(this.size, this.nullValue, this.read, this.write); - - final int size; - final dynamic nullValue; - final dynamic Function(IsarReader reader, int offset, bool nullable) read; - final void Function(IsarWriter reader, int offset, dynamic value) write; -} - -class BinaryTest { - const BinaryTest(this.types, this.values, this.bytes); - - factory BinaryTest.fromJson(Map json) { - return BinaryTest( - (json['types'] as List) - .map((type) => Type.values.firstWhere((t) => t.name == type)) - .toList(), - json['values'] as List, - (json['bytes'] as List).cast(), - ); - } - - final List types; - final List values; - final List bytes; -} - -void _expectIgnoreNull( - dynamic left, - dynamic right, - Type type, { - bool inList = false, -}) { - if (right == null && (type.index < Type.BoolList.index || inList)) { - if (left is double) { - expect(left, isNaN); - } else { - expect(left, type.nullValue); - } - } else if (right is List) { - left as List; - for (var i = 0; i < right.length; i++) { - _expectIgnoreNull(left[i], right[i], type, inList: true); - } - } else { - expect(left, right); - } -} - -bool? _readBool(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readBoolOrNull(offset); - } else { - return reader.readBool(offset); - } -} - -void _writeBool(IsarWriter writer, int offset, dynamic value) { - writer.writeBool(offset, value as bool?); -} - -int? _readByte(IsarReader reader, int offset, bool nullable) { - return reader.readByte(offset); -} - -void _writeByte(IsarWriter writer, int offset, dynamic value) { - writer.writeByte(offset, value as int); -} - -int? _readInt(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readIntOrNull(offset); - } else { - return reader.readInt(offset); - } -} - -void _writeInt(IsarWriter writer, int offset, dynamic value) { - writer.writeInt(offset, value as int?); -} - -double? _readFloat(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readFloatOrNull(offset); - } else { - return reader.readFloat(offset); - } -} - -void _writeFloat(IsarWriter writer, int offset, dynamic value) { - writer.writeFloat(offset, value as double?); -} - -int? _readLong(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readLongOrNull(offset); - } else { - return reader.readLong(offset); - } -} - -void _writeLong(IsarWriter writer, int offset, dynamic value) { - writer.writeLong(offset, value as int?); -} - -double? _readDouble(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readDoubleOrNull(offset); - } else { - return reader.readDouble(offset); - } -} - -void _writeDouble(IsarWriter writer, int offset, dynamic value) { - writer.writeDouble(offset, value as double?); -} - -String? _readString(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readStringOrNull(offset); - } else { - return reader.readString(offset); - } -} - -void _writeString(IsarWriter writer, int offset, dynamic value) { - final bytes = value is String ? utf8.encode(value) as Uint8List : null; - writer.writeByteList(offset, bytes); -} - -List? _readBoolList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readBoolOrNullList(offset); - } else { - return reader.readBoolList(offset); - } -} - -void _writeBoolList(IsarWriter writer, int offset, dynamic value) { - writer.writeBoolList(offset, (value as List?)?.cast()); -} - -List? _readByteList(IsarReader reader, int offset, bool nullable) { - return reader.readByteList(offset); -} - -void _writeByteList(IsarWriter writer, int offset, dynamic value) { - final bytes = value is List ? Uint8List.fromList(value.cast()) : null; - writer.writeByteList(offset, bytes); -} - -List? _readIntList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readIntOrNullList(offset); - } else { - return reader.readIntList(offset); - } -} - -void _writeIntList(IsarWriter writer, int offset, dynamic value) { - writer.writeIntList(offset, (value as List?)?.cast()); -} - -List? _readFloatList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readFloatOrNullList(offset); - } else { - return reader.readFloatList(offset); - } -} - -void _writeFloatList(IsarWriter writer, int offset, dynamic value) { - writer.writeFloatList(offset, (value as List?)?.cast()); -} - -List? _readLongList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readLongOrNullList(offset); - } else { - return reader.readLongList(offset); - } -} - -void _writeLongList(IsarWriter writer, int offset, dynamic value) { - writer.writeLongList(offset, (value as List?)?.cast()); -} - -List? _readDoubleList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readDoubleOrNullList(offset); - } else { - return reader.readDoubleList(offset); - } -} - -void _writeDoubleList(IsarWriter writer, int offset, dynamic value) { - writer.writeDoubleList(offset, (value as List?)?.cast()); -} - -List? _readStringList(IsarReader reader, int offset, bool nullable) { - if (nullable) { - return reader.readStringOrNullList(offset); - } else { - return reader.readStringList(offset); - } -} - -void _writeStringList(IsarWriter writer, int offset, dynamic value) { - writer.writeStringList(offset, (value as List?)?.cast()); -}