105 lines
2.5 KiB
Dart
105 lines
2.5 KiB
Dart
|
|
|
|
import 'dart:typed_data';
|
|
import 'package:msgpack_dart/msgpack_dart.dart';
|
|
import 'package:es_compression/lz4.dart';
|
|
|
|
final lz4Codec = Lz4Codec();
|
|
|
|
|
|
Uint8List packPacket({
|
|
required int ver,
|
|
required int cmd,
|
|
required int seq,
|
|
required int opcode,
|
|
required Map<String, dynamic> payload,
|
|
}) {
|
|
Uint8List payloadBytes = serialize(payload);
|
|
bool isCompressed = false;
|
|
|
|
if (payloadBytes.length >= 32) {
|
|
final uncompressedSize = ByteData(4)
|
|
..setUint32(0, payloadBytes.length, Endian.big);
|
|
|
|
final compressedData = lz4Codec.encode(payloadBytes);
|
|
|
|
final builder = BytesBuilder();
|
|
builder.add(uncompressedSize.buffer.asUint8List());
|
|
builder.add(compressedData);
|
|
payloadBytes = builder.toBytes();
|
|
isCompressed = true;
|
|
}
|
|
|
|
final header = ByteData(10);
|
|
header.setUint8(0, ver);
|
|
header.setUint16(1, cmd, Endian.big);
|
|
header.setUint8(3, seq);
|
|
header.setUint16(4, opcode, Endian.big);
|
|
|
|
int packedLen = payloadBytes.length;
|
|
if (isCompressed) {
|
|
packedLen |= (1 << 24);
|
|
}
|
|
header.setUint32(6, packedLen, Endian.big);
|
|
|
|
final builder = BytesBuilder();
|
|
builder.add(header.buffer.asUint8List());
|
|
builder.add(payloadBytes);
|
|
|
|
return builder.toBytes();
|
|
}
|
|
|
|
|
|
Map<String, dynamic>? unpackPacket(Uint8List data) {
|
|
if (data.length < 10) {
|
|
print("Ошибка распаковки: Пакет слишком короткий для заголовка.");
|
|
return null;
|
|
}
|
|
|
|
final byteData = data.buffer.asByteData(
|
|
data.offsetInBytes,
|
|
data.lengthInBytes,
|
|
);
|
|
|
|
final ver = byteData.getUint8(0);
|
|
final cmd = byteData.getUint16(1, Endian.big);
|
|
final seq = byteData.getUint8(3);
|
|
final opcode = byteData.getUint16(4, Endian.big);
|
|
final packedLen = byteData.getUint32(6, Endian.big);
|
|
|
|
final compFlag = packedLen >> 24;
|
|
final payloadLength = packedLen & 0x00FFFFFF;
|
|
|
|
if (data.length < 10 + payloadLength) {
|
|
print(
|
|
"Ошибка распаковки: Фактическая длина пакета (${data.length}) меньше заявленной (${10 + payloadLength}).",
|
|
);
|
|
return null;
|
|
}
|
|
|
|
Uint8List payloadBytes = data.sublist(10, 10 + payloadLength);
|
|
|
|
if (compFlag != 0) {
|
|
try {
|
|
final compressedData = payloadBytes.sublist(4);
|
|
|
|
|
|
|
|
payloadBytes = Uint8List.fromList(lz4Codec.decode(compressedData));
|
|
} catch (e) {
|
|
print("Ошибка распаковки LZ4: $e");
|
|
return null;
|
|
}
|
|
}
|
|
|
|
final dynamic payload = deserialize(payloadBytes);
|
|
|
|
return {
|
|
"ver": ver,
|
|
"cmd": cmd,
|
|
"seq": seq,
|
|
"opcode": opcode,
|
|
"payload": payload,
|
|
};
|
|
}
|