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 51160x 160x       130451x 130451x       160x 2800x   2800x 2800x     8392x 8392x 8392x 8392x 8392x       1042771x 1042771x 1042771x 1042771x 122059x 122059x 122059x 122059x   1042771x 1042771x 1042771x 1042771x       2180x   2180x 30773x 30773x   2180x      
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;
  }
}