#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 VAR_REF_INFO_INDEXOF_COMMIT_SIZE 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 VAR_REF_MAP_ENTRY_INDEXOF_REF 0
#define VAR_REF_MAP_ENTRY_INDEXOF_INFO 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 VAR_CACHE_DATA_INDEXOF_INSTALLED_SIZE 0
#define VAR_CACHE_DATA_INDEXOF_DOWNLOAD_SIZE 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 VAR_DEPLOY_DATA_INDEXOF_INSTALLED_SIZE 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 VAR_CONTENT_RATING_INDEXOF_RATING_TYPE 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 VAR_EXTRA_DATA_SIZE_INDEXOF_TOTAL_SIZE 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 VAR_OBJECT_LIST_INFO_INDEXOF_IS_LOOSE 0
#define VAR_OBJECT_LIST_INFO_INDEXOF_PACKFILES 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 n_extra_data; /* little endian */
  guchar _padding1[4];
  guint64 total_size; /* 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 byte_size)
{
#if GLIB_CHECK_VERSION(2, 68, 0)
  return g_memdup2(mem, byte_size);
#else
  gpointer new_mem;

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

  return new_mem;
#endif
}

#define VAR_REF_READ_FRAME_OFFSET(_v, _index) readVarRefUnalignedLe((guchar *)((_v).base) + (_v).size - (offset_size * ((_index) + 1)), offset_size)
#define VAR_REF_ALIGN(_offset, _align_to) ((_offset + _align_to - 1) & ~(gsize)(_align_to - 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 **out_type)
{
  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 *type_string = (char *)base + size + 1;
      const char *limit = (char *)base + v.size;
      const char *end;

      if (g_variant_type_string_scan(type_string, limit, &end) && end == limit)
      {
        if (out_type)
          *out_type = (const GVariantType *)type_string;
        return (VarRef){v.base, size};
      }
    }
  }
  if (out_type)
    *out_type = 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 *type_string = (char *)base + size + 1;
      const char *limit = (char *)base + v.size;
      const char *end;

      if (g_variant_type_string_scan(type_string, limit, &end) && end == limit)
        return (const GVariantType *)type_string;
    }
  }
  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 *var_variant_to_gvariant(VarVariantRef v,
                                                GDestroyNotify notify,
                                                gpointer user_data)
{
  return g_variant_new_from_data(G_VARIANT_TYPE_VARIANT, v.base, v.size, TRUE, notify, user_data);
}

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

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

static inline VarVariantRef var_variant_from_variant(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 *var_variant_dup_child_to_gvariant(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 *var_variant_peek_child_as_variant(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 *var_variant_format(VarVariantRef v, GString *s, gboolean type_annotate)
{
#ifdef VAR_DEEP_VARIANT_FORMAT
  GVariant *gv = var_variant_peek_as_variant(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 *var_variant_print(VarVariantRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_variant_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static inline VarMetadataRef var_metadata_from_gvariant(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 var_metadata_from_bytes(GBytes *b)
{
  return (VarMetadataRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_metadata_dup_to_gvariant(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 *var_metadata_to_gvariant(VarMetadataRef v,
                                                 GDestroyNotify notify,
                                                 gpointer user_data)
{
  return g_variant_new_from_data(VAR_METADATA_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_metadata_get_length(VarMetadataRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarMetadataEntryRef var_metadata_get_at(VarMetadataRef v, gsize index)
{
  VarMetadataEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarMetadataEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_metadata_entry_get_key(VarMetadataEntryRef v)
{
  guint offset_size = 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 var_metadata_entry_get_value(VarMetadataEntryRef v)
{
  guint offset_size = 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 - offset_size) - offset};
}

static inline gboolean var_metadata_lookup(VarMetadataRef v, const char *key, gsize *index_out, VarVariantRef *out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  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 <= last_end);
    const char *e_key = var_metadata_entry_get_key(e);
    if (strcmp(canonical_key, e_key) == 0)
    {
      if (index_out)
        *index_out = i;
      if (out)
        *out = var_metadata_entry_get_value(e);
      return TRUE;
    }
    start = VAR_REF_ALIGN(end, 8);
  }
  return FALSE;
}

static inline gboolean var_metadata_lookup_boolean(VarMetadataRef v, const char *key, gboolean default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'b')
    return var_variant_get_boolean(value_v);
  return default_value;
}

static inline guint8 var_metadata_lookup_byte(VarMetadataRef v, const char *key, guint8 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'y')
    return var_variant_get_byte(value_v);
  return default_value;
}

static inline gint16 var_metadata_lookup_int16(VarMetadataRef v, const char *key, gint16 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'n')
    return var_variant_get_int16(value_v);
  return default_value;
}

static inline guint16 var_metadata_lookup_uint16(VarMetadataRef v, const char *key, guint16 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'q')
    return var_variant_get_uint16(value_v);
  return default_value;
}

static inline gint32 var_metadata_lookup_int32(VarMetadataRef v, const char *key, gint32 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'i')
    return var_variant_get_int32(value_v);
  return default_value;
}

static inline guint32 var_metadata_lookup_uint32(VarMetadataRef v, const char *key, guint32 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'u')
    return var_variant_get_uint32(value_v);
  return default_value;
}

static inline gint64 var_metadata_lookup_int64(VarMetadataRef v, const char *key, gint64 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'x')
    return var_variant_get_int64(value_v);
  return default_value;
}

static inline guint64 var_metadata_lookup_uint64(VarMetadataRef v, const char *key, guint64 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 't')
    return var_variant_get_uint64(value_v);
  return default_value;
}

static inline guint32 var_metadata_lookup_handle(VarMetadataRef v, const char *key, guint32 default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'h')
    return var_variant_get_handle(value_v);
  return default_value;
}

static inline double var_metadata_lookup_double(VarMetadataRef v, const char *key, double default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'd')
    return var_variant_get_double(value_v);
  return default_value;
}

static inline const char *var_metadata_lookup_string(VarMetadataRef v, const char *key, const char *default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 's')
    return var_variant_get_string(value_v);
  return default_value;
}

static inline const char *var_metadata_lookup_objectpath(VarMetadataRef v, const char *key, const char *default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'o')
    return var_variant_get_objectpath(value_v);
  return default_value;
}

static inline const char *var_metadata_lookup_signature(VarMetadataRef v, const char *key, const char *default_value)
{
  VarVariantRef value_v;

  if (var_metadata_lookup(v, key, NULL, &value_v) &&
      *(const char *)getVarVariantType(value_v) == 'g')
    return var_variant_get_signature(value_v);
  return default_value;
}

static inline GString *var_metadata_format(VarMetadataRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_metadata_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_METADATA_TYPESTRING);

  g_string_append_c(s, '{');
  for (i = 0; i < len; i++)
  {
    VarMetadataEntryRef entry = var_metadata_get_at(v, i);
    if (i != 0)
      g_string_append(s, ", ");
    varGStringAppendString(s, var_metadata_entry_get_key(entry));
    g_string_append(s, ": ");
    var_variant_format(var_metadata_entry_get_value(entry), s, type_annotate);
  }
  g_string_append_c(s, '}');
  return s;
}

static inline char *var_metadata_print(VarMetadataRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_metadata_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarChecksum *******************/
static inline VarChecksumRef var_checksum_from_gvariant(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 var_checksum_from_bytes(GBytes *b)
{
  return (VarChecksumRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_checksum_dup_to_gvariant(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 *var_checksum_to_gvariant(VarChecksumRef v,
                                                 GDestroyNotify notify,
                                                 gpointer user_data)
{
  return g_variant_new_from_data(VAR_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

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

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

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

static inline GString *var_checksum_format(VarChecksumRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_checksum_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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) ? type_annotate : FALSE) ? "byte " : "", var_checksum_get_at(v, i));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_checksum_print(VarChecksumRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_checksum_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarRefInfo *******************/
static inline VarRefInfoRef var_ref_info_from_gvariant(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 var_ref_info_from_bytes(GBytes *b)
{
  return (VarRefInfoRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_ref_info_dup_to_gvariant(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 *var_ref_info_to_gvariant(VarRefInfoRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_REF_INFO_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline guint64 var_ref_info_get_commit_size(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 var_ref_info_get_checksum(VarRefInfoRef v)
{
  guint offset_size = 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 *var_ref_info_peek_checksum(VarRefInfoRef v, gsize *len)
{
  VarChecksumRef a = var_ref_info_get_checksum(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

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

static inline GString *var_ref_info_format(VarRefInfoRef v, GString *s, gboolean type_annotate)
{
  g_string_append_printf(s, "(%s%" G_GUINT64_FORMAT ", ",
                         type_annotate ? "uint64 " : "",
                         var_ref_info_get_commit_size(v));
  var_checksum_format(var_ref_info_get_checksum(v), s, type_annotate);
  g_string_append(s, ", ");
  var_metadata_format(var_ref_info_get_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_ref_info_print(VarRefInfoRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_ref_info_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarRefMapEntry *******************/
static inline VarRefMapEntryRef var_ref_map_entry_from_gvariant(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 var_ref_map_entry_from_bytes(GBytes *b)
{
  return (VarRefMapEntryRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_ref_map_entry_dup_to_gvariant(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 *var_ref_map_entry_to_gvariant(VarRefMapEntryRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_REF_MAP_ENTRY_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline const char *var_ref_map_entry_get_ref(VarRefMapEntryRef v)
{
  guint offset_size = 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 var_ref_map_entry_get_info(VarRefMapEntryRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 7) & (~(gsize)7)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 1;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarRefInfoRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_ref_map_entry_format(VarRefMapEntryRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  varGStringAppendString(s, var_ref_map_entry_get_ref(v));
  g_string_append(s, ", ");
  var_ref_info_format(var_ref_map_entry_get_info(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_ref_map_entry_print(VarRefMapEntryRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_ref_map_entry_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarRefMap *******************/
static inline VarRefMapRef var_ref_map_from_gvariant(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 var_ref_map_from_bytes(GBytes *b)
{
  return (VarRefMapRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_ref_map_dup_to_gvariant(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 *var_ref_map_to_gvariant(VarRefMapRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_REF_MAP_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_ref_map_get_length(VarRefMapRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarRefMapEntryRef var_ref_map_get_at(VarRefMapRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  return (VarRefMapEntryRef){((const char *)v.base) + start, end - start};
}

static inline GString *var_ref_map_format(VarRefMapRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_ref_map_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, ", ");
    var_ref_map_entry_format(var_ref_map_get_at(v, i), s, ((i == 0) ? type_annotate : FALSE));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_ref_map_print(VarRefMapRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_ref_map_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarSummary *******************/
static inline VarSummaryRef var_summary_from_gvariant(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 var_summary_from_bytes(GBytes *b)
{
  return (VarSummaryRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_summary_dup_to_gvariant(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 *var_summary_to_gvariant(VarSummaryRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_SUMMARY_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline VarRefMapRef var_summary_get_ref_map(VarSummaryRef v)
{
  guint offset_size = 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 var_summary_get_metadata(VarSummaryRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 7) & (~(gsize)7)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 1;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarMetadataRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_summary_format(VarSummaryRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  var_ref_map_format(var_summary_get_ref_map(v), s, type_annotate);
  g_string_append(s, ", ");
  var_metadata_format(var_summary_get_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_summary_print(VarSummaryRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_summary_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarCollectionMap *******************/
static inline VarCollectionMapRef var_collection_map_from_gvariant(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 var_collection_map_from_bytes(GBytes *b)
{
  return (VarCollectionMapRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_collection_map_dup_to_gvariant(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 *var_collection_map_to_gvariant(VarCollectionMapRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_COLLECTION_MAP_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_collection_map_get_length(VarCollectionMapRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarCollectionMapEntryRef var_collection_map_get_at(VarCollectionMapRef v, gsize index)
{
  VarCollectionMapEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarCollectionMapEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_collection_map_entry_get_key(VarCollectionMapEntryRef v)
{
  guint offset_size = 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 var_collection_map_entry_get_value(VarCollectionMapEntryRef v)
{
  guint offset_size = 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 - offset_size) - offset};
}

static inline gboolean var_collection_map_lookup(VarCollectionMapRef v, const char *key, gsize *index_out, VarRefMapRef *out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  gsize start = 0;
  gsize end = len;

  while (start < end)
  {
    gsize mid = (end + start) / 2;
    gsize mid_end = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
    gsize mid_start = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
    g_assert(mid_start <= mid_end);
    g_assert(mid_end <= last_end);
    VarCollectionMapEntryRef e = {((const char *)v.base) + mid_start, mid_end - mid_start};
    const char *e_key = var_collection_map_entry_get_key(e);
    gint32 cmp = strcmp(canonical_key, e_key);
    if (cmp == 0)
    {
      if (index_out)
        *index_out = mid;
      if (out)
        *out = var_collection_map_entry_get_value(e);
      return TRUE;
    }
    if (cmp < 0)
      end = mid; /* canonical_key < e_key */
    else
      start = mid + 1; /* canonical_key > e_key */
  }
  return FALSE;
}

static inline GString *var_collection_map_format(VarCollectionMapRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_collection_map_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_COLLECTION_MAP_TYPESTRING);

  g_string_append_c(s, '{');
  for (i = 0; i < len; i++)
  {
    VarCollectionMapEntryRef entry = var_collection_map_get_at(v, i);
    if (i != 0)
      g_string_append(s, ", ");
    varGStringAppendString(s, var_collection_map_entry_get_key(entry));
    g_string_append(s, ": ");
    var_ref_map_format(var_collection_map_entry_get_value(entry), s, type_annotate);
  }
  g_string_append_c(s, '}');
  return s;
}

static inline char *var_collection_map_print(VarCollectionMapRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_collection_map_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarRelated *******************/
static inline VarRelatedRef var_related_from_gvariant(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 var_related_from_bytes(GBytes *b)
{
  return (VarRelatedRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_related_dup_to_gvariant(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 *var_related_to_gvariant(VarRelatedRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_RELATED_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline const char *var_related_get_ref(VarRelatedRef v)
{
  guint offset_size = 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 var_related_get_commit(VarRelatedRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 0) & (~(gsize)0)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 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 *var_related_peek_commit(VarRelatedRef v, gsize *len)
{
  VarChecksumRef a = var_related_get_commit(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

static inline GString *var_related_format(VarRelatedRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  varGStringAppendString(s, var_related_get_ref(v));
  g_string_append(s, ", ");
  var_checksum_format(var_related_get_commit(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_related_print(VarRelatedRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_related_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarArrayofRelated *******************/
static inline VarArrayofRelatedRef var_arrayof_related_from_gvariant(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 var_arrayof_related_from_bytes(GBytes *b)
{
  return (VarArrayofRelatedRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_arrayof_related_dup_to_gvariant(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 *var_arrayof_related_to_gvariant(VarArrayofRelatedRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_ARRAYOF_RELATED_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_arrayof_related_get_length(VarArrayofRelatedRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarRelatedRef var_arrayof_related_get_at(VarArrayofRelatedRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  return (VarRelatedRef){((const char *)v.base) + start, end - start};
}

static inline GString *var_arrayof_related_format(VarArrayofRelatedRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_arrayof_related_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, ", ");
    var_related_format(var_arrayof_related_get_at(v, i), s, ((i == 0) ? type_annotate : FALSE));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_arrayof_related_print(VarArrayofRelatedRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_arrayof_related_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarCommit *******************/
static inline VarCommitRef var_commit_from_gvariant(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 var_commit_from_bytes(GBytes *b)
{
  return (VarCommitRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_commit_dup_to_gvariant(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 *var_commit_to_gvariant(VarCommitRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_COMMIT_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline VarMetadataRef var_commit_get_metadata(VarCommitRef v)
{
  guint offset_size = 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 var_commit_get_parent(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 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 *var_commit_peek_parent(VarCommitRef v, gsize *len)
{
  VarChecksumRef a = var_commit_get_parent(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

static inline VarArrayofRelatedRef var_commit_get_related(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 1);
  guint offset = ((last_end + 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 *var_commit_get_subject(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 2);
  guint offset = ((last_end + 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 *var_commit_get_body(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 3);
  guint offset = ((last_end + 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 var_commit_get_timestamp(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 4);
  guint offset = ((last_end + 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 var_commit_get_root_contents(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 4);
  guint offset = ((last_end + 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 *var_commit_peek_root_contents(VarCommitRef v, gsize *len)
{
  VarChecksumRef a = var_commit_get_root_contents(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

static inline VarChecksumRef var_commit_get_root_metadata(VarCommitRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 5);
  guint offset = ((last_end + 0) & (~(gsize)0)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 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 *var_commit_peek_root_metadata(VarCommitRef v, gsize *len)
{
  VarChecksumRef a = var_commit_get_root_metadata(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

static inline GString *var_commit_format(VarCommitRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  var_metadata_format(var_commit_get_metadata(v), s, type_annotate);
  g_string_append(s, ", ");
  var_checksum_format(var_commit_get_parent(v), s, type_annotate);
  g_string_append(s, ", ");
  var_arrayof_related_format(var_commit_get_related(v), s, type_annotate);
  g_string_append(s, ", ");
  varGStringAppendString(s, var_commit_get_subject(v));
  g_string_append(s, ", ");
  varGStringAppendString(s, var_commit_get_body(v));
  g_string_append(s, ", ");
  g_string_append_printf(s, "%s%" G_GUINT64_FORMAT ", ",
                         type_annotate ? "uint64 " : "",
                         var_commit_get_timestamp(v));
  var_checksum_format(var_commit_get_root_contents(v), s, type_annotate);
  g_string_append(s, ", ");
  var_checksum_format(var_commit_get_root_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_commit_print(VarCommitRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_commit_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

/************** VarCacheData *******************/
static inline VarCacheDataRef var_cache_data_from_gvariant(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 var_cache_data_from_bytes(GBytes *b)
{
  return (VarCacheDataRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_cache_data_dup_to_gvariant(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 *var_cache_data_to_gvariant(VarCacheDataRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_CACHE_DATA_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

/**
 * @brief : 从VarCacheDataRef的信息中获取安装大小
 * @param : [in] v, VarCacheDataRef类型对象，格式为(tts)
 * @return: guint64 ，安装大小
 * @note  : 此函数用于标准API使用场景，因为标准中summary里的数值都是用大端表示法
 */
static inline guint64 var_cache_data_get_installed_size(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));
}

/**
 * @brief : 从VarCacheDataRef的信息中获取安装大小
 * @param : [in] v, VarCacheDataRef类型对象，格式为(tts)
 * @return: guint64 ，安装大小
 * @note  : 此函数仅用于通过`ostree summary --raw --repo=${repo}`命令获取的summary解析场景，因为此场景中数值已经是当前机型表示，故无需从大端转换
 */
static inline guint64 varCacheDataGetInstalledSize(VarCacheDataRef v)
{
  guint offset = ((7) & (~(gsize)7)) + 0;
  g_assert(offset + 8 <= v.size);
  return (guint64)G_STRUCT_MEMBER(guint64, v.base, offset);
}

// 类似var_cache_data_get_installed_size
static inline guint64 var_cache_data_get_download_size(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));
}

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

static inline const char *var_cache_data_get_metadata(VarCacheDataRef v)
{
  guint offset_size = 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 - offset_size * 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 *var_cache_data_format(VarCacheDataRef v, GString *s, gboolean type_annotate)
{
  g_string_append_printf(s, "(%s%" G_GUINT64_FORMAT ", %s%" G_GUINT64_FORMAT ", ",
                         type_annotate ? "uint64 " : "",
                         var_cache_data_get_installed_size(v),
                         type_annotate ? "uint64 " : "",
                         var_cache_data_get_download_size(v));
  varGStringAppendString(s, var_cache_data_get_metadata(v));
  g_string_append(s, ")");
  return s;
}

static inline char *var_cache_data_print(VarCacheDataRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_cache_data_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarCacheRef var_cache_from_gvariant(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 var_cache_from_bytes(GBytes *b)
{
  return (VarCacheRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_cache_dup_to_gvariant(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 *var_cache_to_gvariant(VarCacheRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_cache_get_length(VarCacheRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarCacheEntryRef var_cache_get_at(VarCacheRef v, gsize index)
{
  VarCacheEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarCacheEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_cache_entry_get_key(VarCacheEntryRef v)
{
  guint offset_size = 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 var_cache_entry_get_value(VarCacheEntryRef v)
{
  guint offset_size = 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 - offset_size) - offset};
}

static inline gboolean var_cache_lookup(VarCacheRef v, const char *key, gsize *index_out, VarCacheDataRef *out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  gsize start = 0;
  gsize end = len;

  while (start < end)
  {
    gsize mid = (end + start) / 2;
    gsize mid_end = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
    gsize mid_start = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
    g_assert(mid_start <= mid_end);
    g_assert(mid_end <= last_end);
    VarCacheEntryRef e = {((const char *)v.base) + mid_start, mid_end - mid_start};
    const char *e_key = var_cache_entry_get_key(e);
    gint32 cmp = strcmp(canonical_key, e_key);
    if (cmp == 0)
    {
      if (index_out)
        *index_out = mid;
      if (out)
        *out = var_cache_entry_get_value(e);
      return TRUE;
    }
    if (cmp < 0)
      end = mid; /* canonical_key < e_key */
    else
      start = mid + 1; /* canonical_key > e_key */
  }
  return FALSE;
}

static inline GString *var_cache_format(VarCacheRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_cache_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_CACHE_TYPESTRING);

  g_string_append_c(s, '{');
  for (i = 0; i < len; i++)
  {
    VarCacheEntryRef entry = var_cache_get_at(v, i);
    if (i != 0)
      g_string_append(s, ", ");
    varGStringAppendString(s, var_cache_entry_get_key(entry));
    g_string_append(s, ": ");
    var_cache_data_format(var_cache_entry_get_value(entry), s, type_annotate);
  }
  g_string_append_c(s, '}');
  return s;
}

static inline char *var_cache_print(VarCacheRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_cache_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarSparseCacheRef var_sparse_cache_from_gvariant(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 var_sparse_cache_from_bytes(GBytes *b)
{
  return (VarSparseCacheRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_sparse_cache_dup_to_gvariant(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 *var_sparse_cache_to_gvariant(VarSparseCacheRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_SPARSE_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_sparse_cache_get_length(VarSparseCacheRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarSparseCacheEntryRef var_sparse_cache_get_at(VarSparseCacheRef v, gsize index)
{
  VarSparseCacheEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarSparseCacheEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_sparse_cache_entry_get_key(VarSparseCacheEntryRef v)
{
  guint offset_size = 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 var_sparse_cache_entry_get_value(VarSparseCacheEntryRef v)
{
  guint offset_size = 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 - offset_size) - offset};
}

static inline gboolean var_sparse_cache_lookup(VarSparseCacheRef v, const char *key, gsize *index_out, VarMetadataRef *out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  gsize start = 0;
  gsize end = len;

  while (start < end)
  {
    gsize mid = (end + start) / 2;
    gsize mid_end = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
    gsize mid_start = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
    g_assert(mid_start <= mid_end);
    g_assert(mid_end <= last_end);
    VarSparseCacheEntryRef e = {((const char *)v.base) + mid_start, mid_end - mid_start};
    const char *e_key = var_sparse_cache_entry_get_key(e);
    gint32 cmp = strcmp(canonical_key, e_key);
    if (cmp == 0)
    {
      if (index_out)
        *index_out = mid;
      if (out)
        *out = var_sparse_cache_entry_get_value(e);
      return TRUE;
    }
    if (cmp < 0)
      end = mid; /* canonical_key < e_key */
    else
      start = mid + 1; /* canonical_key > e_key */
  }
  return FALSE;
}

static inline GString *var_sparse_cache_format(VarSparseCacheRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_sparse_cache_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_SPARSE_CACHE_TYPESTRING);

  g_string_append_c(s, '{');
  for (i = 0; i < len; i++)
  {
    VarSparseCacheEntryRef entry = var_sparse_cache_get_at(v, i);
    if (i != 0)
      g_string_append(s, ", ");
    varGStringAppendString(s, var_sparse_cache_entry_get_key(entry));
    g_string_append(s, ": ");
    var_metadata_format(var_sparse_cache_entry_get_value(entry), s, type_annotate);
  }
  g_string_append_c(s, '}');
  return s;
}

static inline char *var_sparse_cache_print(VarSparseCacheRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_sparse_cache_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarCommitsCacheRef var_commits_cache_from_gvariant(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 var_commits_cache_from_bytes(GBytes *b)
{
  return (VarCommitsCacheRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_commits_cache_dup_to_gvariant(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 *var_commits_cache_to_gvariant(VarCommitsCacheRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_COMMITS_CACHE_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_commits_cache_get_length(VarCommitsCacheRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarChecksumRef var_commits_cache_get_at(VarCommitsCacheRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  return (VarChecksumRef){((const char *)v.base) + start, end - start};
}

static inline GString *var_commits_cache_format(VarCommitsCacheRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_commits_cache_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, ", ");
    var_checksum_format(var_commits_cache_get_at(v, i), s, ((i == 0) ? type_annotate : FALSE));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_commits_cache_print(VarCommitsCacheRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_commits_cache_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarArrayofstringRef var_arrayofstring_from_gvariant(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 var_arrayofstring_from_bytes(GBytes *b)
{
  return (VarArrayofstringRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_arrayofstring_dup_to_gvariant(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 *var_arrayofstring_to_gvariant(VarArrayofstringRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_ARRAYOFSTRING_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_arrayofstring_get_length(VarArrayofstringRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline const char *var_arrayofstring_get_at(VarArrayofstringRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  const char *base = (const char *)v.base;
  g_assert(base[end - 1] == 0);
  return base + start;
}

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

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

  if (length_out)
    *length_out = length;

  return resv;
}

static inline GString *var_arrayofstring_format(VarArrayofstringRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_arrayofstring_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, var_arrayofstring_get_at(v, i));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_arrayofstring_print(VarArrayofstringRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_arrayofstring_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarDeployDataRef var_deploy_data_from_gvariant(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 var_deploy_data_from_bytes(GBytes *b)
{
  return (VarDeployDataRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_deploy_data_dup_to_gvariant(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 *var_deploy_data_to_gvariant(VarDeployDataRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_DEPLOY_DATA_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline const char *var_deploy_data_get_origin(VarDeployDataRef v)
{
  guint offset_size = 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 *var_deploy_data_get_commit(VarDeployDataRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 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 var_deploy_data_get_subpaths(VarDeployDataRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 1);
  guint offset = ((last_end + 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 var_deploy_data_get_installed_size(VarDeployDataRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 2);
  guint offset = ((last_end + 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 var_deploy_data_get_metadata(VarDeployDataRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 2);
  guint offset = ((last_end + 7) & (~(gsize)7)) + 8;
  gsize start = offset;
  gsize end = v.size - offset_size * 3;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarMetadataRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_deploy_data_format(VarDeployDataRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  varGStringAppendString(s, var_deploy_data_get_origin(v));
  g_string_append(s, ", ");
  varGStringAppendString(s, var_deploy_data_get_commit(v));
  g_string_append(s, ", ");
  var_arrayofstring_format(var_deploy_data_get_subpaths(v), s, type_annotate);
  g_string_append(s, ", ");
  g_string_append_printf(s, "%s%" G_GUINT64_FORMAT ", ",
                         type_annotate ? "uint64 " : "",
                         var_deploy_data_get_installed_size(v));
  var_metadata_format(var_deploy_data_get_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_deploy_data_print(VarDeployDataRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_deploy_data_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarRatingsRef var_ratings_from_gvariant(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 var_ratings_from_bytes(GBytes *b)
{
  return (VarRatingsRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_ratings_dup_to_gvariant(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 *var_ratings_to_gvariant(VarRatingsRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_RATINGS_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_ratings_get_length(VarRatingsRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarRatingsEntryRef var_ratings_get_at(VarRatingsRef v, gsize index)
{
  VarRatingsEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarRatingsEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_ratings_entry_get_key(VarRatingsEntryRef v)
{
  guint offset_size = 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 *var_ratings_entry_get_value(VarRatingsEntryRef v)
{
  guint offset_size = 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 - offset_size) - 1] == 0);
  return (const char *)v.base + offset;
}

static inline gboolean var_ratings_lookup(VarRatingsRef v, const char *key, gsize *index_out, const char **out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  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 <= last_end);
    const char *e_key = var_ratings_entry_get_key(e);
    if (strcmp(canonical_key, e_key) == 0)
    {
      if (index_out)
        *index_out = i;
      if (out)
        *out = var_ratings_entry_get_value(e);
      return TRUE;
    }
    start = VAR_REF_ALIGN(end, 1);
  }
  return FALSE;
}

static inline GString *var_ratings_format(VarRatingsRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_ratings_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_RATINGS_TYPESTRING);

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

static inline char *var_ratings_print(VarRatingsRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_ratings_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarContentRatingRef var_content_rating_from_gvariant(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 var_content_rating_from_bytes(GBytes *b)
{
  return (VarContentRatingRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_content_rating_dup_to_gvariant(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 *var_content_rating_to_gvariant(VarContentRatingRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_CONTENT_RATING_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline const char *var_content_rating_get_rating_type(VarContentRatingRef v)
{
  guint offset_size = 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 var_content_rating_get_ratings(VarContentRatingRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 0) & (~(gsize)0)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 1;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarRatingsRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_content_rating_format(VarContentRatingRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  varGStringAppendString(s, var_content_rating_get_rating_type(v));
  g_string_append(s, ", ");
  var_ratings_format(var_content_rating_get_ratings(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_content_rating_print(VarContentRatingRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_content_rating_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarExtraDataSizeRef var_extra_data_size_from_gvariant(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 var_extra_data_size_from_bytes(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 var_extra_data_size_from_data(gconstpointer data, gsize size)
{
  g_assert(size == 16);

  return (VarExtraDataSizeRef){data, size};
}

static inline GVariant *var_extra_data_size_dup_to_gvariant(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 *var_extra_data_size_to_gvariant(VarExtraDataSizeRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_EXTRA_DATA_SIZE_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

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

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

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

static inline GString *var_extra_data_size_format(VarExtraDataSizeRef v, GString *s, gboolean type_annotate)
{
  g_string_append_printf(s, "(%s%" G_GUINT32_FORMAT ", %s%" G_GUINT64_FORMAT ")",
                         type_annotate ? "uint32 " : "",
                         var_extra_data_size_get_n_extra_data(v),
                         type_annotate ? "uint64 " : "",
                         var_extra_data_size_get_total_size(v));
  return s;
}

static inline char *var_extra_data_size_print(VarExtraDataSizeRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_extra_data_size_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarArrayofChecksumRef var_arrayof_checksum_from_gvariant(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 var_arrayof_checksum_from_bytes(GBytes *b)
{
  return (VarArrayofChecksumRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_arrayof_checksum_dup_to_gvariant(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 *var_arrayof_checksum_to_gvariant(VarArrayofChecksumRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_ARRAYOF_CHECKSUM_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_arrayof_checksum_get_length(VarArrayofChecksumRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarChecksumRef var_arrayof_checksum_get_at(VarArrayofChecksumRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  return (VarChecksumRef){((const char *)v.base) + start, end - start};
}

static inline GString *var_arrayof_checksum_format(VarArrayofChecksumRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_arrayof_checksum_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, ", ");
    var_checksum_format(var_arrayof_checksum_get_at(v, i), s, ((i == 0) ? type_annotate : FALSE));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_arrayof_checksum_print(VarArrayofChecksumRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_arrayof_checksum_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarSubsummaryRef var_subsummary_from_gvariant(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 var_subsummary_from_bytes(GBytes *b)
{
  return (VarSubsummaryRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_subsummary_dup_to_gvariant(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 *var_subsummary_to_gvariant(VarSubsummaryRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_SUBSUMMARY_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline VarChecksumRef var_subsummary_get_checksum(VarSubsummaryRef v)
{
  guint offset_size = 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 *var_subsummary_peek_checksum(VarSubsummaryRef v, gsize *len)
{
  VarChecksumRef a = var_subsummary_get_checksum(v);
  if (len != NULL)
    *len = var_checksum_get_length(a);
  return (const guint8 *)a.base;
}

static inline VarArrayofChecksumRef var_subsummary_get_history(VarSubsummaryRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 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 var_subsummary_get_metadata(VarSubsummaryRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 1);
  guint offset = ((last_end + 7) & (~(gsize)7)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 2;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarMetadataRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_subsummary_format(VarSubsummaryRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  var_checksum_format(var_subsummary_get_checksum(v), s, type_annotate);
  g_string_append(s, ", ");
  var_arrayof_checksum_format(var_subsummary_get_history(v), s, type_annotate);
  g_string_append(s, ", ");
  var_metadata_format(var_subsummary_get_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_subsummary_print(VarSubsummaryRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_subsummary_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarSummaryIndexSubsummariesRef var_summary_index_subsummaries_from_gvariant(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 var_summary_index_subsummaries_from_bytes(GBytes *b)
{
  return (VarSummaryIndexSubsummariesRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_summary_index_subsummaries_dup_to_gvariant(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 *var_summary_index_subsummaries_to_gvariant(VarSummaryIndexSubsummariesRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_summary_index_subsummaries_get_length(VarSummaryIndexSubsummariesRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarSummaryIndexSubsummariesEntryRef var_summary_index_subsummaries_get_at(VarSummaryIndexSubsummariesRef v, gsize index)
{
  VarSummaryIndexSubsummariesEntryRef res;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  res = (VarSummaryIndexSubsummariesEntryRef){((const char *)v.base) + start, end - start};
  return res;
}

static inline const char *var_summary_index_subsummaries_entry_get_key(VarSummaryIndexSubsummariesEntryRef v)
{
  guint offset_size = 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 var_summary_index_subsummaries_entry_get_value(VarSummaryIndexSubsummariesEntryRef v)
{
  guint offset_size = 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 - offset_size) - offset};
}

static inline gboolean var_summary_index_subsummaries_lookup(VarSummaryIndexSubsummariesRef v, const char *key, gsize *index_out, VarSubsummaryRef *out)
{
  const char *canonical_key = key;
  if (v.size == 0)
    return FALSE;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  if (last_end > v.size)
    return FALSE;
  gsize offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return FALSE;
  gsize len = offsets_array_size / offset_size;
  gsize start = 0;
  gsize end = len;

  while (start < end)
  {
    gsize mid = (end + start) / 2;
    gsize mid_end = VAR_REF_READ_FRAME_OFFSET(v, len - mid - 1);
    gsize mid_start = mid == 0 ? 0 : VAR_REF_ALIGN(VAR_REF_READ_FRAME_OFFSET(v, len - mid), 8);
    g_assert(mid_start <= mid_end);
    g_assert(mid_end <= last_end);
    VarSummaryIndexSubsummariesEntryRef e = {((const char *)v.base) + mid_start, mid_end - mid_start};
    const char *e_key = var_summary_index_subsummaries_entry_get_key(e);
    gint32 cmp = strcmp(canonical_key, e_key);
    if (cmp == 0)
    {
      if (index_out)
        *index_out = mid;
      if (out)
        *out = var_summary_index_subsummaries_entry_get_value(e);
      return TRUE;
    }
    if (cmp < 0)
      end = mid; /* canonical_key < e_key */
    else
      start = mid + 1; /* canonical_key > e_key */
  }
  return FALSE;
}

static inline GString *var_summary_index_subsummaries_format(VarSummaryIndexSubsummariesRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_summary_index_subsummaries_get_length(v);
  gsize i;

  if (len == 0 && type_annotate)
    g_string_append_printf(s, "@%s ", VAR_SUMMARY_INDEX_SUBSUMMARIES_TYPESTRING);

  g_string_append_c(s, '{');
  for (i = 0; i < len; i++)
  {
    VarSummaryIndexSubsummariesEntryRef entry = var_summary_index_subsummaries_get_at(v, i);
    if (i != 0)
      g_string_append(s, ", ");
    varGStringAppendString(s, var_summary_index_subsummaries_entry_get_key(entry));
    g_string_append(s, ": ");
    var_subsummary_format(var_summary_index_subsummaries_entry_get_value(entry), s, type_annotate);
  }
  g_string_append_c(s, '}');
  return s;
}

static inline char *var_summary_index_subsummaries_print(VarSummaryIndexSubsummariesRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_summary_index_subsummaries_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarSummaryIndexRef var_summary_index_from_gvariant(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 var_summary_index_from_bytes(GBytes *b)
{
  return (VarSummaryIndexRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_summary_index_dup_to_gvariant(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 *var_summary_index_to_gvariant(VarSummaryIndexRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_SUMMARY_INDEX_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline VarSummaryIndexSubsummariesRef var_summary_index_get_subsummaries(VarSummaryIndexRef v)
{
  guint offset_size = 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 var_summary_index_get_metadata(VarSummaryIndexRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 7) & (~(gsize)7)) + 0;
  gsize start = offset;
  gsize end = v.size - offset_size * 1;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarMetadataRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_summary_index_format(VarSummaryIndexRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  var_summary_index_subsummaries_format(var_summary_index_get_subsummaries(v), s, type_annotate);
  g_string_append(s, ", ");
  var_metadata_format(var_summary_index_get_metadata(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_summary_index_print(VarSummaryIndexRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_summary_index_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarObjectListInfoRef var_object_list_info_from_gvariant(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 var_object_list_info_from_bytes(GBytes *b)
{
  return (VarObjectListInfoRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_object_list_info_dup_to_gvariant(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 *var_object_list_info_to_gvariant(VarObjectListInfoRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_OBJECT_LIST_INFO_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gboolean var_object_list_info_get_is_loose(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 var_object_list_info_get_packfiles(VarObjectListInfoRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  guint offset = ((0) & (~(gsize)0)) + 1;
  gsize start = offset;
  gsize end = v.size - offset_size * 0;
  g_assert(start <= end);
  g_assert(end <= v.size);
  return (VarArrayofstringRef){G_STRUCT_MEMBER_P(v.base, start), end - start};
}

static inline GString *var_object_list_info_format(VarObjectListInfoRef v, GString *s, gboolean type_annotate)
{
  g_string_append_printf(s, "(%s, ",
                         (var_object_list_info_get_is_loose(v)) ? "true" : "false");
  var_arrayofstring_format(var_object_list_info_get_packfiles(v), s, type_annotate);
  g_string_append(s, ")");
  return s;
}

static inline char *var_object_list_info_print(VarObjectListInfoRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_object_list_info_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarObjectNameRef var_object_name_from_gvariant(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 var_object_name_from_bytes(GBytes *b)
{
  return (VarObjectNameRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_object_name_dup_to_gvariant(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 *var_object_name_to_gvariant(VarObjectNameRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_OBJECT_NAME_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline const char *var_object_name_get_checksum(VarObjectNameRef v)
{
  guint offset_size = 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 var_object_name_get_objtype(VarObjectNameRef v)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  guint offset = ((last_end + 3) & (~(gsize)3)) + 0;
  g_assert(offset + 4 <= v.size);
  return (guint32)G_STRUCT_MEMBER(guint32, v.base, offset);
}

static inline GString *var_object_name_format(VarObjectNameRef v, GString *s, gboolean type_annotate)
{
  g_string_append(s, "(");
  varGStringAppendString(s, var_object_name_get_checksum(v));
  g_string_append(s, ", ");
  g_string_append_printf(s, "%s%" G_GUINT32_FORMAT ")",
                         type_annotate ? "uint32 " : "",
                         var_object_name_get_objtype(v));
  return s;
}

static inline char *var_object_name_print(VarObjectNameRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_object_name_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}

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

static inline VarObjectNamesRef var_object_names_from_gvariant(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 var_object_names_from_bytes(GBytes *b)
{
  return (VarObjectNamesRef){g_bytes_get_data(b, NULL), g_bytes_get_size(b)};
}

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

static inline GVariant *var_object_names_dup_to_gvariant(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 *var_object_names_to_gvariant(VarObjectNamesRef v, GDestroyNotify notify, gpointer user_data)
{
  return g_variant_new_from_data(VAR_OBJECT_NAMES_TYPEFORMAT, v.base, v.size, TRUE, notify, user_data);
}

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

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

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

static inline gsize var_object_names_get_length(VarObjectNamesRef v)
{
  if (v.size == 0)
    return 0;
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize offsets_array_size;
  if (last_end > v.size)
    return 0;
  offsets_array_size = v.size - last_end;
  if (offsets_array_size % offset_size != 0)
    return 0;
  gsize length = offsets_array_size / offset_size;
  return length;
}

static inline VarObjectNameRef var_object_names_get_at(VarObjectNamesRef v, gsize index)
{
  guint offset_size = getVarRefOffsetSize(v.size);
  gsize last_end = VAR_REF_READ_FRAME_OFFSET(v, 0);
  gsize len = (v.size - last_end) / offset_size;
  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 <= last_end);
  return (VarObjectNameRef){((const char *)v.base) + start, end - start};
}

static inline GString *var_object_names_format(VarObjectNamesRef v, GString *s, gboolean type_annotate)
{
  gsize len = var_object_names_get_length(v);
  gsize i;
  if (len == 0 && type_annotate)
    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, ", ");
    var_object_name_format(var_object_names_get_at(v, i), s, ((i == 0) ? type_annotate : FALSE));
  }
  g_string_append_c(s, ']');
  return s;
}

static inline char *var_object_names_print(VarObjectNamesRef v, gboolean type_annotate)
{
  GString *s = g_string_new("");
  var_object_names_format(v, s, type_annotate);
  return g_string_free(s, FALSE);
}


#endif
