Browse Source

Add stream reader.

Justin 2 years ago
parent
commit
ab5cf60ac7
1 changed files with 264 additions and 0 deletions
  1. 264 0
      lib/us/vid_us_data_stream_reader.dart

+ 264 - 0
lib/us/vid_us_data_stream_reader.dart

@@ -0,0 +1,264 @@
+import 'dart:typed_data';
+
+//Raised when data is not ready.
+class NotReadyException implements Exception {}
+
+class StreamErrorException implements Exception {
+  String _msg;
+
+  StreamErrorException(this._msg);
+
+  @override
+  String toString() {
+    return _msg;
+  }
+}
+
+class VidUsDataStreamReader {
+  late final List<int> _data = [];
+  late int _index;
+  late ByteBuffer _buffer;
+  late bool _error;
+  late String _errorMsg;
+
+  VidUsDataStreamReader(Stream<Uint8List> stream, [int offset = 0]) {
+    _buffer = Uint8List.fromList(_data).buffer;
+    stream.listen(onDataArrived, onError: onStreamError, onDone: onStreamDone);
+    _index = offset;
+  }
+
+  void onDataArrived(Uint8List data) {
+    _data.addAll(data);
+    _buffer = Uint8List.fromList(_data).buffer;
+  }
+
+  void onStreamError(String msg) {
+    _error = true;
+    _errorMsg = msg;
+  }
+
+  void onStreamDone() {
+    //Update the last data into the buffer.
+    _buffer = Uint8List.fromList(_data).buffer;
+  }
+
+  ///Read int value from binary data(little endian),
+  int readInt([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 4) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(_index, 4);
+      _index += 4;
+      return intData.getInt32(0, Endian.little);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 4) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(index, 4);
+      _index = index + 4;
+      return intData.getInt32(0, Endian.little);
+    }
+  }
+
+  ///Read string from the binary data, the string format is utf-16, which is unicode in C#
+  String readString([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    int dataLength;
+    if (index == -1) {
+      dataLength = readInt();
+      if ((_buffer.lengthInBytes - _index) < dataLength) {
+        throw NotReadyException();
+      }
+    } else {
+      dataLength = readInt(index);
+      if ((_buffer.lengthInBytes - index) < dataLength) {
+        throw NotReadyException();
+      }
+    }
+    var stringData = _buffer.asUint8List(_index, dataLength);
+    _index += dataLength;
+    var unicodeStringData = Uint8List.fromList(stringData.toList()).buffer.asUint16List();
+    return String.fromCharCodes(unicodeStringData);
+  }
+
+  ///Read int16 value from binary data(little endian)
+  int readInt16([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 2) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(_index, 2);
+      _index += 2;
+      return intData.getInt16(0, Endian.little);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 2) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(index, 2);
+      _index = index + 2;
+      return intData.getInt16(0, Endian.little);
+    }
+  }
+
+  ///Read int64 value from binary data(little endian)
+  ///this method is not support in web platform use readInt64V2 instead.
+  int readInt64([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 8) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(_index, 8);
+      _index += 8;
+      return intData.getInt64(0, Endian.little);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 8) {
+        throw NotReadyException();
+      }
+      var intData = _buffer.asByteData(index, 8);
+      _index = index + 8;
+      return intData.getInt64(0, Endian.little);
+    }
+  }
+
+  ///Read int64 value from binary data(little endian)
+  ///this method use two int32 to support read int64 on web platform
+  int readInt64V2([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 8) {
+        throw NotReadyException();
+      }
+      int low = readInt();
+      int high = readInt();
+      int value = high >> 32;
+      value |= low;
+      return value;
+    } else {
+      if ((_buffer.lengthInBytes - index) < 8) {
+        throw NotReadyException();
+      }
+      int low = readInt(index);
+      //Read the next int.
+      int high = readInt();
+      int value = high >> 32;
+      value |= low;
+      return value;
+    }
+  }
+
+  ///Read float value from binary data(little endian)
+  double readFloat([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 4) {
+        throw NotReadyException();
+      }
+      var floatData = _buffer.asByteData(_index, 4);
+      _index += 4;
+      return floatData.getFloat32(0, Endian.little);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 4) {
+        throw NotReadyException();
+      }
+      var floatData = _buffer.asByteData(index, 4);
+      _index = index + 4;
+      return floatData.getFloat32(0, Endian.little);
+    }
+  }
+
+  ///Read double value from binary data(little endian)
+  double readDouble([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 8) {
+        throw NotReadyException();
+      }
+      var floatData = _buffer.asByteData(_index, 8);
+      _index += 8;
+      return floatData.getFloat64(0, Endian.little);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 8) {
+        throw NotReadyException();
+      }
+      var floatData = _buffer.asByteData(index, 8);
+      _index = index + 8;
+      return floatData.getFloat64(0, Endian.little);
+    }
+  }
+
+  ///Read bool value from binary data
+  bool readBool([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 1) {
+        throw NotReadyException();
+      }
+      var boolData = _buffer.asByteData(_index, 1);
+      _index++;
+      return boolData.getInt8(0) == 1;
+    } else {
+      if ((_buffer.lengthInBytes - index) < 1) {
+        throw NotReadyException();
+      }
+      var boolData = _buffer.asByteData(index, 1);
+      _index = index + 1;
+      return boolData.getInt8(0) == 1;
+    }
+  }
+
+  ///Read byte value from binary data
+  int readByte([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    if (index == -1) {
+      if ((_buffer.lengthInBytes - _index) < 1) {
+        throw NotReadyException();
+      }
+      var byteData = _buffer.asByteData(_index, 1);
+      _index++;
+      return byteData.getInt8(0);
+    } else {
+      if ((_buffer.lengthInBytes - index) < 1) {
+        throw NotReadyException();
+      }
+      var byteData = _buffer.asByteData(index, 1);
+      _index = index + 1;
+      return byteData.getInt8(0);
+    }
+  }
+
+  ///Read bytes from the binary data.
+  Uint8List readBytes([int index = -1]) {
+    if (_error) {
+      throw StreamErrorException(_errorMsg);
+    }
+    var dataLength = readInt(index);
+    if ((_buffer.lengthInBytes - _index) < dataLength) {
+      throw NotReadyException();
+    }
+    var bytes = _buffer.asUint8List(_index, dataLength);
+    _index += dataLength;
+    return bytes;
+  }
+}