Skip to content

Commit cb9362d

Browse files
committed
feat(json-crdt): 🎸 add ability to encode file without model view
1 parent e26edd5 commit cb9362d

File tree

3 files changed

+45
-2
lines changed

3 files changed

+45
-2
lines changed

src/json-crdt/file/File.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ export class File implements Printable {
6262
constructor(public readonly model: Model, public readonly log: PatchLog) {}
6363

6464
public serialize(params: types.FileSerializeParams = {}): types.FileWriteSequence {
65-
const view = this.model.view();
65+
if (params.noView && (params.model === 'sidecar'))
66+
throw new Error('SIDECAR_MODEL_WITHOUT_VIEW');
6667
const metadata: types.FileMetadata = [{}, FileModelEncoding.Auto];
6768
let model: Uint8Array | unknown | null = null;
6869
const modelFormat = params.model ?? 'sidecar';
@@ -123,7 +124,7 @@ export class File implements Printable {
123124
default:
124125
throw new Error(`Invalid history format: ${patchFormat}`);
125126
}
126-
return [view, metadata, model, history];
127+
return [params.noView ? null : this.model.view(), metadata, model, history];
127128
}
128129

129130
public toBinary(params: types.FileEncodingParams): Uint8Array {

src/json-crdt/file/__tests__/File.spec.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Model} from '../../model';
33
import {File} from '../File';
44
import {JsonDecoder} from '../../../json-pack/json/JsonDecoder';
55
import {CborDecoder} from '../../../json-pack/cbor/CborDecoder';
6+
import {FileEncodingParams} from '../types';
67

78
const setup = (view: unknown) => {
89
const model = Model.withServerClock();
@@ -68,4 +69,36 @@ describe('.toBinary()', () => {
6869
expect(file.log.replayToEnd().view()).toEqual({foo: 'bar'});
6970
});
7071
});
72+
73+
const assertEncoding = (file: File, params: FileEncodingParams) => {
74+
const blob = file.toBinary(params);
75+
// if (params.format === 'ndjson') console.log(Buffer.from(blob).toString('utf8'))
76+
const file2 = params.format === 'seq.cbor' ? File.fromSeqCbor(blob) : File.fromNdjson(blob);
77+
expect(file2.model.view()).toEqual(file.model.view());
78+
expect(file2.model !== file.model).toBe(true);
79+
expect(file2.log.start.view()).toEqual(undefined);
80+
expect(file2.log.replayToEnd().view()).toEqual(file.model.view());
81+
expect(file2.log.patches.size()).toBe(file.log.patches.size());
82+
};
83+
84+
describe('can encode/decode all format combinations', () => {
85+
const formats: FileEncodingParams['format'][] = ['ndjson', 'seq.cbor'];
86+
const modelFormats: FileEncodingParams['model'][] = ['sidecar', 'binary', 'compact', 'verbose'];
87+
const historyFormats: FileEncodingParams['history'][] = ['binary', 'compact', 'verbose'];
88+
const noViews = [true, false];
89+
for (const format of formats) {
90+
for (const model of modelFormats) {
91+
for (const history of historyFormats) {
92+
for (const noView of noViews) {
93+
if (noView && (model === 'sidecar')) continue;
94+
const params = {format, model, history, noView};
95+
test(JSON.stringify(params), () => {
96+
const {file} = setup({foo: 'bar'});
97+
assertEncoding(file, params);
98+
});
99+
}
100+
}
101+
}
102+
}
103+
});
71104
});

src/util/trees/avl/AvlMap.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ export class AvlMap<K, V> implements Printable {
7272
return !!this.find(k);
7373
}
7474

75+
public size(): number {
76+
const root = this.root;
77+
if (!root) return 0;
78+
let curr = first(root);
79+
let size = 1;
80+
while ((curr = next(curr as HeadlessNode) as AvlNode<K, V> | undefined)) size++;
81+
return size;
82+
}
83+
7584
public getOrNextLower(k: K): AvlNode<K, V> | undefined {
7685
return (findOrNextLower(this.root, k, this.comparator) as AvlNode<K, V>) || undefined;
7786
}

0 commit comments

Comments
 (0)