#pragma once

#include <stdio.h>
#include <stdint.h>
/*
typedef struct {                                                           \
    LEN_TYPE len;                                                          \
    ITEM_TYPE items[];                                                     \
} __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_;                       \
  */                                                                       \

#define LENGTH_PREFIX_ARRAY_TYPE(LEN_TYPE, ITEM_TYPE)                           \
    __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_

#define LENGTH_PREFIX_ARRAY_CALL(LEN_TYPE, ITEM_TYPE, METHOD)              \
    length_prefix_##LEN_TYPE##_array_##ITEM_TYPE##_ ## METHOD

#define PRESCAN_LENGTH_PREFIX_CALL(LEN, ITEM, METHOD) \
    LENGTH_PREFIX_ARRAY_CALL(LEN, ITEM, METHOD)

#define DEFINE_LENGTH_PREFIX_ARRAY(LEN_TYPE, ITEM_TYPE)                        \
    static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, clear)    \
       (__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data) {                      \
        data->len = 0;                                                         \
    }                                                                          \
                                                                               \
    static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, push)     \
       (__Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *data,                        \
        ITEM_TYPE value) {                                                     \
        data->items[data->len++] = value;                                      \
    }                                                                          \
                                                                               \
    static inline int PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, reverse)   \
      ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * restrict src,         \
        __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ *restrict dst) {              \
        for (LEN_TYPE i = 0; i < src->len; i++) {                              \
            dst->items[i] = src->items[src->len - 1 - i];                      \
        }                                                                      \
        dst->len = src->len;                                                   \
        return 0;                                                              \
    }                                                                          \
                                                                               \
    static inline void PRESCAN_LENGTH_PREFIX_CALL(LEN_TYPE, ITEM_TYPE, dump)     \
      ( __Seq__LengthPrefix_##LEN_TYPE##___##ITEM_TYPE##_ const * data) {               \
        printf("Length: %llu\n", (unsigned long long) data->len);              \
        for (LEN_TYPE i = 0; i < data->len; i++) {                             \
            printf("%llu ", (unsigned long long) data->items[i]);              \
        }                                                                      \
        printf("\n");                                                          \
    }