#ifndef RAY_ENCIDX_H
#define RAY_ENCIDX_H
#include <stddef.h>
#include <stdint.h>
#define RAY_ENC_IDX_ROOT_BYTES 80
#define RAY_ENC_IDX_FIRST_CHILD 96
#define RAY_ENC_IDX_NAME_MAX 255
#define RAY_ENC_IDX_BLOOM_K_MAX 3
typedef struct {
int8_t parent_type;
uint8_t rsv[7];
int64_t built_for_len;
uint8_t kind_area[64];
} ray_enc_idx_root_t;
typedef struct {
int64_t table, gkeys, offs, rows;
uint64_t mask;
int64_t n_keys, n_groups, order_name;
} ray_enc_idx_hash_t;
typedef struct { int64_t perm; } ray_enc_idx_sort_t;
typedef struct {
int64_t bits;
uint64_t m_mask;
uint32_t k;
uint32_t rsv;
int64_t n_keys;
} ray_enc_idx_bloom_t;
typedef struct {
int64_t keys, starts, lens, n_parts, order_name;
} ray_enc_idx_part_t;
typedef struct {
int64_t codes, first_occ, offs, bytes, n_distinct;
uint64_t bytes_len;
} ray_enc_idx_dict_t;
#define ENCIDX_OFF(T, f, o) _Static_assert(offsetof(T, f) == (o), #T "." #f " offset")
_Static_assert(sizeof(ray_enc_idx_root_t) == RAY_ENC_IDX_ROOT_BYTES, "wire root is 80 bytes");
_Static_assert(RAY_ENC_IDX_FIRST_CHILD == ((RAY_ENC_IDX_ROOT_BYTES + 31) & ~31),
"children start at pad32 of the root");
ENCIDX_OFF(ray_enc_idx_root_t, parent_type, 0);
ENCIDX_OFF(ray_enc_idx_root_t, rsv, 1);
ENCIDX_OFF(ray_enc_idx_root_t, built_for_len, 8);
ENCIDX_OFF(ray_enc_idx_root_t, kind_area, 16);
_Static_assert(sizeof(((ray_enc_idx_root_t*)0)->kind_area) == 64, "kind area is 64 bytes");
_Static_assert(sizeof(ray_enc_idx_hash_t) == 64, "HASH fills the kind area");
ENCIDX_OFF(ray_enc_idx_hash_t, table, 0);
ENCIDX_OFF(ray_enc_idx_hash_t, gkeys, 8);
ENCIDX_OFF(ray_enc_idx_hash_t, offs, 16);
ENCIDX_OFF(ray_enc_idx_hash_t, rows, 24);
ENCIDX_OFF(ray_enc_idx_hash_t, mask, 32);
ENCIDX_OFF(ray_enc_idx_hash_t, n_keys, 40);
ENCIDX_OFF(ray_enc_idx_hash_t, n_groups, 48);
ENCIDX_OFF(ray_enc_idx_hash_t, order_name, 56);
_Static_assert(sizeof(ray_enc_idx_sort_t) == 8, "SORT kind fields");
ENCIDX_OFF(ray_enc_idx_sort_t, perm, 0);
_Static_assert(sizeof(ray_enc_idx_bloom_t) == 32, "BLOOM kind fields");
ENCIDX_OFF(ray_enc_idx_bloom_t, bits, 0);
ENCIDX_OFF(ray_enc_idx_bloom_t, m_mask, 8);
ENCIDX_OFF(ray_enc_idx_bloom_t, k, 16);
ENCIDX_OFF(ray_enc_idx_bloom_t, rsv, 20);
ENCIDX_OFF(ray_enc_idx_bloom_t, n_keys, 24);
_Static_assert(sizeof(ray_enc_idx_part_t) == 40, "PART kind fields");
ENCIDX_OFF(ray_enc_idx_part_t, keys, 0);
ENCIDX_OFF(ray_enc_idx_part_t, starts, 8);
ENCIDX_OFF(ray_enc_idx_part_t, lens, 16);
ENCIDX_OFF(ray_enc_idx_part_t, n_parts, 24);
ENCIDX_OFF(ray_enc_idx_part_t, order_name, 32);
_Static_assert(sizeof(ray_enc_idx_dict_t) == 48, "DICT kind fields");
ENCIDX_OFF(ray_enc_idx_dict_t, codes, 0);
ENCIDX_OFF(ray_enc_idx_dict_t, first_occ, 8);
ENCIDX_OFF(ray_enc_idx_dict_t, offs, 16);
ENCIDX_OFF(ray_enc_idx_dict_t, bytes, 24);
ENCIDX_OFF(ray_enc_idx_dict_t, n_distinct, 32);
ENCIDX_OFF(ray_enc_idx_dict_t, bytes_len, 40);
#define ENCIDX_FITS(T) _Static_assert(sizeof(T) <= sizeof(((ray_enc_idx_root_t*)0)->kind_area), \
#T " fits in the kind area")
ENCIDX_FITS(ray_enc_idx_hash_t);
ENCIDX_FITS(ray_enc_idx_sort_t);
ENCIDX_FITS(ray_enc_idx_bloom_t);
ENCIDX_FITS(ray_enc_idx_part_t);
ENCIDX_FITS(ray_enc_idx_dict_t);
static inline int ray_enc_idx_kind_has_region(uint8_t k) {
return k == 1 || k == 2 || k == 4 || k == 6;
}
static inline int ray_enc_idx_kind_in_file(uint8_t k) {
return ray_enc_idx_kind_has_region(k) || k == 7;
}
#ifndef RAY_ENC_IDX_WIRE_ONLY
#include <stdio.h>
#include <rayforce.h>
typedef struct {
const ray_t* root;
int8_t parent_type;
uint8_t attrs;
int64_t len;
const char* order_name;
uint32_t order_len;
} ray_enc_idx_src_t;
ray_t* ray_enc_index_write(FILE* f, const ray_enc_idx_src_t* s, uint64_t* bytes);
typedef struct {
uint8_t kind;
int8_t parent_type;
uint8_t attrs;
int64_t len;
const uint8_t* base;
uint64_t size;
ray_enc_idx_hash_t hash;
ray_enc_idx_sort_t sort;
ray_enc_idx_bloom_t bloom;
ray_enc_idx_part_t part;
const char* order_name;
uint32_t order_len;
} ray_enc_idx_view_t;
void ray_enc_index_view(const uint8_t* region, uint64_t size, uint8_t kind,
int8_t parent_type, uint8_t attrs, int64_t len, ray_enc_idx_view_t* out);
ray_t* ray_enc_index_parse(const ray_enc_idx_view_t* v, ray_t* vec, ray_t** root_out);
int64_t ray_enc_index_trusted_order(const ray_t* root);
typedef struct {
int64_t len, n_distinct;
const int32_t* codes;
const int32_t* first_occ;
const uint64_t* offs;
const char* bytes;
uint64_t bytes_len;
} ray_enc_dict_src_t;
typedef struct {
int64_t len, n_distinct;
const int32_t* codes;
const int32_t* first_occ;
const uint64_t* offs;
const uint8_t* bytes;
} ray_enc_dict_view_t;
ray_t* ray_enc_dict_write(FILE* f, const ray_enc_dict_src_t* s, uint64_t* bytes);
void ray_enc_dict_parse(const uint8_t* region, ray_enc_dict_view_t* out);
#endif
#endif