/**
  * Deserializes the supplied (wire) buffer into suback data
  * @param pPacketId returned integer - the MQTT packet identifier
  * @param maxExpectedQoSCount - the maximum number of members allowed in the grantedQoSs array
  * @param pGrantedQoSCount returned uint32_t - number of members in the grantedQoSs array
  * @param pGrantedQoSs returned array of QoS type - the granted qualities of service
  * @param pRxBuf the raw buffer data, of the correct length determined by the remaining length field
  * @param rxBufLen the length in bytes of the data in the supplied buffer
  *
  * @return An IoT Error Type defining successful/failed operation
  */
static IoT_Error_t _aws_iot_mqtt_deserialize_suback(uint16_t *pPacketId, uint32_t maxExpectedQoSCount,
													uint32_t *pGrantedQoSCount, QoS *pGrantedQoSs,
													unsigned char *pRxBuf, size_t rxBufLen) {
	unsigned char *curData, *endData;
	uint32_t decodedLen, readBytesLen;
	IoT_Error_t decodeRc;
	MQTTHeader header = {0};

	FUNC_ENTRY;
	if(NULL == pPacketId || NULL == pGrantedQoSCount || NULL == pGrantedQoSs) {
		FUNC_EXIT_RC(NULL_VALUE_ERROR);
	}

	curData = pRxBuf;
	endData = NULL;
	decodeRc = AWS_FAILURE;
	decodedLen = 0;
	readBytesLen = 0;

	/* SUBACK header size is 4 bytes for header and at least one byte for QoS payload
	 * Need at least a 5 bytes buffer. MQTT3.1.1 specification 3.9
	 */
	if(5 > rxBufLen) {
		FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
	}

	header.byte = aws_iot_mqtt_internal_read_char(&curData);
	if(SUBACK != header.bits.type) {
		FUNC_EXIT_RC(AWS_FAILURE);
	}

	/* read remaining length */
	decodeRc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curData, &decodedLen, &readBytesLen);
	if(AWS_SUCCESS != decodeRc) {
		FUNC_EXIT_RC(decodeRc);
	}

	curData += (readBytesLen);
	endData = curData + decodedLen;
	if(endData - curData < 2) {
		FUNC_EXIT_RC(AWS_FAILURE);
	}

	*pPacketId = aws_iot_mqtt_internal_read_uint16_t(&curData);

	*pGrantedQoSCount = 0;
	while(curData < endData) {
		if(*pGrantedQoSCount > maxExpectedQoSCount) {
			FUNC_EXIT_RC(AWS_FAILURE);
		}
		pGrantedQoSs[(*pGrantedQoSCount)++] = (QoS) aws_iot_mqtt_internal_read_char(&curData);
	}

	FUNC_EXIT_RC(AWS_SUCCESS);
}
/**
  * Deserializes the supplied (wire) buffer into connack data - return code
  * @param sessionPresent the session present flag returned (only for MQTT 3.1.1)
  * @param connack_rc returned integer value of the connack return code
  * @param buf the raw buffer data, of the correct length determined by the remaining length field
  * @param buflen the length in bytes of the data in the supplied buffer
  * @return IoT_Error_t indicating function execution status
  */
static IoT_Error_t _aws_iot_mqtt_deserialize_connack(unsigned char *pSessionPresent, IoT_Error_t *pConnackRc,
													 unsigned char *pRxBuf, size_t rxBufLen) {
	unsigned char *curdata, *enddata;
	unsigned char connack_rc_char;
	uint32_t decodedLen, readBytesLen;
	IoT_Error_t rc;
	MQTT_Connack_Header_Flags flags = {0};
	MQTTHeader header = {0};

	FUNC_ENTRY;

	if(NULL == pSessionPresent || NULL == pConnackRc || NULL == pRxBuf) {
		FUNC_EXIT_RC(NULL_VALUE_ERROR);
	}

	/* CONNACK header size is fixed at two bytes for fixed and 2 bytes for variable,
	 * using that as minimum size
	 * MQTT v3.1.1 Specification 3.2.1 */
	if(4 > rxBufLen) {
		FUNC_EXIT_RC(MQTT_RX_BUFFER_TOO_SHORT_ERROR);
	}

	curdata = pRxBuf;
	enddata = NULL;
	decodedLen = 0;
	readBytesLen = 0;

	header.byte = aws_iot_mqtt_internal_read_char(&curdata);
	if(CONNACK != header.bits.type) {
		FUNC_EXIT_RC(FAILURE);
	}

	/* read remaining length */
	rc = aws_iot_mqtt_internal_decode_remaining_length_from_buffer(curdata, &decodedLen, &readBytesLen);
	if(SUCCESS != rc) {
		FUNC_EXIT_RC(rc);
	}

	/* CONNACK remaining length should always be 2 as per MQTT 3.1.1 spec */
	curdata += (readBytesLen);
	enddata = curdata + decodedLen;
	if(2 != (enddata - curdata)) {
		FUNC_EXIT_RC(MQTT_DECODE_REMAINING_LENGTH_ERROR);
	}

	flags.all = aws_iot_mqtt_internal_read_char(&curdata);
	*pSessionPresent = flags.bits.sessionpresent;
	connack_rc_char = aws_iot_mqtt_internal_read_char(&curdata);
	switch(connack_rc_char) {
		case CONNACK_CONNECTION_ACCEPTED:
			*pConnackRc = MQTT_CONNACK_CONNECTION_ACCEPTED;
			break;
		case CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR:
			*pConnackRc = MQTT_CONNACK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR;
			break;
		case CONNACK_IDENTIFIER_REJECTED_ERROR:
			*pConnackRc = MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR;
			break;
		case CONNACK_SERVER_UNAVAILABLE_ERROR:
			*pConnackRc = MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR;
			break;
		case CONNACK_BAD_USERDATA_ERROR:
			*pConnackRc = MQTT_CONNACK_BAD_USERDATA_ERROR;
			break;
		case CONNACK_NOT_AUTHORIZED_ERROR:
			*pConnackRc = MQTT_CONNACK_NOT_AUTHORIZED_ERROR;
			break;
		default:
			*pConnackRc = MQTT_CONNACK_UNKNOWN_ERROR;
			break;
	}

	FUNC_EXIT_RC(SUCCESS);
}