/* 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_msg_migrate(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;
    SpiceMsgMigrate *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMigrate);

    /* 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(SpiceMsgMigrate);
    in = start;

    out = (SpiceMsgMigrate *)data;

    out->flags = 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 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_msg_set_ack(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;
    SpiceMsgSetAck *out;

    nw_size = 8;
    mem_size = sizeof(SpiceMsgSetAck);

    /* 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(SpiceMsgSetAck);
    in = start;

    out = (SpiceMsgSetAck *)data;

    out->generation = consume_uint32(&in);
    out->window = 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_msg_ping(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;
    SpiceMsgPing *out;

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

        data__nw_size = data__nelements;
    }

    nw_size = 12 + data__nw_size;
    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);
    /* use array as pointer */
    out->data = (uint8_t *)in;
    out->data_len = 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_msg_wait_for_channels(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 wait_list__nw_size, wait_list__mem_size;
    uint64_t wait_list__nelements;
    SpiceMsgWaitForChannels *out;
    uint32_t i;

    { /* wait_list */
        uint8_t wait_count__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        wait_count__value = read_uint8(pos);
        wait_list__nelements = wait_count__value;

        wait_list__nw_size = (10) * wait_list__nelements;
        wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements;
    }

    nw_size = 1 + wait_list__nw_size;
    mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__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(SpiceMsgWaitForChannels);
    in = start;

    out = (SpiceMsgWaitForChannels *)data;

    out->wait_count = consume_uint8(&in);
    verify(sizeof(out->wait_list) == 0);
    for (i = 0; i < wait_list__nelements; i++) {
        SpiceWaitForChannel *out2;
        out2 = (SpiceWaitForChannel *)end;
        end += sizeof(SpiceWaitForChannel);

        out2->channel_type = consume_uint8(&in);
        out2->channel_id = consume_uint8(&in);
        out2->message_serial = 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_msg_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_msg_notify(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 message__nw_size, message__mem_size;
    uint64_t message__nelements;
    SpiceMsgNotify *out;

    { /* message */
        uint32_t message_len__value;
        pos = start + 20;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        message_len__value = read_uint32(pos);
        message__nelements = message_len__value;

        message__nw_size = message__nelements;
        message__mem_size = sizeof(uint8_t) * message__nelements;
    }

    nw_size = 24 + message__nw_size;
    mem_size = sizeof(SpiceMsgNotify) + message__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(SpiceMsgNotify);
    in = start;

    out = (SpiceMsgNotify *)data;

    out->time_stamp = consume_uint64(&in);
    out->severity = consume_uint32(&in);
    out->visibilty = consume_uint32(&in);
    out->what = consume_uint32(&in);
    out->message_len = consume_uint32(&in);
    verify(sizeof(out->message) == 0);
    memcpy(out->message, in, message__nelements);
    in += message__nelements;
    end += message__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_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_array_uint8_terminated(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;

    end = struct_data;
    memcpy(end, in, this_ptr_info->nelements);
#if defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
    ((char *) (end))[this_ptr_info->nelements] = 0;
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
    in += this_ptr_info->nelements;
    end += this_ptr_info->nelements;
    end += 1;
    return end;
}

static uint8_t * parse_msg_main_migrate_begin(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t dst_info__extra_size;
    SpiceMsgMainMigrationBegin *out;
    uint32_t i;

    { /* dst_info */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t dst_info_host_data__extra_size;
        uint64_t dst_info_host_data__array__nelements;
        uint64_t dst_info_cert_subject_data__extra_size;
        uint64_t dst_info_cert_subject_data__array__nelements;
        { /* host_data */
            uint32_t host_data__value;
            uint64_t dst_info_host_data__array__nw_size;
            uint64_t dst_info_host_data__array__mem_size;
            uint32_t host_size__value;
            pos = (start2 + 8);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            host_data__value = read_uint32(pos);
            if (SPICE_UNLIKELY(host_data__value == 0)) {
                goto error;
            }
            if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
                goto error;
            }
            pos = start2 + 4;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            host_size__value = read_uint32(pos);
            dst_info_host_data__array__nelements = host_size__value;

            dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements + sizeof(uint8_t);
            dst_info_host_data__array__mem_size = SPICE_ALIGN(dst_info_host_data__array__mem_size, 4);
            if (SPICE_UNLIKELY(dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
                goto error;
            }
            dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3;
        }

        { /* cert_subject_data */
            uint32_t cert_subject_data__value;
            uint64_t dst_info_cert_subject_data__array__nw_size;
            uint64_t dst_info_cert_subject_data__array__mem_size;
            uint32_t cert_subject_size__value;
            pos = (start2 + 16);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            cert_subject_data__value = read_uint32(pos);
            if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
                goto error;
            }
            pos = start2 + 12;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            cert_subject_size__value = read_uint32(pos);
            dst_info_cert_subject_data__array__nelements = cert_subject_size__value;

            dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements + sizeof(uint8_t);
            dst_info_cert_subject_data__array__mem_size = SPICE_ALIGN(dst_info_cert_subject_data__array__mem_size, 4);
            if (SPICE_UNLIKELY(dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
                goto error;
            }
            dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3;
        }

        dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size;
    }

    nw_size = 20;
    mem_size = sizeof(SpiceMsgMainMigrationBegin) + dst_info__extra_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(SpiceMsgMainMigrationBegin);
    in = start;

    out = (SpiceMsgMainMigrationBegin *)data;

    /* dst_info */ {
        uint64_t host_data__array__nelements;
        uint64_t cert_subject_data__array__nelements;
        out->dst_info.port = consume_uint16(&in);
        out->dst_info.sport = consume_uint16(&in);
        out->dst_info.host_size = consume_uint32(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
        ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
        host_data__array__nelements = out->dst_info.host_size;
        ptr_info[n_ptr].nelements = host_data__array__nelements;
        n_ptr++;
        out->dst_info.cert_subject_size = consume_uint32(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
        ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
        cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
        ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
        n_ptr++;
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_main_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;
    SpiceMsgMainInit *out;

    nw_size = 32;
    mem_size = sizeof(SpiceMsgMainInit);

    /* 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(SpiceMsgMainInit);
    in = start;

    out = (SpiceMsgMainInit *)data;

    out->session_id = consume_uint32(&in);
    out->display_channels_hint = consume_uint32(&in);
    out->supported_mouse_modes = consume_uint32(&in);
    out->current_mouse_mode = consume_uint32(&in);
    out->agent_connected = consume_uint32(&in);
    out->agent_tokens = consume_uint32(&in);
    out->multi_media_time = consume_uint32(&in);
    out->ram_hint = 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_msg_main_channels_list(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 channels__nw_size, channels__mem_size;
    uint64_t channels__nelements;
    SpiceMsgChannels *out;
    uint32_t i;

    { /* channels */
        uint32_t num_of_channels__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        num_of_channels__value = read_uint32(pos);
        channels__nelements = num_of_channels__value;

        channels__nw_size = (2) * channels__nelements;
        channels__mem_size = sizeof(SpiceChannelId) * channels__nelements;
    }

    nw_size = 4 + channels__nw_size;
    mem_size = sizeof(SpiceMsgChannels) + channels__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(SpiceMsgChannels);
    in = start;

    out = (SpiceMsgChannels *)data;

    out->num_of_channels = consume_uint32(&in);
    verify(sizeof(out->channels) == 0);
    for (i = 0; i < channels__nelements; i++) {
        SpiceChannelId *out2;
        out2 = (SpiceChannelId *)end;
        end += sizeof(SpiceChannelId);

        out2->type = consume_uint8(&in);
        out2->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_msg_main_mouse_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;
    SpiceMsgMainMouseMode *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainMouseMode);

    /* 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(SpiceMsgMainMouseMode);
    in = start;

    out = (SpiceMsgMainMouseMode *)data;

    out->supported_modes = consume_uint16(&in);
    out->current_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_msg_main_multi_media_time(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;
    SpiceMsgMainMultiMediaTime *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainMultiMediaTime);

    /* 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(SpiceMsgMainMultiMediaTime);
    in = start;

    out = (SpiceMsgMainMultiMediaTime *)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_msg_main_agent_disconnected(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;
    SpiceMsgMainAgentDisconnect *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainAgentDisconnect);

    /* 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(SpiceMsgMainAgentDisconnect);
    in = start;

    out = (SpiceMsgMainAgentDisconnect *)data;

    out->error_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_msg_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_msg_main_migrate_switch_host(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t host_data__extra_size;
    uint64_t host_data__array__nelements;
    uint64_t cert_subject_data__extra_size;
    uint64_t cert_subject_data__array__nelements;
    SpiceMsgMainMigrationSwitchHost *out;
    uint32_t i;

    { /* host_data */
        uint32_t host_data__value;
        uint64_t host_data__array__nw_size;
        uint64_t host_data__array__mem_size;
        uint32_t host_size__value;
        pos = (start + 8);
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        host_data__value = read_uint32(pos);
        if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
            goto error;
        }
        pos = start + 4;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        host_size__value = read_uint32(pos);
        host_data__array__nelements = host_size__value;

        host_data__array__nw_size = host_data__array__nelements;
        host_data__array__mem_size = sizeof(uint8_t) * host_data__array__nelements + sizeof(uint8_t);
        host_data__array__mem_size = SPICE_ALIGN(host_data__array__mem_size, 4);
        if (SPICE_UNLIKELY(host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
            goto error;
        }
        host_data__extra_size = host_data__array__mem_size + /* for alignment */ 3;
    }

    { /* cert_subject_data */
        uint32_t cert_subject_data__value;
        uint64_t cert_subject_data__array__nw_size;
        uint64_t cert_subject_data__array__mem_size;
        uint32_t cert_subject_size__value;
        pos = (start + 16);
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        cert_subject_data__value = read_uint32(pos);
        if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
            goto error;
        }
        pos = start + 12;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        cert_subject_size__value = read_uint32(pos);
        cert_subject_data__array__nelements = cert_subject_size__value;

        cert_subject_data__array__nw_size = cert_subject_data__array__nelements;
        cert_subject_data__array__mem_size = sizeof(uint8_t) * cert_subject_data__array__nelements + sizeof(uint8_t);
        cert_subject_data__array__mem_size = SPICE_ALIGN(cert_subject_data__array__mem_size, 4);
        if (SPICE_UNLIKELY(cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
            goto error;
        }
        cert_subject_data__extra_size = cert_subject_data__array__mem_size + /* for alignment */ 3;
    }

    nw_size = 20;
    mem_size = sizeof(SpiceMsgMainMigrationSwitchHost) + host_data__extra_size + cert_subject_data__extra_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(SpiceMsgMainMigrationSwitchHost);
    in = start;

    out = (SpiceMsgMainMigrationSwitchHost *)data;

    out->port = consume_uint16(&in);
    out->sport = consume_uint16(&in);
    out->host_size = consume_uint32(&in);
    ptr_info[n_ptr].offset = consume_uint32(&in);
    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
    ptr_info[n_ptr].dest = (void **)&out->host_data;
    ptr_info[n_ptr].nelements = host_data__array__nelements;
    n_ptr++;
    out->cert_subject_size = consume_uint32(&in);
    ptr_info[n_ptr].offset = consume_uint32(&in);
    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
    ptr_info[n_ptr].dest = (void **)&out->cert_subject_data;
    ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
    n_ptr++;

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_main_name(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 name__nw_size, name__mem_size;
    uint64_t name__nelements;
    SpiceMsgMainName *out;

    { /* name */
        uint32_t name_len__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        name_len__value = read_uint32(pos);
        name__nelements = name_len__value;

        name__nw_size = name__nelements;
        name__mem_size = sizeof(uint8_t) * name__nelements;
    }

    nw_size = 4 + name__nw_size;
    mem_size = sizeof(SpiceMsgMainName) + name__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(SpiceMsgMainName);
    in = start;

    out = (SpiceMsgMainName *)data;

    out->name_len = consume_uint32(&in);
    verify(sizeof(out->name) == 0);
    memcpy(out->name, in, name__nelements);
    in += name__nelements;
    end += name__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_msg_main_uuid(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;
    SpiceMsgMainUuid *out;
    uint64_t uuid__nelements;

    nw_size = 16;
    mem_size = sizeof(SpiceMsgMainUuid);

    /* 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(SpiceMsgMainUuid);
    in = start;

    out = (SpiceMsgMainUuid *)data;

    uuid__nelements = 16;
    memcpy(out->uuid, in, uuid__nelements);
    in += uuid__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_msg_main_agent_connected_tokens(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;
    SpiceMsgMainAgentConnectedTokens *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgMainAgentConnectedTokens);

    /* 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(SpiceMsgMainAgentConnectedTokens);
    in = start;

    out = (SpiceMsgMainAgentConnectedTokens *)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_msg_main_migrate_begin_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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t dst_info__extra_size;
    SpiceMsgMainMigrateBeginSeamless *out;
    uint32_t i;

    { /* dst_info */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t dst_info_host_data__extra_size;
        uint64_t dst_info_host_data__array__nelements;
        uint64_t dst_info_cert_subject_data__extra_size;
        uint64_t dst_info_cert_subject_data__array__nelements;
        { /* host_data */
            uint32_t host_data__value;
            uint64_t dst_info_host_data__array__nw_size;
            uint64_t dst_info_host_data__array__mem_size;
            uint32_t host_size__value;
            pos = (start2 + 8);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            host_data__value = read_uint32(pos);
            if (SPICE_UNLIKELY(host_data__value == 0)) {
                goto error;
            }
            if (SPICE_UNLIKELY(host_data__value >= (uintptr_t) (message_end - message_start))) {
                goto error;
            }
            pos = start2 + 4;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            host_size__value = read_uint32(pos);
            dst_info_host_data__array__nelements = host_size__value;

            dst_info_host_data__array__nw_size = dst_info_host_data__array__nelements;
            dst_info_host_data__array__mem_size = sizeof(uint8_t) * dst_info_host_data__array__nelements + sizeof(uint8_t);
            dst_info_host_data__array__mem_size = SPICE_ALIGN(dst_info_host_data__array__mem_size, 4);
            if (SPICE_UNLIKELY(dst_info_host_data__array__nw_size > (uintptr_t) (message_end - message_start - host_data__value))) {
                goto error;
            }
            dst_info_host_data__extra_size = dst_info_host_data__array__mem_size + /* for alignment */ 3;
        }

        { /* cert_subject_data */
            uint32_t cert_subject_data__value;
            uint64_t dst_info_cert_subject_data__array__nw_size;
            uint64_t dst_info_cert_subject_data__array__mem_size;
            uint32_t cert_subject_size__value;
            pos = (start2 + 16);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            cert_subject_data__value = read_uint32(pos);
            if (SPICE_UNLIKELY(cert_subject_data__value >= (uintptr_t) (message_end - message_start))) {
                goto error;
            }
            pos = start2 + 12;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            cert_subject_size__value = read_uint32(pos);
            dst_info_cert_subject_data__array__nelements = cert_subject_size__value;

            dst_info_cert_subject_data__array__nw_size = dst_info_cert_subject_data__array__nelements;
            dst_info_cert_subject_data__array__mem_size = sizeof(uint8_t) * dst_info_cert_subject_data__array__nelements + sizeof(uint8_t);
            dst_info_cert_subject_data__array__mem_size = SPICE_ALIGN(dst_info_cert_subject_data__array__mem_size, 4);
            if (SPICE_UNLIKELY(dst_info_cert_subject_data__array__nw_size > (uintptr_t) (message_end - message_start - cert_subject_data__value))) {
                goto error;
            }
            dst_info_cert_subject_data__extra_size = dst_info_cert_subject_data__array__mem_size + /* for alignment */ 3;
        }

        dst_info__extra_size = dst_info_host_data__extra_size + dst_info_cert_subject_data__extra_size;
    }

    nw_size = 24;
    mem_size = sizeof(SpiceMsgMainMigrateBeginSeamless) + dst_info__extra_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(SpiceMsgMainMigrateBeginSeamless);
    in = start;

    out = (SpiceMsgMainMigrateBeginSeamless *)data;

    /* dst_info */ {
        uint64_t host_data__array__nelements;
        uint64_t cert_subject_data__array__nelements;
        out->dst_info.port = consume_uint16(&in);
        out->dst_info.sport = consume_uint16(&in);
        out->dst_info.host_size = consume_uint32(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
        ptr_info[n_ptr].dest = (void **)&out->dst_info.host_data;
        host_data__array__nelements = out->dst_info.host_size;
        ptr_info[n_ptr].nelements = host_data__array__nelements;
        n_ptr++;
        out->dst_info.cert_subject_size = consume_uint32(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_array_uint8_terminated;
        ptr_info[n_ptr].dest = (void **)&out->dst_info.cert_subject_data;
        cert_subject_data__array__nelements = out->dst_info.cert_subject_size;
        ptr_info[n_ptr].nelements = cert_subject_data__array__nelements;
        n_ptr++;
    }
    out->src_mig_version = consume_uint32(&in);

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[19] =  {
        parse_SpiceMsgEmpty,
        parse_msg_main_migrate_begin,
        parse_SpiceMsgEmpty,
        parse_msg_main_init,
        parse_msg_main_channels_list,
        parse_msg_main_mouse_mode,
        parse_msg_main_multi_media_time,
        parse_SpiceMsgEmpty,
        parse_msg_main_agent_disconnected,
        parse_SpiceMsgData,
        parse_msg_main_agent_token,
        parse_msg_main_migrate_switch_host,
        parse_SpiceMsgEmpty,
        parse_msg_main_name,
        parse_msg_main_uuid,
        parse_msg_main_agent_connected_tokens,
        parse_msg_main_migrate_begin_seamless,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgEmpty
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 119) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_display_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;
    SpiceMsgDisplayMode *out;

    nw_size = 12;
    mem_size = sizeof(SpiceMsgDisplayMode);

    /* 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(SpiceMsgDisplayMode);
    in = start;

    out = (SpiceMsgDisplayMode *)data;

    out->x_res = consume_uint32(&in);
    out->y_res = consume_uint32(&in);
    out->bits = 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_struct_SpiceClipRects(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    SpiceClipRects *out;
    uint64_t rects__nelements;
    uint32_t i;

    end = struct_data + sizeof(SpiceClipRects);
    out = (SpiceClipRects *)struct_data;

    out->num_rects = consume_uint32(&in);
    rects__nelements = out->num_rects;
    verify(sizeof(out->rects) == 0);
    for (i = 0; i < rects__nelements; i++) {
        SpiceRect *out2;
        out2 = (SpiceRect *)end;
        end += sizeof(SpiceRect);

        out2->top = consume_int32(&in);
        out2->left = consume_int32(&in);
        out2->bottom = consume_int32(&in);
        out2->right = consume_int32(&in);
    }
    return end;
}

static uint8_t * parse_msg_display_copy_bits(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[1];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    SpiceMsgDisplayCopyBits *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    nw_size = 8 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayCopyBits) + base__extra_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(SpiceMsgDisplayCopyBits);
    in = start;

    out = (SpiceMsgDisplayCopyBits *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* src_pos */ {
        out->src_pos.x = consume_int32(&in);
        out->src_pos.y = consume_int32(&in);
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_inval_list(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 resources__nw_size, resources__mem_size;
    uint64_t resources__nelements;
    SpiceResourceList *out;
    uint32_t i;

    { /* resources */
        uint16_t count__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 2 > message_end)) {
            goto error;
        }
        count__value = read_uint16(pos);
        resources__nelements = count__value;

        resources__nw_size = (9) * resources__nelements;
        resources__mem_size = sizeof(SpiceResourceID) * resources__nelements;
    }

    nw_size = 2 + resources__nw_size;
    mem_size = sizeof(SpiceResourceList) + resources__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(SpiceResourceList);
    in = start;

    out = (SpiceResourceList *)data;

    out->count = consume_uint16(&in);
    verify(sizeof(out->resources) == 0);
    for (i = 0; i < resources__nelements; i++) {
        SpiceResourceID *out2;
        out2 = (SpiceResourceID *)end;
        end += sizeof(SpiceResourceID);

        out2->type = consume_uint8(&in);
        out2->id = 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_msg_display_inval_all_pixmaps(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 wait_list__nw_size, wait_list__mem_size;
    uint64_t wait_list__nelements;
    SpiceMsgWaitForChannels *out;
    uint32_t i;

    { /* wait_list */
        uint8_t wait_count__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        wait_count__value = read_uint8(pos);
        wait_list__nelements = wait_count__value;

        wait_list__nw_size = (10) * wait_list__nelements;
        wait_list__mem_size = sizeof(SpiceWaitForChannel) * wait_list__nelements;
    }

    nw_size = 1 + wait_list__nw_size;
    mem_size = sizeof(SpiceMsgWaitForChannels) + wait_list__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(SpiceMsgWaitForChannels);
    in = start;

    out = (SpiceMsgWaitForChannels *)data;

    out->wait_count = consume_uint8(&in);
    verify(sizeof(out->wait_list) == 0);
    for (i = 0; i < wait_list__nelements; i++) {
        SpiceWaitForChannel *out2;
        out2 = (SpiceWaitForChannel *)end;
        end += sizeof(SpiceWaitForChannel);

        out2->channel_type = consume_uint8(&in);
        out2->channel_id = consume_uint8(&in);
        out2->message_serial = 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_msg_display_inval_palette(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;
    SpiceMsgDisplayInvalOne *out;

    nw_size = 8;
    mem_size = sizeof(SpiceMsgDisplayInvalOne);

    /* 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(SpiceMsgDisplayInvalOne);
    in = start;

    out = (SpiceMsgDisplayInvalOne *)data;

    out->id = 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_msg_display_stream_create(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[1];
    uint64_t clip__nw_size, clip__extra_size;
    uint32_t rects__saved_size = 0;
    SpiceMsgDisplayStreamCreate *out;
    uint32_t i;

    { /* clip */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 50);
        uint64_t clip_u__nw_size, clip_u__extra_size;
        uint8_t type__value;
        { /* u */
            uint64_t clip_u__mem_size;
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                goto error;
            }
            type__value = read_uint8(pos);
            if (type__value == SPICE_CLIP_TYPE_RECTS) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1);
                uint64_t clip_u_rects__nw_size, clip_u_rects__mem_size;
                uint64_t clip_u_rects__nelements;
                { /* rects */
                    uint32_t num_rects__value;
                    pos = start3 + 0;
                    if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                        goto error;
                    }
                    num_rects__value = read_uint32(pos);
                    clip_u_rects__nelements = num_rects__value;

                    clip_u_rects__nw_size = (16) * clip_u_rects__nelements;
                    clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements;
                }

                clip_u__nw_size = 4 + clip_u_rects__nw_size;
                clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size;
                rects__saved_size = clip_u__nw_size;
                clip_u__extra_size = clip_u__mem_size;
            } else {
                clip_u__nw_size = 0;
                clip_u__extra_size = 0;
            }

        }

        clip__nw_size = 1 + clip_u__nw_size;
        clip__extra_size = clip_u__extra_size;
    }

    nw_size = 50 + clip__nw_size;
    mem_size = sizeof(SpiceMsgDisplayStreamCreate) + clip__extra_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(SpiceMsgDisplayStreamCreate);
    in = start;

    out = (SpiceMsgDisplayStreamCreate *)data;

    out->surface_id = consume_uint32(&in);
    out->id = consume_uint32(&in);
    out->flags = consume_uint8(&in);
    out->codec_type = consume_uint8(&in);
    out->stamp = consume_uint64(&in);
    out->stream_width = consume_uint32(&in);
    out->stream_height = consume_uint32(&in);
    out->src_width = consume_uint32(&in);
    out->src_height = consume_uint32(&in);
    /* dest */ {
        out->dest.top = consume_int32(&in);
        out->dest.left = consume_int32(&in);
        out->dest.bottom = consume_int32(&in);
        out->dest.right = consume_int32(&in);
    }
    /* clip */ {
        out->clip.type = consume_uint8(&in);
        if (out->clip.type == SPICE_CLIP_TYPE_RECTS) {
            ptr_info[n_ptr].offset = in - start;
            ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
            ptr_info[n_ptr].dest = (void **)&out->clip.rects;
            n_ptr++;
            in += rects__saved_size;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_stream_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;
    SpiceMsgDisplayStreamData *out;

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

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

    nw_size = 12 + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayStreamData) + 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(SpiceMsgDisplayStreamData);
    in = start;

    out = (SpiceMsgDisplayStreamData *)data;

    /* base */ {
        out->base.id = consume_uint32(&in);
        out->base.multi_media_time = consume_uint32(&in);
    }
    out->data_size = 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_msg_display_stream_clip(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[1];
    uint64_t clip__nw_size, clip__extra_size;
    uint32_t rects__saved_size = 0;
    SpiceMsgDisplayStreamClip *out;
    uint32_t i;

    { /* clip */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 4);
        uint64_t clip_u__nw_size, clip_u__extra_size;
        uint8_t type__value;
        { /* u */
            uint64_t clip_u__mem_size;
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                goto error;
            }
            type__value = read_uint8(pos);
            if (type__value == SPICE_CLIP_TYPE_RECTS) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 1);
                uint64_t clip_u_rects__nw_size, clip_u_rects__mem_size;
                uint64_t clip_u_rects__nelements;
                { /* rects */
                    uint32_t num_rects__value;
                    pos = start3 + 0;
                    if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                        goto error;
                    }
                    num_rects__value = read_uint32(pos);
                    clip_u_rects__nelements = num_rects__value;

                    clip_u_rects__nw_size = (16) * clip_u_rects__nelements;
                    clip_u_rects__mem_size = sizeof(SpiceRect) * clip_u_rects__nelements;
                }

                clip_u__nw_size = 4 + clip_u_rects__nw_size;
                clip_u__mem_size = sizeof(SpiceClipRects) + clip_u_rects__mem_size;
                rects__saved_size = clip_u__nw_size;
                clip_u__extra_size = clip_u__mem_size;
            } else {
                clip_u__nw_size = 0;
                clip_u__extra_size = 0;
            }

        }

        clip__nw_size = 1 + clip_u__nw_size;
        clip__extra_size = clip_u__extra_size;
    }

    nw_size = 4 + clip__nw_size;
    mem_size = sizeof(SpiceMsgDisplayStreamClip) + clip__extra_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(SpiceMsgDisplayStreamClip);
    in = start;

    out = (SpiceMsgDisplayStreamClip *)data;

    out->id = consume_uint32(&in);
    /* clip */ {
        out->clip.type = consume_uint8(&in);
        if (out->clip.type == SPICE_CLIP_TYPE_RECTS) {
            ptr_info[n_ptr].offset = in - start;
            ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
            ptr_info[n_ptr].dest = (void **)&out->clip.rects;
            n_ptr++;
            in += rects__saved_size;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_stream_destroy(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;
    SpiceMsgDisplayStreamDestroy *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgDisplayStreamDestroy);

    /* 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(SpiceMsgDisplayStreamDestroy);
    in = start;

    out = (SpiceMsgDisplayStreamDestroy *)data;

    out->id = 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 intptr_t validate_SpicePalette(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
{
    uint8_t *start = message_start + offset;
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint64_t mem_size, nw_size;
    uint64_t ents__nw_size, ents__mem_size;
    uint64_t ents__nelements;

    if (offset == 0) {
        return 0;
    }

    if (SPICE_UNLIKELY(offset >= (uintptr_t) (message_end - message_start))) {
        goto error;
    }

    { /* ents */
        uint16_t num_ents__value;
        pos = start + 8;
        if (SPICE_UNLIKELY(pos + 2 > message_end)) {
            goto error;
        }
        num_ents__value = read_uint16(pos);
        ents__nelements = num_ents__value;

        ents__nw_size = (4) * ents__nelements;
        ents__mem_size = sizeof(uint32_t) * ents__nelements;
    }

    nw_size = 10 + ents__nw_size;
    mem_size = sizeof(SpicePalette) + ents__mem_size;

    /* Check if struct fits in reported side */
    if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
        goto error;
    }
    return mem_size;

   error:
    return -1;
}

static intptr_t validate_SpiceImage(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
{
    uint8_t *start = message_start + offset;
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint64_t mem_size, nw_size;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint64_t u__nw_size, u__extra_size;
    uint8_t descriptor_type__value;

    if (offset == 0) {
        return 0;
    }

    if (SPICE_UNLIKELY(offset >= (uintptr_t) (message_end - message_start))) {
        goto error;
    }

    { /* u */
        pos = start + 8;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        descriptor_type__value = read_uint8(pos);
        if (descriptor_type__value == SPICE_IMAGE_TYPE_BITMAP) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_pal__nw_size, u_pal__extra_size;
            uint8_t flags__value;
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* pal */
                pos = start2 + 1;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                flags__value = read_uint8(pos);
                if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
                    u_pal__nw_size = 8;
                    u_pal__extra_size = 0;
                } else if (1) {
                    uint32_t u_pal_palette__value;
                    u_pal__nw_size = 4;
                    pos = (start2 + 14);
                    if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                        goto error;
                    }
                    u_pal_palette__value = read_uint32(pos);
                    ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value);
                    if (SPICE_UNLIKELY(ptr_size < 0)) {
                        goto error;
                    }
                    u_pal__extra_size = ptr_size + /* for alignment */ 3;
                } else {
                    u_pal__nw_size = 0;
                    u_pal__extra_size = 0;
                }

            }

            { /* data */
                uint32_t stride__value;
                uint32_t y__value;
                pos = start2 + 10;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                stride__value = read_uint32(pos);
                pos = start2 + 6;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                y__value = read_uint32(pos);
                u_data__nelements = (uint64_t) stride__value * y__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 14 + u_pal__nw_size + u_data__nw_size;
            u__extra_size = u_pal__extra_size + u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_QUIC) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 4 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_RGB || descriptor_type__value == SPICE_IMAGE_TYPE_GLZ_RGB) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 4 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 4 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ4) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 4 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_LZ_PLT) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_pal__nw_size, u_pal__extra_size;
            uint8_t flags__value;
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* pal */
                pos = start2 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                flags__value = read_uint8(pos);
                if ((flags__value & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
                    u_pal__nw_size = 8;
                    u_pal__extra_size = 0;
                } else if (1) {
                    uint32_t u_pal_palette__value;
                    u_pal__nw_size = 4;
                    pos = (start2 + 5);
                    if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                        goto error;
                    }
                    u_pal_palette__value = read_uint32(pos);
                    if (SPICE_UNLIKELY(u_pal_palette__value == 0)) {
                        goto error;
                    }
                    ptr_size = validate_SpicePalette(message_start, message_end, u_pal_palette__value);
                    if (SPICE_UNLIKELY(ptr_size < 0)) {
                        goto error;
                    }
                    u_pal__extra_size = ptr_size + /* for alignment */ 3;
                } else {
                    u_pal__nw_size = 0;
                    u_pal__extra_size = 0;
                }

            }

            { /* data */
                uint32_t data_size__value;
                pos = start2 + 1;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 5 + u_pal__nw_size + u_data__nw_size;
            u__extra_size = u_pal__extra_size + u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 4;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 8 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_JPEG_ALPHA) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            uint64_t u_data__nw_size, u_data__extra_size;
            uint64_t u_data__nelements;
            { /* data */
                uint32_t data_size__value;
                pos = start2 + 5;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_size__value = read_uint32(pos);
                u_data__nelements = data_size__value;

                u_data__nw_size = u_data__nelements;
                u_data__extra_size = sizeof(SpiceChunks) + sizeof(SpiceChunk);
            }

            u__nw_size = 9 + u_data__nw_size;
            u__extra_size = u_data__extra_size;
        } else if (descriptor_type__value == SPICE_IMAGE_TYPE_SURFACE) {
            SPICE_GNUC_UNUSED uint8_t *start2 = (start + 18);
            u__nw_size = 4;
            u__extra_size = 0;
        } else {
            u__nw_size = 0;
            u__extra_size = 0;
        }

    }

    nw_size = 18 + u__nw_size;
    mem_size = sizeof(SpiceImage) + u__extra_size;

    /* Check if struct fits in reported side */
    if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
        goto error;
    }
    return mem_size;

   error:
    return -1;
}

static uint8_t * parse_struct_SpicePalette(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    SpicePalette *out;
    uint64_t ents__nelements;
    uint32_t i;

    end = struct_data + sizeof(SpicePalette);
    out = (SpicePalette *)struct_data;

    out->unique = consume_uint64(&in);
    out->num_ents = consume_uint16(&in);
    ents__nelements = out->num_ents;
    verify(sizeof(out->ents) == 0);
    for (i = 0; i < ents__nelements; i++) {
        out->ents[i] = consume_uint32(&in);
        end += sizeof(uint32_t);
    }
    return end;
}

static uint8_t * parse_struct_SpiceImage(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[1];
    SpiceImage *out;
    uint32_t i;

    end = struct_data + sizeof(SpiceImage);
    out = (SpiceImage *)struct_data;

    /* descriptor */ {
        out->descriptor.id = consume_uint64(&in);
        out->descriptor.type = consume_uint8(&in);
        out->descriptor.flags = consume_uint8(&in);
        out->descriptor.width = consume_uint32(&in);
        out->descriptor.height = consume_uint32(&in);
    }
    if (out->descriptor.type == SPICE_IMAGE_TYPE_BITMAP) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.bitmap.format = consume_uint8(&in);
        out->u.bitmap.flags = consume_uint8(&in);
        out->u.bitmap.x = consume_uint32(&in);
        out->u.bitmap.y = consume_uint32(&in);
        out->u.bitmap.stride = consume_uint32(&in);
        if ((out->u.bitmap.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
            out->u.bitmap.palette_id = consume_uint64(&in);
        } else if (1) {
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpicePalette;
            ptr_info[n_ptr].dest = (void **)&out->u.bitmap.palette;
            n_ptr++;
        }
        data__nelements = ((uint64_t) out->u.bitmap.stride * out->u.bitmap.y);
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.bitmap.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_QUIC) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.quic.data_size = consume_uint32(&in);
        data__nelements = out->u.quic.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.quic.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_RGB || out->descriptor.type == SPICE_IMAGE_TYPE_GLZ_RGB) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.lz_rgb.data_size = consume_uint32(&in);
        data__nelements = out->u.lz_rgb.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.lz_rgb.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.jpeg.data_size = consume_uint32(&in);
        data__nelements = out->u.jpeg.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.jpeg.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ4) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.lz4.data_size = consume_uint32(&in);
        data__nelements = out->u.lz4.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.lz4.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_LZ_PLT) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.lz_plt.flags = consume_uint8(&in);
        out->u.lz_plt.data_size = consume_uint32(&in);
        if ((out->u.lz_plt.flags & SPICE_BITMAP_FLAGS_PAL_FROM_CACHE)) {
            out->u.lz_plt.palette_id = consume_uint64(&in);
        } else if (1) {
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpicePalette;
            ptr_info[n_ptr].dest = (void **)&out->u.lz_plt.palette;
            n_ptr++;
        }
        data__nelements = out->u.lz_plt.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.lz_plt.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_ZLIB_GLZ_RGB) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.zlib_glz.glz_data_size = consume_uint32(&in);
        out->u.zlib_glz.data_size = consume_uint32(&in);
        data__nelements = out->u.zlib_glz.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.zlib_glz.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_JPEG_ALPHA) {
        uint64_t data__nelements;
        SpiceChunks *chunks;
        out->u.jpeg_alpha.flags = consume_uint8(&in);
        out->u.jpeg_alpha.jpeg_size = consume_uint32(&in);
        out->u.jpeg_alpha.data_size = consume_uint32(&in);
        data__nelements = out->u.jpeg_alpha.data_size;
        /* use array as chunk */
        chunks = (SpiceChunks *)end;
        end += sizeof(SpiceChunks) + sizeof(SpiceChunk);
        out->u.jpeg_alpha.data = chunks;
        chunks->data_size = data__nelements;
        chunks->flags = 0;
        chunks->num_chunks = 1;
        chunks->chunk[0].len = data__nelements;
        chunks->chunk[0].data = in;
        in += data__nelements;
    } else if (out->descriptor.type == SPICE_IMAGE_TYPE_SURFACE) {
        out->u.surface.surface_id = consume_uint32(&in);
    }

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    return end;

   error:
    return NULL;
}

static uint8_t * parse_msg_display_draw_fill(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[3];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawFill *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_brush__nw_size, data_brush__extra_size;
        uint64_t data_mask__extra_size;
        { /* brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
            uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_brush_u__nw_size = 4;
                    data_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_brush_u__nw_size = 12;
                    data_brush_u__extra_size = data_brush_u_pat__extra_size;
                } else {
                    data_brush_u__nw_size = 0;
                    data_brush_u__extra_size = 0;
                }

            }

            data_brush__nw_size = 1 + data_brush_u__nw_size;
            data_brush__extra_size = data_brush_u__extra_size;
        }

        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2 + data_brush__nw_size);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__nw_size = 15 + data_brush__nw_size;
        data__extra_size = data_brush__extra_size + data_mask__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawFill) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawFill);
    in = start;

    out = (SpiceMsgDisplayDrawFill *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        /* brush */ {
            out->data.brush.type = consume_uint8(&in);
            if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.brush.u.color = consume_uint32(&in);
            } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        out->data.rop_descriptor = consume_uint16(&in);
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_opaque(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[4];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawOpaque *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        uint64_t data_brush__nw_size, data_brush__extra_size;
        uint64_t data_mask__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_brush_u__nw_size = 4;
                    data_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_brush_u__nw_size = 12;
                    data_brush_u__extra_size = data_brush_u_pat__extra_size;
                } else {
                    data_brush_u__nw_size = 0;
                    data_brush_u__extra_size = 0;
                }

            }

            data_brush__nw_size = 1 + data_brush_u__nw_size;
            data_brush__extra_size = data_brush_u__extra_size;
        }

        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23 + data_brush__nw_size);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__nw_size = 36 + data_brush__nw_size;
        data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawOpaque) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawOpaque);
    in = start;

    out = (SpiceMsgDisplayDrawOpaque *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
        /* brush */ {
            out->data.brush.type = consume_uint8(&in);
            if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.brush.u.color = consume_uint32(&in);
            } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        out->data.rop_descriptor = consume_uint16(&in);
        out->data.scale_mode = consume_uint8(&in);
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_copy(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[3];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawCopy *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        uint64_t data_mask__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size;
    }

    nw_size = 36 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawCopy);
    in = start;

    out = (SpiceMsgDisplayDrawCopy *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
        out->data.rop_descriptor = consume_uint16(&in);
        out->data.scale_mode = consume_uint8(&in);
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_blend(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[3];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawCopy *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        uint64_t data_mask__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 23);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__extra_size = data_src_bitmap__extra_size + data_mask__extra_size;
    }

    nw_size = 36 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawCopy) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawCopy);
    in = start;

    out = (SpiceMsgDisplayDrawCopy *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
        out->data.rop_descriptor = consume_uint16(&in);
        out->data.scale_mode = consume_uint8(&in);
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_blackness(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawBlackness *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_mask__extra_size;
        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__extra_size = data_mask__extra_size;
    }

    nw_size = 13 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawBlackness) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawBlackness);
    in = start;

    out = (SpiceMsgDisplayDrawBlackness *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_whiteness(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawWhiteness *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_mask__extra_size;
        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__extra_size = data_mask__extra_size;
    }

    nw_size = 13 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawWhiteness) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawWhiteness);
    in = start;

    out = (SpiceMsgDisplayDrawWhiteness *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_invers(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawInvers *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_mask__extra_size;
        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 0);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__extra_size = data_mask__extra_size;
    }

    nw_size = 13 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawInvers) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawInvers);
    in = start;

    out = (SpiceMsgDisplayDrawInvers *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_rop3(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[4];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawRop3 *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        uint64_t data_brush__nw_size, data_brush__extra_size;
        uint64_t data_mask__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_brush_u__nw_size = 4;
                    data_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_brush_u__nw_size = 12;
                    data_brush_u__extra_size = data_brush_u_pat__extra_size;
                } else {
                    data_brush_u__nw_size = 0;
                    data_brush_u__extra_size = 0;
                }

            }

            data_brush__nw_size = 1 + data_brush_u__nw_size;
            data_brush__extra_size = data_brush_u__extra_size;
        }

        { /* mask */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 22 + data_brush__nw_size);
            uint64_t data_mask_bitmap__extra_size;
            { /* bitmap */
                uint32_t bitmap__value;
                pos = (start3 + 9);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_mask_bitmap__extra_size = ptr_size + /* for alignment */ 3;
            }

            data_mask__extra_size = data_mask_bitmap__extra_size;
        }

        data__nw_size = 35 + data_brush__nw_size;
        data__extra_size = data_src_bitmap__extra_size + data_brush__extra_size + data_mask__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawRop3) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawRop3);
    in = start;

    out = (SpiceMsgDisplayDrawRop3 *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
        /* brush */ {
            out->data.brush.type = consume_uint8(&in);
            if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.brush.u.color = consume_uint32(&in);
            } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        out->data.rop3 = consume_uint8(&in);
        out->data.scale_mode = consume_uint8(&in);
        /* mask */ {
            out->data.mask.flags = consume_uint8(&in);
            /* pos */ {
                out->data.mask.pos.x = consume_int32(&in);
                out->data.mask.pos.y = consume_int32(&in);
            }
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask.bitmap;
            n_ptr++;
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    assert(end <= data + mem_size);

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

   error:
    free(data);
    return NULL;
}

static intptr_t validate_SpicePath(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
{
    uint8_t *start = message_start + offset;
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint64_t mem_size, nw_size;
    uint64_t segments__nw_size, segments__mem_size;
    uint64_t segments__nelements;
    uint32_t i;

    if (offset == 0) {
        return 0;
    }

    if (SPICE_UNLIKELY(offset >= (uintptr_t) (message_end - message_start))) {
        goto error;
    }

    { /* segments */
        uint32_t num_segments__value;
        uint8_t *start2 = (start + 4);
        uint64_t segments__element__nw_size;
        uint64_t segments__element__mem_size;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        num_segments__value = read_uint32(pos);
        segments__nelements = num_segments__value;

        segments__nw_size = 0;
        segments__mem_size = 0;
        for (i = 0; i < segments__nelements; i++) {
            SPICE_GNUC_UNUSED uint8_t *start3 = start2;
            uint64_t segments__element_points__nw_size, segments__element_points__mem_size;
            uint64_t segments__element_points__nelements;
            { /* points */
                uint32_t count__value;
                pos = start3 + 1;
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                count__value = read_uint32(pos);
                segments__element_points__nelements = count__value;

                segments__element_points__nw_size = (8) * segments__element_points__nelements;
                segments__element_points__mem_size = sizeof(SpicePointFix) * segments__element_points__nelements;
            }

            segments__element__nw_size = 5 + segments__element_points__nw_size;
            segments__element__mem_size = sizeof(SpicePathSeg) + segments__element_points__mem_size;
            segments__nw_size += segments__element__nw_size;
            segments__mem_size += sizeof(void *) + SPICE_ALIGN(segments__element__mem_size, 4);
            start2 += segments__element__nw_size;
        }
    }

    nw_size = 4 + segments__nw_size;
    mem_size = sizeof(SpicePath) + segments__mem_size;

    /* Check if struct fits in reported side */
    if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
        goto error;
    }
    return mem_size;

   error:
    return -1;
}

static uint8_t * parse_struct_SpicePath(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    SpicePath *out;
    uint64_t segments__nelements;
    uint32_t i;
    void * *ptr_array;
    int ptr_array_index;
    uint32_t j;

    end = struct_data + sizeof(SpicePath);
    out = (SpicePath *)struct_data;

    out->num_segments = consume_uint32(&in);
    segments__nelements = out->num_segments;
    ptr_array_index = 0;
    ptr_array = (void **)out->segments;
    end += sizeof(void *) * segments__nelements;
    for (i = 0; i < segments__nelements; i++) {
        SpicePathSeg *out2;
        uint64_t points__nelements;
        ptr_array[ptr_array_index++] = end;
        out2 = (SpicePathSeg *)end;
        end += sizeof(SpicePathSeg);

        out2->flags = consume_uint8(&in);
        out2->count = consume_uint32(&in);
        points__nelements = out2->count;
        verify(sizeof(out2->points) == 0);
        for (j = 0; j < points__nelements; j++) {
            SpicePointFix *out3;
            out3 = (SpicePointFix *)end;
            end += sizeof(SpicePointFix);

            out3->x = consume_int32(&in);
            out3->y = consume_int32(&in);
        }
        /* Align ptr_array element to 4 bytes */
        end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
    }
    return end;
}

static uint8_t * parse_array_int32(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    uint32_t i;

    end = struct_data;
    for (i = 0; i < this_ptr_info->nelements; i++) {
        *(SPICE_FIXED28_4 *)end = consume_int32(&in);
        end += sizeof(SPICE_FIXED28_4);
    }
    return end;
}

static uint8_t * parse_msg_display_draw_stroke(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[4];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawStroke *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_path__extra_size;
        uint64_t data_attr__nw_size, data_attr__extra_size;
        uint64_t data_brush__nw_size, data_brush__extra_size;
        { /* path */
            uint32_t path__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            path__value = read_uint32(pos);
            if (SPICE_UNLIKELY(path__value == 0)) {
                goto error;
            }
            ptr_size = validate_SpicePath(message_start, message_end, path__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_path__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* attr */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4);
            uint64_t data_attr_u1__nw_size;
            uint8_t flags__value;
            uint64_t data_attr_u2__nw_size, data_attr_u2__extra_size;
            { /* u1 */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                flags__value = read_uint8(pos);
                if ((flags__value & SPICE_LINE_FLAGS_STYLED)) {
                    data_attr_u1__nw_size = 1;
                } else {
                    data_attr_u1__nw_size = 0;
                }

            }

            { /* u2 */
                uint64_t data_attr_u2__array__nelements;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                flags__value = read_uint8(pos);
                if ((flags__value & SPICE_LINE_FLAGS_STYLED)) {
                    uint32_t data_attr_u2_style__value;
                    uint64_t data_attr_u2__array__nw_size;
                    uint64_t data_attr_u2__array__mem_size;
                    uint8_t style_nseg__value;
                    data_attr_u2__nw_size = 4;
                    pos = (start3 + 1 + data_attr_u1__nw_size);
                    if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                        goto error;
                    }
                    data_attr_u2_style__value = read_uint32(pos);
                    if (SPICE_UNLIKELY(data_attr_u2_style__value >= (uintptr_t) (message_end - message_start))) {
                        goto error;
                    }
                    pos = start3 + 1;
                    if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                        goto error;
                    }
                    style_nseg__value = read_uint8(pos);
                    data_attr_u2__array__nelements = style_nseg__value;

                    data_attr_u2__array__nw_size = (4) * data_attr_u2__array__nelements;
                    data_attr_u2__array__mem_size = sizeof(SPICE_FIXED28_4) * data_attr_u2__array__nelements;
                    if (SPICE_UNLIKELY(data_attr_u2__array__nw_size > (uintptr_t) (message_end - message_start - data_attr_u2_style__value))) {
                        goto error;
                    }
                    data_attr_u2__extra_size = data_attr_u2__array__mem_size + /* for alignment */ 3;
                } else {
                    data_attr_u2__nw_size = 0;
                    data_attr_u2__extra_size = 0;
                }

            }

            data_attr__nw_size = 1 + data_attr_u1__nw_size + data_attr_u2__nw_size;
            data_attr__extra_size = data_attr_u2__extra_size;
        }

        { /* brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 4 + data_attr__nw_size);
            uint64_t data_brush_u__nw_size, data_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_brush_u__nw_size = 4;
                    data_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_brush_u__nw_size = 12;
                    data_brush_u__extra_size = data_brush_u_pat__extra_size;
                } else {
                    data_brush_u__nw_size = 0;
                    data_brush_u__extra_size = 0;
                }

            }

            data_brush__nw_size = 1 + data_brush_u__nw_size;
            data_brush__extra_size = data_brush_u__extra_size;
        }

        data__nw_size = 8 + data_attr__nw_size + data_brush__nw_size;
        data__extra_size = data_path__extra_size + data_attr__extra_size + data_brush__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawStroke) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawStroke);
    in = start;

    out = (SpiceMsgDisplayDrawStroke *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpicePath;
        ptr_info[n_ptr].dest = (void **)&out->data.path;
        n_ptr++;
        /* attr */ {
            out->data.attr.flags = consume_uint8(&in);
            if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) {
                out->data.attr.style_nseg = consume_uint8(&in);
            }
            if ((out->data.attr.flags & SPICE_LINE_FLAGS_STYLED)) {
                uint64_t style__array__nelements;
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_array_int32;
                ptr_info[n_ptr].dest = (void **)&out->data.attr.style;
                style__array__nelements = out->data.attr.style_nseg;
                ptr_info[n_ptr].nelements = style__array__nelements;
                n_ptr++;
            }
        }
        /* brush */ {
            out->data.brush.type = consume_uint8(&in);
            if (out->data.brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.brush.u.color = consume_uint32(&in);
            } else if (out->data.brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        out->data.fore_mode = consume_uint16(&in);
        out->data.back_mode = consume_uint16(&in);
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    assert(end <= data + mem_size);

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

   error:
    free(data);
    return NULL;
}

static intptr_t validate_SpiceString(uint8_t *message_start, uint8_t *message_end, uint64_t offset)
{
    uint8_t *start = message_start + offset;
    SPICE_GNUC_UNUSED uint8_t *pos;
    uint64_t mem_size, nw_size;
    uint64_t u__nw_size, u__extra_size;
    uint8_t flags__value;
    uint32_t i;

    if (offset == 0) {
        return 0;
    }

    if (SPICE_UNLIKELY(offset >= (uintptr_t) (message_end - message_start))) {
        goto error;
    }

    { /* u */
        uint64_t u__mem_size;
        uint64_t u__nelements;
        pos = start + 2;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        flags__value = read_uint8(pos);
        if ((flags__value & SPICE_STRING_FLAGS_RASTER_A1)) {
            uint16_t length__value;
            uint8_t *start2 = (start + 3);
            uint64_t u__element__nw_size;
            uint64_t u__element__mem_size;
            pos = start + 0;
            if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                goto error;
            }
            length__value = read_uint16(pos);
            u__nelements = length__value;

            u__nw_size = 0;
            u__mem_size = 0;
            for (i = 0; i < u__nelements; i++) {
                SPICE_GNUC_UNUSED uint8_t *start3 = start2;
                uint64_t u__element_data__nw_size, u__element_data__mem_size;
                uint64_t u__element_data__nelements;
                { /* data */
                    uint16_t width__value;
                    uint16_t height__value;
                    pos = start3 + 16;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    width__value = read_uint16(pos);
                    pos = start3 + 18;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    height__value = read_uint16(pos);
                    u__element_data__nelements = (((uint64_t) width__value + 7U) / 8U ) * height__value;

                    u__element_data__nw_size = u__element_data__nelements;
                    u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
                }

                u__element__nw_size = 20 + u__element_data__nw_size;
                u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
                u__nw_size += u__element__nw_size;
                u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
                start2 += u__element__nw_size;
            }
            u__extra_size = u__mem_size;
        } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A4)) {
            uint16_t length__value;
            uint8_t *start2 = (start + 3);
            uint64_t u__element__nw_size;
            uint64_t u__element__mem_size;
            pos = start + 0;
            if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                goto error;
            }
            length__value = read_uint16(pos);
            u__nelements = length__value;

            u__nw_size = 0;
            u__mem_size = 0;
            for (i = 0; i < u__nelements; i++) {
                SPICE_GNUC_UNUSED uint8_t *start3 = start2;
                uint64_t u__element_data__nw_size, u__element_data__mem_size;
                uint64_t u__element_data__nelements;
                { /* data */
                    uint16_t width__value;
                    uint16_t height__value;
                    pos = start3 + 16;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    width__value = read_uint16(pos);
                    pos = start3 + 18;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    height__value = read_uint16(pos);
                    u__element_data__nelements = ((4U * (uint64_t) width__value + 7U) / 8U ) * height__value;

                    u__element_data__nw_size = u__element_data__nelements;
                    u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
                }

                u__element__nw_size = 20 + u__element_data__nw_size;
                u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
                u__nw_size += u__element__nw_size;
                u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
                start2 += u__element__nw_size;
            }
            u__extra_size = u__mem_size;
        } else if ((flags__value & SPICE_STRING_FLAGS_RASTER_A8)) {
            uint16_t length__value;
            uint8_t *start2 = (start + 3);
            uint64_t u__element__nw_size;
            uint64_t u__element__mem_size;
            pos = start + 0;
            if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                goto error;
            }
            length__value = read_uint16(pos);
            u__nelements = length__value;

            u__nw_size = 0;
            u__mem_size = 0;
            for (i = 0; i < u__nelements; i++) {
                SPICE_GNUC_UNUSED uint8_t *start3 = start2;
                uint64_t u__element_data__nw_size, u__element_data__mem_size;
                uint64_t u__element_data__nelements;
                { /* data */
                    uint16_t width__value;
                    uint16_t height__value;
                    pos = start3 + 16;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    width__value = read_uint16(pos);
                    pos = start3 + 18;
                    if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                        goto error;
                    }
                    height__value = read_uint16(pos);
                    u__element_data__nelements = (uint64_t) width__value * height__value;

                    u__element_data__nw_size = u__element_data__nelements;
                    u__element_data__mem_size = sizeof(uint8_t) * u__element_data__nelements;
                }

                u__element__nw_size = 20 + u__element_data__nw_size;
                u__element__mem_size = sizeof(SpiceRasterGlyph) + u__element_data__mem_size;
                u__nw_size += u__element__nw_size;
                u__mem_size += sizeof(void *) + SPICE_ALIGN(u__element__mem_size, 4);
                start2 += u__element__nw_size;
            }
            u__extra_size = u__mem_size;
        } else {
            u__nw_size = 0;
            u__extra_size = 0;
        }

    }

    nw_size = 3 + u__nw_size;
    mem_size = sizeof(SpiceString) + u__extra_size;

    /* Check if struct fits in reported side */
    if (SPICE_UNLIKELY(nw_size > (uintptr_t) (message_end - start))) {
        goto error;
    }
    return mem_size;

   error:
    return -1;
}

static uint8_t * parse_struct_SpiceString(uint8_t *message_start, SPICE_GNUC_UNUSED uint8_t *message_end, uint8_t *struct_data, PointerInfo *this_ptr_info)
{
    uint8_t *in = message_start + this_ptr_info->offset;
    uint8_t *end;
    SpiceString *out;
    uint32_t i;

    end = struct_data + sizeof(SpiceString);
    out = (SpiceString *)struct_data;

    out->length = consume_uint16(&in);
    out->flags = consume_uint8(&in);
    if ((out->flags & SPICE_STRING_FLAGS_RASTER_A1)) {
        uint64_t glyphs__nelements;
        void * *ptr_array;
        int ptr_array_index;
        glyphs__nelements = out->length;
        ptr_array_index = 0;
        ptr_array = (void **)out->glyphs;
        end += sizeof(void *) * glyphs__nelements;
        for (i = 0; i < glyphs__nelements; i++) {
            SpiceRasterGlyph *out2;
            uint64_t data__nelements;
            ptr_array[ptr_array_index++] = end;
            out2 = (SpiceRasterGlyph *)end;
            end += sizeof(SpiceRasterGlyph);

            /* render_pos */ {
                out2->render_pos.x = consume_int32(&in);
                out2->render_pos.y = consume_int32(&in);
            }
            /* glyph_origin */ {
                out2->glyph_origin.x = consume_int32(&in);
                out2->glyph_origin.y = consume_int32(&in);
            }
            out2->width = consume_uint16(&in);
            out2->height = consume_uint16(&in);
            data__nelements = (((uint64_t) out2->width + 7U) / 8U ) * out2->height;
            verify(sizeof(out2->data) == 0);
            memcpy(out2->data, in, data__nelements);
            in += data__nelements;
            end += data__nelements;
            /* Align ptr_array element to 4 bytes */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
        }
    } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A4)) {
        uint64_t glyphs__nelements;
        void * *ptr_array;
        int ptr_array_index;
        glyphs__nelements = out->length;
        ptr_array_index = 0;
        ptr_array = (void **)out->glyphs;
        end += sizeof(void *) * glyphs__nelements;
        for (i = 0; i < glyphs__nelements; i++) {
            SpiceRasterGlyph *out2;
            uint64_t data__nelements;
            ptr_array[ptr_array_index++] = end;
            out2 = (SpiceRasterGlyph *)end;
            end += sizeof(SpiceRasterGlyph);

            /* render_pos */ {
                out2->render_pos.x = consume_int32(&in);
                out2->render_pos.y = consume_int32(&in);
            }
            /* glyph_origin */ {
                out2->glyph_origin.x = consume_int32(&in);
                out2->glyph_origin.y = consume_int32(&in);
            }
            out2->width = consume_uint16(&in);
            out2->height = consume_uint16(&in);
            data__nelements = ((4U * (uint64_t) out2->width + 7U) / 8U ) * out2->height;
            verify(sizeof(out2->data) == 0);
            memcpy(out2->data, in, data__nelements);
            in += data__nelements;
            end += data__nelements;
            /* Align ptr_array element to 4 bytes */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
        }
    } else if ((out->flags & SPICE_STRING_FLAGS_RASTER_A8)) {
        uint64_t glyphs__nelements;
        void * *ptr_array;
        int ptr_array_index;
        glyphs__nelements = out->length;
        ptr_array_index = 0;
        ptr_array = (void **)out->glyphs;
        end += sizeof(void *) * glyphs__nelements;
        for (i = 0; i < glyphs__nelements; i++) {
            SpiceRasterGlyph *out2;
            uint64_t data__nelements;
            ptr_array[ptr_array_index++] = end;
            out2 = (SpiceRasterGlyph *)end;
            end += sizeof(SpiceRasterGlyph);

            /* render_pos */ {
                out2->render_pos.x = consume_int32(&in);
                out2->render_pos.y = consume_int32(&in);
            }
            /* glyph_origin */ {
                out2->glyph_origin.x = consume_int32(&in);
                out2->glyph_origin.y = consume_int32(&in);
            }
            out2->width = consume_uint16(&in);
            out2->height = consume_uint16(&in);
            data__nelements = ((uint64_t) out2->width * out2->height);
            verify(sizeof(out2->data) == 0);
            memcpy(out2->data, in, data__nelements);
            in += data__nelements;
            end += data__nelements;
            /* Align ptr_array element to 4 bytes */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
        }
    }
    return end;
}

static uint8_t * parse_msg_display_draw_text(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[4];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawText *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_str__extra_size;
        uint64_t data_fore_brush__nw_size, data_fore_brush__extra_size;
        uint64_t data_back_brush__nw_size, data_back_brush__extra_size;
        { /* str */
            uint32_t str__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            str__value = read_uint32(pos);
            if (SPICE_UNLIKELY(str__value == 0)) {
                goto error;
            }
            ptr_size = validate_SpiceString(message_start, message_end, str__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_str__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* fore_brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t data_fore_brush_u__nw_size, data_fore_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_fore_brush_u__nw_size = 4;
                    data_fore_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_fore_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_fore_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_fore_brush_u__nw_size = 12;
                    data_fore_brush_u__extra_size = data_fore_brush_u_pat__extra_size;
                } else {
                    data_fore_brush_u__nw_size = 0;
                    data_fore_brush_u__extra_size = 0;
                }

            }

            data_fore_brush__nw_size = 1 + data_fore_brush_u__nw_size;
            data_fore_brush__extra_size = data_fore_brush_u__extra_size;
        }

        { /* back_brush */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20 + data_fore_brush__nw_size);
            uint64_t data_back_brush_u__nw_size, data_back_brush_u__extra_size;
            uint8_t type__value;
            { /* u */
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_BRUSH_TYPE_SOLID) {
                    data_back_brush_u__nw_size = 4;
                    data_back_brush_u__extra_size = 0;
                } else if (type__value == SPICE_BRUSH_TYPE_PATTERN) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t data_back_brush_u_pat__extra_size;
                    { /* pat */
                        uint32_t pat__value;
                        pos = (start4 + 0);
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        pat__value = read_uint32(pos);
                        if (SPICE_UNLIKELY(pat__value == 0)) {
                            goto error;
                        }
                        ptr_size = validate_SpiceImage(message_start, message_end, pat__value);
                        if (SPICE_UNLIKELY(ptr_size < 0)) {
                            goto error;
                        }
                        data_back_brush_u_pat__extra_size = ptr_size + /* for alignment */ 3;
                    }

                    data_back_brush_u__nw_size = 12;
                    data_back_brush_u__extra_size = data_back_brush_u_pat__extra_size;
                } else {
                    data_back_brush_u__nw_size = 0;
                    data_back_brush_u__extra_size = 0;
                }

            }

            data_back_brush__nw_size = 1 + data_back_brush_u__nw_size;
            data_back_brush__extra_size = data_back_brush_u__extra_size;
        }

        data__nw_size = 24 + data_fore_brush__nw_size + data_back_brush__nw_size;
        data__extra_size = data_str__extra_size + data_fore_brush__extra_size + data_back_brush__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawText) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawText);
    in = start;

    out = (SpiceMsgDisplayDrawText *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceString;
        ptr_info[n_ptr].dest = (void **)&out->data.str;
        n_ptr++;
        /* back_area */ {
            out->data.back_area.top = consume_int32(&in);
            out->data.back_area.left = consume_int32(&in);
            out->data.back_area.bottom = consume_int32(&in);
            out->data.back_area.right = consume_int32(&in);
        }
        /* fore_brush */ {
            out->data.fore_brush.type = consume_uint8(&in);
            if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.fore_brush.u.color = consume_uint32(&in);
            } else if (out->data.fore_brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.fore_brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.fore_brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.fore_brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        /* back_brush */ {
            out->data.back_brush.type = consume_uint8(&in);
            if (out->data.back_brush.type == SPICE_BRUSH_TYPE_SOLID) {
                out->data.back_brush.u.color = consume_uint32(&in);
            } else if (out->data.back_brush.type == SPICE_BRUSH_TYPE_PATTERN) {
                ptr_info[n_ptr].offset = consume_uint32(&in);
                ptr_info[n_ptr].parse = parse_struct_SpiceImage;
                ptr_info[n_ptr].dest = (void **)&out->data.back_brush.u.pattern.pat;
                n_ptr++;
                /* pos */ {
                    out->data.back_brush.u.pattern.pos.x = consume_int32(&in);
                    out->data.back_brush.u.pattern.pos.y = consume_int32(&in);
                }
            }
        }
        out->data.fore_mode = consume_uint16(&in);
        out->data.back_mode = consume_uint16(&in);
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_transparent(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawTransparent *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 0);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        data__extra_size = data_src_bitmap__extra_size;
    }

    nw_size = 28 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawTransparent) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawTransparent);
    in = start;

    out = (SpiceMsgDisplayDrawTransparent *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
        out->data.src_color = consume_uint32(&in);
        out->data.true_color = consume_uint32(&in);
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_draw_alpha_blend(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[2];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__extra_size;
    SpiceMsgDisplayDrawAlphaBlend *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 2);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        data__extra_size = data_src_bitmap__extra_size;
    }

    nw_size = 22 + base__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawAlphaBlend) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawAlphaBlend);
    in = start;

    out = (SpiceMsgDisplayDrawAlphaBlend *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        out->data.alpha_flags = consume_uint8(&in);
        out->data.alpha = consume_uint8(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        /* src_area */ {
            out->data.src_area.top = consume_int32(&in);
            out->data.src_area.left = consume_int32(&in);
            out->data.src_area.bottom = consume_int32(&in);
            out->data.src_area.right = consume_int32(&in);
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_surface_create(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;
    SpiceMsgSurfaceCreate *out;

    nw_size = 20;
    mem_size = sizeof(SpiceMsgSurfaceCreate);

    /* 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(SpiceMsgSurfaceCreate);
    in = start;

    out = (SpiceMsgSurfaceCreate *)data;

    out->surface_id = consume_uint32(&in);
    out->width = consume_uint32(&in);
    out->height = consume_uint32(&in);
    out->format = consume_uint32(&in);
    out->flags = 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_msg_display_surface_destroy(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;
    SpiceMsgSurfaceDestroy *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgSurfaceDestroy);

    /* 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(SpiceMsgSurfaceDestroy);
    in = start;

    out = (SpiceMsgSurfaceDestroy *)data;

    out->surface_id = 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_msg_display_stream_data_sized(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;
    SpiceMsgDisplayStreamDataSized *out;

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

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

    nw_size = 36 + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayStreamDataSized) + 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(SpiceMsgDisplayStreamDataSized);
    in = start;

    out = (SpiceMsgDisplayStreamDataSized *)data;

    /* base */ {
        out->base.id = consume_uint32(&in);
        out->base.multi_media_time = consume_uint32(&in);
    }
    out->width = consume_uint32(&in);
    out->height = consume_uint32(&in);
    /* dest */ {
        out->dest.top = consume_int32(&in);
        out->dest.left = consume_int32(&in);
        out->dest.bottom = consume_int32(&in);
        out->dest.right = consume_int32(&in);
    }
    out->data_size = 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_msg_display_monitors_config(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 heads__nw_size, heads__mem_size;
    uint64_t heads__nelements;
    SpiceMsgDisplayMonitorsConfig *out;
    uint32_t i;

    { /* heads */
        uint16_t count__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 2 > message_end)) {
            goto error;
        }
        count__value = read_uint16(pos);
        heads__nelements = count__value;

        heads__nw_size = (28) * heads__nelements;
        heads__mem_size = sizeof(SpiceHead) * heads__nelements;
    }

    nw_size = 4 + heads__nw_size;
    mem_size = sizeof(SpiceMsgDisplayMonitorsConfig) + heads__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(SpiceMsgDisplayMonitorsConfig);
    in = start;

    out = (SpiceMsgDisplayMonitorsConfig *)data;

    out->count = consume_uint16(&in);
    out->max_allowed = consume_uint16(&in);
    verify(sizeof(out->heads) == 0);
    for (i = 0; i < heads__nelements; i++) {
        SpiceHead *out2;
        out2 = (SpiceHead *)end;
        end += sizeof(SpiceHead);

        out2->monitor_id = consume_uint32(&in);
        out2->surface_id = consume_uint32(&in);
        out2->width = consume_uint32(&in);
        out2->height = consume_uint32(&in);
        out2->x = consume_uint32(&in);
        out2->y = consume_uint32(&in);
        out2->flags = 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_msg_display_draw_composite(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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[3];
    uint64_t base__nw_size, base__extra_size;
    uint32_t rects__saved_size = 0;
    uint64_t data__nw_size, data__extra_size;
    SpiceMsgDisplayDrawComposite *out;
    uint32_t i;

    { /* base */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0);
        uint64_t base_clip__nw_size, base_clip__extra_size;
        { /* clip */
            SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 20);
            uint64_t base_clip_u__nw_size, base_clip_u__extra_size;
            uint8_t type__value;
            { /* u */
                uint64_t base_clip_u__mem_size;
                pos = start3 + 0;
                if (SPICE_UNLIKELY(pos + 1 > message_end)) {
                    goto error;
                }
                type__value = read_uint8(pos);
                if (type__value == SPICE_CLIP_TYPE_RECTS) {
                    SPICE_GNUC_UNUSED uint8_t *start4 = (start3 + 1);
                    uint64_t base_clip_u_rects__nw_size, base_clip_u_rects__mem_size;
                    uint64_t base_clip_u_rects__nelements;
                    { /* rects */
                        uint32_t num_rects__value;
                        pos = start4 + 0;
                        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                            goto error;
                        }
                        num_rects__value = read_uint32(pos);
                        base_clip_u_rects__nelements = num_rects__value;

                        base_clip_u_rects__nw_size = (16) * base_clip_u_rects__nelements;
                        base_clip_u_rects__mem_size = sizeof(SpiceRect) * base_clip_u_rects__nelements;
                    }

                    base_clip_u__nw_size = 4 + base_clip_u_rects__nw_size;
                    base_clip_u__mem_size = sizeof(SpiceClipRects) + base_clip_u_rects__mem_size;
                    rects__saved_size = base_clip_u__nw_size;
                    base_clip_u__extra_size = base_clip_u__mem_size;
                } else {
                    base_clip_u__nw_size = 0;
                    base_clip_u__extra_size = 0;
                }

            }

            base_clip__nw_size = 1 + base_clip_u__nw_size;
            base_clip__extra_size = base_clip_u__extra_size;
        }

        base__nw_size = 20 + base_clip__nw_size;
        base__extra_size = base_clip__extra_size;
    }

    { /* data */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 0 + base__nw_size);
        uint64_t data_src_bitmap__extra_size;
        uint64_t data_a__nw_size, data_a__extra_size;
        uint32_t flags__value;
        uint64_t data_b__nw_size;
        uint64_t data_c__nw_size;
        { /* src_bitmap */
            uint32_t src_bitmap__value;
            pos = (start2 + 4);
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            src_bitmap__value = read_uint32(pos);
            ptr_size = validate_SpiceImage(message_start, message_end, src_bitmap__value);
            if (SPICE_UNLIKELY(ptr_size < 0)) {
                goto error;
            }
            data_src_bitmap__extra_size = ptr_size + /* for alignment */ 3;
        }

        { /* a */
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            flags__value = read_uint32(pos);
            if ((flags__value & SPICE_COMPOSITE_HAS_MASK)) {
                uint32_t data_a_mask_bitmap__value;
                data_a__nw_size = 4;
                pos = (start2 + 8);
                if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                    goto error;
                }
                data_a_mask_bitmap__value = read_uint32(pos);
                ptr_size = validate_SpiceImage(message_start, message_end, data_a_mask_bitmap__value);
                if (SPICE_UNLIKELY(ptr_size < 0)) {
                    goto error;
                }
                data_a__extra_size = ptr_size + /* for alignment */ 3;
            } else {
                data_a__nw_size = 0;
                data_a__extra_size = 0;
            }

        }

        { /* b */
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            flags__value = read_uint32(pos);
            if ((flags__value & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size);
                data_b__nw_size = 24;
            } else {
                data_b__nw_size = 0;
            }

        }

        { /* c */
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 4 > message_end)) {
                goto error;
            }
            flags__value = read_uint32(pos);
            if ((flags__value & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 8 + data_a__nw_size + data_b__nw_size);
                data_c__nw_size = 24;
            } else {
                data_c__nw_size = 0;
            }

        }

        data__nw_size = 16 + data_a__nw_size + data_b__nw_size + data_c__nw_size;
        data__extra_size = data_src_bitmap__extra_size + data_a__extra_size;
    }

    nw_size = 0 + base__nw_size + data__nw_size;
    mem_size = sizeof(SpiceMsgDisplayDrawComposite) + base__extra_size + data__extra_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(SpiceMsgDisplayDrawComposite);
    in = start;

    out = (SpiceMsgDisplayDrawComposite *)data;

    /* base */ {
        out->base.surface_id = consume_uint32(&in);
        /* box */ {
            out->base.box.top = consume_int32(&in);
            out->base.box.left = consume_int32(&in);
            out->base.box.bottom = consume_int32(&in);
            out->base.box.right = consume_int32(&in);
        }
        /* clip */ {
            out->base.clip.type = consume_uint8(&in);
            if (out->base.clip.type == SPICE_CLIP_TYPE_RECTS) {
                ptr_info[n_ptr].offset = in - start;
                ptr_info[n_ptr].parse = parse_struct_SpiceClipRects;
                ptr_info[n_ptr].dest = (void **)&out->base.clip.rects;
                n_ptr++;
                in += rects__saved_size;
            }
        }
    }
    /* data */ {
        out->data.flags = consume_uint32(&in);
        ptr_info[n_ptr].offset = consume_uint32(&in);
        ptr_info[n_ptr].parse = parse_struct_SpiceImage;
        ptr_info[n_ptr].dest = (void **)&out->data.src_bitmap;
        n_ptr++;
        if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK)) {
            ptr_info[n_ptr].offset = consume_uint32(&in);
            ptr_info[n_ptr].parse = parse_struct_SpiceImage;
            ptr_info[n_ptr].dest = (void **)&out->data.mask_bitmap;
            n_ptr++;
        }
        if ((out->data.flags & SPICE_COMPOSITE_HAS_SRC_TRANSFORM)) {
            out->data.src_transform.t00 = consume_uint32(&in);
            out->data.src_transform.t01 = consume_uint32(&in);
            out->data.src_transform.t02 = consume_uint32(&in);
            out->data.src_transform.t10 = consume_uint32(&in);
            out->data.src_transform.t11 = consume_uint32(&in);
            out->data.src_transform.t12 = consume_uint32(&in);
        }
        if ((out->data.flags & SPICE_COMPOSITE_HAS_MASK_TRANSFORM)) {
            out->data.mask_transform.t00 = consume_uint32(&in);
            out->data.mask_transform.t01 = consume_uint32(&in);
            out->data.mask_transform.t02 = consume_uint32(&in);
            out->data.mask_transform.t10 = consume_uint32(&in);
            out->data.mask_transform.t11 = consume_uint32(&in);
            out->data.mask_transform.t12 = consume_uint32(&in);
        }
        /* src_origin */ {
            out->data.src_origin.x = consume_int16(&in);
            out->data.src_origin.y = consume_int16(&in);
        }
        /* mask_origin */ {
            out->data.mask_origin.x = consume_int16(&in);
            out->data.mask_origin.y = consume_int16(&in);
        }
    }

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_display_stream_activate_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;
    SpiceMsgDisplayStreamActivateReport *out;

    nw_size = 16;
    mem_size = sizeof(SpiceMsgDisplayStreamActivateReport);

    /* 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(SpiceMsgDisplayStreamActivateReport);
    in = start;

    out = (SpiceMsgDisplayStreamActivateReport *)data;

    out->stream_id = consume_uint32(&in);
    out->unique_id = consume_uint32(&in);
    out->max_window_size = consume_uint32(&in);
    out->timeout_ms = 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_msg_display_gl_scanout_unix(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;
    SpiceMsgDisplayGlScanoutUnix *out;

    nw_size = 20;
    mem_size = sizeof(SpiceMsgDisplayGlScanoutUnix);

    /* 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(SpiceMsgDisplayGlScanoutUnix);
    in = start;

    out = (SpiceMsgDisplayGlScanoutUnix *)data;

    out->drm_dma_buf_fd = consume_fd(&in);
    out->width = consume_uint32(&in);
    out->height = consume_uint32(&in);
    out->stride = consume_uint32(&in);
    out->drm_fourcc_format = consume_uint32(&in);
    out->flags = 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_msg_display_gl_draw(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;
    SpiceMsgDisplayGlDraw *out;

    nw_size = 16;
    mem_size = sizeof(SpiceMsgDisplayGlDraw);

    /* 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(SpiceMsgDisplayGlDraw);
    in = start;

    out = (SpiceMsgDisplayGlDraw *)data;

    out->x = consume_uint32(&in);
    out->y = consume_uint32(&in);
    out->w = consume_uint32(&in);
    out->h = 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_DisplayChannel_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[9] =  {
        parse_SpiceMsgEmpty,
        parse_msg_display_mode,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgEmpty,
        parse_msg_display_copy_bits,
        parse_msg_display_inval_list,
        parse_msg_display_inval_all_pixmaps,
        parse_msg_display_inval_palette,
        parse_SpiceMsgEmpty
    };
    static parse_msg_func_t funcs3[5] =  {
        parse_msg_display_stream_create,
        parse_msg_display_stream_data,
        parse_msg_display_stream_clip,
        parse_msg_display_stream_destroy,
        parse_SpiceMsgEmpty
    };
    static parse_msg_func_t funcs4[21] =  {
        parse_msg_display_draw_fill,
        parse_msg_display_draw_opaque,
        parse_msg_display_draw_copy,
        parse_msg_display_draw_blend,
        parse_msg_display_draw_blackness,
        parse_msg_display_draw_whiteness,
        parse_msg_display_draw_invers,
        parse_msg_display_draw_rop3,
        parse_msg_display_draw_stroke,
        parse_msg_display_draw_text,
        parse_msg_display_draw_transparent,
        parse_msg_display_draw_alpha_blend,
        parse_msg_display_surface_create,
        parse_msg_display_surface_destroy,
        parse_msg_display_stream_data_sized,
        parse_msg_display_monitors_config,
        parse_msg_display_draw_composite,
        parse_msg_display_stream_activate_report,
        parse_msg_display_gl_scanout_unix,
        parse_msg_display_gl_draw,
        parse_SpiceMsgData
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 109) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    } else if (message_type >= 122 && message_type < 127) {
        return funcs3[message_type-122](message_start, message_end, size_out, free_message);
    } else if (message_type >= 302 && message_type < 323) {
        return funcs4[message_type-302](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_inputs_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;
    SpiceMsgInputsInit *out;

    nw_size = 2;
    mem_size = sizeof(SpiceMsgInputsInit);

    /* 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(SpiceMsgInputsInit);
    in = start;

    out = (SpiceMsgInputsInit *)data;

    out->keyboard_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_msg_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;
    SpiceMsgInputsKeyModifiers *out;

    nw_size = 2;
    mem_size = sizeof(SpiceMsgInputsKeyModifiers);

    /* 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(SpiceMsgInputsKeyModifiers);
    in = start;

    out = (SpiceMsgInputsKeyModifiers *)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_InputsChannel_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[3] =  {
        parse_SpiceMsgEmpty,
        parse_msg_inputs_init,
        parse_msg_inputs_key_modifiers
    };
    static parse_msg_func_t funcs3[1] =  {
        parse_SpiceMsgEmpty
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 103) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    } else if (message_type >= 111 && message_type < 112) {
        return funcs3[message_type-111](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_cursor_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;
    uint64_t cursor__nw_size;
    SpiceMsgCursorInit *out;

    { /* cursor */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 9);
        uint64_t cursor_u__nw_size;
        uint16_t flags__value;
        uint64_t cursor_data__nw_size;
        uint64_t cursor_data__nelements;
        { /* u */
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                goto error;
            }
            flags__value = read_uint16(pos);
            if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2);
                cursor_u__nw_size = 17;
            } else {
                cursor_u__nw_size = 0;
            }

        }

        { /* data */
            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
                goto error;
            }
            cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);

            cursor_data__nw_size = cursor_data__nelements;
        }

        cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size;
    }

    nw_size = 9 + cursor__nw_size;
    mem_size = sizeof(SpiceMsgCursorInit);

    /* 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(SpiceMsgCursorInit);
    in = start;

    out = (SpiceMsgCursorInit *)data;

    /* position */ {
        out->position.x = consume_int16(&in);
        out->position.y = consume_int16(&in);
    }
    out->trail_length = consume_uint16(&in);
    out->trail_frequency = consume_uint16(&in);
    out->visible = consume_uint8(&in);
    /* cursor */ {
        uint64_t data__nelements;
        out->cursor.flags = consume_uint16(&in);
        if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) {
            out->cursor.header.unique = consume_uint64(&in);
            out->cursor.header.type = consume_uint8(&in);
            out->cursor.header.width = consume_uint16(&in);
            out->cursor.header.height = consume_uint16(&in);
            out->cursor.header.hot_spot_x = consume_uint16(&in);
            out->cursor.header.hot_spot_y = consume_uint16(&in);
        }
        data__nelements = (message_end - in) / (1);
        /* use array as pointer */
        out->cursor.data = (uint8_t *)in;
        out->cursor.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_msg_cursor_set(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 cursor__nw_size;
    SpiceMsgCursorSet *out;

    { /* cursor */
        SPICE_GNUC_UNUSED uint8_t *start2 = (start + 5);
        uint64_t cursor_u__nw_size;
        uint16_t flags__value;
        uint64_t cursor_data__nw_size;
        uint64_t cursor_data__nelements;
        { /* u */
            pos = start2 + 0;
            if (SPICE_UNLIKELY(pos + 2 > message_end)) {
                goto error;
            }
            flags__value = read_uint16(pos);
            if (!(flags__value & SPICE_CURSOR_FLAGS_NONE)) {
                SPICE_GNUC_UNUSED uint8_t *start3 = (start2 + 2);
                cursor_u__nw_size = 17;
            } else {
                cursor_u__nw_size = 0;
            }

        }

        { /* data */
            if (SPICE_UNLIKELY((start2 + 2 + cursor_u__nw_size) > message_end)) {
                goto error;
            }
            cursor_data__nelements = message_end - (start2 + 2 + cursor_u__nw_size);

            cursor_data__nw_size = cursor_data__nelements;
        }

        cursor__nw_size = 2 + cursor_u__nw_size + cursor_data__nw_size;
    }

    nw_size = 5 + cursor__nw_size;
    mem_size = sizeof(SpiceMsgCursorSet);

    /* 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(SpiceMsgCursorSet);
    in = start;

    out = (SpiceMsgCursorSet *)data;

    /* position */ {
        out->position.x = consume_int16(&in);
        out->position.y = consume_int16(&in);
    }
    out->visible = consume_uint8(&in);
    /* cursor */ {
        uint64_t data__nelements;
        out->cursor.flags = consume_uint16(&in);
        if (!(out->cursor.flags & SPICE_CURSOR_FLAGS_NONE)) {
            out->cursor.header.unique = consume_uint64(&in);
            out->cursor.header.type = consume_uint8(&in);
            out->cursor.header.width = consume_uint16(&in);
            out->cursor.header.height = consume_uint16(&in);
            out->cursor.header.hot_spot_x = consume_uint16(&in);
            out->cursor.header.hot_spot_y = consume_uint16(&in);
        }
        data__nelements = (message_end - in) / (1);
        /* use array as pointer */
        out->cursor.data = (uint8_t *)in;
        out->cursor.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_msg_cursor_move(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;
    SpiceMsgCursorMove *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgCursorMove);

    /* 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(SpiceMsgCursorMove);
    in = start;

    out = (SpiceMsgCursorMove *)data;

    /* position */ {
        out->position.x = consume_int16(&in);
        out->position.y = consume_int16(&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_msg_cursor_trail(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;
    SpiceMsgCursorTrail *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgCursorTrail);

    /* 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(SpiceMsgCursorTrail);
    in = start;

    out = (SpiceMsgCursorTrail *)data;

    out->length = consume_uint16(&in);
    out->frequency = 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_msg_cursor_inval_one(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;
    SpiceMsgDisplayInvalOne *out;

    nw_size = 8;
    mem_size = sizeof(SpiceMsgDisplayInvalOne);

    /* 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(SpiceMsgDisplayInvalOne);
    in = start;

    out = (SpiceMsgDisplayInvalOne *)data;

    out->id = 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_CursorChannel_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[9] =  {
        parse_SpiceMsgEmpty,
        parse_msg_cursor_init,
        parse_SpiceMsgEmpty,
        parse_msg_cursor_set,
        parse_msg_cursor_move,
        parse_SpiceMsgEmpty,
        parse_msg_cursor_trail,
        parse_msg_cursor_inval_one,
        parse_SpiceMsgEmpty
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 109) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_playback_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_msg_playback_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_msg_playback_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;
    SpiceMsgPlaybackStart *out;

    nw_size = 14;
    mem_size = sizeof(SpiceMsgPlaybackStart);

    /* 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(SpiceMsgPlaybackStart);
    in = start;

    out = (SpiceMsgPlaybackStart *)data;

    out->channels = consume_uint32(&in);
    out->format = consume_uint16(&in);
    out->frequency = consume_uint32(&in);
    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_SpiceMsgAudioVolume(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 volume__nw_size, volume__mem_size;
    uint64_t volume__nelements;
    SpiceMsgAudioVolume *out;
    uint32_t i;

    { /* volume */
        uint8_t nchannels__value;
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 1 > message_end)) {
            goto error;
        }
        nchannels__value = read_uint8(pos);
        volume__nelements = nchannels__value;

        volume__nw_size = (2) * volume__nelements;
        volume__mem_size = sizeof(uint16_t) * volume__nelements;
    }

    nw_size = 1 + volume__nw_size;
    mem_size = sizeof(SpiceMsgAudioVolume) + volume__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(SpiceMsgAudioVolume);
    in = start;

    out = (SpiceMsgAudioVolume *)data;

    out->nchannels = consume_uint8(&in);
    verify(sizeof(out->volume) == 0);
    for (i = 0; i < volume__nelements; i++) {
        out->volume[i] = consume_uint16(&in);
        end += sizeof(uint16_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_SpiceMsgAudioMute(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;
    SpiceMsgAudioMute *out;

    nw_size = 1;
    mem_size = sizeof(SpiceMsgAudioMute);

    /* 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(SpiceMsgAudioMute);
    in = start;

    out = (SpiceMsgAudioMute *)data;

    out->mute = 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_msg_playback_latency(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;
    SpiceMsgPlaybackLatency *out;

    nw_size = 4;
    mem_size = sizeof(SpiceMsgPlaybackLatency);

    /* 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(SpiceMsgPlaybackLatency);
    in = start;

    out = (SpiceMsgPlaybackLatency *)data;

    out->latency_ms = 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_PlaybackChannel_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[8] =  {
        parse_SpiceMsgEmpty,
        parse_msg_playback_data,
        parse_msg_playback_mode,
        parse_msg_playback_start,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgAudioVolume,
        parse_SpiceMsgAudioMute,
        parse_msg_playback_latency
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 108) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_record_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;
    SpiceMsgRecordStart *out;

    nw_size = 10;
    mem_size = sizeof(SpiceMsgRecordStart);

    /* 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(SpiceMsgRecordStart);
    in = start;

    out = (SpiceMsgRecordStart *)data;

    out->channels = consume_uint32(&in);
    out->format = consume_uint16(&in);
    out->frequency = 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_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[5] =  {
        parse_SpiceMsgEmpty,
        parse_msg_record_start,
        parse_SpiceMsgEmpty,
        parse_SpiceMsgAudioVolume,
        parse_SpiceMsgAudioMute
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 105) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_TunnelChannel_msg(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_msg_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;
    SpiceMsgSmartcard *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(SpiceMsgSmartcard) + 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(SpiceMsgSmartcard);
    in = start;

    out = (SpiceMsgSmartcard *)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_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[2] =  {
        parse_SpiceMsgEmpty,
        parse_msg_smartcard_data
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 102) {
        return funcs2[message_type-100](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_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[3] =  {
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 103) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_msg_port_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;
    SPICE_GNUC_UNUSED intptr_t ptr_size;
    uint32_t n_ptr=0;
    PointerInfo ptr_info[1];
    uint64_t name__extra_size;
    uint64_t name__array__nelements;
    SpiceMsgPortInit *out;
    uint32_t i;

    { /* name */
        uint32_t name__value;
        uint64_t name__array__nw_size;
        uint64_t name__array__mem_size;
        uint32_t name_size__value;
        pos = (start + 4);
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        name__value = read_uint32(pos);
        if (SPICE_UNLIKELY(name__value == 0)) {
            goto error;
        }
        if (SPICE_UNLIKELY(name__value >= (uintptr_t) (message_end - message_start))) {
            goto error;
        }
        pos = start + 0;
        if (SPICE_UNLIKELY(pos + 4 > message_end)) {
            goto error;
        }
        name_size__value = read_uint32(pos);
        name__array__nelements = name_size__value;

        name__array__nw_size = name__array__nelements;
        name__array__mem_size = sizeof(uint8_t) * name__array__nelements + sizeof(uint8_t);
        name__array__mem_size = SPICE_ALIGN(name__array__mem_size, 4);
        if (SPICE_UNLIKELY(name__array__nw_size > (uintptr_t) (message_end - message_start - name__value))) {
            goto error;
        }
        name__extra_size = name__array__mem_size + /* for alignment */ 3;
    }

    nw_size = 9;
    mem_size = sizeof(SpiceMsgPortInit) + name__extra_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(SpiceMsgPortInit);
    in = start;

    out = (SpiceMsgPortInit *)data;

    out->name_size = consume_uint32(&in);
    ptr_info[n_ptr].offset = consume_uint32(&in);
    ptr_info[n_ptr].parse = parse_array_uint8_terminated;
    ptr_info[n_ptr].dest = (void **)&out->name;
    ptr_info[n_ptr].nelements = name__array__nelements;
    n_ptr++;
    out->opened = consume_uint8(&in);

    assert(in <= message_end);

    for (i = 0; i < n_ptr; i++) {
        if (ptr_info[i].offset == 0) {
            *ptr_info[i].dest = NULL;
        } else {
            /* Align to 32 bit */
            end = (uint8_t *)SPICE_ALIGN((uintptr_t)end, 4);
            *ptr_info[i].dest = (void *)end;
            end = ptr_info[i].parse(message_start, message_end, end, &ptr_info[i]);
            if (SPICE_UNLIKELY(end == NULL)) {
                goto error;
            }
        }
    }

    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_msg_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;
    SpiceMsgPortEvent *out;

    nw_size = 1;
    mem_size = sizeof(SpiceMsgPortEvent);

    /* 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(SpiceMsgPortEvent);
    in = start;

    out = (SpiceMsgPortEvent *)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_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[3] =  {
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    static parse_msg_func_t funcs3[2] =  {
        parse_msg_port_init,
        parse_msg_port_event
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 103) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    } else if (message_type >= 201 && message_type < 203) {
        return funcs3[message_type-201](message_start, message_end, size_out, free_message);
    }
    return NULL;
}



static uint8_t * parse_WebDAVChannel_msg(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[8] =  {
        parse_msg_migrate,
        parse_SpiceMsgData,
        parse_msg_set_ack,
        parse_msg_ping,
        parse_msg_wait_for_channels,
        parse_msg_disconnecting,
        parse_msg_notify,
        parse_SpiceMsgData
    };
    static parse_msg_func_t funcs2[3] =  {
        parse_SpiceMsgEmpty,
        parse_SpiceMsgData,
        parse_SpiceMsgCompressedData
    };
    static parse_msg_func_t funcs3[2] =  {
        parse_msg_port_init,
        parse_msg_port_event
    };
    if (message_type >= 1 && message_type < 9) {
        return funcs1[message_type-1](message_start, message_end, size_out, free_message);
    } else if (message_type >= 100 && message_type < 103) {
        return funcs2[message_type-100](message_start, message_end, size_out, free_message);
    } else if (message_type >= 201 && message_type < 203) {
        return funcs3[message_type-201](message_start, message_end, size_out, free_message);
    }
    return NULL;
}

spice_parse_channel_func_t spice_get_server_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_msg, 118},
        { parse_DisplayChannel_msg, 322},
        { parse_InputsChannel_msg, 111},
        { parse_CursorChannel_msg, 108},
        { parse_PlaybackChannel_msg, 107},
        { parse_RecordChannel_msg, 104},
        { parse_TunnelChannel_msg, 0},
#ifdef USE_SMARTCARD
        { parse_SmartcardChannel_msg, 101},
#else /* USE_SMARTCARD */
        { NULL, 0 },
#endif /* USE_SMARTCARD */
        { parse_UsbredirChannel_msg, 102},
        { parse_PortChannel_msg, 202},
        { parse_WebDAVChannel_msg, 202}
    };
    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_msg(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_server_channel_parser(channel, NULL);
    if (func != NULL) {
        return func(message_start, message_end, message_type, minor, size_out, free_message);
    }
    return NULL;
}
