diff --git a/src/json-crdt/codec/sidecar/binary/Decoder.ts b/src/json-crdt/codec/sidecar/binary/Decoder.ts index e02779b9e3..f28763fd55 100644 --- a/src/json-crdt/codec/sidecar/binary/Decoder.ts +++ b/src/json-crdt/codec/sidecar/binary/Decoder.ts @@ -84,8 +84,8 @@ export class Decoder { return this.cVec(view, id, length); case CRDT_MAJOR.STR: return this.cStr(view, id, length); - // case CRDT_MAJOR.BIN: - // return this.cBin(id, length); + case CRDT_MAJOR.BIN: + return this.cBin(view, id, length); // case CRDT_MAJOR.ARR: // return this.cArr(id, length); } @@ -155,6 +155,23 @@ export class Decoder { return node; } + protected cBin(view: unknown, id: ITimestampStruct, length: number): BinNode { + if (!(view instanceof Uint8Array)) throw new Error('INVALID_BIN'); + const node = new BinNode(id); + const reader = this.decoder.reader; + let offset = 0; + node.ingest(length, (): BinChunk => { + const id = this.ts(); + const span = reader.vu39(); + if (!span) return new BinChunk(id, length, undefined); + const slice = view.slice(offset, offset + span); + offset += span; + return new BinChunk(id, slice.length, slice); + }); + this.doc.index.set(id, node); + return node; + } + // protected cBin(id: ITimestampStruct, length: number): BinNode { // const node = new BinNode(id); // if (length) node.ingest(length, this.cBinChunk); diff --git a/src/json-crdt/codec/sidecar/binary/Encoder.ts b/src/json-crdt/codec/sidecar/binary/Encoder.ts index 55b6f0b07c..bff7394870 100644 --- a/src/json-crdt/codec/sidecar/binary/Encoder.ts +++ b/src/json-crdt/codec/sidecar/binary/Encoder.ts @@ -140,20 +140,15 @@ export class Encoder { } protected cBin(node: nodes.BinNode): void { - // const ts = this.ts; - // const writer = this.writer; - // ts(node.id); - // this.writeTL(CRDT_MAJOR_OVERLAY.BIN, node.count); - // for (let chunk = node.first(); chunk; chunk = node.next(chunk)) { - // // TODO: Encode ID first - // // TODO: Use b1vu56 - // const length = chunk.span; - // const deleted = chunk.del; - // writer.b1vu28(chunk.del, length); - // ts(chunk.id); - // if (deleted) continue; - // // TODO: REFERENCE - // } + const ts = this.ts; + ts(node.id); + this.writeTL(CRDT_MAJOR_OVERLAY.BIN, node.count); + this.viewEncoder.writeBin(node.view()); + const writer = this.metaEncoder.writer; + for (let chunk = node.first(); chunk; chunk = node.next(chunk)) { + ts(chunk.id); + writer.vu39(chunk.span); + } } protected cArr(node: nodes.ArrNode): void { diff --git a/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts b/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts index 10c7001b5d..3fa13f4a14 100644 --- a/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts +++ b/src/json-crdt/codec/sidecar/binary/__tests__/Encoder.spec.ts @@ -119,3 +119,20 @@ test('str', () => { expect(decoded.clock.sid).toBe(model.clock.sid); expect(decoded.clock.time).toBe(model.clock.time); }); + +test('bin', () => { + const model = Model.withLogicalClock(); + const encoder = new Encoder(); + const decoder = new Decoder(); + const cborDecoder = new CborDecoder(); + model.api.root(new Uint8Array([1, 2, 3])); + model.api.bin([]).ins(3, new Uint8Array([4, 5, 6])); + const [view, meta] = encoder.encode(model); + const viewDecoded = cborDecoder.decode(view); + const decoded = decoder.decode(viewDecoded, meta); + expect(model.view()).toEqual(decoded.view()); + expect(model.view()).toEqual(viewDecoded); + expect(decoded.clock.sid).toBe(model.clock.sid); + expect(decoded.clock.time).toBe(model.clock.time); +}); +