All files / json-hash/src hash.ts

98.38% Statements 61/62
100% Branches 14/14
100% Functions 6/6
97.95% Lines 48/49

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 711x     1x 1x   1x 1x 1x 1x 1x 1x 1x     1x 120034x     1x 6695x 6695x 6695x 6695x 57191x 6695x     1x 4x 4x 4x 4x 12x 4x     1x 106640x   102520x   2091x 2091x   1473x 1230x 520x 520x 1815x 520x   710x 706x 706x 706x 706x 4604x 4604x 4604x   706x     556x         100221x  
import {sort} from '@jsonjoy.com/util/lib/sort/insertion';
import type {PackValue} from '@jsonjoy.com/json-pack/lib/types';
 
export enum CONST {
  START_STATE = 5381,
 
  NULL = 982452847,
  TRUE = 982453247,
  FALSE = 982454243,
  ARRAY = 982452259,
  STRING = 982453601,
  OBJECT = 982454533,
  BINARY = 982454837,
}
 
export const updateNum = (state: number, num: number): number => {
  return (state << 5) + state + num;
};
 
export const updateStr = (state: number, str: string): number => {
  const length = str.length;
  state = updateNum(state, CONST.STRING);
  state = updateNum(state, length);
  let i = length;
  while (i) state = (state << 5) + state + str.charCodeAt(--i);
  return state;
};
 
export const updateBin = (state: number, bin: Uint8Array): number => {
  const length = bin.length;
  state = updateNum(state, CONST.BINARY);
  state = updateNum(state, length);
  let i = length;
  while (i) state = (state << 5) + state + bin[--i];
  return state;
};
 
export const updateJson = (state: number, json: unknown): number => {
  switch (typeof json) {
    case 'number':
      return updateNum(state, json);
    case 'string':
      state = updateNum(state, CONST.STRING);
      return updateStr(state, json);
    case 'object': {
      if (json === null) return updateNum(state, CONST.NULL);
      if (Array.isArray(json)) {
        const length = json.length;
        state = updateNum(state, CONST.ARRAY);
        for (let i = 0; i < length; i++) state = updateJson(state, json[i]);
        return state;
      }
      if (json instanceof Uint8Array) return updateBin(state, json);
      state = updateNum(state, CONST.OBJECT);
      const keys = sort(Object.keys(json as object));
      const length = keys.length;
      for (let i = 0; i < length; i++) {
        const key = keys[i];
        state = updateStr(state, key);
        state = updateJson(state, (json as any)[key]);
      }
      return state;
    }
    case 'boolean':
      return updateNum(state, json ? CONST.TRUE : CONST.FALSE);
  }
  return state;
};
 
export const hash = (json: PackValue) => updateJson(CONST.START_STATE, json) >>> 0;