import {Packet} from './packet'; import {idFromPacket, packetFromId} from './registry'; export default class BundlePacket extends Packet { static pack(packet) { const packets = packet.data[1]; // Pack up all the packets. const packedPackets = new Array(packets.length); for (let i = 0; i < packets.length; i++) { const packet = packets[i]; const Packet_ = packet.constructor; const id = idFromPacket(Packet_); packedPackets[i] = Packet_.pack({ data: [id, packet.data], }); } // Calculate total length. All packed + 4 (int) for each. let length = 0; for (let i = 0; i < packedPackets.length; i++) { length += 4 + packedPackets[i].length; } // Allocate buffer. const buffer = Buffer.allocUnsafe(length); let caret = 0; for (let i = 0; i < packedPackets.length; i++) { const packedPacket = packedPackets[i]; // Write packed length. buffer.writeUInt32LE(packedPacket.length, caret); caret += 4; // Write packed data. packedPacket.copy(buffer, caret, 0); caret += packedPacket.length; } packet.data[1] = buffer; return super.pack(packet); } static get schema() { return { ...super.schema, data: 'buffer', }; } static unpack(packet) { const data = super.unpack(packet); const packets = []; let caret = 0; while (caret < data.length) { // Read packed length. const length = data.readUInt32LE(caret); caret += 4; // Read packed data. TODO: manual blitting sucks... const packedPacket = Buffer.allocUnsafe(length); let i = 0; while (i < length) { packedPacket.writeUInt8(data.readUInt8(caret++), i++); } // Lookup packet. const packetId = packedPacket.readUInt8(0); const Packet = packetFromId(packetId); // Unpack and instantiate the packet. const unpacked = Packet.unpack(packedPacket); packets.push(new Packet(unpacked)); } return packets; } }