All files / json-pack/src/ubjson UbjsonDecoder.ts

72.72% Statements 56/77
71.42% Branches 25/35
75% Functions 3/4
72% Lines 54/75

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 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 1253x 3x       3x 3x     117x 117x                 74780x 74780x 74780x   1330x   1462x   1233x   37979x   227x   378x 378x 378x     249x 249x 249x               12048x 12048x 12048x     10x 10x 10x     11482x   9x   3491x 3491x 3491x 18x 18x 18x   3473x 3473x       3473x 3473x       3473x       3473x                                 3473x 9688x 3473x 3473x       4880x 4880x 4880x 26198x 26198x 26198x 26197x   4879x 4879x     2x          
import {Reader} from '@jsonjoy.com/buffers/lib/Reader';
import {JsonPackExtension} from '../JsonPackExtension';
import {ERROR} from '../cbor/constants';
import type {BinaryJsonDecoder, PackValue} from '../types';
 
export class UbjsonDecoder implements BinaryJsonDecoder {
  public reader = new Reader();
 
  public read(uint8: Uint8Array): PackValue {
    this.reader.reset(uint8);
    return this.readAny();
  }
 
  public decode(uint8: Uint8Array): unknown {
    this.reader.reset(uint8);
    return this.readAny();
  }
 
  public readAny(): PackValue {
    const reader = this.reader;
    const octet = reader.u8();
    switch (octet) {
      case 0x5a:
        return null;
      case 0x54:
        return true;
      case 0x46:
        return false;
      case 0x55:
        return reader.u8();
      case 0x69:
        return reader.i8();
      case 0x49: {
        const int = reader.view.getInt16(reader.x, false);
        reader.x += 2;
        return int;
      }
      case 0x6c: {
        const int = reader.view.getInt32(reader.x, false);
        reader.x += 4;
        return int;
      }
      case 0x64: {
        const num = reader.view.getFloat32(reader.x, false);
        reader.x += 4;
        return num;
      }
      case 0x44: {
        const num = reader.view.getFloat64(reader.x, false);
        reader.x += 8;
        return num;
      }
      case 0x4c: {
        const num = reader.view.getBigInt64(reader.x, false);
        reader.x += 8;
        return num;
      }
      case 0x53:
        return reader.utf8(+(this.readAny() as number));
      case 0x43:
        return String.fromCharCode(reader.u8());
      case 0x5b: {
        const uint8 = reader.uint8;
        const x = reader.x;
        if (uint8[x] === 0x24 && uint8[x + 1] === 0x55 && uint8[x + 2] === 0x23) {
          reader.x += 3;
          const size = +(this.readAny() as number);
          return reader.buf(size);
        }
        let type: number = -1;
        Iif (uint8[x] === 0x24) {
          reader.x++;
          type = reader.u8();
        }
        let count: number = -1;
        Iif (uint8[x] === 0x23) {
          reader.x++;
          count = reader.u8();
        }
        Iif (uint8[x] === 0x24) {
          reader.x++;
          type = reader.u8();
        }
        Iif (count >= 0) {
          let wordSize: number = 1;
          switch (type) {
            case 0x49:
              wordSize = 2;
              break;
            case 0x6c:
            case 0x64:
              wordSize = 4;
              break;
            case 0x44:
            case 0x4c:
              wordSize = 8;
              break;
          }
          return new JsonPackExtension(type, reader.buf(count * wordSize));
        } else {
          const arr: PackValue[] = [];
          while (uint8[reader.x] !== 0x5d) arr.push(this.readAny());
          reader.x++;
          return arr;
        }
      }
      case 0x7b: {
        const uint8 = reader.uint8;
        const obj: Record<string, PackValue> = {};
        while (uint8[reader.x] !== 0x7d) {
          const keySize = +(this.readAny() as number);
          const key = reader.utf8(keySize);
          if (key === '__proto__') throw ERROR.UNEXPECTED_OBJ_KEY;
          obj[key] = this.readAny();
        }
        reader.x++;
        return obj;
      }
      case 0x4e:
        return undefined;
    }
    return;
  }
}