From e3ef5ba70f02418faf66dac34273f0aa608a0e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kasper=20Overg=C3=A5rd=20Nielsen?= Date: Mon, 29 Jul 2024 14:57:02 +0200 Subject: [PATCH] Support Set --- packages/ejson/lib/src/decoding.dart | 9 +++++ packages/ejson/lib/src/encoding.dart | 2 +- packages/ejson/test/ejson_test.dart | 12 +++++++ .../realm_dart/test/serialization_test.dart | 34 +++++++++++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/packages/ejson/lib/src/decoding.dart b/packages/ejson/lib/src/decoding.dart index a1ef1ab2a..0ab7c5572 100644 --- a/packages/ejson/lib/src/decoding.dart +++ b/packages/ejson/lib/src/decoding.dart @@ -19,6 +19,7 @@ const _commonDecoders = { Object: _decodeAny, Iterable: _decodeArray, List: _decodeArray, + Set: _decodeSet, bool: _decodeBool, DateTime: _decodeDate, Defined: _decodeDefined, @@ -116,6 +117,7 @@ dynamic _decodeAny(EJsonValue ejson) { {'\$binary': {'base64': _, 'subType': '04'}} => _decodeUuid(ejson), {'\$binary': _} => _decodeBinary(ejson), List _ => _decodeArray(ejson), + Set _ => _decodeSet(ejson), Map _ => _tryDecodeCustomIfAllowed(ejson) ?? _decodeDocument(ejson), // other maps goes last!! _ => raiseInvalidEJson(ejson), }; @@ -142,6 +144,13 @@ List _decodeArray(EJsonValue ejson) { }; } +Set _decodeSet(EJsonValue ejson) { + return switch (ejson) { + Iterable i => i.map((ejson) => fromEJson(ejson)).toSet(), + _ => raiseInvalidEJson(ejson), + }; +} + bool _decodeBool(EJsonValue ejson) { return switch (ejson) { bool b => b, diff --git a/packages/ejson/lib/src/encoding.dart b/packages/ejson/lib/src/encoding.dart index b6348af07..8a3156a1d 100644 --- a/packages/ejson/lib/src/encoding.dart +++ b/packages/ejson/lib/src/encoding.dart @@ -40,7 +40,7 @@ EJsonValue _encodeAny(Object? value) { int i => _encodeInt(i), BsonKey k => _encodeKey(k), Uint8List b => _encodeBinary(b, subtype: '00'), - Iterable l => _encodeArray(l), + Iterable l => _encodeArray(l), // handles List and Set as well Map m => _encodeDocument(m), ObjectId o => _encodeObjectId(o), String s => _encodeString(s), diff --git a/packages/ejson/test/ejson_test.dart b/packages/ejson/test/ejson_test.dart index 41c096877..1251b0ad8 100644 --- a/packages/ejson/test/ejson_test.dart +++ b/packages/ejson/test/ejson_test.dart @@ -114,6 +114,8 @@ void main() { _invalidTestCase(); _invalidTestCase(); _invalidTestCase>(); + _invalidTestCase(); + _invalidTestCase>(); _invalidTestCase([]); _invalidTestCase>([]); _invalidTestCase(); @@ -157,6 +159,16 @@ void main() { ] : [1, 2, 3], ); + _testCase( + {1, 2, 3}, + canonical + ? { + {'\$numberInt': '1'}, + {'\$numberInt': '2'}, + {'\$numberInt': '3'}, + } + : {1, 2, 3}, + ); _testCase( [1, 1.1], canonical diff --git a/packages/realm_dart/test/serialization_test.dart b/packages/realm_dart/test/serialization_test.dart index f3f5a48a1..ddf18cf6f 100644 --- a/packages/realm_dart/test/serialization_test.dart +++ b/packages/realm_dart/test/serialization_test.dart @@ -69,4 +69,38 @@ void main() { expect(toEJson(d), {'\$numberDecimal': '+42E+0'}); expect(fromEJson({'\$numberDecimal': '42'}), d); }); + + test('Set on RealmObject', () { + final oid = ObjectId(); + final realm = Realm(Configuration.inMemory([ObjectWithRealmValue.schema])); + final o = realm.write(() => realm.add(ObjectWithRealmValue(oid, setOfAny: {RealmValue.from(42), RealmValue.from('42')}))); + expect(o.setOfAny, {RealmValue.from(42), RealmValue.from('42')}); + final serialized = toEJsonString(o); + expect(serialized, '{"_id":{"\$oid":"$oid"},"differentiator":null,"oneAny":null,"manyAny":[],"dictOfAny":{},"setOfAny":[{"\$numberInt":"42"},"42"]}'); + final deserialized = fromEJsonString(serialized); + // deserialized is unmanaged, so will never compare equal, but we can test properties + expect(deserialized.id, o.id); + expect(deserialized.setOfAny, o.setOfAny); + }); + + test('Set on RealmObject', () { + final realm = Realm(Configuration.inMemory([AllCollections.schema])); + final o = realm.write(() => realm.add(AllCollections(intSet: {1, 2, 3}))); + expect(o.intSet, {1, 2, 3}); + final deserialized = fromEJsonString(toEJsonString(o)); + // deserialized is unmanaged, so will never compare equal, but we can test properties + expect(deserialized.intSet, o.intSet); + }); + + test('Set in RealmValue', () { + final rv = RealmValue.from({1, 2, 3}); // constructed from a list of ints + expect(rv.value, [RealmValue.from(1), RealmValue.from(2), RealmValue.from(3)]); // but becomes a list RealmValues + expect(rv.toEJson(), [ + // and serializes as a list of EJson + {'\$numberInt': '1'}, + {'\$numberInt': '2'}, + {'\$numberInt': '3'}, + ]); + // expect(rv.as>(), {1, 2, 3}); // doesn't work because the set is a list of RealmValues. Should we support this? + }); }