public async Task <MqttBasePacket> DeserializeAsync(IMqttCommunicationChannel source)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            using (var mqttPacketReader = new MqttPacketReader(source))
            {
                await mqttPacketReader.ReadToEndAsync();

                switch (mqttPacketReader.ControlPacketType)
                {
                case MqttControlPacketType.Connect:
                {
                    return(await DeserializeConnectAsync(mqttPacketReader));
                }

                case MqttControlPacketType.ConnAck:
                {
                    return(await DeserializeConnAck(mqttPacketReader));
                }

                case MqttControlPacketType.Disconnect:
                {
                    return(new MqttDisconnectPacket());
                }

                case MqttControlPacketType.Publish:
                {
                    return(await DeserializePublishAsync(mqttPacketReader));
                }

                case MqttControlPacketType.PubAck:
                {
                    return(new MqttPubAckPacket
                        {
                            PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
                        });
                }

                case MqttControlPacketType.PubRec:
                {
                    return(new MqttPubRecPacket
                        {
                            PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
                        });
                }

                case MqttControlPacketType.PubRel:
                {
                    return(new MqttPubRelPacket
                        {
                            PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
                        });
                }

                case MqttControlPacketType.PubComp:
                {
                    return(new MqttPubCompPacket
                        {
                            PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
                        });
                }

                case MqttControlPacketType.PingReq:
                {
                    return(new MqttPingReqPacket());
                }

                case MqttControlPacketType.PingResp:
                {
                    return(new MqttPingRespPacket());
                }

                case MqttControlPacketType.Subscribe:
                {
                    return(await DeserializeSubscribeAsync(mqttPacketReader));
                }

                case MqttControlPacketType.SubAck:
                {
                    return(await DeserializeSubAck(mqttPacketReader));
                }

                case MqttControlPacketType.Unsubscibe:
                {
                    return(await DeserializeUnsubscribeAsync(mqttPacketReader));
                }

                case MqttControlPacketType.UnsubAck:
                {
                    return(new MqttUnsubAckPacket
                        {
                            PacketIdentifier = await mqttPacketReader.ReadRemainingDataUShortAsync()
                        });
                }

                default:
                {
                    throw new MqttProtocolViolationException($"Packet type ({(int)mqttPacketReader.ControlPacketType}) not supported.");
                }
                }
            }
        }