All files / json-crdt/codec/structural/binary ViewDecoder.ts

98.97% Statements 97/98
100% Branches 27/27
100% Functions 12/12
98.82% Lines 84/85

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 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 1425x 5x 5x   5x 287x     287x       404x 404x 404x 404x 404x 141x 141x   263x   404x       34966x 11286x       404x 404x 404x       23100x 23100x 23100x 23100x 23100x 23100x 23100x   4794x   531x   3x   7638x   5781x   529x   3824x           4794x       7638x 7638x 18338x 18338x 18338x   7638x       3x 3x 3x 9x 9x 1x 1x 8x   3x       5781x 5781x 7975x 7975x 7975x   5781x       529x 529x 529x 529x 1222x 1222x 1222x 1112x 1112x   529x 529x 529x 1112x 1112x 1112x   529x       3824x 3824x 2668x 2668x   3824x       2668x 2668x 2668x 73x   2595x 3820x 2595x        
import {CborDecoderBase} from '@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase';
import {CrdtReader} from '../../../../json-crdt-patch/util/binary/CrdtReader';
import {CRDT_MAJOR} from './constants';
 
export class ViewDecoder extends CborDecoderBase<CrdtReader> {
  protected time: number = -1;
 
  constructor() {
    super(new CrdtReader());
  }
 
  public decode(data: Uint8Array): unknown {
    const reader = this.reader;
    this.time = -1;
    reader.reset(data);
    const isServerTime = reader.peak() & 0b10000000;
    if (isServerTime) {
      reader.x++;
      this.time = reader.vu57();
    } else {
      reader.x += 4;
    }
    return this.cRoot();
  }
 
  protected ts(): any {
    if (this.time < 0) this.reader.idSkip();
    else this.reader.vu57Skip();
  }
 
  protected cRoot(): unknown {
    const reader = this.reader;
    const peek = reader.uint8[reader.x];
    return !peek ? undefined : this.cNode();
  }
 
  protected cNode(): unknown {
    const reader = this.reader;
    this.ts();
    const octet = reader.u8();
    const major = octet >> 5;
    const minor = octet & 0b11111;
    const length = minor < 0b11111 ? minor : reader.vu57();
    switch (major) {
      case CRDT_MAJOR.CON:
        return this.cCon(length);
      case CRDT_MAJOR.VAL:
        return this.cNode();
      case CRDT_MAJOR.VEC:
        return this.cVec(length);
      case CRDT_MAJOR.OBJ:
        return this.cObj(length);
      case CRDT_MAJOR.STR:
        return this.cStr(length);
      case CRDT_MAJOR.BIN:
        return this.cBin(length);
      case CRDT_MAJOR.ARR:
        return this.cArr(length);
    }
    return undefined;
  }
 
  protected cCon(length: number): unknown {
    return !length ? this.val() : (this.ts(), null);
  }
 
  protected cObj(length: number): Record<string, unknown> {
    const obj: Record<string, unknown> = {};
    for (let i = 0; i < length; i++) {
      const key: string = this.key();
      const value = this.cNode();
      if (value !== undefined) obj[key] = value;
    }
    return obj;
  }
 
  protected cVec(length: number): unknown[] {
    const reader = this.reader;
    const obj: unknown[] = [];
    for (let i = 0; i < length; i++) {
      const octet = reader.peak();
      if (!octet) {
        reader.x++;
        obj.push(undefined);
      } else obj.push(this.cNode());
    }
    return obj;
  }
 
  protected cStr(length: number): string {
    let str = '';
    for (let i = 0; i < length; i++) {
      this.ts();
      const val = this.val();
      if (typeof val === 'string') str += val;
    }
    return str;
  }
 
  protected cBin(length: number): Uint8Array {
    const reader = this.reader;
    const buffers: Uint8Array[] = [];
    let totalLength = 0;
    for (let i = 0; i < length; i++) {
      this.ts();
      const [deleted, length] = reader.b1vu56();
      if (deleted) continue;
      buffers.push(reader.buf(length));
      totalLength += length;
    }
    const res = new Uint8Array(totalLength);
    let offset = 0;
    for (let i = 0; i < buffers.length; i++) {
      const byteLength = buffers[i].length;
      res.set(buffers[i], offset);
      offset += byteLength;
    }
    return res;
  }
 
  protected cArr(length: number): unknown[] {
    const arr: unknown[] = [];
    for (let i = 0; i < length; i++) {
      const values = this.cArrChunk();
      if (values && values.length) arr.push(...values);
    }
    return arr;
  }
 
  protected cArrChunk(): unknown[] | undefined {
    this.ts();
    const [deleted, length] = this.reader.b1vu56();
    if (deleted) {
      return undefined;
    } else {
      const values: unknown[] = [];
      for (let i = 0; i < length; i++) values.push(this.cNode());
      return values;
    }
  }
}