@tldraw/state
Version:
tldraw infinite canvas SDK (state).
8 lines (7 loc) • 3.74 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/lib/HistoryBuffer.ts"],
"sourcesContent": ["import { RESET_VALUE } from './types'\n\ntype RangeTuple<Diff> = [fromEpoch: number, toEpoch: number, diff: Diff]\n\n/**\n * A structure that stores diffs between values of an atom.\n *\n * @internal\n */\nexport class HistoryBuffer<Diff> {\n\tprivate index = 0\n\n\t// use a wrap around buffer to store the last N values\n\tbuffer: Array<RangeTuple<Diff> | undefined>\n\n\tconstructor(private readonly capacity: number) {\n\t\tthis.buffer = new Array(capacity)\n\t}\n\n\t/**\n\t * Add a diff to the history buffer.\n\t *\n\t * @param lastComputedEpoch - The epoch when the diff was computed.\n\t * @param currentEpoch - The current epoch.\n\t * @param diff - The diff to add, or else a reset value.\n\t */\n\tpushEntry(lastComputedEpoch: number, currentEpoch: number, diff: Diff | RESET_VALUE) {\n\t\tif (diff === undefined) {\n\t\t\treturn\n\t\t}\n\n\t\tif (diff === RESET_VALUE) {\n\t\t\tthis.clear()\n\t\t\treturn\n\t\t}\n\n\t\t// Add the diff to the buffer as a range tuple.\n\t\tthis.buffer[this.index] = [lastComputedEpoch, currentEpoch, diff]\n\n\t\t// Bump the index, wrapping around if necessary.\n\t\tthis.index = (this.index + 1) % this.capacity\n\t}\n\n\t/**\n\t * Clear the history buffer.\n\t */\n\tclear() {\n\t\tthis.index = 0\n\t\tthis.buffer.fill(undefined)\n\t}\n\n\t/**\n\t * Get the diffs since the given epoch.\n\t *\n\t * @param sinceEpoch - The epoch to get diffs since.\n\t * @returns An array of diffs or a flag to reset the history buffer.\n\t */\n\tgetChangesSince(sinceEpoch: number): RESET_VALUE | Diff[] {\n\t\tconst { index, capacity, buffer } = this\n\n\t\t// For each item in the buffer...\n\t\tfor (let i = 0; i < capacity; i++) {\n\t\t\tconst offset = (index - 1 + capacity - i) % capacity\n\n\t\t\tconst elem = buffer[offset]\n\n\t\t\t// If there's no element in the offset position, return the reset value\n\t\t\tif (!elem) {\n\t\t\t\treturn RESET_VALUE\n\t\t\t}\n\n\t\t\tconst [fromEpoch, toEpoch] = elem\n\n\t\t\t// If the first element is already too early, bail\n\t\t\tif (i === 0 && sinceEpoch >= toEpoch) {\n\t\t\t\treturn []\n\t\t\t}\n\n\t\t\t// If the element is since the given epoch, return an array with all diffs from this element and all following elements\n\t\t\tif (fromEpoch <= sinceEpoch && sinceEpoch < toEpoch) {\n\t\t\t\tconst len = i + 1\n\t\t\t\tconst result = new Array(len)\n\n\t\t\t\tfor (let j = 0; j < len; j++) {\n\t\t\t\t\tresult[j] = buffer[(offset + j) % capacity]![2]\n\t\t\t\t}\n\n\t\t\t\treturn result\n\t\t\t}\n\t\t}\n\n\t\t// If we haven't returned yet, return the reset value\n\t\treturn RESET_VALUE\n\t}\n}\n"],
"mappings": "AAAA,SAAS,mBAAmB;AASrB,MAAM,cAAoB;AAAA,EAMhC,YAA6B,UAAkB;AAAlB;AAC5B,SAAK,SAAS,IAAI,MAAM,QAAQ;AAAA,EACjC;AAAA,EAPQ,QAAQ;AAAA;AAAA,EAGhB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,UAAU,mBAA2B,cAAsB,MAA0B;AACpF,QAAI,SAAS,QAAW;AACvB;AAAA,IACD;AAEA,QAAI,SAAS,aAAa;AACzB,WAAK,MAAM;AACX;AAAA,IACD;AAGA,SAAK,OAAO,KAAK,KAAK,IAAI,CAAC,mBAAmB,cAAc,IAAI;AAGhE,SAAK,SAAS,KAAK,QAAQ,KAAK,KAAK;AAAA,EACtC;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ;AACP,SAAK,QAAQ;AACb,SAAK,OAAO,KAAK,MAAS;AAAA,EAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,gBAAgB,YAA0C;AACzD,UAAM,EAAE,OAAO,UAAU,OAAO,IAAI;AAGpC,aAAS,IAAI,GAAG,IAAI,UAAU,KAAK;AAClC,YAAM,UAAU,QAAQ,IAAI,WAAW,KAAK;AAE5C,YAAM,OAAO,OAAO,MAAM;AAG1B,UAAI,CAAC,MAAM;AACV,eAAO;AAAA,MACR;AAEA,YAAM,CAAC,WAAW,OAAO,IAAI;AAG7B,UAAI,MAAM,KAAK,cAAc,SAAS;AACrC,eAAO,CAAC;AAAA,MACT;AAGA,UAAI,aAAa,cAAc,aAAa,SAAS;AACpD,cAAM,MAAM,IAAI;AAChB,cAAM,SAAS,IAAI,MAAM,GAAG;AAE5B,iBAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC7B,iBAAO,CAAC,IAAI,QAAQ,SAAS,KAAK,QAAQ,EAAG,CAAC;AAAA,QAC/C;AAEA,eAAO;AAAA,MACR;AAAA,IACD;AAGA,WAAO;AAAA,EACR;AACD;",
"names": []
}