summaryrefslogtreecommitdiff
path: root/dart
diff options
context:
space:
mode:
authorIvan Dlugos <6349682+vaind@users.noreply.github.com>2021-07-09 18:55:34 +0200
committerGitHub <noreply@github.com>2021-07-09 09:55:34 -0700
commit3f77dc9a0e83f129e5284b86e24f7956d18826e5 (patch)
tree6cbacb08717d8d5496af9d28ff32da0670c1aabb /dart
parent838c93b84349ac126ff160bf5941e2a3d3219154 (diff)
downloadflatbuffers-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.dart26
-rw-r--r--dart/test/flat_buffers_test.dart22
-rw-r--r--dart/test/monster_test_my_game.example_generated.dart30
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;