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 _data = []; late int _index; late ByteBuffer _buffer; late bool _error; late String _errorMsg; VidUsDataStreamReader(Stream stream, [int offset = 0]) { _error = false; _errorMsg = ''; _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(msg) { _error = true; _errorMsg = msg.toString(); } 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; } }