#ifndef MOLECULE_READER_H
#define MOLECULE_READER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#ifndef MOLECULE_API_DECORATOR
#define __DEFINE_MOLECULE_API_DECORATOR
#define MOLECULE_API_DECORATOR
#endif
#define MOLECULE_API_VERSION 7000
#define MOLECULEC_VERSION_MIN 5000
#if MOLECULE_API_VERSION < MOLECULE_API_VERSION_MIN
#error This file was generated by a newer version of moleculec which is \
incompatible with current headers in use. Please update the headers.
#endif
#if MOLECULEC_VERSION < MOLECULEC_VERSION_MIN
#error This file was generated by an older version of moleculec which is \
incompatible with current headers in use. Please regenerate this file \
with a newer version of moleculec.
#endif
#define is_le() \
((union { \
uint16_t i; \
unsigned char c; \
}){.i = 1} \
.c)
typedef uint32_t mol_num_t;
typedef uint8_t mol_errno;
#define MolNum UINT32_C
#define MOL_NUM_T_SIZE 4
typedef struct {
uint8_t *ptr; mol_num_t size; } mol_seg_t;
typedef struct {
mol_num_t item_id; mol_seg_t seg; } mol_union_t;
typedef struct {
mol_errno errno; mol_seg_t seg; } mol_seg_res_t;
#define MOL_OK 0x00
#define MOL_ERR 0xff
#define MOL_ERR_TOTAL_SIZE 0x01
#define MOL_ERR_HEADER 0x02
#define MOL_ERR_OFFSET 0x03
#define MOL_ERR_UNKNOWN_ITEM 0x04
#define MOL_ERR_INDEX_OUT_OF_BOUNDS 0x05
#define MOL_ERR_FIELD_COUNT 0x06
#define MOL_ERR_DATA 0x07
MOLECULE_API_DECORATOR mol_num_t mol_unpack_number(const uint8_t *src) {
uint32_t output = 0;
uint8_t *dst = (uint8_t *)&output;
if (is_le()) {
dst[3] = src[3];
dst[2] = src[2];
dst[1] = src[1];
dst[0] = src[0];
} else {
dst[3] = src[0];
dst[2] = src[1];
dst[1] = src[2];
dst[0] = src[3];
}
return output;
}
MOLECULE_API_DECORATOR mol_errno mol_verify_fixed_size(const mol_seg_t *input,
mol_num_t total_size) {
return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE;
}
MOLECULE_API_DECORATOR mol_errno mol_fixvec_verify(const mol_seg_t *input,
mol_num_t item_size) {
if (input->size < MOL_NUM_T_SIZE) {
return MOL_ERR_HEADER;
}
mol_num_t item_count = mol_unpack_number(input->ptr);
if (item_count == 0) {
return input->size == MOL_NUM_T_SIZE ? MOL_OK : MOL_ERR_TOTAL_SIZE;
}
mol_num_t total_size = MOL_NUM_T_SIZE + item_size * item_count;
return input->size == total_size ? MOL_OK : MOL_ERR_TOTAL_SIZE;
}
MOLECULE_API_DECORATOR bool mol_option_is_none(const mol_seg_t *input) {
return input->size == 0;
}
MOLECULE_API_DECORATOR mol_union_t mol_union_unpack(const mol_seg_t *input) {
mol_union_t ret;
ret.item_id = mol_unpack_number(input->ptr);
ret.seg.ptr = input->ptr + MOL_NUM_T_SIZE;
ret.seg.size = input->size - MOL_NUM_T_SIZE;
return ret;
}
MOLECULE_API_DECORATOR mol_num_t mol_fixvec_length(const mol_seg_t *input) {
return mol_unpack_number(input->ptr);
}
MOLECULE_API_DECORATOR mol_num_t mol_dynvec_length(const mol_seg_t *input) {
if (input->size == MOL_NUM_T_SIZE) {
return 0;
} else {
return (mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1;
}
}
MOLECULE_API_DECORATOR mol_num_t
mol_table_actual_field_count(const mol_seg_t *input) {
return mol_dynvec_length(input);
}
MOLECULE_API_DECORATOR bool mol_table_has_extra_fields(const mol_seg_t *input,
mol_num_t field_count) {
return mol_table_actual_field_count(input) > field_count;
}
MOLECULE_API_DECORATOR mol_seg_t mol_slice_by_offset(const mol_seg_t *input,
mol_num_t offset,
mol_num_t size) {
mol_seg_t seg;
seg.ptr = input->ptr + offset;
seg.size = size;
return seg;
}
MOLECULE_API_DECORATOR mol_seg_res_t mol_fixvec_slice_by_index(
const mol_seg_t *input, mol_num_t item_size, mol_num_t item_index) {
mol_seg_res_t res;
mol_num_t item_count = mol_unpack_number(input->ptr);
if (item_index >= item_count) {
res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS;
} else {
res.errno = MOL_OK;
res.seg.ptr = input->ptr + MOL_NUM_T_SIZE + item_size * item_index;
res.seg.size = item_size;
}
return res;
}
MOLECULE_API_DECORATOR mol_seg_res_t
mol_dynvec_slice_by_index(const mol_seg_t *input, mol_num_t item_index) {
mol_seg_res_t res;
mol_num_t total_size = mol_unpack_number(input->ptr);
if (total_size == MOL_NUM_T_SIZE) {
res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS;
} else {
mol_num_t item_count =
(mol_unpack_number(input->ptr + MOL_NUM_T_SIZE) / 4) - 1;
if (item_index >= item_count) {
res.errno = MOL_ERR_INDEX_OUT_OF_BOUNDS;
} else {
mol_num_t item_start =
mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 1));
if (item_index + 1 == item_count) {
res.errno = MOL_OK;
res.seg.ptr = input->ptr + item_start;
res.seg.size = total_size - item_start;
} else {
mol_num_t item_end =
mol_unpack_number(input->ptr + MOL_NUM_T_SIZE * (item_index + 2));
res.errno = MOL_OK;
res.seg.ptr = input->ptr + item_start;
res.seg.size = item_end - item_start;
}
}
}
return res;
}
MOLECULE_API_DECORATOR mol_seg_t
mol_table_slice_by_index(const mol_seg_t *input, mol_num_t field_index) {
mol_seg_res_t res = mol_dynvec_slice_by_index(input, field_index);
return res.seg;
}
MOLECULE_API_DECORATOR mol_seg_t
mol_fixvec_slice_raw_bytes(const mol_seg_t *input) {
mol_seg_t seg;
seg.ptr = input->ptr + MOL_NUM_T_SIZE;
seg.size = mol_unpack_number(input->ptr);
return seg;
}
MOLECULE_API_DECORATOR bool mol_contained_by(const mol_seg_t *part,
const mol_seg_t *total) {
if (part->ptr < total->ptr) {
return MOL_ERR_OFFSET;
}
if ((part->ptr + part->size) > (total->ptr + total->size)) {
return MOL_ERR_OFFSET;
}
return MOL_OK;
}
#undef is_le
#ifdef __DEFINE_MOLECULE_API_DECORATOR
#undef MOLECULE_API_DECORATOR
#undef __DEFINE_MOLECULE_API_DECORATOR
#endif
#ifdef __cplusplus
}
#endif
#endif