UNPKG

json-joy

Version:

Collection of libraries for building collaborative editing apps.

158 lines (157 loc) 6.04 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 ClockTable_1 = require("../../../../json-crdt-patch/codec/clock/ClockTable"); 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("../../structural/binary/constants"); class Decoder { constructor(reader) { this.decodeStrChunk = () => { const decoder = this.dec; const reader = decoder.reader; const id = this.ts(); const val = decoder.val(); if (typeof val === 'string') return new nodes.StrChunk(id, val.length, val); return new nodes.StrChunk(id, ~~val, ''); }; this.decodeBinChunk = () => { const id = this.ts(); const reader = this.dec.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.decodeArrChunk = () => { const id = this.ts(); const reader = this.dec.reader; const [deleted, length] = reader.b1vu56(); if (deleted) return new nodes.ArrChunk(id, length, undefined); else { const data = []; for (let i = 0; i < length; i++) data.push(this.ts()); return new nodes.ArrChunk(id, length, data); } }; this.dec = new CborDecoderBase_1.CborDecoderBase(reader || new CrdtReader_1.CrdtReader()); } decode(fields, ModelConstructor = Model_1.Model) { const reader = this.dec.reader; reader.reset(fields.c); const clockTable = (this.clockTable = ClockTable_1.ClockTable.decode(reader)); return this.decodeFields(clockTable, fields, ModelConstructor); } decodeFields(clockTable, fields, ModelConstructor = Model_1.Model) { const reader = this.dec.reader; const firstClock = clockTable.byIdx[0]; const vectorClock = new clock_1.ClockVector(firstClock.sid, firstClock.time + 1); const doc = (this.doc = new ModelConstructor(vectorClock)); const root = fields.r; if (root && root.length) { reader.reset(root); const rootValue = this.ts(); doc.root.set(rootValue); } const index = doc.index; const keys = Object.keys(fields); const length = keys.length; for (let i = 0; i < length; i++) { const field = keys[i]; if (field.length < 3) continue; // Skip "c" and "r". const arr = fields[field]; const id = clockTable.parseField(field); reader.reset(arr); const node = this.decodeNode(id); index.set(id, node); } return doc; } ts() { const [sessionIndex, timeDiff] = this.dec.reader.id(); return new clock_1.Timestamp(this.clockTable.byIdx[sessionIndex].sid, timeDiff); } decodeNode(id) { const reader = this.dec.reader; const octet = reader.u8(); const major = octet >> 5; const minor = octet & 0b11111; const length = minor < 24 ? minor : minor === 24 ? reader.u8() : minor === 25 ? reader.u16() : reader.u32(); switch (major) { case constants_1.CRDT_MAJOR.CON: return this.decodeCon(id, length); case constants_1.CRDT_MAJOR.VAL: return this.decodeVal(id); case constants_1.CRDT_MAJOR.OBJ: return this.decodeObj(id, length); case constants_1.CRDT_MAJOR.VEC: return this.decodeVec(id, length); case constants_1.CRDT_MAJOR.STR: return this.decodeStr(id, length); case constants_1.CRDT_MAJOR.BIN: return this.decodeBin(id, length); case constants_1.CRDT_MAJOR.ARR: return this.decodeArr(id, length); } return Model_1.UNDEFINED; } decodeCon(id, length) { const decoder = this.dec; const data = !length ? decoder.val() : this.ts(); const node = new nodes.ConNode(id, data); return node; } decodeVal(id) { const val = this.ts(); const node = new nodes.ValNode(this.doc, id, val); return node; } decodeObj(id, length) { const decoder = this.dec; const obj = new nodes.ObjNode(this.doc, id); const keys = obj.keys; for (let i = 0; i < length; i++) { const key = decoder.val() + ''; const val = this.ts(); keys.set(key, val); } return obj; } decodeVec(id, length) { const reader = this.dec.reader; const node = new nodes.VecNode(this.doc, id); const elements = node.elements; for (let i = 0; i < length; i++) { const octet = reader.u8(); if (!octet) elements.push(undefined); else elements.push(this.ts()); } return node; } decodeStr(id, length) { const node = new nodes.StrNode(id); node.ingest(length, this.decodeStrChunk); return node; } decodeBin(id, length) { const node = new nodes.BinNode(id); node.ingest(length, this.decodeBinChunk); return node; } decodeArr(id, length) { const node = new nodes.ArrNode(this.doc, id); node.ingest(length, this.decodeArrChunk); return node; } } exports.Decoder = Decoder;