"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hash = exports.updateJson = exports.updateBin = exports.updateStr = exports.updateNum = exports.CONST = void 0;
const insertion_1 = require("@jsonjoy.com/util/lib/sort/insertion");
var CONST;
(function (CONST) {
    CONST[CONST["START_STATE"] = 5381] = "START_STATE";
    CONST[CONST["NULL"] = 982452847] = "NULL";
    CONST[CONST["TRUE"] = 982453247] = "TRUE";
    CONST[CONST["FALSE"] = 982454243] = "FALSE";
    CONST[CONST["ARRAY"] = 982452259] = "ARRAY";
    CONST[CONST["STRING"] = 982453601] = "STRING";
    CONST[CONST["OBJECT"] = 982454533] = "OBJECT";
    CONST[CONST["BINARY"] = 982454837] = "BINARY";
})(CONST || (exports.CONST = CONST = {}));
const updateNum = (state, num) => {
    return (state << 5) + state + num;
};
exports.updateNum = updateNum;
const updateStr = (state, str) => {
    const length = str.length;
    state = (0, exports.updateNum)(state, CONST.STRING);
    state = (0, exports.updateNum)(state, length);
    let i = length;
    while (i)
        state = (state << 5) + state + str.charCodeAt(--i);
    return state;
};
exports.updateStr = updateStr;
const updateBin = (state, bin) => {
    const length = bin.length;
    state = (0, exports.updateNum)(state, CONST.BINARY);
    state = (0, exports.updateNum)(state, length);
    let i = length;
    while (i)
        state = (state << 5) + state + bin[--i];
    return state;
};
exports.updateBin = updateBin;
const updateJson = (state, json) => {
    switch (typeof json) {
        case 'number':
            return (0, exports.updateNum)(state, json);
        case 'string':
            state = (0, exports.updateNum)(state, CONST.STRING);
            return (0, exports.updateStr)(state, json);
        case 'object': {
            if (json === null)
                return (0, exports.updateNum)(state, CONST.NULL);
            if (Array.isArray(json)) {
                const length = json.length;
                state = (0, exports.updateNum)(state, CONST.ARRAY);
                for (let i = 0; i < length; i++)
                    state = (0, exports.updateJson)(state, json[i]);
                return state;
            }
            if (json instanceof Uint8Array)
                return (0, exports.updateBin)(state, json);
            state = (0, exports.updateNum)(state, CONST.OBJECT);
            const keys = (0, insertion_1.sort)(Object.keys(json));
            const length = keys.length;
            for (let i = 0; i < length; i++) {
                const key = keys[i];
                state = (0, exports.updateStr)(state, key);
                state = (0, exports.updateJson)(state, json[key]);
            }
            return state;
        }
        case 'boolean':
            return (0, exports.updateNum)(state, json ? CONST.TRUE : CONST.FALSE);
    }
    return state;
};
exports.updateJson = updateJson;
const hash = (json) => (0, exports.updateJson)(CONST.START_STATE, json) >>> 0;
exports.hash = hash;
//# sourceMappingURL=hash.js.map