static int32_t parseGeneric(const struct Reader* reader,
                            const struct Allocator* allocator,
                            Object** output)
{
    int ret = 0;
    char firstChar;

    for (;;) {
        ret = reader->read(&firstChar, 0, reader);
        switch (firstChar) {
            case ' ':
            case '\r':
            case '\n':
            case '\t':
                reader->skip(1, reader);
                continue;

            case '/':;
                if ((ret = parseComment(reader)) != 0) {
                    return ret;
                }
                continue;

            default:
                break;
        }
        if (ret) {
            printf("Unexpected end of input\n");
            return OUT_OF_CONTENT_TO_READ;
        }
        break;
    }

    Object* out = allocator->malloc(sizeof(Object), allocator);

    switch (firstChar) {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':;
            // int64_t. Int is special because it is not a pointer but a int64_t.
            int64_t bint;
            ret = parseint64_t(reader, &bint);
            out->type = Object_INTEGER;
            out->as.number = bint;
            break;

        case '[':;
            // List.
            List* list = allocator->calloc(sizeof(List), 1, allocator);
            ret = parseList(reader, allocator, list);
            out->type = Object_LIST;
            out->as.list = list;
            break;

        case '{':;
            // Dictionary
            Dict* dict = allocator->calloc(sizeof(Dict), 1, allocator);
            ret = parseDictionary(reader, allocator, dict);
            out->type = Object_DICT;
            out->as.dictionary = dict;
            break;

        case '"':;
            // String
            String* string = NULL;
            ret = parseString(reader, allocator, &string);
            out->type = Object_STRING;
            out->as.string = string;
            break;

        default:
            printf("While looking for something to parse: "
                   "expected one of 0 1 2 3 4 5 6 7 8 9 [ { \", found '%c'\n", firstChar);
            return UNPARSABLE;
    }

    if (ret != 0) {
        // Something went wrong while parsing.
        return ret;
    }

    *output = out;
    return 0;
}
/**
 * Parse an unknown data type.
 * This is not exposed to the world because it is expected that one would
 * know what type they are parsing to begin with. This is used by parseDictionary
 * and parseList to grab pieces of data which are of unknown type and parse them.
 *
 * @param reader the reader to get the stream of data from.
 * @param allocator the means of storing the parsed data.
 * @param output a pointer which will be pointed to the output.
 */
static int32_t parseGeneric(const struct Reader* reader,
                            const struct Allocator* allocator,
                            Object** output)
{
    #define OUT_OF_CONTENT_TO_READ -2
    #define UNPARSABLE -3

    int ret;
    char firstChar;
    ret = reader->read(&firstChar, 0, reader);
    if (ret != 0) {
        return OUT_OF_CONTENT_TO_READ;
    }

    Object* out = Allocator_malloc(allocator, sizeof(Object));

    if (firstChar <= '9' && firstChar >= '0') {
        /* It's a string! */
        String* string = NULL;
        ret = parseString(reader, allocator, &string);
        out->type = Object_STRING;
        out->as.string = string;
    } else {
        switch (firstChar) {
            case 'i':;
                /* int64_t. Int is special because it is not a pointer but a int64_t. */
                int64_t bint = 0;
                ret = parseint64_t(reader, &bint);
                out->type = Object_INTEGER;
                out->as.number = bint;
                break;
            case 'l':;
                /* List. */
                List* list = Allocator_calloc(allocator, sizeof(List), 1);
                ret = parseList(reader, allocator, list);
                out->type = Object_LIST;
                out->as.list = list;
                break;
            case 'd':;
                /* Dictionary. */
                Dict* dict = Allocator_calloc(allocator, sizeof(Dict), 1);
                ret = parseDictionary(reader, allocator, dict);
                out->type = Object_DICT;
                out->as.dictionary = dict;
                break;
            default:
                return UNPARSABLE;
        }
    }

    if (ret != 0) {
        /* Something went wrong while parsing. */
        return ret;
    }

    *output = out;
    return 0;

    #undef OUT_OF_CONTENT_TO_READ
    #undef UNPARSABLE
}