UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

188 lines (187 loc) 6.74 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Decoder = void 0; const tslib_1 = require("tslib"); const nodes = tslib_1.__importStar(require("../../../nodes")); const ClockDecoder_1 = require("../../../../json-crdt-patch/codec/clock/ClockDecoder"); const CrdtReader_1 = require("../../../../json-crdt-patch/util/binary/CrdtReader"); const clock_1 = require("../../../../json-crdt-patch/clock"); const Model_1 = require("../../../model/Model"); const CborDecoderBase_1 = require("@jsonjoy.com/json-pack/lib/cbor/CborDecoderBase"); const constants_1 = require("../../../../json-crdt-patch/constants"); const constants_2 = require("./constants"); class Decoder extends CborDecoderBase_1.CborDecoderBase { constructor() { super(new CrdtReader_1.CrdtReader()); this.clockDecoder = undefined; this.time = -1; this.cStrChunk = () => { const id = this.ts(); const val = this.val(); if (typeof val === 'string') return new nodes.StrChunk(id, val.length, val); return new nodes.StrChunk(id, ~~val, ''); }; this.cBinChunk = () => { const id = this.ts(); const reader = this.reader; const [deleted, length] = reader.b1vu56(); if (deleted) return new nodes.BinChunk(id, length, undefined); return new nodes.BinChunk(id, length, reader.buf(length)); }; this.cArrChunk = () => { const id = this.ts(); const [deleted, length] = this.reader.b1vu56(); if (deleted) return new nodes.ArrChunk(id, length, undefined); const ids = []; for (let i = 0; i < length; i++) ids.push(this.cNode().id); return new nodes.ArrChunk(id, length, ids); }; } decode(data, model) { this.clockDecoder = undefined; this.time = -1; const reader = this.reader; reader.reset(data); const isServerTime = reader.peak() & 0b10000000; if (isServerTime) { reader.x++; const time = (this.time = reader.vu57()); if (!model) model = Model_1.Model.withServerClock(time); } else { this.decodeClockTable(); if (!model) { const clock = this.clockDecoder.clock; model = Model_1.Model.withLogicalClock(clock); } } this.doc = model; model.root = new nodes.RootNode(this.doc, this.cRoot().id); this.clockDecoder = undefined; return model; } decodeClockTable() { const reader = this.reader; const clockTableOffset = reader.u32(); const offset = reader.x; reader.x += clockTableOffset; const length = reader.vu57(); const sessionId = reader.vu57(); const time = reader.vu57(); this.clockDecoder = new ClockDecoder_1.ClockDecoder(sessionId, time); for (let i = 1; i < length; i++) { const sid = reader.vu57(); const time = reader.vu57(); this.clockDecoder.pushTuple(sid, time); } reader.x = offset; } ts() { const decoderTime = this.time; const isLogical = decoderTime < 0; if (isLogical) { const [sessionIndex, timeDiff] = this.reader.id(); return this.clockDecoder.decodeId(sessionIndex, timeDiff); } else { return new clock_1.Timestamp(constants_1.SESSION.SERVER, this.reader.vu57()); } } cRoot() { const reader = this.reader; const peek = reader.uint8[reader.x]; return !peek ? Model_1.UNDEFINED : this.cNode(); } cNode() { const reader = this.reader; const id = this.ts(); const octet = reader.u8(); const major = octet >> 5; const minor = octet & 0b11111; switch (major) { case constants_2.CRDT_MAJOR.CON: return this.cCon(id, minor); case constants_2.CRDT_MAJOR.VAL: return this.cVal(id); case constants_2.CRDT_MAJOR.OBJ: return this.cObj(id, minor !== 0b11111 ? minor : reader.vu57()); case constants_2.CRDT_MAJOR.VEC: return this.cVec(id, minor !== 0b11111 ? minor : reader.vu57()); case constants_2.CRDT_MAJOR.STR: return this.cStr(id, minor !== 0b11111 ? minor : reader.vu57()); case constants_2.CRDT_MAJOR.BIN: return this.cBin(id, minor !== 0b11111 ? minor : reader.vu57()); case constants_2.CRDT_MAJOR.ARR: return this.cArr(id, minor !== 0b11111 ? minor : reader.vu57()); } throw new Error('UNKNOWN_NODE'); } cCon(id, length) { const doc = this.doc; const data = !length ? this.val() : this.ts(); const node = new nodes.ConNode(id, data); doc.index.set(id, node); return node; } cVal(id) { const child = this.cNode(); const doc = this.doc; const node = new nodes.ValNode(doc, id, child.id); doc.index.set(id, node); return node; } cObj(id, length) { const obj = new nodes.ObjNode(this.doc, id); for (let i = 0; i < length; i++) this.cObjChunk(obj); this.doc.index.set(id, obj); return obj; } cObjChunk(obj) { const key = this.key(); obj.keys.set(key, this.cNode().id); } cVec(id, length) { const reader = this.reader; const obj = new nodes.VecNode(this.doc, id); const elements = obj.elements; for (let i = 0; i < length; i++) { const octet = reader.peak(); if (!octet) { reader.x++; elements.push(undefined); } else elements.push(this.cNode().id); } this.doc.index.set(id, obj); return obj; } cStr(id, length) { const node = new nodes.StrNode(id); if (length) node.ingest(length, this.cStrChunk); this.doc.index.set(id, node); return node; } cBin(id, length) { const node = new nodes.BinNode(id); if (length) node.ingest(length, this.cBinChunk); this.doc.index.set(id, node); return node; } cArr(id, length) { const obj = new nodes.ArrNode(this.doc, id); if (length) obj.ingest(length, this.cArrChunk); this.doc.index.set(id, obj); return obj; } } exports.Decoder = Decoder;