import 'dart:convert'; import 'dart:io'; import 'dart:typed_data'; class ByteLayer { Uint8List _byteBuffer = Uint8List(0); int _position = 0; ByteLayer() { _byteBuffer = Uint8List(0); // Initial size, can be adjusted _position = 0; } int get length => _byteBuffer.length; int get currentPosition => _position; Uint8List get bytes => _byteBuffer.sublist(0, _position); void _ensureCapacity(int additionalBytes) { final requiredCapacity = _position + additionalBytes; if (requiredCapacity > _byteBuffer.length) { final newCapacity = _position + additionalBytes; // Adjust capacity as needed final newBuffer = Uint8List(newCapacity); newBuffer.setAll(0, _byteBuffer); _byteBuffer = newBuffer; } } void writeInt(int value) { _ensureCapacity(4); _byteBuffer.buffer.asByteData().setInt32(_position, value, Endian.big); _position += 4; } void writeDouble(double value) { _ensureCapacity(8); _byteBuffer.buffer.asByteData().setFloat64(_position, value, Endian.big); _position += 8; } void writeString(String value) { final encoded = utf8.encode(value); writeShort(encoded.length); _ensureCapacity(encoded.length); _byteBuffer.setAll(_position, encoded); _position += encoded.length; } int readInt() { final value = _byteBuffer.buffer.asByteData().getInt32(_position, Endian.big); _position += 4; return value; } double readDouble() { final value = _byteBuffer.buffer.asByteData().getFloat64(_position, Endian.big); _position += 8; return value; } String readString() { final length = readShort(); final encoded = _byteBuffer.sublist(_position, _position + length); _position += length; return utf8.decode(encoded); } void writeIntZigZag(int value) { final zigzag = (value << 1) ^ (value >> 31); writeInt(zigzag); } int readIntZigZag() { final zigzag = readInt(); final value = (zigzag >> 1) ^ -(zigzag & 1); return value; } void writeByte(int value) { _ensureCapacity(1); _byteBuffer[_position] = value & 0xFF; _position++; } void writeUnsignedByte(int value) { _ensureCapacity(1); _byteBuffer.buffer.asByteData().setUint8(_position, value); _position++; } int readByte() { final value = _byteBuffer[_position]; _position++; return value; } int readUnsignedByte() { final value = _byteBuffer.buffer.asByteData().getUint8(_position); _position++; return value; } void writeVarInt(int value) { while ((value & ~0x7F) != 0) { writeByte((value & 0x7F) | 0x80); value = (value >> 7) & 0x1FFFFFFF; } writeByte(value & 0x7F); } int readVarInt() { int result = 0; int shift = 0; int byte; do { byte = readByte(); result |= (byte & 0x7F) << shift; if ((byte & 0x80) == 0) { break; } shift += 7; } while (true); return result; } void writeVarIntNoZigZag(int value) { while ((value & ~0x7F) != 0) { writeByte((value & 0x7F) | 0x80); value >>= 7; } writeByte(value & 0x7F); } int readVarIntNoZigZag() { int result = 0; int shift = 0; int byte; do { byte = readByte(); result |= (byte & 0x7F) << shift; if ((byte & 0x80) == 0) { break; } shift += 7; } while (true); return result; } void writeShort(int value) { _ensureCapacity(2); _byteBuffer.buffer.asByteData().setInt16(_position, value, Endian.big); _position += 2; } int readShort() { final value = _byteBuffer.buffer.asByteData().getInt16(_position, Endian.big); _position += 2; return value; } void writeFloat(double value) { _ensureCapacity(4); // Round the float to 8 decimal places before writing value = double.parse(value.toStringAsFixed(8)); _byteBuffer.buffer.asByteData().setFloat32(_position, value, Endian.big); _position += 4; } double readFloat() { final value = _byteBuffer.buffer.asByteData().getFloat32(_position, Endian.big); _position += 4; // Round the float to 8 decimal places after reading return double.parse(value.toStringAsFixed(8)); } void writeTagName(String name) { final encodedName = utf8.encode(name); writeShort(encodedName.length); _ensureCapacity(encodedName.length); _byteBuffer.setAll(_position, encodedName); _position += encodedName.length; } String readTagName() { final length = readShort(); final encodedName = _byteBuffer.sublist(_position, _position + length); _position += length; return utf8.decode(encodedName); } void resetPosition() { _position = 0; } void clear() { resetPosition(); _byteBuffer = Uint8List(0); } Future writeToFile(String filePath) async { final file = File(filePath); await file.writeAsBytes(bytes); } Future readFromFile(String filePath) async { final file = File(filePath); final exists = await file.exists(); if (!exists) { print('File does not exist.'); return; } _byteBuffer = await file.readAsBytes(); resetPosition(); } Future compress() async { final gzip = GZipCodec(); final compressedData = gzip.encode(_byteBuffer); _byteBuffer = Uint8List.fromList(compressedData); _position = _byteBuffer.length; } Future decompress() async { final gzip = GZipCodec(); final decompressedData = gzip.decode(_byteBuffer); _byteBuffer = Uint8List.fromList(decompressedData); _position = _byteBuffer.length; } void writeLong(int value) { _ensureCapacity(8); _byteBuffer.buffer.asByteData().setInt64(_position, value, Endian.big); _position += 8; } void writeUnsignedLong(int value) { _ensureCapacity(8); _byteBuffer.buffer.asByteData().setUint64(_position, value, Endian.big); _position += 8; } int readLong() { final value = _byteBuffer.buffer.asByteData().getInt64(_position, Endian.big); _position += 8; return value; } int readUnsignedLong() { final value = _byteBuffer.buffer.asByteData().getUint64(_position, Endian.big); _position += 8; return value; } void writeVarLongNoZigZag(int value) { while (true) { if ((value & ~0x7F) == 0) { writeByte(value); return; } writeByte((value & 0x7F) | 0x80); value = value >> 7; } } void writeVarLongZigZag(int value) { value = (value << 1) ^ (value >> 63); writeVarLongNoZigZag(value); } void writeLongZigZag(int value) { value = (value << 1) & (value >> 63); _byteBuffer.buffer.asByteData().setInt64(_position, value, Endian.big); } int readVarLongNoZigZag() { int result = 0; int shift = 0; int b; do { b = readByte(); result |= (b & 0x7F) << shift; shift += 7; } while ((b & 0x80) != 0); return result; } int readVarLongZigZag() { int result = readVarLongNoZigZag(); return (result >> 1) ^ -(result & 1); } int readLongZigZag() { int value = readLong(); return (value >> 1) ^ (-(value & 1)); } void writeBytes(Iterable bytes) { for (int byte in bytes) { writeUnsignedByte(byte); } } List readBytes(int num) { List lst = []; for (int i = 0; i < num; i++) { lst.add(readUnsignedByte()); } return lst; } void setBit(int position, int maskToSet) { if (position < _byteBuffer.length) { // Set the value now seek(position); int current = readUnsignedByte(); seek(position); current |= maskToSet; writeUnsignedByte(current); } } void clearBit(int position, int maskToClear) { if (position < _byteBuffer.length) { // Lets clear the bit seek(position); int current = readUnsignedByte(); current = current & ~maskToClear; seek(position); writeUnsignedByte(current); } } bool checkBit(int position, int mask) { if (position < _byteBuffer.length) { seek(position); int current = readUnsignedByte(); return (current & mask) == mask; } else { return false; } } int getBit(int position) { if (position < _byteBuffer.length) { seek(position); return readUnsignedByte(); } else { return 0; } } void seek(int position) { _position = 0; _ensureCapacity(position); _position = position; } /// Unsets a mask, then sets a mask void unsetSetBit(int position, int maskToClear, int maskToSet) { clearBit(position, maskToClear); setBit(position, maskToSet); } }