public static IPacket[] Deserialize(byte[] buffer)
        {
            var packetsCount = BitConverter.ToInt32(buffer, 0);
            var packetTypes  = new PacketType[packetsCount];
            var bufferIndex  = Packet.HeaderSize;

            // Extract packet data.
            for (var i = 0; i < packetsCount; i++)
            {
                packetTypes[i] = (PacketType)buffer[bufferIndex];

                bufferIndex++;
            }

            // Create packets.
            var packets = new IPacket[packetTypes.Length];
            var handle  = Marshal.AllocHGlobal(packetTypes.Max(p => Packet.GetSize(p)));

            bufferIndex = Packet.HeaderSize + Packet.PacketTypeSize * packetsCount;

            for (var i = 0; i < packets.Length; i++)
            {
                var packetType = packetTypes[i];
                var packetSize = Packet.GetSize(packetType);
                var type       = Packet.GetType(packetType);

                Marshal.Copy(buffer, bufferIndex, handle, packetSize);

                var packet = (IPacket)Marshal.PtrToStructure(handle, type);

                bufferIndex += packetSize;
                packets[i]   = packet;
            }

            Marshal.FreeHGlobal(handle);

            return(packets);
        }