json-joy
Version:
Collection of libraries for building collaborative editing apps.
158 lines (157 loc) • 6.04 kB
JavaScript
"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;