All files / json-crdt-patch/codec/clock ClockEncoder.ts

96.87% Statements 31/32
66.66% Branches 2/3
100% Functions 6/6
100% Lines 30/30

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 51157x 157x       127557x 127557x       157x 2789x   2789x 2789x     8435x 8435x 8435x 8435x 8435x       1026642x 1026642x 1026642x 1026642x 119122x 119122x 119122x 119122x   1026642x 1026642x 1026642x 1026642x       2172x   2172x 29921x 29921x   2172x      
import {type ITimestampStruct, type IClockVector, tick, Timestamp} from '../../clock';
import {RelativeTimestamp} from './RelativeTimestamp';
 
class ClockTableEntry {
  constructor(
    public index: number,
    public clock: ITimestampStruct,
  ) {}
}
 
export class ClockEncoder {
  public readonly table: Map<number, ClockTableEntry> = new Map<number, ClockTableEntry>();
  /** Start from 1, as 0 is reserved for system session ID. */
  protected index: number = 1;
  public clock: IClockVector | null = null;
 
  public reset(clock: IClockVector) {
    this.index = 1;
    this.clock = clock;
    const entry = new ClockTableEntry(this.index++, tick(clock, -1));
    this.table.clear();
    this.table.set(clock.sid, entry);
  }
 
  public append(ts: ITimestampStruct): RelativeTimestamp {
    const time = ts.time;
    const sid = ts.sid;
    let entry = this.table.get(sid);
    if (!entry) {
      let clock = this.clock!.peers.get(sid);
      if (!clock) clock = new Timestamp(sid, this.clock!.time - 1);
      entry = new ClockTableEntry(this.index++, clock);
      this.table.set(sid, entry);
    }
    const clock = entry.clock;
    const timeDiff = clock.time - time;
    Iif (timeDiff < 0) throw new Error('TIME_TRAVEL');
    return new RelativeTimestamp(entry.index, timeDiff);
  }
 
  public toJson(): number[] {
    const out: number[] = [];
    // biome-ignore lint: using .forEach() on Map is the fastest way to iterate
    this.table.forEach((entry) => {
      const clock = entry.clock;
      out.push(clock.sid, clock.time);
    });
    return out;
  }
}