typedef struct {
uint32_t first_rank;
uint32_t serialised[MAX_QUERY_TERMS * 2 + 3];
} index_query_t;
typedef struct {
int32_t continuation;
uint8_t count;
doc_id_t documents[MAX_RESULTS];
} results_t;
uint32_t min(uint32_t a, uint32_t b) {
return a < b ? a : b;
}
WASM_EXPORT index_query_t* index_query_init(void) {
return malloc(sizeof(index_query_t));
}
WASM_EXPORT byte* index_alloc_serialised(size_t size) {
return malloc(size);
}
inline roaring_bitmap_t* index_deserialise_and_combine(roaring_bitmap_t** deserialised_holding, uint32_t* mode_query_data, size_t* mode_query_data_next) {
size_t bitmaps_to_combine_count = 0;
while (mode_query_data[*mode_query_data_next]) {
size_t serialised_size = mode_query_data[*mode_query_data_next];
char const* serialised = (char const*) mode_query_data[*mode_query_data_next + 1];
roaring_bitmap_t* bitmap = roaring_bitmap_portable_deserialize_safe(serialised, serialised_size);
deserialised_holding[bitmaps_to_combine_count] = bitmap;
bitmaps_to_combine_count++;
*mode_query_data_next += 2;
}
(*mode_query_data_next)++;
if (bitmaps_to_combine_count) {
roaring_bitmap_t* combined = roaring_bitmap_or_many(bitmaps_to_combine_count, (roaring_bitmap_t const**) deserialised_holding);
return combined;
}
return NULL;
}
WASM_EXPORT results_t* index_query(index_query_t* query) {
roaring_bitmap_t* result_bitmap = NULL;
size_t i = 0;
while (query->serialised[i]) {
size_t serialised_size = query->serialised[i];
char const* serialised = (char const*) query->serialised[i + 1];
roaring_bitmap_t* bitmap = roaring_bitmap_portable_deserialize_safe(serialised, serialised_size);
if (result_bitmap == NULL) result_bitmap = bitmap;
else roaring_bitmap_and_inplace(result_bitmap, bitmap);
i += 2;
}
i++;
roaring_bitmap_t* contain_bitmaps_combined = index_deserialise_and_combine((roaring_bitmap_t**) &query->serialised[i], query->serialised, &i);
if (contain_bitmaps_combined != NULL) {
if (result_bitmap == NULL) result_bitmap = contain_bitmaps_combined;
else roaring_bitmap_and_inplace(result_bitmap, contain_bitmaps_combined);
}
roaring_bitmap_t* exclude_bitmaps_combined = index_deserialise_and_combine((roaring_bitmap_t**) &query->serialised[i], query->serialised, &i);
if (exclude_bitmaps_combined != NULL) {
if (result_bitmap == NULL) result_bitmap = exclude_bitmaps_combined;
else roaring_bitmap_andnot_inplace(result_bitmap, exclude_bitmaps_combined);
}
if (result_bitmap == NULL) {
return NULL;
}
uint64_t doc_count = roaring_bitmap_get_cardinality(result_bitmap);
results_t* results = malloc(sizeof(results_t));
uint32_t first_rank = query->first_rank;
if (first_rank >= doc_count) {
results->continuation = -1;
results->count = 0;
} else {
uint32_t last_rank = min(doc_count - 1, first_rank + MAX_RESULTS - 1);
uint32_t count = last_rank + 1 - first_rank;
roaring_bitmap_range_uint32_array(result_bitmap, first_rank, count, results->documents);
results->continuation = last_rank == doc_count - 1 ? -1 : last_rank + 1;
results->count = count;
}
return results;
}