#ifndef __VAR___KAIMING_VARIANTS_GV__H__
#define __VAR___KAIMING_VARIANTS_GV__H__

#include <string.h>
#include <glib.h>

#define VAR_METADATA_TYPESTRING "a{sv}"
#define VAR_METADATA_TYPEFORMAT ((const GVariantType *)VAR_METADATA_TYPESTRING)
#define VAR_CHECKSUM_TYPESTRING "ay"
#define VAR_CHECKSUM_TYPEFORMAT ((const GVariantType *)VAR_CHECKSUM_TYPESTRING)

#define VAR_REF_INFO_TYPESTRING "(taya{sv})"
#define VAR_REF_INFO_TYPEFORMAT ((const GVariantType *)VAR_REF_INFO_TYPESTRING)

#define VARREFINFOINDEXOFCOMMITSIZE 0
#define VAR_REF_INFO_INDEXOF_CHECKSUM 1
#define VAR_REF_INFO_INDEXOF_METADATA 2

#define VAR_REF_MAP_ENTRY_TYPESTRING "(s(taya{sv}))"
#define VAR_REF_MAP_ENTRY_TYPEFORMAT ((const GVariantType *)VAR_REF_MAP_ENTRY_TYPESTRING)

#define VARREFMAPENTRYINDEXOFREF 0
#define VARREFMAPENTRYINDEXOFINFO 1

#define VAR_REF_MAP_TYPESTRING "a(s(taya{sv}))"
#define VAR_REF_MAP_TYPEFORMAT ((const GVariantType *)VAR_REF_MAP_TYPESTRING)

#define VAR_SUMMARY_TYPESTRING "(a(s(taya{sv}))a{sv})"
#define VAR_SUMMARY_TYPEFORMAT ((const GVariantType *)VAR_SUMMARY_TYPESTRING)

#define VAR_SUMMARY_INDEXOF_REF_MAP 0
#define VAR_SUMMARY_INDEXOF_METADATA 1

#define VAR_COLLECTION_MAP_TYPESTRING "a{sa(s(taya{sv}))}"
#define VAR_COLLECTION_MAP_TYPEFORMAT ((const GVariantType *)VAR_COLLECTION_MAP_TYPESTRING)

#define VAR_RELATED_TYPESTRING "(say)"
#define VAR_RELATED_TYPEFORMAT ((const GVariantType *)VAR_RELATED_TYPESTRING)

#define VAR_RELATED_INDEXOF_REF 0
#define VAR_RELATED_INDEXOF_COMMIT 1

#define VAR_ARRAYOF_RELATED_TYPESTRING "a(say)"
#define VAR_ARRAYOF_RELATED_TYPEFORMAT ((const GVariantType *)VAR_ARRAYOF_RELATED_TYPESTRING)

#define VAR_COMMIT_TYPESTRING "(a{sv}aya(say)sstayay)"
#define VAR_COMMIT_TYPEFORMAT ((const GVariantType *)VAR_COMMIT_TYPESTRING)

#define VAR_COMMIT_INDEXOF_METADATA 0
#define VAR_COMMIT_INDEXOF_PARENT 1
#define VAR_COMMIT_INDEXOF_RELATED 2
#define VAR_COMMIT_INDEXOF_SUBJECT 3
#define VAR_COMMIT_INDEXOF_BODY 4
#define VAR_COMMIT_INDEXOF_TIMESTAMP 5
#define VAR_COMMIT_INDEXOF_ROOT_CONTENTS 6
#define VAR_COMMIT_INDEXOF_ROOT_METADATA 7

#define VAR_CACHE_DATA_TYPESTRING "(tts)"
#define VAR_CACHE_DATA_TYPEFORMAT ((const GVariantType *)VAR_CACHE_DATA_TYPESTRING)

#define VARCACHEDATAINDEXOFINSTALLEDSIZE 0
#define VARCACHEDATAINDEXOFDOWNLOADSIZE 1
#define VAR_CACHE_DATA_INDEXOF_METADATA 2

#define VAR_CACHE_TYPESTRING "a{s(tts)}"
#define VAR_CACHE_TYPEFORMAT ((const GVariantType *)VAR_CACHE_TYPESTRING)

#define VAR_SPARSE_CACHE_TYPESTRING "a{sa{sv}}"
#define VAR_SPARSE_CACHE_TYPEFORMAT ((const GVariantType *)VAR_SPARSE_CACHE_TYPESTRING)

#define VAR_COMMITS_CACHE_TYPESTRING "aay"
#define VAR_COMMITS_CACHE_TYPEFORMAT ((const GVariantType *)VAR_COMMITS_CACHE_TYPESTRING)

#define VAR_ARRAYOFSTRING_TYPESTRING "as"
#define VAR_ARRAYOFSTRING_TYPEFORMAT ((const GVariantType *)VAR_ARRAYOFSTRING_TYPESTRING)

#define VAR_DEPLOY_DATA_TYPESTRING "(ssasta{sv})"
#define VAR_DEPLOY_DATA_TYPEFORMAT ((const GVariantType *)VAR_DEPLOY_DATA_TYPESTRING)

#define VAR_DEPLOY_DATA_INDEXOF_ORIGIN 0
#define VAR_DEPLOY_DATA_INDEXOF_COMMIT 1
#define VAR_DEPLOY_DATA_INDEXOF_SUBPATHS 2
#define VARDEPLOYDATAINDEXOFINSTALLEDSIZE 3
#define VAR_DEPLOY_DATA_INDEXOF_METADATA 4

#define VAR_RATINGS_TYPESTRING "a{ss}"
#define VAR_RATINGS_TYPEFORMAT ((const GVariantType *)VAR_RATINGS_TYPESTRING)

#define VAR_CONTENT_RATING_TYPESTRING "(sa{ss})"
#define VAR_CONTENT_RATING_TYPEFORMAT ((const GVariantType *)VAR_CONTENT_RATING_TYPESTRING)

#define VARCONTENTRATINGINDEXOFRATINGTYPE 0
#define VAR_CONTENT_RATING_INDEXOF_RATINGS 1

#define VAR_EXTRA_DATA_SIZE_TYPESTRING "(ut)"
#define VAR_EXTRA_DATA_SIZE_TYPEFORMAT ((const GVariantType *)VAR_EXTRA_DATA_SIZE_TYPESTRING)

#define VAR_EXTRA_DATA_SIZE_INDEXOF_N_EXTRA_DATA 0
#define VAREXTRADATASIZEINDEXOFTOTALSIZE 1

#define VAR_ARRAYOF_CHECKSUM_TYPESTRING "aay"
#define VAR_ARRAYOF_CHECKSUM_TYPEFORMAT ((const GVariantType *)VAR_ARRAYOF_CHECKSUM_TYPESTRING)

#define VAR_SUBSUMMARY_TYPESTRING "(ayaaya{sv})"
#define VAR_SUBSUMMARY_TYPEFORMAT ((const GVariantType *)VAR_SUBSUMMARY_TYPESTRING)

#define VAR_SUBSUMMARY_INDEXOF_CHECKSUM 0
#define VAR_SUBSUMMARY_INDEXOF_HISTORY 1
#define VAR_SUBSUMMARY_INDEXOF_METADATA 2

#define VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING "a{s(ayaaya{sv})}"
#define VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPEFORMAT ((const GVariantType *)VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING)

#define VAR_SUMMARY_INDEX_TYPESTRING "(a{s(ayaaya{sv})}a{sv})"
#define VAR_SUMMARY_INDEX_TYPEFORMAT ((const GVariantType *)VAR_SUMMARY_INDEX_TYPESTRING)

#define VAR_SUMMARY_INDEX_INDEXOF_SUBSUMMARIES 0
#define VAR_SUMMARY_INDEX_INDEXOF_METADATA 1

#define VAR_OBJECT_LIST_INFO_TYPESTRING "(bas)"
#define VAR_OBJECT_LIST_INFO_TYPEFORMAT ((const GVariantType *)VAR_OBJECT_LIST_INFO_TYPESTRING)
#define VAROBJECTLISTINFOINDEXOFISLOOSE 0
#define VAROBJECTLISTINFOINDEXOFPACKFILES 1

#define VAR_OBJECT_NAME_TYPESTRING "(su)"
#define VAR_OBJECT_NAME_TYPEFORMAT ((const GVariantType *)VAR_OBJECT_NAME_TYPESTRING)

#define VAR_OBJECT_NAME_INDEXOF_CHECKSUM 0
#define VAR_OBJECT_NAME_INDEXOF_OBJTYPE 1

#define VAR_OBJECT_NAMES_TYPESTRING "a(su)"
#define VAR_OBJECT_NAMES_TYPEFORMAT ((const GVariantType *)VAR_OBJECT_NAMES_TYPESTRING)

/********** Basic types *****************/

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarVariantRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarMetadataRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarMetadataEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarChecksumRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRefInfoRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRefMapEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRefMapRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSummaryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCollectionMapRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCollectionMapEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRelatedRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarArrayofRelatedRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCommitRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCacheDataRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCacheRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCacheEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSparseCacheRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSparseCacheEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarCommitsCacheRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarArrayofstringRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarDeployDataRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRatingsRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarRatingsEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarContentRatingRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarExtraDataSizeRef;

typedef struct
{
    guint32 NExtraData; /* little endian */
    guchar padding1[4];
    guint64 varTotalSize; /* little endian */
} VarExtraDataSize;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarArrayofChecksumRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSubsummaryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSummaryIndexSubsummariesRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSummaryIndexSubsummariesEntryRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarSummaryIndexRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarObjectListInfoRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarObjectNameRef;

typedef struct
{
    gconstpointer base;
    gsize size;
} VarObjectNamesRef;

/* Make sure code works with older glib versions without g_memdup2 */
static inline gpointer varMemdup2(gconstpointer mem, gsize byteSize)
{
#if GLIB_CHECK_VERSION(2, 68, 0)
    return g_memdup2(mem, byteSize);
#else
    gpointer newMem;

    if (mem && byteSize != 0)
    {
        newMem = g_malloc(byteSize);
        memcpy(newMem, mem, byteSize);
    }
    else
    {
        newMem = NULL;
    }

    return newMem;
#endif
}

#define VAR_REF_READ_FRAME_OFFSET(varFrame, varFrameIndex) readVarRefUnalignedLe((guchar *)((varFrame).base) + (varFrame).size - (offsetSize * ((varFrameIndex) + 1)), offsetSize)
#define VAR_REF_ALIGN(offsetVar, alignToVar) ((offsetVar + alignToVar - 1) & ~(gsize)(alignToVar - 1))

/* Note: clz is undefinded for 0, so never call this size == 0 */
G_GNUC_CONST static inline guint getVarRefOffsetSize(gsize size)
{
#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(__OPTIMIZE__) && defined(__LP64__)
    /* Instead of using a lookup table we use nibbles in a lookup word */
    guint32 v = (guint32)0x88884421;
    return (v >> (((__builtin_clzl(size) ^ 63) / 8) * 4)) & 0xf;
#else
    if (size > G_MAXUINT16)
    {
        if (size > G_MAXUINT32)
        {
            return 8;
        }
        else
        {
            return 4;
        }
    }
    else
    {
        if (size > G_MAXUINT8)
        {
            return 2;
        }
        else
        {
            return 1;
        }
    }
#endif
}

G_GNUC_PURE static inline guint64 readVarRefUnalignedLe(guchar *bytes, guint size)
{
    union
    {
        guchar bytes[8];
        guint64 integer;
    } tmpvalue;

    tmpvalue.integer = 0;
    /* we unroll the size checks here so that memcpy gets constant args */
    if (size >= 4)
    {
        if (size == 8)
        {
            memcpy(&tmpvalue.bytes, bytes, 8);
        }
        else
        {
            memcpy(&tmpvalue.bytes, bytes, 4);
        }
    }
    else
    {
        if (size == 2)
        {
            memcpy(&tmpvalue.bytes, bytes, 2);
        }
        else
        {
            memcpy(&tmpvalue.bytes, bytes, 1);
        }
    }

    return GUINT64_FROM_LE(tmpvalue.integer);
}

static inline void varGStringAppendDouble(GString *string, double d)
{
    gchar buffer[100];
    gint i;

    g_ascii_dtostr(buffer, sizeof buffer, d);
    for (i = 0; buffer[i]; i++)
    {
        if (buffer[i] == '.' || buffer[i] == 'e' || buffer[i] == 'n' || buffer[i] == 'N')
        {
            break;
        }
    }

    /* if there is no '.' or 'e' in the float then add one */
    if (buffer[i] == '\0')
    {
        buffer[i++] = '.';
        buffer[i++] = '0';
        buffer[i++] = '\0';
    }
    g_string_append(string, buffer);
}

static inline void varGStringAppendString(GString *string, const char *str)
{
    gunichar quote = strchr(str, '\'') ? '"' : '\'';

    g_string_append_c(string, quote);
    while (*str)
    {
        gunichar c = g_utf8_get_char(str);

        if (c == quote || c == '\\')
        {
            g_string_append_c(string, '\\');
        }

        if (g_unichar_isprint(c))
        {
            g_string_append_unichar(string, c);
        }
        else
        {
            g_string_append_c(string, '\\');
            if (c < 0x10000)
            {
                switch (c)
                {
                case '\a':
                    g_string_append_c(string, 'a');
                    break;

                case '\b':
                    g_string_append_c(string, 'b');
                    break;

                case '\f':
                    g_string_append_c(string, 'f');
                    break;

                case '\n':
                    g_string_append_c(string, 'n');
                    break;

                case '\r':
                    g_string_append_c(string, 'r');
                    break;

                case '\t':
                    g_string_append_c(string, 't');
                    break;

                case '\v':
                    g_string_append_c(string, 'v');
                    break;

                default:
                    g_string_append_printf(string, "u%04x", c);
                    break;
                }
            }
            else
            {
                g_string_append_printf(string, "U%08x", c);
            }

            str = g_utf8_next_char(str);
        }

        g_string_append_c(string, quote);
    }
}

/************** VarVariantRef *******************/

static inline VarRef getVarVariantChild(VarVariantRef v, const GVariantType **outType)
{
    if (v.size)
    {
        guchar *base = (guchar *)v.base;
        gsize size = v.size - 1;

        /* find '\0' character */
        while (size > 0 && base[size] != 0)
        {
            size--;
        }

        /* ensure we didn't just hit the start of the string */
        if (base[size] == 0)
        {
            const char *typeString = (char *)base + size + 1;
            const char *limit = (char *)base + v.size;
            const char *end;

            if (g_variant_type_string_scan(typeString, limit, &end) && end == limit)
            {
                if (outType)
                {
                    *outType = (const GVariantType *)typeString;
                }
                return (VarRef){ v.base, size };
            }
        }
    }
    if (outType)
    {
        *outType = G_VARIANT_TYPE_UNIT;
    }
    return (VarRef){ "\0", 1 };
}

static inline const GVariantType *getVarVariantType(VarVariantRef v)
{
    if (v.size)
    {
        guchar *base = (guchar *)v.base;
        gsize size = v.size - 1;

        /* find '\0' character */
        while (size > 0 && base[size] != 0)
        {
            size--;
        }

        /* ensure we didn't just hit the start of the string */
        if (base[size] == 0)
        {
            const char *typeString = (char *)base + size + 1;
            const char *limit = (char *)base + v.size;
            const char *end;

            if (g_variant_type_string_scan(typeString, limit, &end) && end == limit)
            {
                return (const GVariantType *)typeString;
            }
        }
    }
    return G_VARIANT_TYPE_UNIT;
}

static inline gboolean isVarVariantType(VarVariantRef v, const GVariantType *type)
{
    return g_variant_type_equal(getVarVariantType(v), type);
}

static inline VarVariantRef varVariantFromGVariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), G_VARIANT_TYPE_VARIANT));
    return (VarVariantRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarVariantRef varVariantFromBytes(GBytes *b)
{
    return (VarVariantRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarVariantRef varVariantFromData(gconstpointer data, gsize size)
{
    return (VarVariantRef){ data, size };
}

static inline GVariant *varVariantDupToGVaraint(VarVariantRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(G_VARIANT_TYPE_VARIANT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varVariantToGVariant(VarVariantRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(G_VARIANT_TYPE_VARIANT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varVariantToOwnedGVariant(VarVariantRef v, GVariant *base)
{
    return varVariantToGVariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varVariantPeekAsVariant(VarVariantRef v)
{
    return g_variant_new_from_data(G_VARIANT_TYPE_VARIANT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarVariantRef varVariantFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, G_VARIANT_TYPE_VARIANT));
    return varVariantFromData(child.base, child.size);
}

static inline GVariant *varVariantDupChildToGVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    guint8 *duped = (guint8 *)varMemdup2(child.base, child.size);
    return g_variant_new_from_data(type, duped, child.size, TRUE, g_free, duped);
}

static inline GVariant *varVariantPeekChildAsVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    return g_variant_new_from_data(type, child.base, child.size, TRUE, NULL, NULL);
}

static inline GString *varVariantFormat(VarVariantRef v, GString *s, gboolean typeAnnotate)
{
#ifdef VAR_DEEP_VARIANT_FORMAT
    GVariant *gv = varVariantPeekAsVariant(v);
    return g_variant_print_string(gv, s, TRUE);
#else
    const GVariantType *type = getVarVariantType(v);
    g_string_append_printf(s, "<@%.*s>", (int)g_variant_type_get_string_length(type), (const char *)type);
    return s;
#endif
}

static inline char *varVariantPrint(VarVariantRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varVariantFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

static inline gboolean varVariantGetBoolean(VarVariantRef v)
{
    return (gboolean) * ((guint8 *)v.base);
}

static inline guint8 varVariantGetByte(VarVariantRef v)
{
    return (guint8) * ((guint8 *)v.base);
}

static inline gint16 varVariantGetInt16(VarVariantRef v)
{
    return (gint16) * ((gint16 *)v.base);
}

static inline guint16 varVariantGetUint16(VarVariantRef v)
{
    return (guint16) * ((guint16 *)v.base);
}

static inline gint32 varVariantGetInt32(VarVariantRef v)
{
    return (gint32) * ((gint32 *)v.base);
}

static inline guint32 varVariantGetUint32(VarVariantRef v)
{
    return (guint32) * ((guint32 *)v.base);
}

static inline gint64 varVariantGetInt64(VarVariantRef v)
{
    return (gint64) * ((gint64 *)v.base);
}

static inline guint64 varVariantGetUint64(VarVariantRef v)
{
    return (guint64) * ((guint64 *)v.base);
}

static inline guint32 varVariantGetHandle(VarVariantRef v)
{
    return (guint32) * ((guint32 *)v.base);
}

static inline double varVariantGetDouble(VarVariantRef v)
{
    return (double)*((double *)v.base);
}

static inline const char *varVariantGetString(VarVariantRef v)
{
    return (const char *)v.base;
}

static inline const char *varVariantGetObjectpath(VarVariantRef v)
{
    return (const char *)v.base;
}

static inline const char *varVariantGetSignature(VarVariantRef v)
{
    return (const char *)v.base;
}

/************** VarMetadata *******************/

static inline VarMetadataRef varMetadataFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_METADATA_TYPESTRING));
    return (VarMetadataRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarMetadataRef varMetadataFromBytes(GBytes *b)
{
    return (VarMetadataRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarMetadataRef varMetadataFromData(gconstpointer data, gsize size)
{
    return (VarMetadataRef){ data, size };
}

static inline GVariant *varMetadataDupToGvariant(VarMetadataRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_METADATA_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varMetadataToGvariant(VarMetadataRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_METADATA_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varMetadataToOwnedGvariant(VarMetadataRef v, GVariant *base)
{
    return varMetadataToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varVetadataPeekAsGvariant(VarMetadataRef v)
{
    return g_variant_new_from_data(VAR_METADATA_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarMetadataRef varMetadataFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_METADATA_TYPESTRING));
    return varMetadataFromData(child.base, child.size);
}

static inline gsize varMetadataGetLength(VarMetadataRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarMetadataEntryRef varMetadataGetAt(VarMetadataRef v, gsize index)
{
    VarMetadataEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarMetadataEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varMetadataEntryGetKey(VarMetadataEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline VarVariantRef varMetadataEntryGetValue(VarMetadataEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 8);
    g_assert(offset <= v.size);
    return (VarVariantRef){ (char *)v.base + offset, (v.size - offsetSize) - offset };
}

static inline gboolean varMetadataLookup(VarMetadataRef v, const char *key, gsize *indexOut, VarVariantRef *out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize i;

    for (i = 0; i < len; i++)
    {
        gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - i - 1);
        VarMetadataEntryRef e = { ((const guchar *)v.base) + start, end - start };
        g_assert(start <= end);
        g_assert(end <= lastEnd);
        const char *entryKey = varMetadataEntryGetKey(e);
        if (strcmp(canonicalKey, entryKey) == 0)
        {
            if (indexOut)
            {
                *indexOut = i;
            }
            if (out)
            {
                *out = varMetadataEntryGetValue(e);
            }
            return TRUE;
        }
        start = VAR_REF_ALIGN(end, 8);
    }
    return FALSE;
}

static inline gboolean varMetadataLookupBoolean(VarMetadataRef v, const char *key, gboolean varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'b')
    {
        return varVariantGetBoolean(varValue);
    }
    return varDefaultValue;
}

static inline guint8 varMetadataLookupByte(VarMetadataRef v, const char *key, guint8 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'y')
    {
        return varVariantGetByte(varValue);
    }
    return varDefaultValue;
}

static inline gint16 varMetadataLookupInt16(VarMetadataRef v, const char *key, gint16 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'n')
    {
        return varVariantGetInt16(varValue);
    }
    return varDefaultValue;
}

static inline guint16 varMetadataLookupUint16(VarMetadataRef v, const char *key, guint16 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'q')
    {
        return varVariantGetUint16(varValue);
    }
    return varDefaultValue;
}

static inline gint32 varMetadataLookupInt32(VarMetadataRef v, const char *key, gint32 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'i')
    {
        return varVariantGetInt32(varValue);
    }
    return varDefaultValue;
}

static inline guint32 varMetadataLookupUint32(VarMetadataRef v, const char *key, guint32 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'u')
    {
        return varVariantGetUint32(varValue);
    }
    return varDefaultValue;
}

static inline gint64 varMetadataLookupInt64(VarMetadataRef v, const char *key, gint64 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'x')
    {
        return varVariantGetInt64(varValue);
    }
    return varDefaultValue;
}

static inline guint64 varMetadataLookupUint64(VarMetadataRef v, const char *key, guint64 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 't')
    {
        return varVariantGetUint64(varValue);
    }
    return varDefaultValue;
}

static inline guint32 varMetadataLookupHandle(VarMetadataRef v, const char *key, guint32 varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'h')
    {
        return varVariantGetHandle(varValue);
    }
    return varDefaultValue;
}

static inline double varMetadataLookupDouble(VarMetadataRef v, const char *key, double varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'd')
    {
        return varVariantGetDouble(varValue);
    }
    return varDefaultValue;
}

static inline const char *varMetadataLookupString(VarMetadataRef v, const char *key, const char *varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 's')
    {
        return varVariantGetString(varValue);
    }
    return varDefaultValue;
}

static inline const char *varMetadataLookupObjectpath(VarMetadataRef v, const char *key, const char *varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'o')
    {
        return varVariantGetObjectpath(varValue);
    }
    return varDefaultValue;
}

static inline const char *varMetadataLookupSignature(VarMetadataRef v, const char *key, const char *varDefaultValue)
{
    VarVariantRef varValue;

    if (varMetadataLookup(v, key, NULL, &varValue) && *(const char *)getVarVariantType(varValue) == 'g')
    {
        return varVariantGetSignature(varValue);
    }
    return varDefaultValue;
}

static inline GString *varMetadataFormat(VarMetadataRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varMetadataGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_METADATA_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarMetadataEntryRef entry = varMetadataGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varMetadataEntryGetKey(entry));
        g_string_append(s, ": ");
        varVariantFormat(varMetadataEntryGetValue(entry), s, typeAnnotate);
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varMetadataPrint(VarMetadataRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varMetadataFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarChecksum *******************/
static inline VarChecksumRef varChecksumFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_CHECKSUM_TYPESTRING));
    return (VarChecksumRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarChecksumRef varChecksumFromBytes(GBytes *b)
{
    return (VarChecksumRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarChecksumRef varChecksumFromData(gconstpointer data, gsize size)
{
    return (VarChecksumRef){ data, size };
}

static inline GVariant *varChecksumDupToGvariant(VarChecksumRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_CHECKSUM_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varChecksumToGvariant(VarChecksumRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varChecksumToOwnedGvariant(VarChecksumRef v, GVariant *base)
{
    return varChecksumToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varChecksumPeekAsGvariant(VarChecksumRef v)
{
    return g_variant_new_from_data(VAR_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarChecksumRef varChecksumFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_CHECKSUM_TYPESTRING));
    return varChecksumFromData(child.base, child.size);
}

static inline gsize varChecksumGetLength(VarChecksumRef v)
{
    gsize length = v.size / 1;
    return length;
}

static inline guint8 varChecksumGetAt(VarChecksumRef v, gsize index)
{
    return (guint8)G_STRUCT_MEMBER(guint8, v.base, index * 1);
}

static inline const guint8 *varChecksumPeek(VarChecksumRef v)
{
    return (const guint8 *)v.base;
}

static inline GString *varChecksumFormat(VarChecksumRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varChecksumGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_CHECKSUM_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        g_string_append_printf(s, "%s0x%02x", ((i == 0) ? typeAnnotate : FALSE) ? "byte " : "", varChecksumGetAt(v, i));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varChecksumPrint(VarChecksumRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varChecksumFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarRefInfo *******************/
static inline VarRefInfoRef varRefInfoFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_REF_INFO_TYPESTRING));
    return (VarRefInfoRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarRefInfoRef varRefInfoFromBytes(GBytes *b)
{
    return (VarRefInfoRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarRefInfoRef varRefInfoFromData(gconstpointer data, gsize size)
{
    return (VarRefInfoRef){ data, size };
}

static inline GVariant *varRefInfoDupToGvariant(VarRefInfoRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_REF_INFO_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varRefInfoToGvariant(VarRefInfoRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_REF_INFO_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varRefInfoToOwnedGvariant(VarRefInfoRef v, GVariant *base)
{
    return varRefInfoToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varRefInfoPeekAsGvariant(VarRefInfoRef v)
{
    return g_variant_new_from_data(VAR_REF_INFO_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarRefInfoRef varRefInfoFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_REF_INFO_TYPESTRING));
    return varRefInfoFromData(child.base, child.size);
}

static inline guint64 varRefInfoGetCommitSize(VarRefInfoRef v)
{
    guint offset = ((7) & (~(gsize)7)) + 0;
    g_assert(offset + 8 <= v.size);
    return (guint64)G_STRUCT_MEMBER(guint64, v.base, offset);
}

static inline VarChecksumRef varRefInfoGetChecksum(VarRefInfoRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((7) & (~(gsize)7)) + 8;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varRefInfoPeekChecksum(VarRefInfoRef v, gsize *len)
{
    VarChecksumRef a = varRefInfoGetChecksum(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline VarMetadataRef varRefInfoGetMetadata(VarRefInfoRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varRefInfoFormat(VarRefInfoRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append_printf(s, "(%s%" G_GUINT64_FORMAT ", ", typeAnnotate ? "uint64 " : "", varRefInfoGetCommitSize(v));
    varChecksumFormat(varRefInfoGetChecksum(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varMetadataFormat(varRefInfoGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varRefInfoPrint(VarRefInfoRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varRefInfoFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarRefMapEntry *******************/
static inline VarRefMapEntryRef varRefMapEntryFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_REF_MAP_ENTRY_TYPESTRING));
    return (VarRefMapEntryRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarRefMapEntryRef varRefMapEntryFromBytes(GBytes *b)
{
    return (VarRefMapEntryRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarRefMapEntryRef varRefMapEntryFromData(gconstpointer data, gsize size)
{
    return (VarRefMapEntryRef){ data, size };
}

static inline GVariant *varRefMapEntryDupToGvariant(VarRefMapEntryRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_REF_MAP_ENTRY_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varRefMapEntryToGvariant(VarRefMapEntryRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_REF_MAP_ENTRY_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varRefMapEntryToOwnedGvariant(VarRefMapEntryRef v, GVariant *base)
{
    return varRefMapEntryToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varRefMapEntryPeekAsGvariant(VarRefMapEntryRef v)
{
    return g_variant_new_from_data(VAR_REF_MAP_ENTRY_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarRefMapEntryRef varRefMapEntryFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_REF_MAP_ENTRY_TYPESTRING));
    return varRefMapEntryFromData(child.base, child.size);
}

static inline const char *varRefMapEntryGetRef(VarRefMapEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline VarRefInfoRef varRefMapEntryGetInfo(VarRefMapEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarRefInfoRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varRefMapEntryFormat(VarRefMapEntryRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varGStringAppendString(s, varRefMapEntryGetRef(v));
    g_string_append(s, ", ");
    varRefInfoFormat(varRefMapEntryGetInfo(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varRefMapEntryPrint(VarRefMapEntryRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varRefMapEntryFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarRefMap *******************/
static inline VarRefMapRef varRefMapFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_REF_MAP_TYPESTRING));
    return (VarRefMapRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarRefMapRef varRefMapFromBytes(GBytes *b)
{
    return (VarRefMapRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarRefMapRef varRefMapFromData(gconstpointer data, gsize size)
{
    return (VarRefMapRef){ data, size };
}

static inline GVariant *varRefMapDupToGvariant(VarRefMapRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_REF_MAP_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varRefMapToGvariant(VarRefMapRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_REF_MAP_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varRefMapToOwnedGvariant(VarRefMapRef v, GVariant *base)
{
    return varRefMapToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varRefMapPeekAsGvariant(VarRefMapRef v)
{
    return g_variant_new_from_data(VAR_REF_MAP_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarRefMapRef varRefMapFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_REF_MAP_TYPESTRING));
    return varRefMapFromData(child.base, child.size);
}

static inline gsize varRefMapGetLength(VarRefMapRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarRefMapEntryRef varRefMapGetAt(VarRefMapRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    return (VarRefMapEntryRef){ ((const char *)v.base) + start, end - start };
}

static inline GString *varRefMapFormat(VarRefMapRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varRefMapGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_REF_MAP_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varRefMapEntryFormat(varRefMapGetAt(v, i), s, ((i == 0) ? typeAnnotate : FALSE));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varRefMapPrint(VarRefMapRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varRefMapFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarSummary *******************/
static inline VarSummaryRef varSummaryFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_SUMMARY_TYPESTRING));
    return (VarSummaryRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarSummaryRef varSummaryFromBytes(GBytes *b)
{
    return (VarSummaryRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarSummaryRef varSummaryFromData(gconstpointer data, gsize size)
{
    return (VarSummaryRef){ data, size };
}

static inline GVariant *varSummaryDupToGvariant(VarSummaryRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_SUMMARY_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varSummaryToGvariant(VarSummaryRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_SUMMARY_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varSummaryToOwnedGvariant(VarSummaryRef v, GVariant *base)
{
    return varSummaryToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varSummaryPeekAsGvariant(VarSummaryRef v)
{
    return g_variant_new_from_data(VAR_SUMMARY_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarSummaryRef varSummaryFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_SUMMARY_TYPESTRING));
    return varSummaryFromData(child.base, child.size);
}

static inline VarRefMapRef varSummaryGetRefMap(VarSummaryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarRefMapRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline VarMetadataRef varSummaryGetMetadata(VarSummaryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varSummaryFormat(VarSummaryRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varRefMapFormat(varSummaryGetRefMap(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varMetadataFormat(varSummaryGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varSummaryPrint(VarSummaryRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varSummaryFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarCollectionMap *******************/
static inline VarCollectionMapRef varCollectionMapFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_COLLECTION_MAP_TYPESTRING));
    return (VarCollectionMapRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarCollectionMapRef varCollectionMapFromBytes(GBytes *b)
{
    return (VarCollectionMapRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarCollectionMapRef varCollectionMapFromData(gconstpointer data, gsize size)
{
    return (VarCollectionMapRef){ data, size };
}

static inline GVariant *varCollectionMapDupToGvariant(VarCollectionMapRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_COLLECTION_MAP_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varCollectionMapToGvariant(VarCollectionMapRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_COLLECTION_MAP_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varCollectionMapToOwnedGvariant(VarCollectionMapRef v, GVariant *base)
{
    return varCollectionMapToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varCollectionMapPeekAsGvariant(VarCollectionMapRef v)
{
    return g_variant_new_from_data(VAR_COLLECTION_MAP_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarCollectionMapRef varCollectionMapFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_COLLECTION_MAP_TYPESTRING));
    return varCollectionMapFromData(child.base, child.size);
}

static inline gsize varCollectionMapGetLength(VarCollectionMapRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarCollectionMapEntryRef varCollectionMapGetAt(VarCollectionMapRef v, gsize index)
{
    VarCollectionMapEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarCollectionMapEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varCollectionMapEntryGetKey(VarCollectionMapEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline VarRefMapRef varCollectionMapEntryGetValue(VarCollectionMapEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 8);
    g_assert(offset <= v.size);
    return (VarRefMapRef){ (char *)v.base + offset, (v.size - offsetSize) - offset };
}

static inline gboolean varCollectionMapLookup(VarCollectionMapRef v, const char *key, gsize *indexOut, VarRefMapRef *out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize end = len;

    while (start < end)
    {
        gsize mid = (end + start) / 2;
        gsize midEnd = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
        gsize midStart = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
        g_assert(midStart <= midEnd);
        g_assert(midEnd <= lastEnd);
        VarCollectionMapEntryRef e = { ((const char *)v.base) + midStart, midEnd - midStart };
        const char *entryKey = varCollectionMapEntryGetKey(e);
        gint32 cmp = strcmp(canonicalKey, entryKey);
        if (cmp == 0)
        {
            if (indexOut)
            {
                *indexOut = mid;
            }
            if (out)
            {
                *out = varCollectionMapEntryGetValue(e);
            }
            return TRUE;
        }
        if (cmp < 0)
        {
            end = mid; /* canonicalKey < entryKey */
        }
        else
        {
            start = mid + 1; /* canonicalKey > entryKey */
        }
    }
    return FALSE;
}

static inline GString *varCollectionMapFormat(VarCollectionMapRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varCollectionMapGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_COLLECTION_MAP_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarCollectionMapEntryRef entry = varCollectionMapGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varCollectionMapEntryGetKey(entry));
        g_string_append(s, ": ");
        varRefMapFormat(varCollectionMapEntryGetValue(entry), s, typeAnnotate);
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varCollectionMapPrint(VarCollectionMapRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varCollectionMapFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarRelated *******************/
static inline VarRelatedRef varRelatedFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_RELATED_TYPESTRING));
    return (VarRelatedRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarRelatedRef varRelatedFromBytes(GBytes *b)
{
    return (VarRelatedRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarRelatedRef varRelatedFromData(gconstpointer data, gsize size)
{
    return (VarRelatedRef){ data, size };
}

static inline GVariant *varRelatedDupToGvariant(VarRelatedRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_RELATED_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varRelatedToGvariant(VarRelatedRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_RELATED_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varRelatedToOwnedGvariant(VarRelatedRef v, GVariant *base)
{
    return varRelatedToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varRelatedPeekAsGvariant(VarRelatedRef v)
{
    return g_variant_new_from_data(VAR_RELATED_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarRelatedRef varRelatedFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_RELATED_TYPESTRING));
    return varRelatedFromData(child.base, child.size);
}

static inline const char *varRelatedGetRef(VarRelatedRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline VarChecksumRef varRelatedGetCommit(VarRelatedRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varRelatedPeekCommit(VarRelatedRef v, gsize *len)
{
    VarChecksumRef a = varRelatedGetCommit(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline GString *varRelatedFormat(VarRelatedRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varGStringAppendString(s, varRelatedGetRef(v));
    g_string_append(s, ", ");
    varChecksumFormat(varRelatedGetCommit(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varRelatedPrint(VarRelatedRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varRelatedFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarArrayofRelated *******************/
static inline VarArrayofRelatedRef varArrayofRelatedFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_ARRAYOF_RELATED_TYPESTRING));
    return (VarArrayofRelatedRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarArrayofRelatedRef varArrayofRelatedFromBytes(GBytes *b)
{
    return (VarArrayofRelatedRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarArrayofRelatedRef varArrayofRelatedFromData(gconstpointer data, gsize size)
{
    return (VarArrayofRelatedRef){ data, size };
}

static inline GVariant *varArrayofRelatedDupToGvariant(VarArrayofRelatedRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_ARRAYOF_RELATED_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varArrayofRelatedToGvariant(VarArrayofRelatedRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_ARRAYOF_RELATED_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varArrayofRelatedToOwnedGvariant(VarArrayofRelatedRef v, GVariant *base)
{
    return varArrayofRelatedToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varArrayofRelatedPeekAsGvariant(VarArrayofRelatedRef v)
{
    return g_variant_new_from_data(VAR_ARRAYOF_RELATED_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarArrayofRelatedRef varArrayofRelatedFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_ARRAYOF_RELATED_TYPESTRING));
    return varArrayofRelatedFromData(child.base, child.size);
}

static inline gsize varArrayofRelatedGetLength(VarArrayofRelatedRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarRelatedRef varArrayofRelatedGetAt(VarArrayofRelatedRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 1) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    return (VarRelatedRef){ ((const char *)v.base) + start, end - start };
}

static inline GString *varArrayofRelatedFormat(VarArrayofRelatedRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varArrayofRelatedGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_ARRAYOF_RELATED_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varRelatedFormat(varArrayofRelatedGetAt(v, i), s, ((i == 0) ? typeAnnotate : FALSE));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varArrayofRelatedPrint(VarArrayofRelatedRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varArrayofRelatedFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarCommit *******************/
static inline VarCommitRef varCommitFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_COMMIT_TYPESTRING));
    return (VarCommitRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarCommitRef varCommitFromBytes(GBytes *b)
{
    return (VarCommitRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarCommitRef varCommitFromData(gconstpointer data, gsize size)
{
    return (VarCommitRef){ data, size };
}

static inline GVariant *varCommitDupToGvariant(VarCommitRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_COMMIT_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varCommitToGvariant(VarCommitRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_COMMIT_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varCommitToOwnedGvariant(VarCommitRef v, GVariant *base)
{
    return varCommitToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varCommitPeekAsGvariant(VarCommitRef v)
{
    return g_variant_new_from_data(VAR_COMMIT_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarCommitRef varCommitFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_COMMIT_TYPESTRING));
    return varCommitFromData(child.base, child.size);
}

static inline VarMetadataRef varCommitGetMetadata(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline VarChecksumRef varCommitGetParent(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 1);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varCommitPeekParent(VarCommitRef v, gsize *len)
{
    VarChecksumRef a = varCommitGetParent(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline VarArrayofRelatedRef varCommitGetRelated(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 1);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 2);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarArrayofRelatedRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const char *varCommitGetSubject(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 2);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 3);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline const char *varCommitGetBody(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 3);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 4);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline guint64 varCommitGetTimestamp(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 4);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    g_assert(offset + 8 <= v.size);
    return GUINT64_FROM_BE((guint64)G_STRUCT_MEMBER(guint64, v.base, offset));
}

static inline VarChecksumRef varCommitGetRootContents(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 4);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 8;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 5);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varCommitPeekRootContents(VarCommitRef v, gsize *len)
{
    VarChecksumRef a = varCommitGetRootContents(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline VarChecksumRef varCommitGetRootMetadata(VarCommitRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 5);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 6;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varCommitPeekRootMetadata(VarCommitRef v, gsize *len)
{
    VarChecksumRef a = varCommitGetRootMetadata(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline GString *varCommitFormat(VarCommitRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varMetadataFormat(varCommitGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varChecksumFormat(varCommitGetParent(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varArrayofRelatedFormat(varCommitGetRelated(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varGStringAppendString(s, varCommitGetSubject(v));
    g_string_append(s, ", ");
    varGStringAppendString(s, varCommitGetBody(v));
    g_string_append(s, ", ");
    g_string_append_printf(s, "%s%" G_GUINT64_FORMAT ", ", typeAnnotate ? "uint64 " : "", varCommitGetTimestamp(v));
    varChecksumFormat(varCommitGetRootContents(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varChecksumFormat(varCommitGetRootMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varCommitPrint(VarCommitRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varCommitFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarCacheData *******************/
static inline VarCacheDataRef varCacheDataFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_CACHE_DATA_TYPESTRING));
    return (VarCacheDataRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarCacheDataRef varCacheDataFromBytes(GBytes *b)
{
    return (VarCacheDataRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarCacheDataRef varCacheDataFromData(gconstpointer data, gsize size)
{
    return (VarCacheDataRef){ data, size };
}

static inline GVariant *varCacheDataDupToGvariant(VarCacheDataRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_CACHE_DATA_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varCacheDataToGvariant(VarCacheDataRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_CACHE_DATA_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varCacheDataToOwnedGvariant(VarCacheDataRef v, GVariant *base)
{
    return varCacheDataToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varCacheDataPeekAsGvariant(VarCacheDataRef v)
{
    return g_variant_new_from_data(VAR_CACHE_DATA_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarCacheDataRef varCacheDataFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_CACHE_DATA_TYPESTRING));
    return varCacheDataFromData(child.base, child.size);
}

static inline guint64 varCacheDataGetInstalledSize(VarCacheDataRef v)
{
    guint offset = ((7) & (~(gsize)7)) + 0;
    g_assert(offset + 8 <= v.size);
    return GUINT64_FROM_BE((guint64)G_STRUCT_MEMBER(guint64, v.base, offset));
}

static inline guint64 varCacheDataGetDownloadSize(VarCacheDataRef v)
{
    guint offset = ((7) & (~(gsize)7)) + 8;
    g_assert(offset + 8 <= v.size);
    return GUINT64_FROM_BE((guint64)G_STRUCT_MEMBER(guint64, v.base, offset));
}

static inline const char *varCacheDataGetMetadata(VarCacheDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((7) & (~(gsize)7)) + 16;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = v.size - offsetSize * 0;
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline GString *varCacheDataFormat(VarCacheDataRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append_printf(s, "(%s%" G_GUINT64_FORMAT ", %s%" G_GUINT64_FORMAT ", ", typeAnnotate ? "uint64 " : "", varCacheDataGetInstalledSize(v), typeAnnotate ? "uint64 " : "",
                           varCacheDataGetDownloadSize(v));
    varGStringAppendString(s, varCacheDataGetMetadata(v));
    g_string_append(s, ")");
    return s;
}

static inline char *varCacheDataPrint(VarCacheDataRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varCacheDataFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarCache *******************/

static inline VarCacheRef varCacheFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_CACHE_TYPESTRING));
    return (VarCacheRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarCacheRef varCacheFromBytes(GBytes *b)
{
    return (VarCacheRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarCacheRef varCacheFromData(gconstpointer data, gsize size)
{
    return (VarCacheRef){ data, size };
}

static inline GVariant *varCacheDupToGvariant(VarCacheRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_CACHE_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varCacheToGvariant(VarCacheRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varCacheToOwnedGvariant(VarCacheRef v, GVariant *base)
{
    return varCacheToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varCachePeekAsGvariant(VarCacheRef v)
{
    return g_variant_new_from_data(VAR_CACHE_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarCacheRef varCacheFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_CACHE_TYPESTRING));
    return varCacheFromData(child.base, child.size);
}

static inline gsize varCacheGetLength(VarCacheRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarCacheEntryRef varCacheGetAt(VarCacheRef v, gsize index)
{
    VarCacheEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarCacheEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varCacheEntryGetKey(VarCacheEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline VarCacheDataRef varCacheEntryGetValue(VarCacheEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 8);
    g_assert(offset <= v.size);
    return (VarCacheDataRef){ (char *)v.base + offset, (v.size - offsetSize) - offset };
}

static inline gboolean varCacheLookup(VarCacheRef v, const char *key, gsize *indexOut, VarCacheDataRef *out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize end = len;

    while (start < end)
    {
        gsize mid = (end + start) / 2;
        gsize midEnd = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
        gsize midStart = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
        g_assert(midStart <= midEnd);
        g_assert(midEnd <= lastEnd);
        VarCacheEntryRef e = { ((const char *)v.base) + midStart, midEnd - midStart };
        const char *entryKey = varCacheEntryGetKey(e);
        gint32 cmp = strcmp(canonicalKey, entryKey);
        if (cmp == 0)
        {
            if (indexOut)
            {
                *indexOut = mid;
            }
            if (out)
            {
                *out = varCacheEntryGetValue(e);
            }
            return TRUE;
        }
        if (cmp < 0)
        {
            end = mid; /* canonicalKey < entryKey */
        }
        else
        {
            start = mid + 1; /* canonicalKey > entryKey */
        }
    }
    return FALSE;
}

static inline GString *varCacheFormat(VarCacheRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varCacheGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_CACHE_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarCacheEntryRef entry = varCacheGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varCacheEntryGetKey(entry));
        g_string_append(s, ": ");
        varCacheDataFormat(varCacheEntryGetValue(entry), s, typeAnnotate);
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varCachePrint(VarCacheRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varCacheFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarSparseCache *******************/

static inline VarSparseCacheRef varSparseCacheFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_SPARSE_CACHE_TYPESTRING));
    return (VarSparseCacheRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarSparseCacheRef varSparseCacheFromBytes(GBytes *b)
{
    return (VarSparseCacheRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarSparseCacheRef varSparseCacheFromData(gconstpointer data, gsize size)
{
    return (VarSparseCacheRef){ data, size };
}

static inline GVariant *varSparseCacheDupToGvariant(VarSparseCacheRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_SPARSE_CACHE_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varSparseCacheToGvariant(VarSparseCacheRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_SPARSE_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varSparseCacheToOwnedGvariant(VarSparseCacheRef v, GVariant *base)
{
    return varSparseCacheToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varSparseCachePeekAsGvariant(VarSparseCacheRef v)
{
    return g_variant_new_from_data(VAR_SPARSE_CACHE_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarSparseCacheRef varSparseCacheFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_SPARSE_CACHE_TYPESTRING));
    return varSparseCacheFromData(child.base, child.size);
}

static inline gsize varSparseCacheGetLength(VarSparseCacheRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarSparseCacheEntryRef varSparseCacheGetAt(VarSparseCacheRef v, gsize index)
{
    VarSparseCacheEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarSparseCacheEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varSparseCacheEntryGetKey(VarSparseCacheEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline VarMetadataRef varSparseCacheEntryGetValue(VarSparseCacheEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 8);
    g_assert(offset <= v.size);
    return (VarMetadataRef){ (char *)v.base + offset, (v.size - offsetSize) - offset };
}

static inline gboolean varSparseCacheLookup(VarSparseCacheRef v, const char *key, gsize *indexOut, VarMetadataRef *out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize end = len;

    while (start < end)
    {
        gsize mid = (end + start) / 2;
        gsize midEnd = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
        gsize midStart = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
        g_assert(midStart <= midEnd);
        g_assert(midEnd <= lastEnd);
        VarSparseCacheEntryRef e = { ((const char *)v.base) + midStart, midEnd - midStart };
        const char *entryKey = varSparseCacheEntryGetKey(e);
        gint32 cmp = strcmp(canonicalKey, entryKey);
        if (cmp == 0)
        {
            if (indexOut)
            {
                *indexOut = mid;
            }
            if (out)
            {
                *out = varSparseCacheEntryGetValue(e);
            }
            return TRUE;
        }
        if (cmp < 0)
        {
            end = mid; /* canonicalKey < entryKey */
        }
        else
        {
            start = mid + 1; /* canonicalKey > entryKey */
        }
    }
    return FALSE;
}

static inline GString *varSparseCacheFormat(VarSparseCacheRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varSparseCacheGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_SPARSE_CACHE_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarSparseCacheEntryRef entry = varSparseCacheGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varSparseCacheEntryGetKey(entry));
        g_string_append(s, ": ");
        varMetadataFormat(varSparseCacheEntryGetValue(entry), s, typeAnnotate);
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varSparseCachePrint(VarSparseCacheRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varSparseCacheFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarCommitsCache *******************/

static inline VarCommitsCacheRef varCommitsCacheFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_COMMITS_CACHE_TYPESTRING));
    return (VarCommitsCacheRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarCommitsCacheRef varCommitsCacheFromBytes(GBytes *b)
{
    return (VarCommitsCacheRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarCommitsCacheRef varCommitsCacheFromData(gconstpointer data, gsize size)
{
    return (VarCommitsCacheRef){ data, size };
}

static inline GVariant *varCommitsCacheDupToGvariant(VarCommitsCacheRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_COMMITS_CACHE_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varCommitsCacheToGvariant(VarCommitsCacheRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_COMMITS_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varCommitsCacheToOwnedGvariant(VarCommitsCacheRef v, GVariant *base)
{
    return varCommitsCacheToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varCommitsCachePeekAsGvariant(VarCommitsCacheRef v)
{
    return g_variant_new_from_data(VAR_COMMITS_CACHE_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarCommitsCacheRef varCommitsCacheFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_COMMITS_CACHE_TYPESTRING));
    return varCommitsCacheFromData(child.base, child.size);
}

static inline gsize varCommitsCacheGetLength(VarCommitsCacheRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarChecksumRef varCommitsCacheGetAt(VarCommitsCacheRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 1) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    return (VarChecksumRef){ ((const char *)v.base) + start, end - start };
}

static inline GString *varCommitsCacheFormat(VarCommitsCacheRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varCommitsCacheGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_COMMITS_CACHE_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varChecksumFormat(varCommitsCacheGetAt(v, i), s, ((i == 0) ? typeAnnotate : FALSE));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varCommitsCachePrint(VarCommitsCacheRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varCommitsCacheFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarArrayofstring *******************/

static inline VarArrayofstringRef varArrayofstringFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_ARRAYOFSTRING_TYPESTRING));
    return (VarArrayofstringRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarArrayofstringRef varArrayofstringFromBytes(GBytes *b)
{
    return (VarArrayofstringRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarArrayofstringRef varArrayofstringFromData(gconstpointer data, gsize size)
{
    return (VarArrayofstringRef){ data, size };
}

static inline GVariant *varArrayofstringDupToGvariant(VarArrayofstringRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_ARRAYOFSTRING_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varArrayofstringToGvariant(VarArrayofstringRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_ARRAYOFSTRING_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varArrayofstringToOwnedGvariant(VarArrayofstringRef v, GVariant *base)
{
    return varArrayofstringToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varArrayofstringPeekAsGvariant(VarArrayofstringRef v)
{
    return g_variant_new_from_data(VAR_ARRAYOFSTRING_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarArrayofstringRef varArrayofstringFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_ARRAYOFSTRING_TYPESTRING));
    return varArrayofstringFromData(child.base, child.size);
}

static inline gsize varArrayofstringGetLength(VarArrayofstringRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline const char *varArrayofstringGetAt(VarArrayofstringRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 1) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    const char *base = (const char *)v.base;
    g_assert(base[end - 1] == 0);
    return base + start;
}

static inline const char **varArrayofstringToStrv(VarArrayofstringRef v, gsize *length_out)
{
    gsize length = varArrayofstringGetLength(v);
    gsize i;
    const char **resv = g_new(const char *, length + 1);

    for (i = 0; i < length; i++)
    {
        resv[i] = varArrayofstringGetAt(v, i);
    }
    resv[i] = NULL;

    if (length_out)
    {
        *length_out = length;
    }

    return resv;
}

static inline GString *varArrayofstringFormat(VarArrayofstringRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varArrayofstringGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_ARRAYOFSTRING_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varArrayofstringGetAt(v, i));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varArrayofstringPrint(VarArrayofstringRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varArrayofstringFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarDeployData *******************/

static inline VarDeployDataRef varDeployDataFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_DEPLOY_DATA_TYPESTRING));
    return (VarDeployDataRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarDeployDataRef varDeployDataFromBytes(GBytes *b)
{
    return (VarDeployDataRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarDeployDataRef varDeployDataFromData(gconstpointer data, gsize size)
{
    return (VarDeployDataRef){ data, size };
}

static inline GVariant *varDeployDataDupToGvariant(VarDeployDataRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_DEPLOY_DATA_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varDeployDataToGvariant(VarDeployDataRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_DEPLOY_DATA_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varDeployDataToOwnedGvariant(VarDeployDataRef v, GVariant *base)
{
    return varDeployDataToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varDeployDataPeekAsGvariant(VarDeployDataRef v)
{
    return g_variant_new_from_data(VAR_DEPLOY_DATA_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarDeployDataRef varDeployDataFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_DEPLOY_DATA_TYPESTRING));
    return varDeployDataFromData(child.base, child.size);
}

static inline const char *varDeployDataGetOrigin(VarDeployDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline const char *varDeployDataGetCommit(VarDeployDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 1);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline VarArrayofstringRef varDeployDataGetSubpaths(VarDeployDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 1);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 2);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarArrayofstringRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline guint64 varDeployDataGetInstalledSize(VarDeployDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 2);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    g_assert(offset + 8 <= v.size);
    return GUINT64_FROM_BE((guint64)G_STRUCT_MEMBER(guint64, v.base, offset));
}

static inline VarMetadataRef varDeployDataGetMetadata(VarDeployDataRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 2);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 8;
    gsize start = offset;
    gsize end = v.size - offsetSize * 3;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varDeployDataFormat(VarDeployDataRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varGStringAppendString(s, varDeployDataGetOrigin(v));
    g_string_append(s, ", ");
    varGStringAppendString(s, varDeployDataGetCommit(v));
    g_string_append(s, ", ");
    varArrayofstringFormat(varDeployDataGetSubpaths(v), s, typeAnnotate);
    g_string_append(s, ", ");
    g_string_append_printf(s, "%s%" G_GUINT64_FORMAT ", ", typeAnnotate ? "uint64 " : "", varDeployDataGetInstalledSize(v));
    varMetadataFormat(varDeployDataGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varDeployDataPrint(VarDeployDataRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varDeployDataFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarRatings *******************/

static inline VarRatingsRef varRatingsFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_RATINGS_TYPESTRING));
    return (VarRatingsRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarRatingsRef varRatingsFromBytes(GBytes *b)
{
    return (VarRatingsRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarRatingsRef varRatingsFromData(gconstpointer data, gsize size)
{
    return (VarRatingsRef){ data, size };
}

static inline GVariant *varRatingsDupToGvariant(VarRatingsRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_RATINGS_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varRatingsToGvariant(VarRatingsRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_RATINGS_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varRatingsToOwnedGvariant(VarRatingsRef v, GVariant *base)
{
    return varRatingsToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varRatingsPeekAsGvariant(VarRatingsRef v)
{
    return g_variant_new_from_data(VAR_RATINGS_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarRatingsRef varRatingsFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_RATINGS_TYPESTRING));
    return varRatingsFromData(child.base, child.size);
}

static inline gsize varRatingsGetLength(VarRatingsRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarRatingsEntryRef varRatingsGetAt(VarRatingsRef v, gsize index)
{
    VarRatingsEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 1) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarRatingsEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varRatingsEntryGetKey(VarRatingsEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline const char *varRatingsEntryGetValue(VarRatingsEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 1);
    g_assert(offset <= v.size);
    g_assert(((char *)v.base)[(v.size - offsetSize) - 1] == 0);
    return (const char *)v.base + offset;
}

static inline gboolean varRatingsLookup(VarRatingsRef v, const char *key, gsize *indexOut, const char **out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize i;

    for (i = 0; i < len; i++)
    {
        gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - i - 1);
        VarRatingsEntryRef e = { ((const guchar *)v.base) + start, end - start };
        g_assert(start <= end);
        g_assert(end <= lastEnd);
        const char *entryKey = varRatingsEntryGetKey(e);
        if (strcmp(canonicalKey, entryKey) == 0)
        {
            if (indexOut)
            {
                *indexOut = i;
            }
            if (out)
            {
                *out = varRatingsEntryGetValue(e);
            }
            return TRUE;
        }
        start = VAR_REF_ALIGN(end, 1);
    }
    return FALSE;
}

static inline GString *varRatingsFormat(VarRatingsRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varRatingsGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_RATINGS_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarRatingsEntryRef entry = varRatingsGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varRatingsEntryGetKey(entry));
        g_string_append(s, ": ");
        varGStringAppendString(s, varRatingsEntryGetValue(entry));
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varRatingsPrint(VarRatingsRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varRatingsFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarContentRating *******************/

static inline VarContentRatingRef varContentRatingFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_CONTENT_RATING_TYPESTRING));
    return (VarContentRatingRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarContentRatingRef varContentRatingFromBytes(GBytes *b)
{
    return (VarContentRatingRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarContentRatingRef varContentRatingFromData(gconstpointer data, gsize size)
{
    return (VarContentRatingRef){ data, size };
}

static inline GVariant *varContentRatingDupToGvariant(VarContentRatingRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_CONTENT_RATING_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varContentRatingToGvariant(VarContentRatingRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_CONTENT_RATING_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varContentRatingToOwnedGvariant(VarContentRatingRef v, GVariant *base)
{
    return varContentRatingToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varContentRatingPeekAsGvariant(VarContentRatingRef v)
{
    return g_variant_new_from_data(VAR_CONTENT_RATING_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarContentRatingRef varContentRatingFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_CONTENT_RATING_TYPESTRING));
    return varContentRatingFromData(child.base, child.size);
}

static inline const char *varContentRatingGetRatingType(VarContentRatingRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline VarRatingsRef varContentRatingGetRatings(VarContentRatingRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarRatingsRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varContentRatingFormat(VarContentRatingRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varGStringAppendString(s, varContentRatingGetRatingType(v));
    g_string_append(s, ", ");
    varRatingsFormat(varContentRatingGetRatings(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varContentRatingPrint(VarContentRatingRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varContentRatingFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarExtraDataSize *******************/

static inline VarExtraDataSizeRef varExtraDataSizeFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_EXTRA_DATA_SIZE_TYPESTRING));
    return (VarExtraDataSizeRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarExtraDataSizeRef varExtraDataSizeFromBytes(GBytes *b)
{
    g_assert(g_bytes_get_size(b) == 16);

    return (VarExtraDataSizeRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarExtraDataSizeRef varExtraDataSizeFromData(gconstpointer data, gsize size)
{
    g_assert(size == 16);

    return (VarExtraDataSizeRef){ data, size };
}

static inline GVariant *varExtraDataSizeDupToGvariant(VarExtraDataSizeRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_EXTRA_DATA_SIZE_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varExtraDataSizeToGvariant(VarExtraDataSizeRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_EXTRA_DATA_SIZE_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varExtraDataSizeToOwnedGvariant(VarExtraDataSizeRef v, GVariant *base)
{
    return varExtraDataSizeToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varExtraDataSizePeekAsGvariant(VarExtraDataSizeRef v)
{
    return g_variant_new_from_data(VAR_EXTRA_DATA_SIZE_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarExtraDataSizeRef varExtraDataSizeFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_EXTRA_DATA_SIZE_TYPESTRING));
    return varExtraDataSizeFromData(child.base, child.size);
}

static inline const VarExtraDataSize *varExtraDataSizePeek(VarExtraDataSizeRef v)
{
    return (const VarExtraDataSize *)v.base;
}

static inline guint32 varExtraDataSizeGetNExtraData(VarExtraDataSizeRef v)
{
    guint offset = ((3) & (~(gsize)3)) + 0;
    return GUINT32_FROM_LE((guint32)G_STRUCT_MEMBER(guint32, v.base, offset));
}

static inline guint64 varExtraDataSizeGetTotalSize(VarExtraDataSizeRef v)
{
    guint offset = ((11) & (~(gsize)7)) + 0;
    return GUINT64_FROM_LE((guint64)G_STRUCT_MEMBER(guint64, v.base, offset));
}

static inline GString *varExtraDataSizeFormat(VarExtraDataSizeRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append_printf(s, "(%s%" G_GUINT32_FORMAT ", %s%" G_GUINT64_FORMAT ")", typeAnnotate ? "uint32 " : "", varExtraDataSizeGetNExtraData(v), typeAnnotate ? "uint64 " : "",
                           varExtraDataSizeGetTotalSize(v));
    return s;
}

static inline char *varExtraDataSizePrint(VarExtraDataSizeRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varExtraDataSizeFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarArrayofChecksum *******************/

static inline VarArrayofChecksumRef varArrayofChecksumFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_ARRAYOF_CHECKSUM_TYPESTRING));
    return (VarArrayofChecksumRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarArrayofChecksumRef varArrayofChecksumFromBytes(GBytes *b)
{
    return (VarArrayofChecksumRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarArrayofChecksumRef varArrayofChecksumFromData(gconstpointer data, gsize size)
{
    return (VarArrayofChecksumRef){ data, size };
}

static inline GVariant *varArrayofChecksumDupToGvariant(VarArrayofChecksumRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_ARRAYOF_CHECKSUM_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varArrayofChecksumToGvariant(VarArrayofChecksumRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_ARRAYOF_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varArrayofChecksumToOwnedGvariant(VarArrayofChecksumRef v, GVariant *base)
{
    return varArrayofChecksumToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varArrayofChecksumPeekAsGvariant(VarArrayofChecksumRef v)
{
    return g_variant_new_from_data(VAR_ARRAYOF_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarArrayofChecksumRef varArrayofChecksumFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_ARRAYOF_CHECKSUM_TYPESTRING));
    return varArrayofChecksumFromData(child.base, child.size);
}

static inline gsize varArrayofChecksumGetLength(VarArrayofChecksumRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarChecksumRef varArrayofChecksumGetAt(VarArrayofChecksumRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 1) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    return (VarChecksumRef){ ((const char *)v.base) + start, end - start };
}

static inline GString *varArrayofChecksumFormat(VarArrayofChecksumRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varArrayofChecksumGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_ARRAYOF_CHECKSUM_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varChecksumFormat(varArrayofChecksumGetAt(v, i), s, ((i == 0) ? typeAnnotate : FALSE));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varArrayofChecksumPrint(VarArrayofChecksumRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varArrayofChecksumFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarSubsummary *******************/

static inline VarSubsummaryRef varSubsummaryFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_SUBSUMMARY_TYPESTRING));
    return (VarSubsummaryRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarSubsummaryRef varSubsummaryFromBytes(GBytes *b)
{
    return (VarSubsummaryRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarSubsummaryRef varSubsummaryFromData(gconstpointer data, gsize size)
{
    return (VarSubsummaryRef){ data, size };
}

static inline GVariant *varSubsummaryDupToGvariant(VarSubsummaryRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_SUBSUMMARY_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varSubsummaryToGvariant(VarSubsummaryRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_SUBSUMMARY_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varSubsummaryToOwnedGvariant(VarSubsummaryRef v, GVariant *base)
{
    return varSubsummaryToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varSubsummaryPeekAsGvariant(VarSubsummaryRef v)
{
    return g_variant_new_from_data(VAR_SUBSUMMARY_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarSubsummaryRef varSubsummaryFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_SUBSUMMARY_TYPESTRING));
    return varSubsummaryFromData(child.base, child.size);
}

static inline VarChecksumRef varSubsummaryGetChecksum(VarSubsummaryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline const guint8 *varSubsummaryPeekChecksum(VarSubsummaryRef v, gsize *len)
{
    VarChecksumRef a = varSubsummaryGetChecksum(v);
    if (len != NULL)
    {
        *len = varChecksumGetLength(a);
    }
    return (const guint8 *)a.base;
}

static inline VarArrayofChecksumRef varSubsummaryGetHistory(VarSubsummaryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 0) & (~(gsize)0)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 1);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarArrayofChecksumRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline VarMetadataRef varSubsummaryGetMetadata(VarSubsummaryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 1);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 2;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varSubsummaryFormat(VarSubsummaryRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varChecksumFormat(varSubsummaryGetChecksum(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varArrayofChecksumFormat(varSubsummaryGetHistory(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varMetadataFormat(varSubsummaryGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varSubsummaryPrint(VarSubsummaryRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varSubsummaryFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarSummaryIndexSubsummaries *******************/

static inline VarSummaryIndexSubsummariesRef varSummaryIndexSubsummariesFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING));
    return (VarSummaryIndexSubsummariesRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarSummaryIndexSubsummariesRef varSummaryIndexSubsummariesFromBytes(GBytes *b)
{
    return (VarSummaryIndexSubsummariesRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarSummaryIndexSubsummariesRef varSummaryIndexSubsummariesFromData(gconstpointer data, gsize size)
{
    return (VarSummaryIndexSubsummariesRef){ data, size };
}

static inline GVariant *varSummaryIndexSubsummariesDupToGvariant(VarSummaryIndexSubsummariesRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varSummaryIndexSubsummariesToGvariant(VarSummaryIndexSubsummariesRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varSummaryIndexSubsummariesToOwnedGvariant(VarSummaryIndexSubsummariesRef v, GVariant *base)
{
    return varSummaryIndexSubsummariesToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varSummaryIndexSubsummariesPeekAsGvariant(VarSummaryIndexSubsummariesRef v)
{
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarSummaryIndexSubsummariesRef varSummaryIndexSubsummariesFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING));
    return varSummaryIndexSubsummariesFromData(child.base, child.size);
}

static inline gsize varSummaryIndexSubsummariesGetLength(VarSummaryIndexSubsummariesRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarSummaryIndexSubsummariesEntryRef varSummaryIndexSubsummariesGetAt(VarSummaryIndexSubsummariesRef v, gsize index)
{
    VarSummaryIndexSubsummariesEntryRef res;
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 8) : 0;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    res = (VarSummaryIndexSubsummariesEntryRef){ ((const char *)v.base) + start, end - start };
    return res;
}

static inline const char *varSummaryIndexSubsummariesEntryGetKey(VarSummaryIndexSubsummariesEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    const char *base = (const char *)v.base;
    g_assert(end < v.size);
    g_assert(base[end - 1] == 0);
    return base;
}

static inline VarSubsummaryRef varSummaryIndexSubsummariesEntryGetValue(VarSummaryIndexSubsummariesEntryRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offset = VAR_REF_ALIGN(end, 8);
    g_assert(offset <= v.size);
    return (VarSubsummaryRef){ (char *)v.base + offset, (v.size - offsetSize) - offset };
}

static inline gboolean varSummaryIndexSubsummariesLookup(VarSummaryIndexSubsummariesRef v, const char *key, gsize *indexOut, VarSubsummaryRef *out)
{
    const char *canonicalKey = key;
    if (v.size == 0)
    {
        return FALSE;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    if (lastEnd > v.size)
    {
        return FALSE;
    }
    gsize offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return FALSE;
    }
    gsize len = offsetsArraySize / offsetSize;
    gsize start = 0;
    gsize end = len;

    while (start < end)
    {
        gsize mid = (end + start) / 2;
        gsize midEnd = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
        gsize midStart = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
        g_assert(midStart <= midEnd);
        g_assert(midEnd <= lastEnd);
        VarSummaryIndexSubsummariesEntryRef e = { ((const char *)v.base) + midStart, midEnd - midStart };
        const char *entryKey = varSummaryIndexSubsummariesEntryGetKey(e);
        gint32 cmp = strcmp(canonicalKey, entryKey);
        if (cmp == 0)
        {
            if (indexOut)
            {
                *indexOut = mid;
            }
            if (out)
            {
                *out = varSummaryIndexSubsummariesEntryGetValue(e);
            }
            return TRUE;
        }
        if (cmp < 0)
        {
            end = mid; /* canonicalKey < entryKey */
        }
        else
        {
            start = mid + 1; /* canonicalKey > entryKey */
        }
    }
    return FALSE;
}

static inline GString *varSummaryIndexSubsummariesFormat(VarSummaryIndexSubsummariesRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varSummaryIndexSubsummariesGetLength(v);
    gsize i;

    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING);
    }

    g_string_append_c(s, '{');
    for (i = 0; i < len; i++)
    {
        VarSummaryIndexSubsummariesEntryRef entry = varSummaryIndexSubsummariesGetAt(v, i);
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varGStringAppendString(s, varSummaryIndexSubsummariesEntryGetKey(entry));
        g_string_append(s, ": ");
        varSubsummaryFormat(varSummaryIndexSubsummariesEntryGetValue(entry), s, typeAnnotate);
    }
    g_string_append_c(s, '}');
    return s;
}

static inline char *varSummaryIndexSubsummariesPrint(VarSummaryIndexSubsummariesRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varSummaryIndexSubsummariesFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarSummaryIndex *******************/

static inline VarSummaryIndexRef varSummaryIndexFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_SUMMARY_INDEX_TYPESTRING));
    return (VarSummaryIndexRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarSummaryIndexRef varSummaryIndexFromBytes(GBytes *b)
{
    return (VarSummaryIndexRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarSummaryIndexRef varSummaryIndexFromData(gconstpointer data, gsize size)
{
    return (VarSummaryIndexRef){ data, size };
}

static inline GVariant *varSummaryIndexDupToGvariant(VarSummaryIndexRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varSummaryIndexToGvariant(VarSummaryIndexRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varSummaryIndexToOwnedGvariant(VarSummaryIndexRef v, GVariant *base)
{
    return varSummaryIndexToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varSummaryIndexPeekAsGvariant(VarSummaryIndexRef v)
{
    return g_variant_new_from_data(VAR_SUMMARY_INDEX_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarSummaryIndexRef varSummaryIndexFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_SUMMARY_INDEX_TYPESTRING));
    return varSummaryIndexFromData(child.base, child.size);
}

static inline VarSummaryIndexSubsummariesRef varSummaryIndexGetSubsummaries(VarSummaryIndexRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarSummaryIndexSubsummariesRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline VarMetadataRef varSummaryIndexGetMetadata(VarSummaryIndexRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 7) & (~(gsize)7)) + 0;
    gsize start = offset;
    gsize end = v.size - offsetSize * 1;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarMetadataRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varSummaryIndexFormat(VarSummaryIndexRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varSummaryIndexSubsummariesFormat(varSummaryIndexGetSubsummaries(v), s, typeAnnotate);
    g_string_append(s, ", ");
    varMetadataFormat(varSummaryIndexGetMetadata(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varSummaryIndexPrint(VarSummaryIndexRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varSummaryIndexFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarObjectListInfo *******************/

static inline VarObjectListInfoRef varObjectListInfoFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_OBJECT_LIST_INFO_TYPESTRING));
    return (VarObjectListInfoRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarObjectListInfoRef varObjectListInfoFromBytes(GBytes *b)
{
    return (VarObjectListInfoRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarObjectListInfoRef varObjectListInfoFromData(gconstpointer data, gsize size)
{
    return (VarObjectListInfoRef){ data, size };
}

static inline GVariant *varObjectListInfoDupToGvariant(VarObjectListInfoRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_OBJECT_LIST_INFO_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varObjectListInfoToGvariant(VarObjectListInfoRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_OBJECT_LIST_INFO_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varObjectListInfoToOwnedGvariant(VarObjectListInfoRef v, GVariant *base)
{
    return varObjectListInfoToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varObjectListInfoPeekAsGvariant(VarObjectListInfoRef v)
{
    return g_variant_new_from_data(VAR_OBJECT_LIST_INFO_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarObjectListInfoRef varObjectListInfoFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_OBJECT_LIST_INFO_TYPESTRING));
    return varObjectListInfoFromData(child.base, child.size);
}

static inline gboolean varObjectListInfoGetIsLoose(VarObjectListInfoRef v)
{
    guint offset = ((0) & (~(gsize)0)) + 0;
    g_assert(offset + 1 <= v.size);
    return (gboolean)G_STRUCT_MEMBER(guint8, v.base, offset);
}

static inline VarArrayofstringRef varObjectListInfoGetPackfiles(VarObjectListInfoRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 1;
    gsize start = offset;
    gsize end = v.size - offsetSize * 0;
    g_assert(start <= end);
    g_assert(end <= v.size);
    return (VarArrayofstringRef){ G_STRUCT_MEMBER_P(v.base, start), end - start };
}

static inline GString *varObjectListInfoFormat(VarObjectListInfoRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append_printf(s, "(%s, ", (varObjectListInfoGetIsLoose(v)) ? "true" : "false");
    varArrayofstringFormat(varObjectListInfoGetPackfiles(v), s, typeAnnotate);
    g_string_append(s, ")");
    return s;
}

static inline char *varObjectListInfoPrint(VarObjectListInfoRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varObjectListInfoFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarObjectName *******************/

static inline VarObjectNameRef varObjectNameFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_OBJECT_NAME_TYPESTRING));
    return (VarObjectNameRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarObjectNameRef varObjectNameFromBytes(GBytes *b)
{
    return (VarObjectNameRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarObjectNameRef varObjectNameFromData(gconstpointer data, gsize size)
{
    return (VarObjectNameRef){ data, size };
}

static inline GVariant *varObjectNameDupToGvariant(VarObjectNameRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_OBJECT_NAME_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varObjectNameToGvariant(VarObjectNameRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_OBJECT_NAME_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varObjectNameToOwnedGvariant(VarObjectNameRef v, GVariant *base)
{
    return varObjectNameToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varObjectNamePeekAsGvariant(VarObjectNameRef v)
{
    return g_variant_new_from_data(VAR_OBJECT_NAME_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarObjectNameRef varObjectNameFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_OBJECT_NAME_TYPESTRING));
    return varObjectNameFromData(child.base, child.size);
}

static inline const char *varObjectNameGetChecksum(VarObjectNameRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    guint offset = ((0) & (~(gsize)0)) + 0;
    const char *base = (const char *)v.base;
    gsize start = offset;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, 0);
    g_assert(start <= end);
    g_assert(end <= v.size);
    g_assert(base[end - 1] == 0);
    return &G_STRUCT_MEMBER(const char, v.base, start);
}

static inline guint32 varObjectNameGetObjtype(VarObjectNameRef v)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    guint offset = ((lastEnd + 3) & (~(gsize)3)) + 0;
    g_assert(offset + 4 <= v.size);
    return (guint32)G_STRUCT_MEMBER(guint32, v.base, offset);
}

static inline GString *varObjectNameFormat(VarObjectNameRef v, GString *s, gboolean typeAnnotate)
{
    g_string_append(s, "(");
    varGStringAppendString(s, varObjectNameGetChecksum(v));
    g_string_append(s, ", ");
    g_string_append_printf(s, "%s%" G_GUINT32_FORMAT ")", typeAnnotate ? "uint32 " : "", varObjectNameGetObjtype(v));
    return s;
}

static inline char *varObjectNamePrint(VarObjectNameRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varObjectNameFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

/************** VarObjectNames *******************/

static inline VarObjectNamesRef varObjectNamesFromGvariant(GVariant *v)
{
    g_assert(g_variant_type_equal(g_variant_get_type(v), VAR_OBJECT_NAMES_TYPESTRING));
    return (VarObjectNamesRef){ g_variant_get_data(v), g_variant_get_size(v) };
}

static inline VarObjectNamesRef varObjectNamesFromBytes(GBytes *b)
{
    return (VarObjectNamesRef){ g_bytes_get_data(b, NULL), g_bytes_get_size(b) };
}

static inline VarObjectNamesRef varObjectNamesFromData(gconstpointer data, gsize size)
{
    return (VarObjectNamesRef){ data, size };
}

static inline GVariant *varObjectNamesDupToGvariant(VarObjectNamesRef v)
{
    guint8 *duped = (guint8 *)varMemdup2(v.base, v.size);
    return g_variant_new_from_data(VAR_OBJECT_NAMES_TYPEFORMAT, duped, v.size, TRUE, g_free, duped);
}

static inline GVariant *varObjectNamesToGvariant(VarObjectNamesRef v, GDestroyNotify notify, gpointer userData)
{
    return g_variant_new_from_data(VAR_OBJECT_NAMES_TYPEFORMAT, v.base, v.size, TRUE, notify, userData);
}

static inline GVariant *varObjectNamesToOwnedGvariant(VarObjectNamesRef v, GVariant *base)
{
    return varObjectNamesToGvariant(v, (GDestroyNotify)g_variant_unref, g_variant_ref(base));
}

static inline GVariant *varObjectNamesPeekAsGvariant(VarObjectNamesRef v)
{
    return g_variant_new_from_data(VAR_OBJECT_NAMES_TYPEFORMAT, v.base, v.size, TRUE, NULL, NULL);
}

static inline VarObjectNamesRef varObjectNamesFromVariant(VarVariantRef v)
{
    const GVariantType *type;
    VarRef child = getVarVariantChild(v, &type);
    g_assert(g_variant_type_equal(type, VAR_OBJECT_NAMES_TYPESTRING));
    return varObjectNamesFromData(child.base, child.size);
}

static inline gsize varObjectNamesGetLength(VarObjectNamesRef v)
{
    if (v.size == 0)
    {
        return 0;
    }
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize offsetsArraySize;
    if (lastEnd > v.size)
    {
        return 0;
    }
    offsetsArraySize = v.size - lastEnd;
    if (offsetsArraySize % offsetSize != 0)
    {
        return 0;
    }
    gsize length = offsetsArraySize / offsetSize;
    return length;
}

static inline VarObjectNameRef varObjectNamesGetAt(VarObjectNamesRef v, gsize index)
{
    guint offsetSize = getVarRefOffsetSize(v.size);
    gsize lastEnd = VAR_REF_READ_FRAME_OFFSET(v, 0);
    gsize len = (v.size - lastEnd) / offsetSize;
    gsize start = (index > 0) ? VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - index), 4) : 0;
    G_GNUC_UNUSED gsize end = VAR_REF_READ_FRAME_OFFSET(v, len - index - 1);
    g_assert(start <= end);
    g_assert(end <= lastEnd);
    return (VarObjectNameRef){ ((const char *)v.base) + start, end - start };
}

static inline GString *varObjectNamesFormat(VarObjectNamesRef v, GString *s, gboolean typeAnnotate)
{
    gsize len = varObjectNamesGetLength(v);
    gsize i;
    if (len == 0 && typeAnnotate)
    {
        g_string_append_printf(s, "@%s ", VAR_OBJECT_NAMES_TYPESTRING);
    }
    g_string_append_c(s, '[');
    for (i = 0; i < len; i++)
    {
        if (i != 0)
        {
            g_string_append(s, ", ");
        }
        varObjectNameFormat(varObjectNamesGetAt(v, i), s, ((i == 0) ? typeAnnotate : FALSE));
    }
    g_string_append_c(s, ']');
    return s;
}

static inline char *varObjectNamesPrint(VarObjectNamesRef v, gboolean typeAnnotate)
{
    GString *s = g_string_new("");
    varObjectNamesFormat(v, s, typeAnnotate);
    return g_string_free(s, FALSE);
}

#endif
