Unverified Commit 32c021bd authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] use Uint8List for SMC (#100582)

parent 015732c7
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:math' as math;
import 'dart:typed_data'; import 'dart:typed_data';
/// Write-only buffer for incrementally building a [ByteData] instance. /// Write-only buffer for incrementally building a [ByteData] instance.
...@@ -13,30 +14,59 @@ import 'dart:typed_data'; ...@@ -13,30 +14,59 @@ import 'dart:typed_data';
class WriteBuffer { class WriteBuffer {
/// Creates an interface for incrementally building a [ByteData] instance. /// Creates an interface for incrementally building a [ByteData] instance.
factory WriteBuffer() { factory WriteBuffer() {
final List<int> buffer = <int>[];
final ByteData eightBytes = ByteData(8); final ByteData eightBytes = ByteData(8);
final Uint8List eightBytesAsList = eightBytes.buffer.asUint8List(); final Uint8List eightBytesAsList = eightBytes.buffer.asUint8List();
return WriteBuffer._(buffer, eightBytes, eightBytesAsList); return WriteBuffer._(Uint8List(8), eightBytes, eightBytesAsList);
} }
WriteBuffer._(this._buffer, this._eightBytes, this._eightBytesAsList); WriteBuffer._(this._buffer, this._eightBytes, this._eightBytesAsList);
List<int> _buffer; Uint8List _buffer;
int _currentSize = 0;
bool _isDone = false; bool _isDone = false;
final ByteData _eightBytes; final ByteData _eightBytes;
final Uint8List _eightBytesAsList; final Uint8List _eightBytesAsList;
static final Uint8List _zeroBuffer = Uint8List(8); static final Uint8List _zeroBuffer = Uint8List(8);
void _add(int byte) {
if (_currentSize == _buffer.length) {
_resize();
}
_buffer[_currentSize] = byte;
_currentSize += 1;
}
void _append(Uint8List other) {
final int newSize = _currentSize + other.length;
if (newSize >= _buffer.length) {
_resize(newSize);
}
_buffer.setRange(_currentSize, newSize, other);
_currentSize += other.length;
}
void _addAll(Uint8List data, [int start = 0, int? end]) { void _addAll(Uint8List data, [int start = 0, int? end]) {
for (int i = start; i < (end ?? _eightBytesAsList.length); i++) { final int newEnd = end ?? _eightBytesAsList.length;
_buffer.add(data[i]); final int newSize = _currentSize + (newEnd - start);
if (newSize >= _buffer.length) {
_resize(newSize);
} }
_buffer.setRange(_currentSize, newSize, data);
_currentSize = newSize;
}
void _resize([int? requiredLength]) {
final int doubleLength = _buffer.length * 2;
final int newLength = math.max(requiredLength ?? 0, doubleLength);
final Uint8List newBuffer = Uint8List(newLength);
newBuffer.setRange(0, _buffer.length, _buffer);
_buffer = newBuffer;
} }
/// Write a Uint8 into the buffer. /// Write a Uint8 into the buffer.
void putUint8(int byte) { void putUint8(int byte) {
assert(!_isDone); assert(!_isDone);
_buffer.add(byte); _add(byte);
} }
/// Write a Uint16 into the buffer. /// Write a Uint16 into the buffer.
...@@ -78,40 +108,40 @@ class WriteBuffer { ...@@ -78,40 +108,40 @@ class WriteBuffer {
/// Write all the values from a [Uint8List] into the buffer. /// Write all the values from a [Uint8List] into the buffer.
void putUint8List(Uint8List list) { void putUint8List(Uint8List list) {
assert(!_isDone); assert(!_isDone);
_buffer.addAll(list); _append(list);
} }
/// Write all the values from an [Int32List] into the buffer. /// Write all the values from an [Int32List] into the buffer.
void putInt32List(Int32List list) { void putInt32List(Int32List list) {
assert(!_isDone); assert(!_isDone);
_alignTo(4); _alignTo(4);
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length)); _append(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length));
} }
/// Write all the values from an [Int64List] into the buffer. /// Write all the values from an [Int64List] into the buffer.
void putInt64List(Int64List list) { void putInt64List(Int64List list) {
assert(!_isDone); assert(!_isDone);
_alignTo(8); _alignTo(8);
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); _append(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} }
/// Write all the values from a [Float32List] into the buffer. /// Write all the values from a [Float32List] into the buffer.
void putFloat32List(Float32List list) { void putFloat32List(Float32List list) {
assert(!_isDone); assert(!_isDone);
_alignTo(4); _alignTo(4);
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length)); _append(list.buffer.asUint8List(list.offsetInBytes, 4 * list.length));
} }
/// Write all the values from a [Float64List] into the buffer. /// Write all the values from a [Float64List] into the buffer.
void putFloat64List(Float64List list) { void putFloat64List(Float64List list) {
assert(!_isDone); assert(!_isDone);
_alignTo(8); _alignTo(8);
_buffer.addAll(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length)); _append(list.buffer.asUint8List(list.offsetInBytes, 8 * list.length));
} }
void _alignTo(int alignment) { void _alignTo(int alignment) {
assert(!_isDone); assert(!_isDone);
final int mod = _buffer.length % alignment; final int mod = _currentSize % alignment;
if (mod != 0) { if (mod != 0) {
_addAll(_zeroBuffer, 0, alignment - mod); _addAll(_zeroBuffer, 0, alignment - mod);
} }
...@@ -122,8 +152,8 @@ class WriteBuffer { ...@@ -122,8 +152,8 @@ class WriteBuffer {
if (_isDone) { if (_isDone) {
throw StateError('done() must not be called more than once on the same $runtimeType.'); throw StateError('done() must not be called more than once on the same $runtimeType.');
} }
final ByteData result = Uint8List.fromList(_buffer).buffer.asByteData(); final ByteData result = _buffer.buffer.asByteData(0, _currentSize);
_buffer = <int>[]; _buffer = Uint8List(0);
_isDone = true; _isDone = true;
return result; return result;
} }
......
...@@ -9,6 +9,12 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -9,6 +9,12 @@ import 'package:flutter_test/flutter_test.dart';
void main() { void main() {
group('Write and read buffer round-trip', () { group('Write and read buffer round-trip', () {
test('of empty buffer', () {
final WriteBuffer write = WriteBuffer();
final ByteData written = write.done();
expect(written.lengthInBytes, 0);
});
test('of single byte', () { test('of single byte', () {
final WriteBuffer write = WriteBuffer(); final WriteBuffer write = WriteBuffer();
write.putUint8(201); write.putUint8(201);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment