[framework] use Uint8List for SMC (#100582)

This commit is contained in:
Jonah Williams 2022-03-22 15:00:13 -07:00 committed by GitHub
parent 015732c732
commit 32c021bd33
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 51 additions and 15 deletions

View file

@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:math' as math;
import 'dart:typed_data';
/// Write-only buffer for incrementally building a [ByteData] instance.
@ -13,30 +14,59 @@ import 'dart:typed_data';
class WriteBuffer {
/// Creates an interface for incrementally building a [ByteData] instance.
factory WriteBuffer() {
final List<int> buffer = <int>[];
final ByteData eightBytes = ByteData(8);
final Uint8List eightBytesAsList = eightBytes.buffer.asUint8List();
return WriteBuffer._(buffer, eightBytes, eightBytesAsList);
return WriteBuffer._(Uint8List(8), eightBytes, eightBytesAsList);
}
WriteBuffer._(this._buffer, this._eightBytes, this._eightBytesAsList);
List<int> _buffer;
Uint8List _buffer;
int _currentSize = 0;
bool _isDone = false;
final ByteData _eightBytes;
final Uint8List _eightBytesAsList;
static final Uint8List _zeroBuffer = Uint8List(8);
void _addAll(Uint8List data, [int start = 0, int? end]) {
for (int i = start; i < (end ?? _eightBytesAsList.length); i++) {
_buffer.add(data[i]);
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]) {
final int newEnd = end ?? _eightBytesAsList.length;
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.
void putUint8(int byte) {
assert(!_isDone);
_buffer.add(byte);
_add(byte);
}
/// Write a Uint16 into the buffer.
@ -78,40 +108,40 @@ class WriteBuffer {
/// Write all the values from a [Uint8List] into the buffer.
void putUint8List(Uint8List list) {
assert(!_isDone);
_buffer.addAll(list);
_append(list);
}
/// Write all the values from an [Int32List] into the buffer.
void putInt32List(Int32List list) {
assert(!_isDone);
_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.
void putInt64List(Int64List list) {
assert(!_isDone);
_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.
void putFloat32List(Float32List list) {
assert(!_isDone);
_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.
void putFloat64List(Float64List list) {
assert(!_isDone);
_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) {
assert(!_isDone);
final int mod = _buffer.length % alignment;
final int mod = _currentSize % alignment;
if (mod != 0) {
_addAll(_zeroBuffer, 0, alignment - mod);
}
@ -122,8 +152,8 @@ class WriteBuffer {
if (_isDone) {
throw StateError('done() must not be called more than once on the same $runtimeType.');
}
final ByteData result = Uint8List.fromList(_buffer).buffer.asByteData();
_buffer = <int>[];
final ByteData result = _buffer.buffer.asByteData(0, _currentSize);
_buffer = Uint8List(0);
_isDone = true;
return result;
}

View file

@ -9,6 +9,12 @@ import 'package:flutter_test/flutter_test.dart';
void main() {
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', () {
final WriteBuffer write = WriteBuffer();
write.putUint8(201);