/*
 * Copyright (c) 2022 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: Apache-2.0
 */
/*
 * Generated using zcbor version 0.5.1
 * https://github.com/zephyrproject-rtos/zcbor
 * Generated with a --default-max-qty of 99
 */


#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "zcbor_decode.h"
#include "lwm2m_senml_cbor_decode.h"

static bool decode_repeated_record_bn(zcbor_state_t *state, struct record_bn *result);
static bool decode_repeated_record_n(zcbor_state_t *state, struct record_n *result);
static bool decode_repeated_record_union(zcbor_state_t *state, struct record_union_ *result);
static bool decode_value(zcbor_state_t *state, struct value_ *result);
static bool decode_key_value_pair(zcbor_state_t *state, struct key_value_pair *result);
static bool decode_repeated_record__key_value_pair(zcbor_state_t *state,
						   struct record__key_value_pair *result);
static bool decode_record(zcbor_state_t *state, struct record *result);
static bool decode_lwm2m_senml(zcbor_state_t *state, struct lwm2m_senml *result);

static bool decode_repeated_record_bn(zcbor_state_t *state, struct record_bn *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result = ((((zcbor_int32_expect(state, (-2)))) &&
			    (zcbor_tstr_decode(state, (&(*result)._record_bn)))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_repeated_record_n(zcbor_state_t *state, struct record_n *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result = ((((zcbor_uint32_expect(state, (0)))) &&
			    (zcbor_tstr_decode(state, (&(*result)._record_n)))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_repeated_record_union(zcbor_state_t *state, struct record_union_ *result)
{
	zcbor_print("%s\r\n", __func__);
	bool int_res;

	bool tmp_result = (((zcbor_union_start_code(state) &&
			     (int_res = (((((zcbor_uint32_expect_union(state, (2)))) &&
					   (zcbor_int64_decode(state, (&(*result)._union_vi))) &&
					   ((((*result)._union_vi >= INT64_MIN) &&
					     ((*result)._union_vi <= INT64_MAX)) ||
					    (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) &&
					  (((*result)._record_union_choice = _union_vi) || 1)) ||
					 ((((zcbor_uint32_expect_union(state, (2)))) &&
					   (zcbor_float_decode(state, (&(*result)._union_vf)))) &&
					  (((*result)._record_union_choice = _union_vf) || 1)) ||
					 ((((zcbor_uint32_expect_union(state, (3)))) &&
					   (zcbor_tstr_decode(state, (&(*result)._union_vs)))) &&
					  (((*result)._record_union_choice = _union_vs) || 1)) ||
					 ((((zcbor_uint32_expect_union(state, (4)))) &&
					   (zcbor_bool_decode(state, (&(*result)._union_vb)))) &&
					  (((*result)._record_union_choice = _union_vb) || 1)) ||
					 ((((zcbor_uint32_expect_union(state, (8)))) &&
					   (zcbor_bstr_decode(state, (&(*result)._union_vd)))) &&
					  (((*result)._record_union_choice = _union_vd) || 1))),
			      zcbor_union_end_code(state), int_res))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_value(zcbor_state_t *state, struct value_ *result)
{
	zcbor_print("%s\r\n", __func__);
	bool int_res;

	bool tmp_result =
		(((zcbor_union_start_code(state) &&
		   (int_res = ((((zcbor_tstr_decode(state, (&(*result)._value_tstr)))) &&
				(((*result)._value_choice = _value_tstr) || 1)) ||
			       (((zcbor_bstr_decode(state, (&(*result)._value_bstr)))) &&
				(((*result)._value_choice = _value_bstr) || 1)) ||
			       (((zcbor_int64_decode(state, (&(*result)._value_int))) &&
				 ((((*result)._value_int >= INT64_MIN) &&
				   ((*result)._value_int <= INT64_MAX)) ||
				  (zcbor_error(state, ZCBOR_ERR_WRONG_RANGE), false))) &&
				(((*result)._value_choice = _value_int) || 1)) ||
			       (((zcbor_float_decode(state, (&(*result)._value_float)))) &&
				(((*result)._value_choice = _value_float) || 1)) ||
			       (((zcbor_bool_decode(state, (&(*result)._value_bool)))) &&
				(((*result)._value_choice = _value_bool) || 1))),
		    zcbor_union_end_code(state), int_res))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_key_value_pair(zcbor_state_t *state, struct key_value_pair *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result = ((((zcbor_int32_decode(state, (&(*result)._key_value_pair_key)))) &&
			    (decode_value(state, (&(*result)._key_value_pair)))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_repeated_record__key_value_pair(zcbor_state_t *state,
						   struct record__key_value_pair *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result = (((decode_key_value_pair(state, (&(*result)._record__key_value_pair)))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_record(zcbor_state_t *state, struct record *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result =
		(((zcbor_map_start_decode(state) &&
		   ((zcbor_present_decode(&((*result)._record_bn_present),
					  (zcbor_decoder_t *)decode_repeated_record_bn, state,
					  (&(*result)._record_bn)) &&
		     zcbor_present_decode(&((*result)._record_n_present),
					  (zcbor_decoder_t *)decode_repeated_record_n, state,
					  (&(*result)._record_n)) &&
		     zcbor_present_decode(&((*result)._record_union_present),
					  (zcbor_decoder_t *)decode_repeated_record_union, state,
					  (&(*result)._record_union)) &&
		     zcbor_multi_decode(0, ARRAY_SIZE(result->_record__key_value_pair),
					&(*result)._record__key_value_pair_count,
					(zcbor_decoder_t *)decode_repeated_record__key_value_pair,
					state, (&(*result)._record__key_value_pair),
					sizeof(struct record__key_value_pair))) ||
		    (zcbor_list_map_end_force_decode(state), false)) &&
		   zcbor_map_end_decode(state))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

static bool decode_lwm2m_senml(zcbor_state_t *state, struct lwm2m_senml *result)
{
	zcbor_print("%s\r\n", __func__);

	bool tmp_result = ((
		(zcbor_list_start_decode(state) &&
		 ((zcbor_multi_decode(1, ARRAY_SIZE(result->_lwm2m_senml__record),
				      &(*result)._lwm2m_senml__record_count,
				      (zcbor_decoder_t *)decode_record, state,
				      (&(*result)._lwm2m_senml__record), sizeof(struct record))) ||
		  (zcbor_list_map_end_force_decode(state), false)) &&
		 zcbor_list_end_decode(state))));

	if (!tmp_result) {
		zcbor_trace();
	}

	return tmp_result;
}

int cbor_decode_lwm2m_senml(const uint8_t *payload, size_t payload_len, struct lwm2m_senml *result,
			    size_t *payload_len_out)
{
	zcbor_state_t states[5];

	zcbor_new_state(states, sizeof(states) / sizeof(zcbor_state_t), payload, payload_len, 1);

	bool ret = decode_lwm2m_senml(states, result);

	if (ret && (payload_len_out != NULL)) {
		*payload_len_out = MIN(payload_len, (size_t)states[0].payload - (size_t)payload);
	}

	if (!ret) {
		int err = zcbor_pop_error(states);

		zcbor_print("Return error: %d\r\n", err);
		return (err == ZCBOR_SUCCESS) ? ZCBOR_ERR_UNKNOWN : err;
	}
	return ZCBOR_SUCCESS;
}
