| Index: pkg/fletchc/lib/src/shared_command_infrastructure.dart
|
| diff --git a/pkg/fletchc/lib/src/shared_command_infrastructure.dart b/pkg/fletchc/lib/src/shared_command_infrastructure.dart
|
| deleted file mode 100644
|
| index d9325af3144e68abdef4ad3c3792049ef4b0ea83..0000000000000000000000000000000000000000
|
| --- a/pkg/fletchc/lib/src/shared_command_infrastructure.dart
|
| +++ /dev/null
|
| @@ -1,223 +0,0 @@
|
| -// Copyright (c) 2015, the Dartino project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE.md file.
|
| -
|
| -/// Provides common infrastructure for reading commads from a [Stream].
|
| -///
|
| -/// We have two independent command kinds that follow the same scheme:
|
| -///
|
| -/// 1. ../vm_commands.dart
|
| -/// 2. hub/client_commands.dart
|
| -///
|
| -/// Both commands are serialized in this format (using little endian):
|
| -///
|
| -/// * Byte offset 0: one byte (code) which corresponds to an enum value.
|
| -/// * Byte offset 1: four bytes payload length (unsigned int).
|
| -/// * Byte offset 5: payload length bytes of payload.
|
| -library fletchc.src.command_transformer_builder;
|
| -
|
| -import 'dart:async' show
|
| - EventSink,
|
| - StreamTransformer;
|
| -
|
| -import 'dart:convert' show
|
| - ASCII;
|
| -
|
| -import 'dart:io' show
|
| - BytesBuilder;
|
| -
|
| -import 'dart:typed_data' show
|
| - ByteData,
|
| - Endianness,
|
| - TypedData,
|
| - Uint32List,
|
| - Uint8List;
|
| -
|
| -const Endianness commandEndianness = Endianness.LITTLE_ENDIAN;
|
| -
|
| -/// 32 bit package length + 8 bit code is 5 bytes.
|
| -const headerSize = 5;
|
| -
|
| -/// [C] is the command implementation class.
|
| -abstract class CommandTransformerBuilder<C> {
|
| - StreamTransformer<List<int>, C> build() {
|
| - BytesBuilder builder = new BytesBuilder(copy: false);
|
| -
|
| - ByteData toByteData(TypedData data, [int offset = 0, int length]) {
|
| - return data.buffer.asByteData(data.offsetInBytes + offset, length);
|
| - }
|
| -
|
| - void handleData(Uint8List data, EventSink<C> sink) {
|
| - builder.add(toUint8ListView(data));
|
| - Uint8List list = builder.takeBytes();
|
| -
|
| - ByteData view = toByteData(list);
|
| -
|
| - while (view.lengthInBytes >= headerSize) {
|
| - int length = view.getUint32(0, commandEndianness);
|
| - if ((view.lengthInBytes - headerSize) < length) {
|
| - // Not all of the payload has arrived yet.
|
| - break;
|
| - }
|
| - int code = view.getUint8(4);
|
| -
|
| - ByteData payload = toByteData(view, headerSize, length);
|
| -
|
| - C command = makeCommand(code, payload);
|
| -
|
| - if (command != null) {
|
| - sink.add(command);
|
| - } else {
|
| - sink.addError("Command not implemented yet: $code");
|
| - }
|
| -
|
| - view = toByteData(payload, length);
|
| - }
|
| -
|
| - if (view.lengthInBytes > 0) {
|
| - builder.add(toUint8ListView(view));
|
| - }
|
| - }
|
| -
|
| - void handleError(error, StackTrace stackTrace, EventSink<C> sink) {
|
| - sink.addError(error, stackTrace);
|
| - }
|
| -
|
| - void handleDone(EventSink<C> sink) {
|
| - List trailing = builder.takeBytes();
|
| - if (trailing.length != 0) {
|
| - sink.addError(
|
| - new StateError("Stream closed with trailing bytes : $trailing"));
|
| - }
|
| - sink.close();
|
| - }
|
| -
|
| - return new StreamTransformer<List<int>, C>.fromHandlers(
|
| - handleData: handleData,
|
| - handleError: handleError,
|
| - handleDone: handleDone);
|
| - }
|
| -
|
| - C makeCommand(int code, ByteData payload);
|
| -}
|
| -
|
| -Uint8List toUint8ListView(TypedData list, [int offset = 0, int length]) {
|
| - if (length == null) {
|
| - length = list.lengthInBytes;
|
| - }
|
| - return new Uint8List.view(list.buffer, list.offsetInBytes + offset, length);
|
| -}
|
| -
|
| -/// [E] is an enum.
|
| -class CommandBuffer<E> {
|
| - int position = headerSize;
|
| -
|
| - Uint8List list = new Uint8List(16);
|
| -
|
| - ByteData view;
|
| -
|
| - CommandBuffer() {
|
| - view = new ByteData.view(list.buffer, list.offsetInBytes);
|
| - }
|
| -
|
| - void growBytes(int size) {
|
| - while (position + size >= list.length) {
|
| - list = new Uint8List(list.length * 2)
|
| - ..setRange(0, list.length, list);
|
| - view = new ByteData.view(list.buffer, list.offsetInBytes);
|
| - }
|
| - }
|
| -
|
| - void addUint8(int value) {
|
| - growBytes(1);
|
| - view.setUint8(position++, value);
|
| - }
|
| -
|
| - void addUint32(int value) {
|
| - // TODO(ahe): The C++ appears to often read 32-bit values into a signed
|
| - // integer. Figure which is signed and which is unsigned.
|
| - growBytes(4);
|
| - view.setUint32(position, value, commandEndianness);
|
| - position += 4;
|
| - }
|
| -
|
| - void addUint64(int value) {
|
| - growBytes(8);
|
| - view.setUint64(position, value, commandEndianness);
|
| - position += 8;
|
| - }
|
| -
|
| - void addDouble(double value) {
|
| - growBytes(8);
|
| - view.setFloat64(position, value, commandEndianness);
|
| - position += 8;
|
| - }
|
| -
|
| - void addUint8List(List<int> value) {
|
| - growBytes(value.length);
|
| - list.setRange(position, position + value.length, value);
|
| - position += value.length;
|
| - }
|
| -
|
| - void addAsciiString(String value) {
|
| - addUint8List(ASCII.encode(value));
|
| - }
|
| -
|
| - void addBool(bool value) {
|
| - addUint8(value ? 1 : 0);
|
| - }
|
| -
|
| - void sendOn(Sink<List<int>> sink, E code) {
|
| - view.setUint32(0, position - headerSize, commandEndianness);
|
| - view.setUint8(4, (code as dynamic).index);
|
| - sink.add(new Uint8List.view(list.buffer, list.offsetInBytes, position));
|
| - }
|
| -
|
| - static bool readBoolFromBuffer(Uint8List buffer, int offset) {
|
| - return buffer[offset] != 0;
|
| - }
|
| -
|
| - static String readStringFromBuffer(Uint8List buffer, int offset, int length) {
|
| - const bytesPerCharacter = 4;
|
| - int numberOfCharacters = length ~/ bytesPerCharacter;
|
| - assert(length == numberOfCharacters * bytesPerCharacter);
|
| - if (((buffer.offsetInBytes + offset) % Uint32List.BYTES_PER_ELEMENT) != 0) {
|
| - // Uint32List.view throws ArgumentError if offset isn't muliple of 4.
|
| - buffer = new Uint8List.fromList(buffer);
|
| - }
|
| - return new String.fromCharCodes(
|
| - new Uint32List.view(
|
| - buffer.buffer, buffer.offsetInBytes + offset, numberOfCharacters));
|
| - }
|
| -
|
| - static String readAsciiStringFromBuffer(
|
| - Uint8List buffer, int offset, int length) {
|
| - return new String.fromCharCodes(
|
| - new Uint8List.view(
|
| - buffer.buffer, buffer.offsetInBytes + offset, length));
|
| - }
|
| -
|
| - static int readInt32FromBuffer(Uint8List buffer, int offset) {
|
| - return buffer.buffer.asByteData(buffer.offsetInBytes)
|
| - .getInt32(offset, commandEndianness);
|
| - }
|
| -
|
| - static int readInt64FromBuffer(Uint8List buffer, int offset) {
|
| - return buffer.buffer.asByteData(buffer.offsetInBytes)
|
| - .getInt64(offset, commandEndianness);
|
| - }
|
| -
|
| - static double readDoubleFromBuffer(Uint8List buffer, int offset) {
|
| - {
|
| - // TODO(ahe): On ARM the Dart VM might crash when reading a double from
|
| - // an unaligned address. Remove this block when this bug is fixed:
|
| - // https://github.com/dart-lang/sdk/issues/23953
|
| - buffer = new Uint8List.fromList(
|
| - buffer.buffer.asUint8List(buffer.offsetInBytes + offset));
|
| - assert(buffer.offsetInBytes == 0);
|
| - offset = 0;
|
| - }
|
| - return buffer.buffer.asByteData(buffer.offsetInBytes)
|
| - .getFloat64(offset, commandEndianness);
|
| - }
|
| -}
|
|
|