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       128324x 128324x       157x 2791x   2791x 2791x     8360x 8360x 8360x 8360x 8360x       1008568x 1008568x 1008568x 1008568x 119964x 119964x 119964x 119964x   1008568x 1008568x 1008568x 1008568x       2174x   2174x 31094x 31094x   2174x      
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;
  }
}