Skip to content

Commit

Permalink
Return dart:typed_data equivalent for Float32List and Float64List
Browse files Browse the repository at this point in the history
* This involved fixing writeListFloat32 and writeListFloat64 by
  preventing misalignment from occurring
  • Loading branch information
NotTsunami committed Feb 17, 2025
1 parent dcede74 commit 9210c38
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 26 deletions.
75 changes: 50 additions & 25 deletions dart/lib/flat_buffers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class BufferContext {
@pragma('vm:prefer-inline')
Uint8List _asUint8List(int offset, int length) =>
_buffer.buffer.asUint8List(_buffer.offsetInBytes + offset, length);

@pragma('vm:prefer-inline')
Int8List _asInt8List(int offset, int length) =>
_buffer.buffer.asInt8List(_buffer.offsetInBytes + offset, length);
Expand All @@ -58,6 +58,20 @@ class BufferContext {
return _buffer.buffer.asUint32List(_buffer.offsetInBytes + offset, length);
}

@pragma('vm:prefer-inline')
Float32List _asFloat32List(int offset, int length) {
assert(Endian.host == Endian.little);
return _buffer.buffer
.asFloat32List(_buffer.offsetInBytes + offset, length);
}

@pragma('vm:prefer-inline')
Float64List _asFloat64List(int offset, int length) {
assert(Endian.host == Endian.little);
return _buffer.buffer
.asFloat64List(_buffer.offsetInBytes + offset, length);
}

@pragma('vm:prefer-inline')
double _getFloat64(int offset) => _buffer.getFloat64(offset, Endian.little);

Expand Down Expand Up @@ -540,7 +554,8 @@ class Builder {
/// Write the given list of 64-bit float [values].
int writeListFloat64(List<double> values) {
assert(!_inVTable);
_prepare(_sizeofFloat64, values.length, additionalBytes: _sizeofUint32);
_prepare(_sizeofUint32, 1,
additionalBytes: values.length * _sizeofFloat64);
final result = _tail;
var tail = _tail;
_setUint32AtTail(tail, values.length);
Expand All @@ -555,7 +570,8 @@ class Builder {
/// Write the given list of 32-bit float [values].
int writeListFloat32(List<double> values) {
assert(!_inVTable);
_prepare(_sizeofFloat32, 1 + values.length);
_prepare(_sizeofUint32, 1,
additionalBytes: values.length * _sizeofFloat32);
final result = _tail;
var tail = _tail;
_setUint32AtTail(tail, values.length);
Expand Down Expand Up @@ -894,8 +910,6 @@ class BoolReader extends Reader<bool> {
/// The reader of lists of 64-bit float values.
///
/// The returned unmodifiable lists lazily read values on access.
///
/// TODO: Return dart:typed_data Float64List type on LE systems
class Float64ListReader extends Reader<List<double>> {
const Float64ListReader();

Expand All @@ -905,15 +919,20 @@ class Float64ListReader extends Reader<List<double>> {

@override
@pragma('vm:prefer-inline')
List<double> read(BufferContext bc, int offset) =>
_FbFloat64List(bc, bc.derefObject(offset));
List<double> read(BufferContext bc, int offset) {
if (Endian.host == Endian.little) {
final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asFloat64List(listOffset + _sizeofUint32, length);
} else {
return _FbFloat64List(bc, bc.derefObject(offset));
}
}
}

/// The reader of lists of 32-bit float values.
///
/// The returned unmodifiable lists lazily read values on access.
///
/// TODO: Return dart:typed_data Float32List type on LE systems
class Float32ListReader extends Reader<List<double>> {
const Float32ListReader();

Expand All @@ -923,8 +942,15 @@ class Float32ListReader extends Reader<List<double>> {

@override
@pragma('vm:prefer-inline')
List<double> read(BufferContext bc, int offset) =>
_FbFloat32List(bc, bc.derefObject(offset));
List<double> read(BufferContext bc, int offset) {
if (Endian.host == Endian.little) {
final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asFloat32List(listOffset + _sizeofUint32, length);
} else {
return _FbFloat32List(bc, bc.derefObject(offset));
}
}
}

class Float64Reader extends Reader<double> {
Expand Down Expand Up @@ -1146,14 +1172,13 @@ class Uint32ListReader extends Reader<List<int>> {
@pragma('vm:prefer-inline')
List<int> read(BufferContext bc, int offset) {
if (Endian.host == Endian.little) {
final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asUint32List(listOffset + _sizeofUint32, length);
} else {
return _FbUint32List(bc, bc.derefObject(offset));
}
}

final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asUint32List(listOffset + _sizeofUint32, length);
} else {
return _FbUint32List(bc, bc.derefObject(offset));
}
}
}

/// The reader of unsigned 64-bit integers.
Expand Down Expand Up @@ -1198,12 +1223,12 @@ class Uint16ListReader extends Reader<List<int>> {
@pragma('vm:prefer-inline')
List<int> read(BufferContext bc, int offset) {
if (Endian.host == Endian.little) {
final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asUint16List(listOffset + _sizeofUint32, length);
} else {
return _FbUint16List(bc, bc.derefObject(offset));
}
final listOffset = bc.derefObject(offset);
final length = bc._getUint32(listOffset);
return bc._asUint16List(listOffset + _sizeofUint32, length);
} else {
return _FbUint16List(bc, bc.derefObject(offset));
}
}
}

Expand Down
23 changes: 22 additions & 1 deletion dart/test/flat_buffers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -542,9 +542,19 @@ class BuilderTest {
byteList = builder.buffer;
}

// verify alignment
ByteData byteData = ByteData.view(Uint8List.fromList(byteList).buffer);
int vectorOffset = byteData.getUint32(0, Endian.little);
expect(vectorOffset, 8);
int length = byteData.getUint32(vectorOffset, Endian.little);
expect(length, values.length);
int floatDataOffset = vectorOffset + 4;
expect(floatDataOffset % 8, 0);

// read and verify
BufferContext buf = BufferContext.fromBytes(byteList);
List<double> items = const Float64ListReader().read(buf, 0);
expect(items is Float64List, Endian.host == Endian.little);
expect(items, hasLength(values.length));
for (int i = 0; i < values.length; i++) {
expect(values[i], closeTo(items[i], .001));
Expand All @@ -561,10 +571,21 @@ class BuilderTest {
builder.finish(offset);
byteList = builder.buffer;
}

// verify alignment
ByteData byteData = ByteData.view(Uint8List.fromList(byteList).buffer);
int vectorOffset = byteData.getUint32(0, Endian.little);
expect(vectorOffset, 4);
int length = byteData.getUint32(vectorOffset, Endian.little);
expect(length, values.length);
int floatDataOffset = vectorOffset + 4;
expect(floatDataOffset % 4, 0);

// read and verify
BufferContext buf = BufferContext.fromBytes(byteList);
List<double> items = const Float32ListReader().read(buf, 0);
expect(items, hasLength(5));
expect(items is Float32List, Endian.host == Endian.little);
expect(items, hasLength(values.length));
for (int i = 0; i < values.length; i++) {
expect(values[i], closeTo(items[i], .001));
}
Expand Down

0 comments on commit 9210c38

Please sign in to comment.