flatpack-json 9.7.0 → 9.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/CompactStorage.d.mts +10 -0
- package/dist/CompactStorage.mjs +7 -0
- package/dist/Flatpack.d.mts +2 -86
- package/dist/Flatpack.mjs +5 -610
- package/dist/FlatpackData.d.mts +24 -0
- package/dist/FlatpackData.mjs +122 -0
- package/dist/FlatpackV1.d.mts +100 -0
- package/dist/FlatpackV1.mjs +642 -0
- package/dist/FlatpackV2.d.mts +16 -0
- package/dist/FlatpackV2.mjs +41 -0
- package/dist/RefCounter.d.mts +17 -0
- package/dist/RefCounter.mjs +42 -0
- package/dist/RefElements.d.mts +2 -2
- package/dist/Trie.d.mts +37 -7
- package/dist/Trie.mjs +95 -4
- package/dist/WeakCache.d.mts +15 -0
- package/dist/WeakCache.mjs +41 -0
- package/dist/flatpackUtil.d.mts +1 -2
- package/dist/flatpacked.d.mts +14 -0
- package/dist/flatpacked.mjs +129 -0
- package/dist/optimizeFlatpacked.mjs +54 -71
- package/dist/proxy.mjs +0 -1
- package/dist/storage.d.mts +3 -64
- package/dist/storage.mjs +31 -439
- package/dist/storageV1.d.mts +67 -0
- package/dist/storageV1.mjs +445 -0
- package/dist/storageV2.d.mts +70 -0
- package/dist/storageV2.mjs +451 -0
- package/dist/stringTable.d.mts +39 -0
- package/dist/stringTable.mjs +213 -0
- package/dist/stringify.d.mts +6 -1
- package/dist/stringify.mjs +31 -2
- package/dist/types.d.mts +63 -15
- package/dist/types.mjs +6 -2
- package/dist/unpack.d.mts +1 -1
- package/dist/unpack.mjs +70 -31
- package/dist/unpackedAnnotation.d.mts +23 -0
- package/dist/unpackedAnnotation.mjs +32 -0
- package/package.json +5 -5
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
import assert from 'node:assert';
|
|
2
|
+
import { CompactStorage } from './CompactStorage.mjs';
|
|
3
|
+
import { optimizeFlatpacked } from './optimizeFlatpacked.mjs';
|
|
4
|
+
import { stringifyFlatpacked } from './stringify.mjs';
|
|
5
|
+
import { TrieOfStrings } from './Trie.mjs';
|
|
6
|
+
import { blockSplitRegex, dataHeaderV1_0, ElementType } from './types.mjs';
|
|
7
|
+
const collator = new Intl.Collator('en', {
|
|
8
|
+
usage: 'sort',
|
|
9
|
+
numeric: true,
|
|
10
|
+
sensitivity: 'variant',
|
|
11
|
+
caseFirst: 'upper',
|
|
12
|
+
ignorePunctuation: false,
|
|
13
|
+
});
|
|
14
|
+
const compare = collator.compare;
|
|
15
|
+
const forceStringPrimitives = false;
|
|
16
|
+
const minSubStringLen = 4;
|
|
17
|
+
export class CompactStorageV1 extends CompactStorage {
|
|
18
|
+
data = [dataHeaderV1_0];
|
|
19
|
+
dedupe = true;
|
|
20
|
+
sortKeys = true;
|
|
21
|
+
emptyObjIdx = 0;
|
|
22
|
+
/**
|
|
23
|
+
* Cache of primitives and objects that have been added to the data.
|
|
24
|
+
*/
|
|
25
|
+
cache = new Map([[undefined, 0]]);
|
|
26
|
+
/**
|
|
27
|
+
* Set of indexes that have been referenced by other indexes.
|
|
28
|
+
*/
|
|
29
|
+
referenced = new Set();
|
|
30
|
+
/**
|
|
31
|
+
* Cache of arrays that have been deduped.
|
|
32
|
+
* The key is a hash of the array elements as a function of the index of the element.
|
|
33
|
+
*/
|
|
34
|
+
cachedArrays = new Map();
|
|
35
|
+
/**
|
|
36
|
+
* Cache of strings used for prefix matching.
|
|
37
|
+
*/
|
|
38
|
+
knownStrings = new TrieOfStrings();
|
|
39
|
+
/**
|
|
40
|
+
* Cache of reversed strings used for suffix matching.
|
|
41
|
+
*/
|
|
42
|
+
knownStringsRev = new TrieOfStrings();
|
|
43
|
+
cachedElements = new Map();
|
|
44
|
+
constructor(options) {
|
|
45
|
+
super(options);
|
|
46
|
+
this.dedupe = options?.dedupe ?? true;
|
|
47
|
+
this.sortKeys = options?.sortKeys || this.dedupe;
|
|
48
|
+
}
|
|
49
|
+
primitiveToIdx(value) {
|
|
50
|
+
if (typeof value === 'string')
|
|
51
|
+
return this.stringToIdx(value);
|
|
52
|
+
if (typeof value === 'bigint')
|
|
53
|
+
return this.bigintToIdx(value);
|
|
54
|
+
const found = this.cache.get(value);
|
|
55
|
+
if (found !== undefined) {
|
|
56
|
+
return found;
|
|
57
|
+
}
|
|
58
|
+
const idx = this.data.push(value) - 1;
|
|
59
|
+
this.cache.set(value, idx);
|
|
60
|
+
return idx;
|
|
61
|
+
}
|
|
62
|
+
addSubStringRef(idxString, value, offset) {
|
|
63
|
+
const found = this.cache.get(value);
|
|
64
|
+
if (found !== undefined) {
|
|
65
|
+
return found;
|
|
66
|
+
}
|
|
67
|
+
const sub = offset
|
|
68
|
+
? [ElementType.SubString, idxString, value.length, offset]
|
|
69
|
+
: [ElementType.SubString, idxString, value.length];
|
|
70
|
+
const idx = this.data.push(sub) - 1;
|
|
71
|
+
this.cache.set(value, idx);
|
|
72
|
+
return idx;
|
|
73
|
+
}
|
|
74
|
+
estimateSubStringCost(idxString, value, offset) {
|
|
75
|
+
if (this.cache.has(value)) {
|
|
76
|
+
return 0;
|
|
77
|
+
}
|
|
78
|
+
let cost = 5;
|
|
79
|
+
cost += Math.ceil(Math.log10(idxString));
|
|
80
|
+
cost += Math.ceil(Math.log10(value.length));
|
|
81
|
+
if (offset) {
|
|
82
|
+
cost += Math.ceil(Math.log10(offset)) + 1;
|
|
83
|
+
}
|
|
84
|
+
return cost;
|
|
85
|
+
}
|
|
86
|
+
addKnownString(idx, value) {
|
|
87
|
+
if (value.length >= minSubStringLen) {
|
|
88
|
+
const data = { idx, value };
|
|
89
|
+
this.knownStrings.add(value.length > 256 ? [...value].slice(0, 256) : value, data);
|
|
90
|
+
this.knownStringsRev.add(revStr(value, 256), data);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
addStringPrimitive(value) {
|
|
94
|
+
const idx = this.data.push(value) - 1;
|
|
95
|
+
this.addKnownString(idx, value);
|
|
96
|
+
this.cache.set(value, idx);
|
|
97
|
+
return idx;
|
|
98
|
+
}
|
|
99
|
+
duplicateIndex(idx) {
|
|
100
|
+
const element = this.data[idx];
|
|
101
|
+
const duplicate = this.data.push(element) - 1;
|
|
102
|
+
return duplicate;
|
|
103
|
+
}
|
|
104
|
+
stringToIdx(value) {
|
|
105
|
+
const found = this.cache.get(value);
|
|
106
|
+
if (found !== undefined) {
|
|
107
|
+
return found;
|
|
108
|
+
}
|
|
109
|
+
if (forceStringPrimitives || value.length < minSubStringLen || blockSplitRegex.test(value)) {
|
|
110
|
+
return this.addStringPrimitive(value);
|
|
111
|
+
}
|
|
112
|
+
const foundPrefix = this.findPrefix(value);
|
|
113
|
+
const foundSuffix = this.findSuffix(value);
|
|
114
|
+
if (!foundPrefix && !foundSuffix) {
|
|
115
|
+
return this.addStringPrimitive(value);
|
|
116
|
+
}
|
|
117
|
+
if (foundPrefix &&
|
|
118
|
+
(!foundSuffix ||
|
|
119
|
+
foundPrefix.subStr.length - foundPrefix.cost >= foundSuffix.subStr.length - foundSuffix.cost)) {
|
|
120
|
+
const { idx: pfIdx, subStr, offset } = foundPrefix;
|
|
121
|
+
const sIdx = this.addSubStringRef(pfIdx, subStr, offset);
|
|
122
|
+
if (subStr === value)
|
|
123
|
+
return sIdx;
|
|
124
|
+
const v = [sIdx, this.stringToIdx(value.slice(subStr.length))];
|
|
125
|
+
const idx = this.data.push([ElementType.String, ...v]) - 1;
|
|
126
|
+
this.cache.set(value, idx);
|
|
127
|
+
this.addKnownString(idx, value);
|
|
128
|
+
return idx;
|
|
129
|
+
}
|
|
130
|
+
if (!foundSuffix) {
|
|
131
|
+
return this.addStringPrimitive(value);
|
|
132
|
+
}
|
|
133
|
+
const { idx: pfIdx, subStr, offset } = foundSuffix;
|
|
134
|
+
const sIdx = this.addSubStringRef(pfIdx, subStr, offset);
|
|
135
|
+
const v = [this.stringToIdx(value.slice(0, -subStr.length)), sIdx];
|
|
136
|
+
const idx = this.data.push([ElementType.String, ...v]) - 1;
|
|
137
|
+
this.cache.set(value, idx);
|
|
138
|
+
this.addKnownString(idx, value);
|
|
139
|
+
return idx;
|
|
140
|
+
}
|
|
141
|
+
findPrefix(value) {
|
|
142
|
+
const trieFound = this.knownStrings.find(value);
|
|
143
|
+
if (!trieFound || !trieFound.data || trieFound.found.length < minSubStringLen) {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const { data: tData, found: subStr } = trieFound;
|
|
147
|
+
const cost = this.estimateSubStringCost(tData.idx, subStr, undefined);
|
|
148
|
+
if (cost > subStr.length) {
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
return { idx: tData.idx, subStr, offset: undefined, cost };
|
|
152
|
+
}
|
|
153
|
+
findSuffix(value) {
|
|
154
|
+
const rev = revStr(value, 256);
|
|
155
|
+
const trieFound = this.knownStringsRev.find(rev);
|
|
156
|
+
if (!trieFound || !trieFound.data || trieFound.found.length < minSubStringLen) {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
const { data: tData, found: subStrRev } = trieFound;
|
|
160
|
+
const offset = tData.value.length - subStrRev.length;
|
|
161
|
+
const cost = this.estimateSubStringCost(tData.idx, subStrRev, offset);
|
|
162
|
+
if (cost > subStrRev.length) {
|
|
163
|
+
return undefined;
|
|
164
|
+
}
|
|
165
|
+
const srcStr = tData.value;
|
|
166
|
+
const subStr = srcStr.slice(-subStrRev.length);
|
|
167
|
+
return { idx: tData.idx, subStr, offset, cost };
|
|
168
|
+
}
|
|
169
|
+
objSetToIdx(value) {
|
|
170
|
+
const found = this.cache.get(value);
|
|
171
|
+
if (found !== undefined) {
|
|
172
|
+
this.referenced.add(found);
|
|
173
|
+
return found;
|
|
174
|
+
}
|
|
175
|
+
const idx = this.data.push(0) - 1;
|
|
176
|
+
this.cache.set(value, idx);
|
|
177
|
+
const keys = [...value];
|
|
178
|
+
const k = this.createUniqueKeys(keys, false);
|
|
179
|
+
const element = [ElementType.Set, k];
|
|
180
|
+
return this.storeElement(value, idx, element);
|
|
181
|
+
}
|
|
182
|
+
createUniqueKeys(keys, cacheValue = true) {
|
|
183
|
+
let k = this.arrToIdx(keys, cacheValue);
|
|
184
|
+
const elementKeys = this.data[k];
|
|
185
|
+
const uniqueKeys = new Set(elementKeys.slice(1));
|
|
186
|
+
if (uniqueKeys.size !== keys.length) {
|
|
187
|
+
// one or more of the keys got deduped. We need to duplicate it.
|
|
188
|
+
uniqueKeys.clear();
|
|
189
|
+
const indexes = elementKeys.slice(1).map((idx) => {
|
|
190
|
+
if (uniqueKeys.has(idx)) {
|
|
191
|
+
return this.duplicateIndex(idx);
|
|
192
|
+
}
|
|
193
|
+
uniqueKeys.add(idx);
|
|
194
|
+
return idx;
|
|
195
|
+
});
|
|
196
|
+
k = this.createArrayElementFromIndexValues(this.data.length, indexes);
|
|
197
|
+
}
|
|
198
|
+
return k;
|
|
199
|
+
}
|
|
200
|
+
objMapToIdx(value) {
|
|
201
|
+
const found = this.cache.get(value);
|
|
202
|
+
if (found !== undefined) {
|
|
203
|
+
this.referenced.add(found);
|
|
204
|
+
return found;
|
|
205
|
+
}
|
|
206
|
+
const idx = this.data.push(0) - 1;
|
|
207
|
+
this.cache.set(value, idx);
|
|
208
|
+
const entries = [...value.entries()];
|
|
209
|
+
const k = this.createUniqueKeys(entries.map(([key]) => key), false);
|
|
210
|
+
const v = this.arrToIdx(entries.map(([, value]) => value), false);
|
|
211
|
+
const element = [ElementType.Map, k, v];
|
|
212
|
+
return this.storeElement(value, idx, element);
|
|
213
|
+
}
|
|
214
|
+
objRegExpToIdx(value) {
|
|
215
|
+
const found = this.cache.get(value);
|
|
216
|
+
if (found !== undefined) {
|
|
217
|
+
return found;
|
|
218
|
+
}
|
|
219
|
+
const idx = this.data.push(0) - 1;
|
|
220
|
+
this.cache.set(value, idx);
|
|
221
|
+
const element = [
|
|
222
|
+
ElementType.RegExp,
|
|
223
|
+
this.stringToIdx(value.source),
|
|
224
|
+
this.stringToIdx(value.flags),
|
|
225
|
+
];
|
|
226
|
+
return this.storeElement(value, idx, element);
|
|
227
|
+
}
|
|
228
|
+
objDateToIdx(value) {
|
|
229
|
+
const found = this.cache.get(value);
|
|
230
|
+
if (found !== undefined) {
|
|
231
|
+
return found;
|
|
232
|
+
}
|
|
233
|
+
const idx = this.data.push(0) - 1;
|
|
234
|
+
this.cache.set(value, idx);
|
|
235
|
+
const element = [ElementType.Date, value.getTime()];
|
|
236
|
+
return this.storeElement(value, idx, element);
|
|
237
|
+
}
|
|
238
|
+
bigintToIdx(value) {
|
|
239
|
+
const found = this.cache.get(value);
|
|
240
|
+
if (found !== undefined) {
|
|
241
|
+
return found;
|
|
242
|
+
}
|
|
243
|
+
const idx = this.data.push(0) - 1;
|
|
244
|
+
this.cache.set(value, idx);
|
|
245
|
+
const element = [
|
|
246
|
+
ElementType.BigInt,
|
|
247
|
+
this.primitiveToIdx(value <= Number.MAX_SAFE_INTEGER && value >= -Number.MAX_SAFE_INTEGER
|
|
248
|
+
? Number(value)
|
|
249
|
+
: value.toString()),
|
|
250
|
+
];
|
|
251
|
+
return this.storeElement(value, idx, element);
|
|
252
|
+
}
|
|
253
|
+
objToIdx(value) {
|
|
254
|
+
const found = this.cache.get(value);
|
|
255
|
+
if (found !== undefined) {
|
|
256
|
+
this.referenced.add(found);
|
|
257
|
+
return found;
|
|
258
|
+
}
|
|
259
|
+
if (isObjectWrapper(value)) {
|
|
260
|
+
const idx = this.data.push({}) - 1;
|
|
261
|
+
this.cache.set(value, idx);
|
|
262
|
+
const element = [ElementType.Object, 0, this.valueToIdx(value.valueOf())];
|
|
263
|
+
return this.storeElement(value, idx, element);
|
|
264
|
+
}
|
|
265
|
+
const entries = Object.entries(value);
|
|
266
|
+
if (!entries.length) {
|
|
267
|
+
if (this.emptyObjIdx) {
|
|
268
|
+
return this.emptyObjIdx;
|
|
269
|
+
}
|
|
270
|
+
const idx = this.data.push({}) - 1;
|
|
271
|
+
this.emptyObjIdx = idx;
|
|
272
|
+
return idx;
|
|
273
|
+
}
|
|
274
|
+
const idx = this.data.push(0) - 1;
|
|
275
|
+
this.cache.set(value, idx);
|
|
276
|
+
if (this.sortKeys) {
|
|
277
|
+
entries.sort(([a], [b]) => compare(a, b));
|
|
278
|
+
}
|
|
279
|
+
const k = this.arrToIdx(entries.map(([key]) => key));
|
|
280
|
+
const v = this.arrToIdx(entries.map(([, value]) => value));
|
|
281
|
+
const element = [ElementType.Object, k, v];
|
|
282
|
+
return this.storeElement(value, idx, element);
|
|
283
|
+
}
|
|
284
|
+
storeElement(value, idx, element) {
|
|
285
|
+
const useIdx = this.dedupe ? this.cacheElement(idx, element) : idx;
|
|
286
|
+
if (useIdx !== idx && idx === this.data.length - 1) {
|
|
287
|
+
this.data.length = idx;
|
|
288
|
+
this.cache.set(value, useIdx);
|
|
289
|
+
return useIdx;
|
|
290
|
+
}
|
|
291
|
+
this.data[idx] = element;
|
|
292
|
+
return idx;
|
|
293
|
+
}
|
|
294
|
+
cacheElement(elemIdx, element) {
|
|
295
|
+
let map = this.cachedElements;
|
|
296
|
+
for (let i = 0; i < element.length - 1; i++) {
|
|
297
|
+
const idx = element[i];
|
|
298
|
+
let found = map.get(idx);
|
|
299
|
+
if (!found) {
|
|
300
|
+
found = new Map();
|
|
301
|
+
map.set(idx, found);
|
|
302
|
+
}
|
|
303
|
+
assert(found instanceof Map);
|
|
304
|
+
map = found;
|
|
305
|
+
}
|
|
306
|
+
const idx = element[element.length - 1];
|
|
307
|
+
const foundIdx = map.get(idx);
|
|
308
|
+
if (typeof foundIdx === 'number') {
|
|
309
|
+
return this.referenced.has(elemIdx) ? elemIdx : foundIdx;
|
|
310
|
+
}
|
|
311
|
+
map.set(idx, elemIdx);
|
|
312
|
+
return elemIdx;
|
|
313
|
+
}
|
|
314
|
+
stashArray(idx, element) {
|
|
315
|
+
const indexHash = simpleHash(element);
|
|
316
|
+
let found = this.cachedArrays.get(indexHash);
|
|
317
|
+
if (!found) {
|
|
318
|
+
found = [];
|
|
319
|
+
this.cachedArrays.set(indexHash, found);
|
|
320
|
+
}
|
|
321
|
+
const foundIdx = found.find((entry) => isEqual(entry.v, element));
|
|
322
|
+
if (foundIdx) {
|
|
323
|
+
return this.referenced.has(idx) ? idx : foundIdx.idx;
|
|
324
|
+
}
|
|
325
|
+
found.push({ idx, v: element });
|
|
326
|
+
return idx;
|
|
327
|
+
}
|
|
328
|
+
createArrayElementFromIndexValues(idx, indexValues) {
|
|
329
|
+
const element = [ElementType.Array, ...indexValues];
|
|
330
|
+
const useIdx = this.dedupe ? this.stashArray(idx, element) : idx;
|
|
331
|
+
if (useIdx !== idx) {
|
|
332
|
+
assert(this.data.length === idx + 1, `Expected ${idx + 1} but got ${this.data.length}`);
|
|
333
|
+
this.data.length = idx;
|
|
334
|
+
return useIdx;
|
|
335
|
+
}
|
|
336
|
+
this.data[idx] = element;
|
|
337
|
+
return idx;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Convert an array to an index.
|
|
341
|
+
* @param value - The array to convert to an index.
|
|
342
|
+
* @param cacheValue - Whether to cache the value.
|
|
343
|
+
* @returns the index of the array.
|
|
344
|
+
*/
|
|
345
|
+
arrToIdx(value, cacheValue = true) {
|
|
346
|
+
const found = this.cache.get(value);
|
|
347
|
+
if (found !== undefined) {
|
|
348
|
+
this.referenced.add(found);
|
|
349
|
+
return found;
|
|
350
|
+
}
|
|
351
|
+
const idx = this.data.push(0) - 1;
|
|
352
|
+
this.cache.set(value, idx);
|
|
353
|
+
const useIdx = this.createArrayElementFromIndexValues(idx, value.map((idx) => this.valueToIdx(idx)));
|
|
354
|
+
if (cacheValue) {
|
|
355
|
+
this.cache.set(value, useIdx);
|
|
356
|
+
}
|
|
357
|
+
return useIdx;
|
|
358
|
+
}
|
|
359
|
+
valueToIdx(value) {
|
|
360
|
+
if (value === null) {
|
|
361
|
+
return this.primitiveToIdx(value);
|
|
362
|
+
}
|
|
363
|
+
if (typeof value === 'object') {
|
|
364
|
+
if (value instanceof Set) {
|
|
365
|
+
return this.objSetToIdx(value);
|
|
366
|
+
}
|
|
367
|
+
if (value instanceof Map) {
|
|
368
|
+
return this.objMapToIdx(value);
|
|
369
|
+
}
|
|
370
|
+
if (value instanceof RegExp) {
|
|
371
|
+
return this.objRegExpToIdx(value);
|
|
372
|
+
}
|
|
373
|
+
if (Array.isArray(value)) {
|
|
374
|
+
return this.arrToIdx(value);
|
|
375
|
+
}
|
|
376
|
+
if (value instanceof Date) {
|
|
377
|
+
return this.objDateToIdx(value);
|
|
378
|
+
}
|
|
379
|
+
return this.objToIdx(value);
|
|
380
|
+
}
|
|
381
|
+
return this.primitiveToIdx(value);
|
|
382
|
+
}
|
|
383
|
+
/**
|
|
384
|
+
* Reset things in a way that allows for reuse.
|
|
385
|
+
*/
|
|
386
|
+
softReset() {
|
|
387
|
+
this.cache.clear();
|
|
388
|
+
this.cache.set(undefined, 0);
|
|
389
|
+
}
|
|
390
|
+
toJSON(json) {
|
|
391
|
+
this.softReset();
|
|
392
|
+
this.valueToIdx(json);
|
|
393
|
+
return this.options?.optimize ? optimizeFlatpacked(this.data) : this.data;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
function* revStr(str, limit) {
|
|
397
|
+
let i = str.length - 1;
|
|
398
|
+
let n = 0;
|
|
399
|
+
while (i >= 0 && n < limit) {
|
|
400
|
+
// eslint-disable-next-line unicorn/prefer-code-point
|
|
401
|
+
const code = str.charCodeAt(i);
|
|
402
|
+
if (code & 0xfc00) {
|
|
403
|
+
// surrogate pair
|
|
404
|
+
i -= 1;
|
|
405
|
+
yield str.slice(i, i + 2);
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
yield str[i];
|
|
409
|
+
}
|
|
410
|
+
i -= 1;
|
|
411
|
+
n += 1;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
function isEqual(a, b) {
|
|
415
|
+
if (a === b)
|
|
416
|
+
return true;
|
|
417
|
+
if (a.length !== b.length)
|
|
418
|
+
return false;
|
|
419
|
+
for (let i = 0; i < a.length; i++) {
|
|
420
|
+
if (a[i] !== b[i])
|
|
421
|
+
return false;
|
|
422
|
+
}
|
|
423
|
+
return true;
|
|
424
|
+
}
|
|
425
|
+
function simpleHash(values) {
|
|
426
|
+
let hash = Math.sqrt(values.length);
|
|
427
|
+
for (const value of values) {
|
|
428
|
+
hash += value * value;
|
|
429
|
+
}
|
|
430
|
+
return hash;
|
|
431
|
+
}
|
|
432
|
+
function isObjectWrapper(value) {
|
|
433
|
+
return (typeof value === 'object' &&
|
|
434
|
+
value !== null &&
|
|
435
|
+
typeof value.valueOf === 'function' &&
|
|
436
|
+
value.valueOf() !== value);
|
|
437
|
+
}
|
|
438
|
+
export function toJSON(json, options) {
|
|
439
|
+
return new CompactStorageV1(options).toJSON(json);
|
|
440
|
+
}
|
|
441
|
+
export function stringify(data, pretty = true, options) {
|
|
442
|
+
const json = toJSON(data, options);
|
|
443
|
+
return pretty ? stringifyFlatpacked(json) : JSON.stringify(json);
|
|
444
|
+
}
|
|
445
|
+
//# sourceMappingURL=storageV1.mjs.map
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { CompactStorage } from './CompactStorage.mjs';
|
|
2
|
+
import type { Flatpacked, FlatpackOptions, Serializable, UnpackMetaData } from './types.mjs';
|
|
3
|
+
export declare class CompactStorageV2 extends CompactStorage {
|
|
4
|
+
#private;
|
|
5
|
+
private data;
|
|
6
|
+
private stringTable;
|
|
7
|
+
private dedupe;
|
|
8
|
+
private sortKeys;
|
|
9
|
+
private emptyObjIdx;
|
|
10
|
+
/**
|
|
11
|
+
* Cache of primitives and objects that have been added to the data.
|
|
12
|
+
*/
|
|
13
|
+
private cache;
|
|
14
|
+
/**
|
|
15
|
+
* Set of indexes that have been referenced by other indexes.
|
|
16
|
+
*/
|
|
17
|
+
private referencedFromCache;
|
|
18
|
+
/**
|
|
19
|
+
* Cache of arrays that have been deduped.
|
|
20
|
+
* The key is a hash of the array elements as a function of the index of the element.
|
|
21
|
+
*/
|
|
22
|
+
private cachedArrays;
|
|
23
|
+
private cachedElementsTrie;
|
|
24
|
+
private unpackMetaData;
|
|
25
|
+
private used;
|
|
26
|
+
constructor(options?: FlatpackOptions | undefined);
|
|
27
|
+
private primitiveToIdx;
|
|
28
|
+
private addStringPrimitive;
|
|
29
|
+
private stringToIdx;
|
|
30
|
+
private objSetToIdx;
|
|
31
|
+
private createUniqueKeys;
|
|
32
|
+
private objMapToIdx;
|
|
33
|
+
private objRegExpToIdx;
|
|
34
|
+
private objDateToIdx;
|
|
35
|
+
private bigintToIdx;
|
|
36
|
+
private objToIdx;
|
|
37
|
+
private objectKeysOrValuesToIdx;
|
|
38
|
+
private mapValuesToIndexes;
|
|
39
|
+
/**
|
|
40
|
+
* Store an element in the data array, using the cache if deduplication is enabled.
|
|
41
|
+
* @param value - the value being stored, used for caching purposes.
|
|
42
|
+
* @param idx - the index at which to store the element if it is not found in the cache.
|
|
43
|
+
* @param element - the element to store if it is not found in the cache.
|
|
44
|
+
* @returns the index at which the element is stored.
|
|
45
|
+
*/
|
|
46
|
+
private storeElement;
|
|
47
|
+
private cacheElement;
|
|
48
|
+
private stashArray;
|
|
49
|
+
private createArrayElementFromIndexValues;
|
|
50
|
+
/**
|
|
51
|
+
* Convert an array to an index.
|
|
52
|
+
* @param value - The array to convert to an index.
|
|
53
|
+
* @param cacheValue - Whether to cache the value.
|
|
54
|
+
* @returns the index of the array.
|
|
55
|
+
*/
|
|
56
|
+
private arrToIdx;
|
|
57
|
+
private valueToIdx;
|
|
58
|
+
/**
|
|
59
|
+
* Reset things in a way that allows for reuse.
|
|
60
|
+
*/
|
|
61
|
+
private softReset;
|
|
62
|
+
useFlatpackMetaData(data: UnpackMetaData | undefined): void;
|
|
63
|
+
/**
|
|
64
|
+
* Cache the primitives from the unpacked data to improve performance when re-packing the same data.
|
|
65
|
+
*/
|
|
66
|
+
private initFromFlatpackData;
|
|
67
|
+
private useFlattenedElement;
|
|
68
|
+
toJSON<V extends Serializable>(json: V): Flatpacked;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=storageV2.d.mts.map
|