@@ -41,12 +41,14 @@ class BufferContext {
4141
4242 ByteData get buffer => _buffer;
4343
44+ /// Create from a FlatBuffer represented by a list of bytes (uint8).
4445 factory BufferContext .fromBytes (List <int > byteList) {
4546 Uint8List uint8List = _asUint8List (byteList);
4647 ByteData buf = new ByteData .view (uint8List.buffer, uint8List.offsetInBytes);
47- return new BufferContext (buf);
48+ return BufferContext (buf);
4849 }
4950
51+ /// Create from a FlatBuffer represented by ByteData.
5052 BufferContext (this ._buffer);
5153
5254 @pragma ('vm:prefer-inline' )
@@ -125,16 +127,17 @@ abstract class ObjectBuilder {
125127
126128/// Class that helps building flat buffers.
127129class Builder {
130+ bool _finished = false ;
131+
128132 final int initialSize;
129133
130134 /// The list of existing VTable(s).
131- //final List<_VTable> _vTables = <_VTable>[];
132135 final List <int > _vTables = List <int >.filled (16 , 0 , growable: true )
133136 ..length = 0 ;
134137
135- late ByteData _buf;
138+ ByteData _buf;
136139
137- Allocator _allocator;
140+ final Allocator _allocator;
138141
139142 /// The maximum alignment that has been seen so far. If [_buf] has to be
140143 /// reallocated in the future (to insert room at its start for more bytes) the
@@ -146,7 +149,7 @@ class Builder {
146149 int _tail = 0 ;
147150
148151 /// The location of the end of the current table, measured in bytes from the
149- /// end of [_buf] , or `null` if a table is not currently being built .
152+ /// end of [_buf] .
150153 int _currentTableEndTail = 0 ;
151154
152155 _VTable ? _currentVTable;
@@ -163,17 +166,18 @@ class Builder {
163166 /// automatically grow the array if/as needed. `internStrings` , if set to
164167 /// true, will cause [writeString] to pool strings in the buffer so that
165168 /// identical strings will always use the same offset in tables.
166- Builder (
167- { this .initialSize: 1024 ,
168- bool internStrings = false ,
169- Allocator ? allocator})
170- : _allocator = allocator ?? DefaultAllocator () {
171- _buf = _allocator .allocate (initialSize);
172- if (internStrings == true ) {
169+ Builder ({
170+ this .initialSize: 1024 ,
171+ bool internStrings = false ,
172+ Allocator allocator = const DefaultAllocator (),
173+ }) : _allocator = allocator,
174+ _buf = allocator .allocate (initialSize) {
175+ if (internStrings) {
173176 _strings = new Map <String , int >();
174177 }
175178 }
176179
180+ /// Calculate the finished buffer size (aligned).
177181 int size () => _tail + ((- _tail) & (_maxAlign - 1 ));
178182
179183 /// Add the [field] with the given boolean [value] . The field is not added if
@@ -323,20 +327,21 @@ class Builder {
323327 _prepare (_sizeofInt32, 1 );
324328 int tableTail = _tail;
325329 // Prepare the size of the current table.
326- _currentVTable! .tableSize = tableTail - _currentTableEndTail;
330+ final currentVTable = _currentVTable! ;
331+ currentVTable.tableSize = tableTail - _currentTableEndTail;
327332 // Prepare the VTable to use for the current table.
328333 int ? vTableTail;
329334 {
330- _currentVTable ! .computeFieldOffsets (tableTail);
335+ currentVTable .computeFieldOffsets (tableTail);
331336 // Try to find an existing compatible VTable.
332337 // Search backward - more likely to have recently used one
333338 for (int i = _vTables.length - 1 ; i >= 0 ; i-- ) {
334339 final int vt2Offset = _vTables[i];
335340 final int vt2Start = _buf.lengthInBytes - vt2Offset;
336341 final int vt2Size = _buf.getUint16 (vt2Start, Endian .little);
337342
338- if (_currentVTable ! ._vTableSize == vt2Size &&
339- _currentVTable ! ._offsetsMatch (vt2Start, _buf)) {
343+ if (currentVTable ._vTableSize == vt2Size &&
344+ currentVTable ._offsetsMatch (vt2Start, _buf)) {
340345 vTableTail = vt2Offset;
341346 break ;
342347 }
@@ -345,9 +350,9 @@ class Builder {
345350 if (vTableTail == null ) {
346351 _prepare (_sizeofUint16, _currentVTable! .numOfUint16);
347352 vTableTail = _tail;
348- _currentVTable ! .tail = vTableTail;
349- _currentVTable ! .output (_buf, _buf.lengthInBytes - _tail);
350- _vTables.add (_currentVTable ! .tail);
353+ currentVTable .tail = vTableTail;
354+ currentVTable .output (_buf, _buf.lengthInBytes - _tail);
355+ _vTables.add (currentVTable .tail);
351356 }
352357 }
353358 // Set the VTable offset.
@@ -357,11 +362,9 @@ class Builder {
357362 return tableTail;
358363 }
359364
360- /// This method low level method can be used to return a raw piece of the buffer
361- /// after using the the put* methods.
362- ///
363- /// Most clients should prefer calling [finish] .
364- Uint8List lowFinish () {
365+ /// Returns the finished buffer. You must call [finish] before accessing this.
366+ Uint8List get buffer {
367+ assert (_finished);
365368 final finishedSize = size ();
366369 return _buf.buffer
367370 .asUint8List (_buf.lengthInBytes - finishedSize, finishedSize);
@@ -372,7 +375,8 @@ class Builder {
372375 /// written object. If [fileIdentifier] is specified (and not `null` ), it is
373376 /// interpreted as a 4-byte Latin-1 encoded string that should be placed at
374377 /// bytes 4-7 of the file.
375- Uint8List finish (int offset, [String ? fileIdentifier]) {
378+ void finish (int offset, [String ? fileIdentifier]) {
379+ assert (! _finished);
376380 final sizeBeforePadding = size ();
377381 final requiredBytes = _sizeofUint32 * (fileIdentifier == null ? 1 : 2 );
378382 _prepare (max (requiredBytes, _maxAlign), 1 );
@@ -391,9 +395,7 @@ class Builder {
391395 i++ ) {
392396 _setUint8AtTail (_buf, i, 0 );
393397 }
394-
395- return _buf.buffer
396- .asUint8List (_buf.lengthInBytes - finishedSize, finishedSize);
398+ _finished = true ;
397399 }
398400
399401 /// Writes a Float64 to the tail of the buffer after preparing space for it.
@@ -478,6 +480,7 @@ class Builder {
478480
479481 /// Reset the builder and make it ready for filling a new buffer.
480482 void reset () {
483+ _finished = false ;
481484 _maxAlign = 1 ;
482485 _tail = 0 ;
483486 _currentVTable = null ;
@@ -753,7 +756,7 @@ class Builder {
753756 int deltaCapacity = desiredNewCapacity - oldCapacity;
754757 deltaCapacity += (- deltaCapacity) & (_maxAlign - 1 );
755758 int newCapacity = oldCapacity + deltaCapacity;
756- _buf = _allocator.reallocateDownward (_buf, newCapacity, _tail, 0 );
759+ _buf = _allocator.resize (_buf, newCapacity, _tail, 0 );
757760 }
758761 }
759762
@@ -972,13 +975,11 @@ abstract class Reader<T> {
972975 /// Read the value at the given [offset] in [bc] .
973976 T read (BufferContext bc, int offset);
974977
978+ /// Read the value of the given [field] in the given [object] .
975979 @pragma ('vm:prefer-inline' )
976- int _vTableFieldOffset (BufferContext object, int offset, int field) {
977- int vTableSOffset = object._getInt32 (offset);
978- int vTableOffset = offset - vTableSOffset;
979- int vTableSize = object._getUint16 (vTableOffset);
980- if (field >= vTableSize) return 0 ;
981- return object._getUint16 (vTableOffset + field);
980+ T vTableGet (BufferContext object, int offset, int field, T defaultValue) {
981+ int fieldOffset = _vTableFieldOffset (object, offset, field);
982+ return fieldOffset == 0 ? defaultValue : read (object, offset + fieldOffset);
982983 }
983984
984985 /// Read the value of the given [field] in the given [object] .
@@ -988,11 +989,13 @@ abstract class Reader<T> {
988989 return fieldOffset == 0 ? null : read (object, offset + fieldOffset);
989990 }
990991
991- /// Read the value of the given [field] in the given [object] .
992992 @pragma ('vm:prefer-inline' )
993- T vTableGet (BufferContext object, int offset, int field, T defaultValue) {
994- int fieldOffset = _vTableFieldOffset (object, offset, field);
995- return fieldOffset == 0 ? defaultValue : read (object, offset + fieldOffset);
993+ int _vTableFieldOffset (BufferContext object, int offset, int field) {
994+ int vTableSOffset = object._getInt32 (offset);
995+ int vTableOffset = offset - vTableSOffset;
996+ int vTableSize = object._getUint16 (vTableOffset);
997+ if (field >= vTableSize) return 0 ;
998+ return object._getUint16 (vTableOffset + field);
996999 }
9971000}
9981001
@@ -1335,25 +1338,29 @@ class _VTable {
13351338 }
13361339}
13371340
1338- // Allocator interface. This is flatbuffers-specific - only for [Builder] .
1341+ /// The interface that [Builder] uses to allocate buffers for encoding .
13391342abstract class Allocator {
1343+ const Allocator ();
1344+
1345+ /// Allocate a [ByteData] buffer of a given size.
13401346 ByteData allocate (int size);
13411347
1348+ /// Free the given [ByteData] buffer previously allocated by [allocate] .
13421349 void deallocate (ByteData data);
13431350
13441351 /// Reallocate [newSize] bytes of memory, replacing the old [oldData] . This
13451352 /// grows downwards, and is intended specifically for use with [Builder] .
13461353 /// Params [inUseBack] and [inUseFront] indicate how much of [oldData] is
13471354 /// actually in use at each end, and needs to be copied.
1348- ByteData reallocateDownward (
1355+ ByteData resize (
13491356 ByteData oldData, int newSize, int inUseBack, int inUseFront) {
13501357 final newData = allocate (newSize);
13511358 _copyDownward (oldData, newData, inUseBack, inUseFront);
13521359 deallocate (oldData);
13531360 return newData;
13541361 }
13551362
1356- /// Called by [reallocate ] to copy memory from [oldData] to [newData] . Only
1363+ /// Called by [resize ] to copy memory from [oldData] to [newData] . Only
13571364 /// memory of size [inUseFront] and [inUseBack] will be copied from the front
13581365 /// and back of the old memory allocation.
13591366 void _copyDownward (
@@ -1373,6 +1380,8 @@ abstract class Allocator {
13731380}
13741381
13751382class DefaultAllocator extends Allocator {
1383+ const DefaultAllocator ();
1384+
13761385 @override
13771386 ByteData allocate (int size) => ByteData (size);
13781387
0 commit comments