All files / json-crdt/nodes/bin BinNode.ts

92.59% Statements 50/54
77.77% Branches 7/9
80% Functions 12/15
92.45% Lines 49/53

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  176x 176x           176x                             522195x 522195x 522195x 522195x 522195x 522195x 522195x 522195x 522195x       1248x 1248x 1248x 1248x 1248x 1248x       85631x 79374x 79374x 79374x 79374x 79374x 79374x   6257x 6257x 6257x       115384x 115384x                 1x                   176x       33748x   53429x 51732x 51732x 51732x 51732x 961170x 323331x 323331x 323331x   961170x   51732x                                 33748x     2440x             110818x         159236x       1220x      
import type {JsonNode} from '..';
import {type ITimestampStruct, tick} from '../../../json-crdt-patch/clock';
import {AbstractRga, type Chunk} from '../rga/AbstractRga';
 
/**
 * @ignore
 * @category CRDT Node
 */
export class BinChunk implements Chunk<Uint8Array> {
  public readonly id: ITimestampStruct;
  public span: number;
  public del: boolean;
  public data: Uint8Array | undefined;
  public len: number;
  public p: BinChunk | undefined;
  public l: BinChunk | undefined;
  public r: BinChunk | undefined;
  public p2: BinChunk | undefined;
  public l2: BinChunk | undefined;
  public r2: BinChunk | undefined;
  public s: BinChunk | undefined;
 
  constructor(id: ITimestampStruct, span: number, buf: Uint8Array | undefined) {
    this.id = id;
    this.span = span;
    this.len = buf ? span : 0;
    this.del = !buf;
    this.p = undefined;
    this.l = undefined;
    this.r = undefined;
    this.s = undefined;
    this.data = buf;
  }
 
  public merge(data: Uint8Array) {
    const length = this.data!.length;
    const combined = new Uint8Array(length + data.length);
    combined.set(this.data!);
    combined.set(data, length);
    this.data = combined;
    this.span = combined.length;
  }
 
  public split(ticks: number): BinChunk {
    if (!this.del) {
      const data = this.data!;
      const rightBuffer = data.subarray(ticks);
      const chunk = new BinChunk(tick(this.id, ticks), this.span - ticks, rightBuffer);
      this.data = data.subarray(0, ticks);
      this.span = ticks;
      return chunk;
    }
    const chunk = new BinChunk(tick(this.id, ticks), this.span - ticks, undefined);
    this.span = ticks;
    return chunk;
  }
 
  public delete(): void {
    this.del = true;
    this.data = undefined;
  }
 
  public clone(): BinChunk {
    const chunk = new BinChunk(this.id, this.span, this.data);
    return chunk;
  }
 
  public view(): Uint8Array {
    return this.data || new Uint8Array(0);
  }
}
 
/**
 * Represents the `bin` type in JSON CRDT. The `bin` is a blob of binary data,
 * powered by a Replicated Growable Array (RGA) algorithm.
 *
 * @category CRDT Node
 */
export class BinNode extends AbstractRga<Uint8Array> implements JsonNode<Uint8Array> {
  // ----------------------------------------------------------------- JsonNode
 
  /** @ignore */
  private _view: null | Uint8Array = null;
  public view(): Uint8Array {
    if (this._view) return this._view;
    const res = new Uint8Array(this.length());
    let offset = 0;
    let chunk = this.first();
    while (chunk) {
      if (!chunk.del) {
        const buf = chunk.data!;
        res.set(buf, offset);
        offset += buf.length;
      }
      chunk = this.next(chunk);
    }
    return (this._view = res);
  }
 
  /** @ignore */
  public children() {}
 
  /** @ignore */
  public child() {
    return undefined;
  }
 
  /** @ignore */
  public container(): JsonNode | undefined {
    return undefined;
  }
 
  /** @ignore */
  public api: undefined | unknown = undefined;
 
  public name(): string {
    return 'bin';
  }
 
  // -------------------------------------------------------------- AbstractRga
 
  /** @ignore */
  public createChunk(id: ITimestampStruct, buf: Uint8Array | undefined): BinChunk {
    return new BinChunk(id, buf ? buf.length : 0, buf);
  }
 
  /** @ignore */
  protected onChange(): void {
    this._view = null;
  }
 
  protected toStringName(): string {
    return this.name();
  }
}