uint32_t ble_gatts_attr_enc(void const * const p_void_gatts_attr,
                            uint8_t * const    p_buf,
                            uint32_t           buf_len,
                            uint32_t * const   p_index)
{
    uint32_t           err_code     = NRF_SUCCESS;
    ble_gatts_attr_t * p_gatts_attr = (ble_gatts_attr_t *)p_void_gatts_attr;

    err_code = cond_field_enc((void *)p_gatts_attr->p_uuid, p_buf, buf_len, p_index, ble_uuid_t_enc);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = cond_field_enc((void *)p_gatts_attr->p_attr_md,
                              p_buf,
                              buf_len,
                              p_index,
                              ble_gatts_attr_md_enc);
    SER_ERROR_CHECK(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&p_gatts_attr->init_offs, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&p_gatts_attr->max_len, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    SER_ERROR_CHECK(p_gatts_attr->init_len <= BLE_GATTS_VAR_ATTR_LEN_MAX, NRF_ERROR_INVALID_PARAM);
    //init len move just before p_data to be able to use len16data decoder.
    err_code = len16data_enc(p_gatts_attr->p_value, p_gatts_attr->init_len, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
uint32_t ble_gap_device_name_get_rsp_enc(uint32_t              return_code,
                                         uint8_t const * const p_dev_name,
                                         uint16_t              dev_name_len,
                                         uint8_t * const       p_buf,
                                         uint32_t * const      p_buflen)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_buflen);

    uint32_t buflen   = *p_buflen;
    uint32_t err_code = ser_ble_cmd_rsp_status_code_enc(SD_BLE_GAP_DEVICE_NAME_GET, return_code,
                                                        p_buf, p_buflen);
    uint32_t index = *p_buflen;

    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

    if (return_code != NRF_SUCCESS)
    {
        return NRF_SUCCESS;
    }

    err_code = len16data_enc(p_dev_name, dev_name_len, p_buf, buflen, &index);

    *p_buflen = index;

    return err_code;
}
uint32_t ble_gattc_write_params_t_enc(void const * const p_void_write,
                                      uint8_t * const    p_buf,
                                      uint32_t           buf_len,
                                      uint32_t * const   p_index)
{
    SER_ASSERT_NOT_NULL(p_void_write);
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_index);

    uint32_t err_code = NRF_SUCCESS;

    ble_gattc_write_params_t * p_write = (ble_gattc_write_params_t *)p_void_write;

    err_code = uint8_t_enc(&(p_write->write_op), p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint8_t_enc(&(p_write->flags), p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&(p_write->handle), p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&(p_write->offset), p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = len16data_enc(p_write->p_value, p_write->len, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
uint32_t ble_gatts_char_md_enc(void const * const p_void_char_md,
                               uint8_t * const    p_buf,
                               uint32_t           buf_len,
                               uint32_t * const   p_index)
{
    uint32_t err_code = NRF_SUCCESS;

    ble_gatts_char_md_t * p_char_md = (ble_gatts_char_md_t *)p_void_char_md;
    uint8_t               temp8;

    temp8 = p_char_md->char_props.broadcast |
            (p_char_md->char_props.read << 1) |
            (p_char_md->char_props.write_wo_resp << 2) |
            (p_char_md->char_props.write << 3) |
            (p_char_md->char_props.notify << 4) |
            (p_char_md->char_props.indicate << 5) |
            (p_char_md->char_props.auth_signed_wr << 6);

    err_code = uint8_t_enc(&temp8, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    temp8 = p_char_md->char_ext_props.reliable_wr |
            (p_char_md->char_ext_props.wr_aux << 1);

    err_code = uint8_t_enc(&temp8, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&p_char_md->char_user_desc_max_size, p_buf, buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    SER_ERROR_CHECK(p_char_md->char_user_desc_size <= BLE_GATTS_VAR_ATTR_LEN_MAX,
                    NRF_ERROR_INVALID_PARAM);
    err_code = len16data_enc(p_char_md->p_char_user_desc, p_char_md->char_user_desc_size, p_buf,
                             buf_len, p_index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = cond_field_enc(p_char_md->p_char_pf,
                              p_buf,
                              buf_len,
                              p_index,
                              ser_ble_gatts_char_pf_enc);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = cond_field_enc(p_char_md->p_user_desc_md,
                              p_buf,
                              buf_len,
                              p_index,
                              ble_gatts_attr_md_enc);
    SER_ERROR_CHECK(err_code == NRF_SUCCESS, err_code);

    err_code = cond_field_enc(p_char_md->p_cccd_md, p_buf, buf_len, p_index, ble_gatts_attr_md_enc);
    SER_ERROR_CHECK(err_code == NRF_SUCCESS, err_code);

    err_code = cond_field_enc(p_char_md->p_sccd_md, p_buf, buf_len, p_index, ble_gatts_attr_md_enc);
    SER_ERROR_CHECK(err_code == NRF_SUCCESS, err_code);

    return err_code;
}
uint32_t ble_gatts_evt_write_enc(ble_evt_t const * const p_event,
                                 uint32_t                event_len,
                                 uint8_t * const         p_buf,
                                 uint32_t * const        p_buf_len)
{

    uint32_t err_code = NRF_SUCCESS;

    SER_ASSERT_NOT_NULL(p_event);
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_buf_len);

    uint32_t index      = 0;
    uint32_t total_len  = *p_buf_len;
    uint16_t evt_header = BLE_GATTS_EVT_WRITE;

    err_code = uint16_t_enc(&evt_header, p_buf, total_len, &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&(p_event->evt.gatts_evt.conn_handle), p_buf, total_len, &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);
    
    err_code = ble_gatts_evt_write_t_enc(&(p_event->evt.gatts_evt.params.write),
                                         p_buf,
                                         total_len,
                                         &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);
    
    if(p_event->evt.gatts_evt.params.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW)
    {
        uint32_t conn_index;
        
        if(conn_ble_user_mem_context_find(p_event->evt.gatts_evt.conn_handle, &conn_index) != NRF_ERROR_NOT_FOUND)
        {
            err_code = len16data_enc(m_conn_user_mem_table[conn_index].mem_block.p_mem, m_conn_user_mem_table[conn_index].mem_block.len, p_buf, *p_buf_len, &index);
            SER_ASSERT(err_code == NRF_SUCCESS, err_code);
        }
    }

    *p_buf_len = index;

    return err_code;
}
uint32_t ble_gatts_evt_rw_authorize_request_enc(ble_evt_t const * const p_event,
                                                uint32_t                event_len,
                                                uint8_t * const         p_buf,
                                                uint32_t * const        p_buf_len)
{
    SER_ASSERT_NOT_NULL(p_buf);
    SER_ASSERT_NOT_NULL(p_buf_len);
    SER_ASSERT_NOT_NULL(p_event);

    uint32_t index     = 0;
    uint32_t total_len = *p_buf_len;
    uint32_t err_code  = NRF_SUCCESS;

    err_code = uint16_t_enc(&p_event->header.evt_id, p_buf, total_len, &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = uint16_t_enc(&(p_event->evt.gatts_evt.conn_handle), p_buf, total_len, &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);

    err_code = ble_gatts_evt_rw_authorize_request_t_enc(
        &(p_event->evt.gatts_evt.params.authorize_request),
        p_buf, total_len, &index);
    SER_ASSERT(err_code == NRF_SUCCESS, err_code);
    
    if((p_event->evt.gatts_evt.params.authorize_request.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE) && (p_event->evt.gatts_evt.params.authorize_request.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW))
    {
        uint32_t conn_index;
        
        if(conn_ble_user_mem_context_find(p_event->evt.gatts_evt.conn_handle, &conn_index) != NRF_ERROR_NOT_FOUND)
        {
            err_code = len16data_enc(m_conn_user_mem_table[conn_index].mem_block.p_mem, m_conn_user_mem_table[conn_index].mem_block.len, p_buf, *p_buf_len, &index);
            SER_ASSERT(err_code == NRF_SUCCESS, err_code);
        }
    }

    *p_buf_len = index;

    return err_code;
}
uint32_t ble_gatts_read_authorize_params_t_enc(void const * const p_void_struct,
                                               uint8_t * const    p_buf,
                                               uint32_t           buf_len,
                                               uint32_t * const   p_index)
{
    ble_gatts_read_authorize_params_t * p_params =
        (ble_gatts_read_authorize_params_t *) p_void_struct;
    uint32_t error_code = NRF_SUCCESS;

    error_code = uint16_t_enc(&(p_params->gatt_status), p_buf, buf_len, p_index);
    SER_ASSERT(error_code == NRF_SUCCESS, error_code);

    uint8_t temp_val = p_params->update;
    error_code = uint8_t_enc(&temp_val, p_buf, buf_len, p_index);
    SER_ASSERT(error_code == NRF_SUCCESS, error_code);

    error_code = uint16_t_enc(&(p_params->offset), p_buf, buf_len, p_index);
    SER_ASSERT(error_code == NRF_SUCCESS, error_code);

    error_code = len16data_enc(p_params->p_data, p_params->len, p_buf, buf_len, p_index);
    SER_ASSERT(error_code == NRF_SUCCESS, error_code);

    return error_code;
}