All files / json-pack/src/util DecompressionTable.ts

70.17% Statements 40/57
53.84% Branches 7/13
66.66% Functions 4/6
70.58% Lines 36/51

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 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 901x   1x   1x 2x     2x 2x 2x 2x 2x 2x 2x 2x   2x 8x 8x 6x 6x 6x   2x       12x       22x   22x       12x   9x     3x 3x 3x   1x 1x 3x 1x     2x 2x 2x 8x 2x                                                                
import {JsonPackExtension} from '../JsonPackExtension';
 
const isSafeInteger = Number.isSafeInteger;
 
export class DecompressionTable {
  protected readonly table: unknown[] = [];
 
  public importTable(rleTable: unknown[]) {
    const length = rleTable.length;
    Iif (!length) return;
    const table = this.table;
    const first = rleTable[0];
    table.push(first);
    let i = 1;
    if (isSafeInteger(first)) {
      let prev: number = <number>first;
      let value: unknown;
      while (i < length) {
        value = rleTable[i];
        if (isSafeInteger(value)) {
          prev = prev + <number>value;
          table.push(prev);
          i++;
        } else {
          break;
        }
      }
    }
    while (i < length) table.push(rleTable[i++]);
  }
 
  public getLiteral(index: number): unknown {
    const table = this.table;
    // if (index < 0 || index >= table.length) throw new Error('OUT_OF_BOUNDS');
    return table[index];
  }
 
  public decompress(value: unknown): unknown {
    switch (typeof value) {
      case 'number': {
        return this.getLiteral(value);
      }
      case 'object': {
        Iif (!value) return null;
        const construct = value.constructor;
        switch (construct) {
          case Object: {
            const obj = value as Record<string, unknown>;
            const newObj: Record<string, unknown> = {};
            for (const key in obj) newObj[String(this.getLiteral(Number(key)))] = this.decompress(obj[key]);
            return newObj;
          }
          case Array: {
            const arr = value as unknown[];
            const newArr: unknown[] = [];
            const len = arr.length;
            for (let i = 0; i < len; i++) newArr.push(this.decompress(arr[i]));
            return newArr;
          }
          case Map: {
            const map = value as Map<unknown, unknown>;
            const newMap = new Map<unknown, unknown>();
            map.forEach((value, key) => {
              newMap.set(this.decompress(key), this.decompress(value));
            });
            return newMap;
          }
          case Set: {
            const set = value as Set<unknown>;
            const newSet = new Set<unknown>();
            set.forEach((value) => {
              newSet.add(this.decompress(value));
            });
            break;
          }
          case JsonPackExtension: {
            const ext = value as JsonPackExtension;
            const newExt = new JsonPackExtension(Number(this.getLiteral(ext.tag)), this.decompress(ext.val));
            return newExt;
          }
        }
        return value;
      }
      default: {
        return value;
      }
    }
  }
}