/// <summary>
        /// Decode messages from a payload and assign it a given kafka offset.
        /// </summary>
        /// <param name="reader">The reader</param>
        /// <param name="messageSize">The size of the message, for Crc Hash calculation</param>
        /// <param name="offset">The offset represting the log entry from kafka of this message.</param>
        /// <returns>Enumerable representing stream of messages decoded from byte[].</returns>
        /// <remarks>The return type is an Enumerable as the message could be a compressed message set.</remarks>
        public static IImmutableList <Message> ReadMessage(this IKafkaReader reader, int messageSize, long offset)
        {
            var crc     = reader.ReadUInt32();
            var crcHash = reader.ReadCrc(messageSize - 4);

            if (crc != crcHash)
            {
                throw new CrcValidationException(crc, crcHash);
            }

            var            messageVersion = reader.ReadByte();
            var            attribute      = reader.ReadByte();
            DateTimeOffset?timestamp      = null;

            if (messageVersion >= 1)
            {
                var milliseconds = reader.ReadInt64();
                if (milliseconds >= 0)
                {
                    timestamp = DateTimeOffset.FromUnixTimeMilliseconds(milliseconds);
                }
            }
            var key   = reader.ReadBytes();
            var value = reader.ReadBytes();

            var codec = (MessageCodec)(Message.CodecMask & attribute);

            if (codec == MessageCodec.None)
            {
                return(ImmutableList <Message> .Empty.Add(new Message(value, key, attribute, offset, messageVersion, timestamp)));
            }
            var uncompressedBytes = value.ToUncompressed(codec);

            using (var messageSetReader = new KafkaReader(uncompressedBytes)) {
                return(messageSetReader.ReadMessages(codec));
            }
        }