private static MqttBasePacket DecodePublishPacket(byte header, IMqttPacketBodyReader body)
        {
            ThrowIfBodyIsEmpty(body);

            var retain = (header & 1) > 0;
            var qos    = (MqttQualityOfServiceLevel)(header >> 1 & 3);
            var dup    = (header >> 3 & 1) > 0;

            var packet = new MqttPublishPacket
            {
                Topic  = body.ReadStringWithLengthPrefix(),
                Retain = retain,
                QualityOfServiceLevel = qos,
                Dup = dup
            };

            if (qos > 0)
            {
                packet.PacketIdentifier = body.ReadTwoByteInteger();
            }

            var propertiesReader = new MqttV500PropertiesReader(body);

            while (propertiesReader.MoveNext())
            {
                if (packet.Properties == null)
                {
                    packet.Properties = new MqttPublishPacketProperties();
                }

                if (propertiesReader.CurrentPropertyId == MqttPropertyId.PayloadFormatIndicator)
                {
                    packet.Properties.PayloadFormatIndicator = propertiesReader.ReadPayloadFormatIndicator();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.MessageExpiryInterval)
                {
                    packet.Properties.MessageExpiryInterval = propertiesReader.ReadMessageExpiryInterval();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.TopicAlias)
                {
                    packet.Properties.TopicAlias = propertiesReader.ReadTopicAlias();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ResponseTopic)
                {
                    packet.Properties.ResponseTopic = propertiesReader.ReadResponseTopic();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.CorrelationData)
                {
                    packet.Properties.CorrelationData = propertiesReader.ReadCorrelationData();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.SubscriptionIdentifier)
                {
                    if (packet.Properties.SubscriptionIdentifiers == null)
                    {
                        packet.Properties.SubscriptionIdentifiers = new List <uint>();
                    }

                    packet.Properties.SubscriptionIdentifiers.Add(propertiesReader.ReadSubscriptionIdentifier());
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.ContentType)
                {
                    packet.Properties.ContentType = propertiesReader.ReadContentType();
                }
                else if (propertiesReader.CurrentPropertyId == MqttPropertyId.UserProperty)
                {
                    if (packet.Properties.UserProperties == null)
                    {
                        packet.Properties.UserProperties = new List <MqttUserProperty>();
                    }

                    propertiesReader.AddUserPropertyTo(packet.Properties.UserProperties);
                }
                else
                {
                    propertiesReader.ThrowInvalidPropertyIdException(typeof(MqttPublishPacket));
                }
            }

            if (!body.EndOfStream)
            {
                packet.Payload = body.ReadRemainingData();
            }

            return(packet);
        }