diff options
author | Ivan Dlugos <6349682+vaind@users.noreply.github.com> | 2021-07-09 18:55:34 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-09 09:55:34 -0700 |
commit | 3f77dc9a0e83f129e5284b86e24f7956d18826e5 (patch) | |
tree | 6cbacb08717d8d5496af9d28ff32da0670c1aabb /dart | |
parent | 838c93b84349ac126ff160bf5941e2a3d3219154 (diff) | |
download | flatbuffers-3f77dc9a0e83f129e5284b86e24f7956d18826e5.tar.gz flatbuffers-3f77dc9a0e83f129e5284b86e24f7956d18826e5.tar.bz2 flatbuffers-3f77dc9a0e83f129e5284b86e24f7956d18826e5.zip |
Dart - unpack() must use eager list reader (#6723)
Diffstat (limited to 'dart')
-rw-r--r-- | dart/lib/flat_buffers.dart | 26 | ||||
-rw-r--r-- | dart/test/flat_buffers_test.dart | 22 | ||||
-rw-r--r-- | dart/test/monster_test_my_game.example_generated.dart | 30 |
3 files changed, 57 insertions, 21 deletions
diff --git a/dart/lib/flat_buffers.dart b/dart/lib/flat_buffers.dart index a389a892..8b31f21b 100644 --- a/dart/lib/flat_buffers.dart +++ b/dart/lib/flat_buffers.dart @@ -907,20 +907,34 @@ class Int8Reader extends Reader<int> { int read(BufferContext bc, int offset) => bc._getInt8(offset); } -/// The reader of lists of objects. -/// -/// The returned unmodifiable lists lazily read objects on access. +/// The reader of lists of objects. Lazy by default - see [lazy]. class ListReader<E> extends Reader<List<E>> { final Reader<E> _elementReader; - const ListReader(this._elementReader); + /// Enables lazy reading of the list + /// + /// If true, the returned unmodifiable list lazily reads objects on access. + /// Therefore, the underlying buffer must not change while accessing the list. + /// + /// If false, reads the whole list immediately on access. + final bool lazy; + + const ListReader(this._elementReader, {this.lazy = true}); @override int get size => _sizeofUint32; @override - List<E> read(BufferContext bc, int offset) => - new _FbGenericList<E>(_elementReader, bc, bc.derefObject(offset)); + List<E> read(BufferContext bc, int offset) { + final listOffset = bc.derefObject(offset); + return lazy + ? _FbGenericList<E>(_elementReader, bc, listOffset) + : List<E>.generate( + bc.buffer.getUint32(listOffset, Endian.little), + (int index) => _elementReader.read( + bc, listOffset + size + _elementReader.size * index), + growable: true); + } } /// Object that can read a value at a [BufferContext]. diff --git a/dart/test/flat_buffers_test.dart b/dart/test/flat_buffers_test.dart index b536ecd8..ff77ff37 100644 --- a/dart/test/flat_buffers_test.dart +++ b/dart/test/flat_buffers_test.dart @@ -763,6 +763,28 @@ class ObjectAPITest { // final monster3 = monster2.unpack(); // MonsterT // expect(monster3.toString(), monster.toString()); } + + void test_Lists() { + // Ensure unpack() reads lists eagerly by reusing the same builder and + // overwriting data. Why: because standard reader reads lists lazily... + final fbb = Builder(); + + final object1 = example.TypeAliasesT(v8: [1, 2, 3], vf64: [5, 6]); + final data1 = fbb.finish(object1.pack(fbb)); + final object1Read = example.TypeAliases(data1).unpack(); + + // overwrite the original buffer by writing to the same builder + fbb.reset(); + final object2 = example.TypeAliasesT(v8: [7, 8, 9], vf64: [10, 11]); + final data2 = fbb.finish(object2.pack(fbb)); + final object2Read = example.TypeAliases(data2).unpack(); + + // this is fine even with lazy lists: + expect(object2.toString(), object2Read.toString()); + + // this fails with lazy lists: + expect(object1.toString(), object1Read.toString()); + } } class StringListWrapperImpl { diff --git a/dart/test/monster_test_my_game.example_generated.dart b/dart/test/monster_test_my_game.example_generated.dart index 36ada7d5..ca4efd1c 100644 --- a/dart/test/monster_test_my_game.example_generated.dart +++ b/dart/test/monster_test_my_game.example_generated.dart @@ -1117,15 +1117,15 @@ class Monster { mana: mana, hp: hp, name: name, - inventory: inventory, + inventory: const fb.ListReader<int>(const fb.Uint8Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 14), color: color, testType: testType, test: test, test4: test4?.map((e) => e.unpack()).toList(), - testarrayofstring: testarrayofstring, + testarrayofstring: const fb.ListReader<String>(const fb.StringReader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 24), testarrayoftables: testarrayoftables?.map((e) => e.unpack()).toList(), enemy: enemy?.unpack(), - testnestedflatbuffer: testnestedflatbuffer, + testnestedflatbuffer: const fb.ListReader<int>(const fb.Uint8Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 30), testempty: testempty?.unpack(), testbool: testbool, testhashs32Fnv1: testhashs32Fnv1, @@ -1136,32 +1136,32 @@ class Monster { testhashu32Fnv1a: testhashu32Fnv1a, testhashs64Fnv1a: testhashs64Fnv1a, testhashu64Fnv1a: testhashu64Fnv1a, - testarrayofbools: testarrayofbools, + testarrayofbools: const fb.ListReader<bool>(const fb.BoolReader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 52), testf: testf, testf2: testf2, testf3: testf3, - testarrayofstring2: testarrayofstring2, + testarrayofstring2: const fb.ListReader<String>(const fb.StringReader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 60), testarrayofsortedstruct: testarrayofsortedstruct?.map((e) => e.unpack()).toList(), - flex: flex, + flex: const fb.ListReader<int>(const fb.Uint8Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 64), test5: test5?.map((e) => e.unpack()).toList(), - vectorOfLongs: vectorOfLongs, - vectorOfDoubles: vectorOfDoubles, + vectorOfLongs: const fb.ListReader<int>(const fb.Int64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 68), + vectorOfDoubles: const fb.ListReader<double>(const fb.Float64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 70), parentNamespaceTest: parentNamespaceTest?.unpack(), vectorOfReferrables: vectorOfReferrables?.map((e) => e.unpack()).toList(), singleWeakReference: singleWeakReference, - vectorOfWeakReferences: vectorOfWeakReferences, + vectorOfWeakReferences: const fb.ListReader<int>(const fb.Uint64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 78), vectorOfStrongReferrables: vectorOfStrongReferrables?.map((e) => e.unpack()).toList(), coOwningReference: coOwningReference, - vectorOfCoOwningReferences: vectorOfCoOwningReferences, + vectorOfCoOwningReferences: const fb.ListReader<int>(const fb.Uint64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 84), nonOwningReference: nonOwningReference, - vectorOfNonOwningReferences: vectorOfNonOwningReferences, + vectorOfNonOwningReferences: const fb.ListReader<int>(const fb.Uint64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 88), anyUniqueType: anyUniqueType, anyUnique: anyUnique, anyAmbiguousType: anyAmbiguousType, anyAmbiguous: anyAmbiguous, - vectorOfEnums: vectorOfEnums, + vectorOfEnums: const fb.ListReader<Color>(Color.reader, lazy: false).vTableGetNullable(_bc, _bcOffset, 98), signedEnum: signedEnum, - testrequirednestedflatbuffer: testrequirednestedflatbuffer, + testrequirednestedflatbuffer: const fb.ListReader<int>(const fb.Uint8Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 102), scalarKeySortedTables: scalarKeySortedTables?.map((e) => e.unpack()).toList()); static int pack(fb.Builder fbBuilder, MonsterT? object) { @@ -1966,8 +1966,8 @@ class TypeAliases { u64: u64, f32: f32, f64: f64, - v8: v8, - vf64: vf64); + v8: const fb.ListReader<int>(const fb.Int8Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 24), + vf64: const fb.ListReader<double>(const fb.Float64Reader(), lazy: false).vTableGetNullable(_bc, _bcOffset, 26)); static int pack(fb.Builder fbBuilder, TypeAliasesT? object) { if (object == null) return 0; |