Support Float32Lists in StandardMessageCodec (#72613) (#83318)

This commit is contained in:
Jeff Ward 2021-07-20 17:31:07 -04:00 committed by GitHub
parent 376584289c
commit 841beff520
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 7 deletions

View file

@ -61,6 +61,17 @@ class _TestAppState extends State<TestApp> {
0,
0x7fffffffffffffff,
]);
static final Float32List someFloat32s = Float32List.fromList(<double>[
double.nan,
double.negativeInfinity,
-double.maxFinite,
-double.minPositive,
-0.0,
0.0,
double.minPositive,
double.maxFinite,
double.infinity,
]);
static final Float64List someFloat64s =
Float64List.fromList(<double>[
double.nan,
@ -142,6 +153,7 @@ class _TestAppState extends State<TestApp> {
() => basicStandardHandshake(someUint8s),
() => basicStandardHandshake(someInt32s),
() => basicStandardHandshake(someInt64s),
() => basicStandardHandshake(someFloat32s),
() => basicStandardHandshake(someFloat64s),
() => basicStandardHandshake(<dynamic>[]),
() => basicStandardHandshake(aList),

View file

@ -89,6 +89,13 @@ class WriteBuffer {
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
}
/// Write all the values from a [Float32List] into the buffer.
void putFloat32List(Float32List list) {
assert(!_isDone);
_alignTo(4);
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length));
}
/// Write all the values from a [Float64List] into the buffer.
void putFloat64List(Float64List list) {
assert(!_isDone);
@ -197,6 +204,14 @@ class ReadBuffer {
return list;
}
/// Reads the given number of Float32s from the buffer
Float32List getFloat32List(int length) {
_alignTo(4);
final Float32List list = data.buffer.asFloat32List(data.offsetInBytes + _position, length);
_position += 4 * length;
return list;
}
/// Reads the given number of Float64s from the buffer.
Float64List getFloat64List(int length) {
_alignTo(8);

View file

@ -274,12 +274,13 @@ class StandardMessageCodec implements MessageCodec<Object?> {
// * Strings are encoded using their UTF-8 representation. First the length
// of that in bytes is encoded using the expanding format, then follows the
// UTF-8 encoding itself.
// * Uint8Lists, Int32Lists, Int64Lists, and Float64Lists are encoded by first
// encoding the list's element count in the expanding format, then the
// smallest number of zero bytes needed to align the position in the full
// message with a multiple of the number of bytes per element, then the
// encoding of the list elements themselves, end-to-end with no additional
// type information, using two's complement or IEEE 754 as applicable.
// * Uint8Lists, Int32Lists, Int64Lists, Float32Lists, and Float64Lists are
// encoded by first encoding the list's element count in the expanding
// format, then the smallest number of zero bytes needed to align the
// position in the full message with a multiple of the number of bytes per
// element, then the encoding of the list elements themselves, end-to-end
// with no additional type information, using two's complement or IEEE 754
// as applicable.
// * Lists are encoded by first encoding their length in the expanding format,
// then follows the recursive encoding of each element value, including the
// type byte (Lists are assumed to be heterogeneous).
@ -303,6 +304,7 @@ class StandardMessageCodec implements MessageCodec<Object?> {
static const int _valueFloat64List = 11;
static const int _valueList = 12;
static const int _valueMap = 13;
static const int _valueFloat32List = 14;
@override
ByteData? encodeMessage(Object? message) {
@ -346,7 +348,8 @@ class StandardMessageCodec implements MessageCodec<Object?> {
/// * Float64List = 11
/// * List = 12
/// * Map = 13
/// * Reserved for future expansion: 14..127
/// * Float32List = 14
/// * Reserved for future expansion: 15..127
///
/// The codec can be extended by overriding this method, calling super
/// for values that the extension does not handle. Type discriminators
@ -398,6 +401,10 @@ class StandardMessageCodec implements MessageCodec<Object?> {
buffer.putUint8(_valueInt64List);
writeSize(buffer, value.length);
buffer.putInt64List(value);
} else if (value is Float32List) {
buffer.putUint8(_valueFloat32List);
writeSize(buffer, value.length);
buffer.putFloat32List(value);
} else if (value is Float64List) {
buffer.putUint8(_valueFloat64List);
writeSize(buffer, value.length);
@ -463,6 +470,9 @@ class StandardMessageCodec implements MessageCodec<Object?> {
case _valueInt64List:
final int length = readSize(buffer);
return buffer.getInt64List(length);
case _valueFloat32List:
final int length = readSize(buffer);
return buffer.getFloat32List(length);
case _valueFloat64List:
final int length = readSize(buffer);
return buffer.getFloat64List(length);

View file

@ -87,6 +87,19 @@ void main() {
read.getUint8();
expect(read.getInt64List(3), equals(integers));
}, skip: kIsWeb);
test('of float list when unaligned', () {
final Float32List floats = Float32List.fromList(<double>[3.14, double.nan]);
final WriteBuffer write = WriteBuffer();
write.putUint8(9);
write.putFloat32List(floats);
final ByteData written = write.done();
expect(written.lengthInBytes, equals(12));
final ReadBuffer read = ReadBuffer(written);
read.getUint8();
final Float32List readFloats = read.getFloat32List(2);
expect(readFloats[0], closeTo(3.14, 0.0001));
expect(readFloats[1], isNaN);
});
test('of double list when unaligned', () {
final Float64List doubles = Float64List.fromList(<double>[3.14, double.nan]);
final WriteBuffer write = WriteBuffer();

View file

@ -224,6 +224,17 @@ void main() {
double.infinity,
double.nan,
]),
Float32List.fromList(<double>[
double.negativeInfinity,
-double.maxFinite,
-double.minPositive,
-0.0,
0.0,
double.minPositive,
double.maxFinite,
double.infinity,
double.nan,
]),
<dynamic>['nested', <dynamic>[]],
<dynamic, dynamic>{'a': 'nested', null: <dynamic, dynamic>{}},
'world',

View file

@ -54,6 +54,8 @@ bool deepEqualsTypedData(TypedData valueA, TypedData valueB) {
return valueB is Int32List && deepEqualsList(valueA, valueB);
if (valueA is Int64List)
return valueB is Int64List && deepEqualsList(valueA, valueB);
if (valueA is Float32List)
return valueB is Float32List && deepEqualsList(valueA, valueB);
if (valueA is Float64List)
return valueB is Float64List && deepEqualsList(valueA, valueB);
throw 'Unexpected typed data: $valueA';