diff --git a/common/lib/src/realm_types.dart b/common/lib/src/realm_types.dart index 33d8c2114a..bd4f074c53 100644 --- a/common/lib/src/realm_types.dart +++ b/common/lib/src/realm_types.dart @@ -188,27 +188,45 @@ class RealmValue { const RealmValue.decimal128(Decimal128 decimal) : this._(decimal); const RealmValue.uuid(Uuid uuid) : this._(uuid); const RealmValue.uint8List(Uint8List binary) : this._(binary); + const RealmValue.dictionary(Map dictionary) : this._(dictionary); + const RealmValue.list(Iterable list) : this._(list); + const RealmValue.set(Set set) : this._(set); - /// Will throw [ArgumentError] - factory RealmValue.from(Object? object) { - if (object == null || - object is bool || - object is String || - object is int || - object is Float || - object is double || - object is RealmObjectMarker || - object is DateTime || - object is ObjectId || - object is Decimal128 || - object is Uuid || - object is Uint8List) { - return RealmValue._(object); - } else { - throw ArgumentError.value(object, 'object', 'Unsupported type'); - } + /// Will throw [ArgumentError] if the type is not supported + static RealmValue from(T object) { + return switch (object) { + null => const RealmValue.nullValue(), + bool b => RealmValue.bool(b), + String s => RealmValue.string(s), + int i => RealmValue.int(i), + double d => RealmValue.double(d), + RealmObjectMarker o => RealmValue.realmObject(o), + DateTime dt => RealmValue.dateTime(dt), + ObjectId id => RealmValue.objectId(id), + Decimal128 decimal => RealmValue.decimal128(decimal), + Uuid uuid => RealmValue.uuid(uuid), + Uint8List binary => RealmValue.uint8List(binary), + Map d => RealmValue.dictionary(d), + Map d => RealmValue.dictionary(Map.fromEntries(d.entries.map((e) => MapEntry(e.key, RealmValue.from(e.value))))), + List l => RealmValue.list(l), + List l => RealmValue.list(l.map((o) => RealmValue.from(o)).toList()), + Set s => RealmValue.set(s), + Set s => RealmValue.set(s.map((o) => RealmValue.from(o)).toSet()), + _ => throw ArgumentError.value(object.runtimeType, 'object', 'Unsupported type'), + }; + } + + RealmValue? operator [](Object index) { + return switch (index) { + int i => as>().elementAtOrNull(i), + String s => as>()[s], + RealmValue v => as>().lookup(v), + _ => throw ArgumentError.value(index, 'index', 'Unsupported type'), + }; } + T call() => as(); // is this useful? + @override operator ==(Object? other) { if (other is RealmValue) { @@ -224,3 +242,20 @@ class RealmValue { @override String toString() => 'RealmValue($value)'; } + +void demo() { + final any = RealmValue.from([ + 1, + 2, + { + 'x': {1, 2} + }, + ]); + + final x = any[2]?['x']?[1]?.as(); + assert(x == 1); + + // or, if you are sure + int y = any[2]!['x']![1]!(); + assert(y == 1); +} diff --git a/test/realm_value_test.dart b/test/realm_value_test.dart index 0f34ebdcce..0b865bedb2 100644 --- a/test/realm_value_test.dart +++ b/test/realm_value_test.dart @@ -59,7 +59,10 @@ Future main([List? args]) async { ObjectId.fromTimestamp(now), Uuid.v4(), Decimal128.fromDouble(128.128), - Uint8List.fromList([1, 2, 0]) + Uint8List.fromList([1, 2, 0]), + [1, 2, 3], + {1, 2, 3}, + {'a': 1, 'b': 2}, ]; for (final x in values) { @@ -80,7 +83,7 @@ Future main([List? args]) async { test('Illegal value', () { final config = Configuration.local([AnythingGoes.schema, Stuff.schema, TuckedIn.schema]); final realm = getRealm(config); - expect(() => realm.write(() => realm.add(AnythingGoes(oneAny: RealmValue.from([1, 2])))), throwsArgumentError); + expect(() => realm.write(() => realm.add(AnythingGoes(oneAny: RealmValue.from((1, 2))))), throwsArgumentError); // records not supported }); test('Embedded object not allowed in RealmValue', () {