/* this is a file autogenerated by spice_codegen.py */
/*
  Copyright (C) 2013 Red Hat, Inc.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/

#include <config.h>
#include "common/messages.h"
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <spice/protocol.h>
#include <spice/macros.h>
#include <common/mem.h>
#include <common/demarshallers.h>

#ifdef _MSC_VER
#pragma warning(disable:4101)
#endif



#include <spice/start-packed.h>
typedef struct SPICE_ATTR_PACKED {
    int16_t v;
} int16_unaligned_t;
typedef struct SPICE_ATTR_PACKED {
    uint16_t v;
} uint16_unaligned_t;
typedef struct SPICE_ATTR_PACKED {
    int32_t v;
} int32_unaligned_t;
typedef struct SPICE_ATTR_PACKED {
    uint32_t v;
} uint32_unaligned_t;
typedef struct SPICE_ATTR_PACKED {
    int64_t v;
} int64_unaligned_t;
typedef struct SPICE_ATTR_PACKED {
    uint64_t v;
} uint64_unaligned_t;
#include <spice/end-packed.h>

#define read_int8(ptr) (*((int8_t *)(ptr)))
#define write_int8(ptr, val) *(int8_t *)(ptr) = val
#define read_uint8(ptr) (*((uint8_t *)(ptr)))
#define write_uint8(ptr, val) *(uint8_t *)(ptr) = val

#ifdef WORDS_BIGENDIAN
#define read_int16(ptr) ((int16_t)SPICE_BYTESWAP16(((uint16_unaligned_t *)(ptr))->v))
#define write_int16(ptr, val) ((uint16_unaligned_t *)(ptr))->v = SPICE_BYTESWAP16((uint16_t)val)
#define read_uint16(ptr) ((uint16_t)SPICE_BYTESWAP16(((uint16_unaligned_t *)(ptr))->v))
#define write_uint16(ptr, val) ((uint16_unaligned_t *)(ptr))->v = SPICE_BYTESWAP16((uint16_t)val)
#define read_int32(ptr) ((int32_t)SPICE_BYTESWAP32(((uint32_unaligned_t *)(ptr))->v))
#define write_int32(ptr, val) ((uint32_unaligned_t *)(ptr))->v = SPICE_BYTESWAP32((uint32_t)val)
#define read_uint32(ptr) ((uint32_t)SPICE_BYTESWAP32(((uint32_unaligned_t *)(ptr))->v))
#define write_uint32(ptr, val) ((uint32_unaligned_t *)(ptr))->v = SPICE_BYTESWAP32((uint32_t)val)
#define read_int64(ptr) ((int64_t)SPICE_BYTESWAP64(((uint64_unaligned_t *)(ptr))->v))
#define write_int64(ptr, val) ((uint64_unaligned_t *)(ptr))->v = SPICE_BYTESWAP64((uint64_t)val)
#define read_uint64(ptr) ((uint64_t)SPICE_BYTESWAP64(((uint64_unaligned_t *)(ptr))->v))
#define write_uint64(ptr, val) ((uint64_unaligned_t *)(ptr))->v = SPICE_BYTESWAP64((uint64_t)val)
#else
#define read_int16(ptr) (((int16_unaligned_t *)(ptr))->v)
#define write_int16(ptr, val) (((int16_unaligned_t *)(ptr))->v) = val
#define read_uint16(ptr) (((uint16_unaligned_t *)(ptr))->v)
#define write_uint16(ptr, val) (((uint16_unaligned_t *)(ptr))->v) = val
#define read_int32(ptr) (((int32_unaligned_t *)(ptr))->v)
#define write_int32(ptr, val) (((int32_unaligned_t *)(ptr))->v) = val
#define read_uint32(ptr) (((uint32_unaligned_t *)(ptr))->v)
#define write_uint32(ptr, val) (((uint32_unaligned_t *)(ptr))->v) = val
#define read_int64(ptr) (((int64_unaligned_t *)(ptr))->v)
#define write_int64(ptr, val) (((int64_unaligned_t *)(ptr))->v) = val
#define read_uint64(ptr) (((uint64_unaligned_t *)(ptr))->v)
#define write_uint64(ptr, val) (((uint64_unaligned_t *)(ptr))->v) = val
#endif

static int8_t SPICE_GNUC_UNUSED consume_int8(uint8_t **ptr)
{
    int8_t val;
    val = read_int8(*ptr);
    *ptr += 1;
    return val;
}

static uint8_t SPICE_GNUC_UNUSED consume_uint8(uint8_t **ptr)
{
    uint8_t val;
    val = read_uint8(*ptr);
    *ptr += 1;
    return val;
}

static int16_t SPICE_GNUC_UNUSED consume_int16(uint8_t **ptr)
{
    int16_t val;
    val = read_int16(*ptr);
    *ptr += 2;
    return val;
}

static uint16_t SPICE_GNUC_UNUSED consume_uint16(uint8_t **ptr)
{
    uint16_t val;
    val = read_uint16(*ptr);
    *ptr += 2;
    return val;
}

static int32_t SPICE_GNUC_UNUSED consume_int32(uint8_t **ptr)
{
    int32_t val;
    val = read_int32(*ptr);
    *ptr += 4;
    return val;
}

static uint32_t SPICE_GNUC_UNUSED consume_uint32(uint8_t **ptr)
{
    uint32_t val;
    val = read_uint32(*ptr);
    *ptr += 4;
    return val;
}

static int64_t SPICE_GNUC_UNUSED consume_int64(uint8_t **ptr)
{
    int64_t val;
    val = read_int64(*ptr);
    *ptr += 8;
    return val;
}

static uint64_t SPICE_GNUC_UNUSED consume_uint64(uint8_t **ptr)
{
    uint64_t val;
    val = read_uint64(*ptr);
    *ptr += 8;
    return val;
}
static int SPICE_GNUC_UNUSED consume_fd(uint8_t **ptr SPICE_GNUC_UNUSED)
{
    return -1;
}

typedef struct PointerInfo PointerInfo;
typedef void (*message_destructor_t)(uint8_t *message);
typedef uint8_t * (*parse_func_t)(uint8_t *message_start, uint8_t *message_end, uint8_t *struct_data, PointerInfo *ptr_info);
typedef uint8_t * (*parse_msg_func_t)(uint8_t *message_start, uint8_t *message_end, size_t *size_out, message_destructor_t *free_message);
typedef uint8_t * (*spice_parse_channel_func_t)(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, int minor, size_t *size_out, message_destructor_t *free_message);

struct PointerInfo {
    uint64_t offset;
    parse_func_t parse;
    void * *dest;
    uint64_t nelements;
};

static uint8_t * parse_msgc_ack_sync(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcAckSync *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgcAckSync);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcAckSync);
    in = start;

    out = (SpiceMsgcAckSync *)data;

    out->generation = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_SpiceMsgEmpty(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;

    nw_size = 0;
    mem_size = sizeof(SpiceMsgEmpty);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgEmpty);
    in = start;


    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_pong(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgPing *out;

    nw_size = 12;
    mem_size = sizeof(SpiceMsgPing);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgPing);
    in = start;

    out = (SpiceMsgPing *)data;

    out->id = consume_uint32(&in);
    out->timestamp = consume_uint64(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static void nofree(SPICE_GNUC_UNUSED uint8_t *data)
{
}

static uint8_t * parse_SpiceMsgData(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t data__nw_size;
    uint64_t data__nelements;

    { /* data */
        if (SPICE_UNLIKELY((start + 0) > message_end)) {
            goto error;
        }
        data__nelements = message_end - (start + 0);

        data__nw_size = data__nelements;
    }

    nw_size = 0 + data__nw_size;

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = message_start;
    *size = message_end - message_start;
    *free_message = nofree;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_disconnecting(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgDisconnect *out;

    nw_size = 12;
    mem_size = sizeof(SpiceMsgDisconnect);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgDisconnect);
    in = start;

    out = (SpiceMsgDisconnect *)data;

    out->time_stamp = consume_uint64(&in);
    out->reason = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_main_client_info(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcClientInfo *out;

    nw_size = 8;
    mem_size = sizeof(SpiceMsgcClientInfo);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcClientInfo);
    in = start;

    out = (SpiceMsgcClientInfo *)data;

    out->cache_size = consume_uint64(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_main_mouse_mode_request(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMainMouseModeRequest *out;

    nw_size = 2;
    mem_size = sizeof(SpiceMsgcMainMouseModeRequest);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMainMouseModeRequest);
    in = start;

    out = (SpiceMsgcMainMouseModeRequest *)data;

    out->mode = consume_uint16(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_main_agent_start(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgMainAgentTokens *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainAgentTokens);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgMainAgentTokens);
    in = start;

    out = (SpiceMsgMainAgentTokens *)data;

    out->num_tokens = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_main_agent_token(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgMainAgentTokens *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainAgentTokens);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgMainAgentTokens);
    in = start;

    out = (SpiceMsgMainAgentTokens *)data;

    out->num_tokens = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_main_migrate_dst_do_seamless(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMainMigrateDstDoSeamless *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgcMainMigrateDstDoSeamless);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMainMigrateDstDoSeamless);
    in = start;

    out = (SpiceMsgcMainMigrateDstDoSeamless *)data;

    out->src_version = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_MainChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[12] =  {
        parse_msgc_main_client_info,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgEmpty,
        parse_msgc_main_mouse_mode_request,
        parse_msgc_main_agent_start,
        parse_SpiceMsgData,
        parse_msgc_main_agent_token,
        parse_SpiceMsgEmpty,
        parse_msgc_main_migrate_dst_do_seamless,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 113) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msgc_display_init(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcDisplayInit *out;

    nw_size = 14;
    mem_size = sizeof(SpiceMsgcDisplayInit);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcDisplayInit);
    in = start;

    out = (SpiceMsgcDisplayInit *)data;

    out->pixmap_cache_id = consume_uint8(&in);
    out->pixmap_cache_size = consume_int64(&in);
    out->glz_dictionary_id = consume_uint8(&in);
    out->glz_dictionary_window_size = consume_int32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_display_stream_report(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcDisplayStreamReport *out;

    nw_size = 32;
    mem_size = sizeof(SpiceMsgcDisplayStreamReport);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcDisplayStreamReport);
    in = start;

    out = (SpiceMsgcDisplayStreamReport *)data;

    out->stream_id = consume_uint32(&in);
    out->unique_id = consume_uint32(&in);
    out->start_frame_mm_time = consume_uint32(&in);
    out->end_frame_mm_time = consume_uint32(&in);
    out->num_frames = consume_uint32(&in);
    out->num_drops = consume_uint32(&in);
    out->last_frame_delay = consume_int32(&in);
    out->audio_delay = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_display_preferred_compression(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcDisplayPreferredCompression *out;

    nw_size = 1;
    mem_size = sizeof(SpiceMsgcDisplayPreferredCompression);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcDisplayPreferredCompression);
    in = start;

    out = (SpiceMsgcDisplayPreferredCompression *)data;

    out->image_compression = consume_uint8(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_display_gl_draw_done(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;

    nw_size = 0;
    mem_size = sizeof(SpiceMsgcDisplayGlDrawDone);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcDisplayGlDrawDone);
    in = start;


    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_display_preferred_video_codec_type(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    uint64_t codecs__nw_size, codecs__mem_size;
    uint64_t codecs__nelements;
    SpiceMsgcDisplayPreferredVideoCodecType *out;
    uint32_t i;

    { /* codecs */
        uint8_t num_of_codecs__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        num_of_codecs__value = read_uint8(pos);
        codecs__nelements = num_of_codecs__value;

        codecs__nw_size = codecs__nelements;
        codecs__mem_size = sizeof(uint8_t) * codecs__nelements;
    }

    nw_size = 1 + codecs__nw_size;
    mem_size = sizeof(SpiceMsgcDisplayPreferredVideoCodecType) + codecs__mem_size;

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcDisplayPreferredVideoCodecType);
    in = start;

    out = (SpiceMsgcDisplayPreferredVideoCodecType *)data;

    out->num_of_codecs = consume_uint8(&in);
    verify(sizeof(out->codecs) == 0);
    for (i = 0; i < codecs__nelements; i++) {
        out->codecs[i] = consume_uint8(&in);
        end += sizeof(uint8_t);
    }

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_DisplayChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[5] =  {
        parse_msgc_display_init,
        parse_msgc_display_stream_report,
        parse_msgc_display_preferred_compression,
        parse_msgc_display_gl_draw_done,
        parse_msgc_display_preferred_video_codec_type
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 106) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msgc_inputs_key_down(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcKeyDown *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgcKeyDown);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcKeyDown);
    in = start;

    out = (SpiceMsgcKeyDown *)data;

    out->code = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_key_up(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcKeyUp *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgcKeyUp);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcKeyUp);
    in = start;

    out = (SpiceMsgcKeyUp *)data;

    out->code = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_key_modifiers(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcKeyModifiers *out;

    nw_size = 2;
    mem_size = sizeof(SpiceMsgcKeyModifiers);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcKeyModifiers);
    in = start;

    out = (SpiceMsgcKeyModifiers *)data;

    out->modifiers = consume_uint16(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_mouse_motion(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMouseMotion *out;

    nw_size = 10;
    mem_size = sizeof(SpiceMsgcMouseMotion);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMouseMotion);
    in = start;

    out = (SpiceMsgcMouseMotion *)data;

    out->dx = consume_int32(&in);
    out->dy = consume_int32(&in);
    out->buttons_state = consume_uint16(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_mouse_position(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMousePosition *out;

    nw_size = 11;
    mem_size = sizeof(SpiceMsgcMousePosition);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMousePosition);
    in = start;

    out = (SpiceMsgcMousePosition *)data;

    out->x = consume_uint32(&in);
    out->y = consume_uint32(&in);
    out->buttons_state = consume_uint16(&in);
    out->display_id = consume_uint8(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_mouse_press(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMousePress *out;

    nw_size = 3;
    mem_size = sizeof(SpiceMsgcMousePress);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMousePress);
    in = start;

    out = (SpiceMsgcMousePress *)data;

    out->button = consume_uint8(&in);
    out->buttons_state = consume_uint16(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_inputs_mouse_release(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcMouseRelease *out;

    nw_size = 3;
    mem_size = sizeof(SpiceMsgcMouseRelease);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcMouseRelease);
    in = start;

    out = (SpiceMsgcMouseRelease *)data;

    out->button = consume_uint8(&in);
    out->buttons_state = consume_uint16(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_InputsChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[4] =  {
        parse_msgc_inputs_key_down,
        parse_msgc_inputs_key_up,
        parse_msgc_inputs_key_modifiers,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs3[4] =  {
        parse_msgc_inputs_mouse_motion,
        parse_msgc_inputs_mouse_position,
        parse_msgc_inputs_mouse_press,
        parse_msgc_inputs_mouse_release
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 105) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    } else if (message_type >= 111 && message_type < 115) {
        return funcs3[message_type-111](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_CursorChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_PlaybackChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msgc_record_data(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    uint64_t data__nw_size;
    uint64_t data__nelements;
    SpiceMsgPlaybackPacket *out;

    { /* data */
        if (SPICE_UNLIKELY((start + 4) > message_end)) {
            goto error;
        }
        data__nelements = message_end - (start + 4);

        data__nw_size = data__nelements;
    }

    nw_size = 4 + data__nw_size;
    mem_size = sizeof(SpiceMsgPlaybackPacket);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgPlaybackPacket);
    in = start;

    out = (SpiceMsgPlaybackPacket *)data;

    out->time = consume_uint32(&in);
    /* use array as pointer */
    out->data = (uint8_t *)in;
    out->data_size = data__nelements;
    in += data__nelements;

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_record_mode(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    uint64_t data__nw_size;
    uint64_t data__nelements;
    SpiceMsgPlaybackMode *out;

    { /* data */
        if (SPICE_UNLIKELY((start + 6) > message_end)) {
            goto error;
        }
        data__nelements = message_end - (start + 6);

        data__nw_size = data__nelements;
    }

    nw_size = 6 + data__nw_size;
    mem_size = sizeof(SpiceMsgPlaybackMode);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgPlaybackMode);
    in = start;

    out = (SpiceMsgPlaybackMode *)data;

    out->time = consume_uint32(&in);
    out->mode = consume_uint16(&in);
    /* use array as pointer */
    out->data = (uint8_t *)in;
    out->data_size = data__nelements;
    in += data__nelements;

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_msgc_record_start_mark(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcRecordStartMark *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgcRecordStartMark);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcRecordStartMark);
    in = start;

    out = (SpiceMsgcRecordStartMark *)data;

    out->time = consume_uint32(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_RecordChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[3] =  {
        parse_msgc_record_data,
        parse_msgc_record_mode,
        parse_msgc_record_start_mark
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 104) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_TunnelChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{

    return NULL;
}


#ifdef USE_SMARTCARD

static uint8_t * parse_msgc_smartcard_data(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    uint64_t data__nw_size, data__mem_size;
    uint64_t data__nelements;
    VSCMsgHeader *out;

    { /* data */
        uint32_t length__value;
        pos = start + 8;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        length__value = read_uint32(pos);
        data__nelements = length__value;

        data__nw_size = data__nelements;
        data__mem_size = sizeof(uint8_t) * data__nelements;
    }

    nw_size = 12 + data__nw_size;
    mem_size = sizeof(VSCMsgHeader) + data__mem_size;

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(VSCMsgHeader);
    in = start;

    out = (VSCMsgHeader *)data;

    out->type = consume_uint32(&in);
    out->reader_id = consume_uint32(&in);
    out->length = consume_uint32(&in);
    verify(sizeof(out->data) == 0);
    memcpy(out->data, in, data__nelements);
    in += data__nelements;
    end += data__nelements;

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_SmartcardChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[1] =  {
        parse_msgc_smartcard_data
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 102) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    }
    return NULL;
}
#endif /* USE_SMARTCARD */



static uint8_t * parse_SpiceMsgCompressedData(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    uint64_t u__nw_size;
    uint8_t type__value;
    uint64_t compressed_data__nw_size;
    uint64_t compressed_data__nelements;
    SpiceMsgCompressedData *out;

    { /* u */
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        type__value = read_uint8(pos);
        if (type__value == SPICE_DATA_COMPRESSION_TYPE_NONE) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 1);
            u__nw_size = 0;
        } else if (1) {
            u__nw_size = 4;
        } else {
            u__nw_size = 0;
        }

    }

    { /* compressed_data */
        if (SPICE_UNLIKELY((start + 1 + u__nw_size) > message_end)) {
            goto error;
        }
        compressed_data__nelements = message_end - (start + 1 + u__nw_size);

        compressed_data__nw_size = compressed_data__nelements;
    }

    nw_size = 1 + u__nw_size + compressed_data__nw_size;
    mem_size = sizeof(SpiceMsgCompressedData);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgCompressedData);
    in = start;

    out = (SpiceMsgCompressedData *)data;

    out->type = consume_uint8(&in);
    if (out->type == SPICE_DATA_COMPRESSION_TYPE_NONE) {
    } else if (1) {
        out->uncompressed_size = consume_uint32(&in);
    }
    /* use array as pointer */
    out->compressed_data = (uint8_t *)in;
    out->compressed_size = compressed_data__nelements;
    in += compressed_data__nelements;

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_UsbredirChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[2] =  {
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 103) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msgc_port_event(uint8_t *message_start, uint8_t *message_end, size_t *size, message_destructor_t *free_message)
{
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint8_t *start = message_start;
    uint8_t *data = NULL;
    uint64_t nw_size;
    uint64_t mem_size;
    uint8_t *in, *end;
    SpiceMsgcPortEvent *out;

    nw_size = 1;
    mem_size = sizeof(SpiceMsgcPortEvent);

    /* Check if message fits in reported side */
    if (nw_size > (uintptr_t) (message_end - start)) {
        return NULL;
    }

    /* Validated extents and calculated size */
    data = (uint8_t *)(mem_size > UINT32_MAX ? NULL : malloc(mem_size));
    if (SPICE_UNLIKELY(data == NULL)) {
        goto error;
    }
    end = data + sizeof(SpiceMsgcPortEvent);
    in = start;

    out = (SpiceMsgcPortEvent *)data;

    out->event = consume_uint8(&in);

    assert(in <= message_end);
    assert(end <= data + mem_size);

    *size = end - data;
    *free_message = (message_destructor_t) free;
    return data;

   error:
    free(data);
    return NULL;
}

static uint8_t * parse_PortChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[2] =  {
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    static parse_msg_func_t funcs3[1] =  {
        parse_msgc_port_event
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 103) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    } else if (message_type >= 201 && message_type < 202) {
        return funcs3[message_type-201](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_WebDAVChannel_msgc(uint8_t *message_start, uint8_t *message_end, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    static parse_msg_func_t funcs1[6] =  {
        parse_msgc_ack_sync,
        parse_SpiceMsgEmpty,
        parse_msgc_pong,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_msgc_disconnecting
    };
    static parse_msg_func_t funcs2[2] =  {
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    static parse_msg_func_t funcs3[1] =  {
        parse_msgc_port_event
    };
    if (message_type >= 1 && message_type < 7) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 101 && message_type < 103) {
        return funcs2[message_type-101](message_start, message_end, size_out, free_message);
    } else if (message_type >= 201 && message_type < 202) {
        return funcs3[message_type-201](message_start, message_end, size_out, free_message);
    }
    return NULL;
}

spice_parse_channel_func_t spice_get_client_channel_parser(uint32_t channel, unsigned int *max_message_type)
{
    static struct {spice_parse_channel_func_t func; unsigned int max_messages; } channels[12] =  {
        { NULL, 0 },
        { parse_MainChannel_msgc, 112},
        { parse_DisplayChannel_msgc, 105},
        { parse_InputsChannel_msgc, 114},
        { parse_CursorChannel_msgc, 6},
        { parse_PlaybackChannel_msgc, 6},
        { parse_RecordChannel_msgc, 103},
        { parse_TunnelChannel_msgc, 0},
#ifdef USE_SMARTCARD
        { parse_SmartcardChannel_msgc, 101},
#else /* USE_SMARTCARD */
        { NULL, 0 },
#endif /* USE_SMARTCARD */
        { parse_UsbredirChannel_msgc, 102},
        { parse_PortChannel_msgc, 201},
        { parse_WebDAVChannel_msgc, 201}
    };
    if (channel < 12) {
        if (max_message_type != NULL) {
            *max_message_type = channels[channel].max_messages;
        }
        return channels[channel].func;
    }
    return NULL;
}

uint8_t * spice_parse_reply(uint8_t *message_start, uint8_t *message_end, uint32_t channel, uint16_t message_type, SPICE_GNUC_UNUSED int minor, size_t *size_out, message_destructor_t *free_message)
{
    spice_parse_channel_func_t func;
    func = spice_get_client_channel_parser(channel, NULL);
    if (func != NULL) {
        return func(message_start, message_end, message_type, minor, size_out, free_message);
    }
    return NULL;
}
