#include "array.h"
#include "crash.h"
#include <string.h>
#include <stdlib.h>

#define CRASH_IF_OOB(array, len) {\
    if (len > array->length)\
        crash(\
            "Array does not have expected length: %ld > %ld\n",\
            len,\
            array->length);\
}

void* array_at(const array_t* array, size_t idx) {
    CRASH_IF_OOB(array, idx + 1);
    return (char*)array->__data + idx*array->elemsz;
}

array_t array_slice(const array_t* array, size_t start, size_t length) {
    CRASH_IF_OOB(array, start + length);
    return (array_t) {
        .length = length,
        .__data = (char*)array->__data + start * array->elemsz
    };
}

array_t array_heap_alloc(size_t length, size_t elemsz) {
    void* data_ptr = calloc(length, elemsz);
    if (data_ptr == NULL)
        crash(
            "Out of memory allocating %ld elements of size %ld\n",
            length,
            elemsz);

    return (array_t) {
        .length = length,
        .elemsz = elemsz,
        .__data = data_ptr,
    };
}

void array_heap_destroy(array_t array) {
    free(array.__data);
}
