zkjson 0.4.1 → 0.5.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.
@@ -0,0 +1,1330 @@
1
+ const {
2
+ clone,
3
+ uniq,
4
+ sortBy,
5
+ map,
6
+ concat,
7
+ compose,
8
+ is,
9
+ descend,
10
+ ascend,
11
+ sortWith,
12
+ prop,
13
+ equals,
14
+ append,
15
+ isNil,
16
+ includes,
17
+ splitEvery,
18
+ flatten,
19
+ } = require("ramda")
20
+ const ops = {
21
+ $eq: 10,
22
+ $ne: 11,
23
+ $gt: 12,
24
+ $gte: 13,
25
+ $lt: 14,
26
+ $lte: 15,
27
+ $in: 16,
28
+ $nin: 17,
29
+ $contains: 18,
30
+ $contains_any: 19,
31
+ $contains_all: 20,
32
+ $contains_none: 21,
33
+ }
34
+ const opMap = {}
35
+ for (let k in ops) opMap[ops[k]] = k
36
+
37
+ const base64Map = {
38
+ A: "00",
39
+ B: "01",
40
+ C: "02",
41
+ D: "03",
42
+ E: "04",
43
+ F: "05",
44
+ G: "06",
45
+ H: "07",
46
+ I: "08",
47
+ J: "09",
48
+ K: "10",
49
+ L: "11",
50
+ M: "12",
51
+ N: "13",
52
+ O: "14",
53
+ P: "15",
54
+ Q: "16",
55
+ R: "17",
56
+ S: "18",
57
+ T: "19",
58
+ U: "20",
59
+ V: "21",
60
+ W: "22",
61
+ X: "23",
62
+ Y: "24",
63
+ Z: "25",
64
+ a: "26",
65
+ b: "27",
66
+ c: "28",
67
+ d: "29",
68
+ e: "30",
69
+ f: "31",
70
+ g: "32",
71
+ h: "33",
72
+ i: "34",
73
+ j: "35",
74
+ k: "36",
75
+ l: "37",
76
+ m: "38",
77
+ n: "39",
78
+ o: "40",
79
+ p: "41",
80
+ q: "42",
81
+ r: "43",
82
+ s: "44",
83
+ t: "45",
84
+ u: "46",
85
+ v: "47",
86
+ w: "48",
87
+ x: "49",
88
+ y: "50",
89
+ z: "51",
90
+ 0: "52",
91
+ 1: "53",
92
+ 2: "54",
93
+ 3: "55",
94
+ 4: "56",
95
+ 5: "57",
96
+ 6: "58",
97
+ 7: "59",
98
+ 8: "60",
99
+ 9: "61",
100
+ "-": "62",
101
+ _: "63",
102
+ }
103
+
104
+ let strMap = {}
105
+ for (const k in base64Map) strMap[base64Map[k]] = k
106
+
107
+ function pad(arr, max = 0) {
108
+ arr = arr.map(n => n.toString())
109
+ for (let i = arr.length; i < max; i++) {
110
+ arr.push("0")
111
+ }
112
+ return arr
113
+ }
114
+
115
+ function encodePath(path) {
116
+ const parts = []
117
+ let str = ""
118
+ let num = 0
119
+ for (const s of path) {
120
+ if (num == 2 && !(s == "." || s == "[")) throw Error()
121
+ if (s == ".") {
122
+ if (num == 2) {
123
+ num = 0
124
+ } else {
125
+ parts.push(str)
126
+ str = ""
127
+ }
128
+ } else if (s == "[") {
129
+ if (num != 2) {
130
+ if (str != "" || parts.length > 0) parts.push(str)
131
+ str = ""
132
+ }
133
+ num = 1
134
+ } else if (s == "]") {
135
+ if (num != 1) throw Error()
136
+ num = 2
137
+ if (str == "" || Number.isNaN(+str)) throw Error()
138
+ parts.push(+str)
139
+ str = ""
140
+ } else {
141
+ str += s
142
+ }
143
+ }
144
+ if (str != "") parts.push(str)
145
+ if (parts.length == 0) parts.push("")
146
+ let encoded = [parts.length]
147
+ for (const p of parts) {
148
+ if (typeof p == "number") {
149
+ encoded = encoded.concat([0, 0, p])
150
+ } else {
151
+ let plen = [p.length]
152
+ if (p.length == 0) plen.push(1)
153
+ encoded = encoded.concat([
154
+ ...plen,
155
+ ...p.split("").map(c => c.charCodeAt(0)),
156
+ ])
157
+ }
158
+ }
159
+ return encoded
160
+ }
161
+
162
+ function decodePath(path) {
163
+ let str = ""
164
+ let p = []
165
+ let len = path.shift()
166
+ while (path.length > 0) {
167
+ const type = path.shift()
168
+ let val = null
169
+ if (type == 0) {
170
+ const type2 = path.shift()
171
+ if (type2 == 0) {
172
+ val = [type2, path.shift()]
173
+ } else {
174
+ val = [type2]
175
+ }
176
+ } else {
177
+ val = []
178
+ for (let i = 0; i < type; i++) {
179
+ val.push(path.shift())
180
+ }
181
+ }
182
+ p.push([type, ...val])
183
+ }
184
+ let i = 0
185
+ for (let s of p) {
186
+ if (s[0] == 0 && s[1] == 0) str += `[${s[2]}]`
187
+ else if (s[0] == 0 && s[1] == 1) {
188
+ if (str != "") str += "."
189
+ } else {
190
+ str += `${i == 0 ? "" : "."}${s
191
+ .slice(1)
192
+ .map(c => String.fromCharCode(Number(c)))
193
+ .join("")}`
194
+ }
195
+ i++
196
+ }
197
+ return str
198
+ }
199
+
200
+ function flattenPath(path) {
201
+ let p = [...to128(path.length)]
202
+ for (const v of path) p = p.concat(v)
203
+ return p
204
+ }
205
+
206
+ class u8 {
207
+ constructor(size = 100) {
208
+ this.size = size
209
+ this.chunks = [new Uint8Array(this.size)]
210
+ this.len = 0
211
+ }
212
+ }
213
+ function _encode(v, path = []) {
214
+ let vals = []
215
+ if (typeof v == "number") vals.push([path, encodeVal(v)])
216
+ else if (typeof v == "boolean") vals.push([path, encodeVal(v)])
217
+ else if (v == null) vals.push([path, encodeVal(v)])
218
+ else if (typeof v == "string") vals.push([path, encodeVal(v)])
219
+ else if (Array.isArray(v)) {
220
+ let i = 0
221
+ for (const v2 of v) {
222
+ for (const v3 of _encode(v2, [...path, i])) vals.push(v3)
223
+ i++
224
+ }
225
+ } else if (typeof v == "object") {
226
+ for (const k in v) for (let v4 of _encode(v[k], [...path, k])) vals.push(v4)
227
+ }
228
+ return vals
229
+ }
230
+
231
+ const filterDic = keys => keys.filter(entry => entry.count > 1)
232
+
233
+ function countKeys(keys) {
234
+ let keys2 = []
235
+ for (let v of keys) {
236
+ let i = 0
237
+ for (let v2 of v) {
238
+ const _key = v.slice(0, i + 1)
239
+ let exists = false
240
+ for (let v3 of keys2) {
241
+ if (equals(_key, v3.key)) {
242
+ v3.count += 1
243
+ exists = true
244
+ }
245
+ }
246
+ if (!exists) keys2.push({ key: _key, count: 1 })
247
+ i++
248
+ }
249
+ }
250
+ return keys2
251
+ }
252
+
253
+ function sortKeys(keys) {
254
+ return keys.sort((a, b) => {
255
+ if (b.count !== a.count) return b.count - a.count
256
+ for (let i = 0; i < Math.min(a.key.length, b.key.length); i++) {
257
+ const aVal = a.key[i]
258
+ const bVal = b.key[i]
259
+ if (typeof aVal === "number" && typeof bVal === "string") return -1
260
+ if (typeof aVal === "string" && typeof bVal === "number") return 1
261
+ if (aVal < bVal) return -1
262
+ if (aVal > bVal) return 1
263
+ }
264
+
265
+ return a.key.length - b.key.length
266
+ })
267
+ }
268
+
269
+ function buildDic(data) {
270
+ // --- Step 1. (Optional) Save original input order if needed.
271
+ data.forEach((entry, idx) => (entry._origIdx = idx))
272
+
273
+ // --- Step 2. Sort the data in "dictionary order."
274
+ // Primary: by key array length (shorter arrays come first).
275
+ // Secondary: for keys of equal length, by the total character length (ascending)
276
+ // so that, for example, ["jane"] (4 chars) comes before ["alice"] (5 chars).
277
+ // Tertiary: if still equal, compare element-by-element using natural order.
278
+ data.sort((a, b) => {
279
+ const keyA = a.key
280
+ const keyB = b.key
281
+
282
+ // Primary: Compare array lengths.
283
+ if (keyA.length !== keyB.length) return keyA.length - keyB.length
284
+
285
+ // Secondary: Compare total character lengths (ascending).
286
+ const totalA = keyA.reduce((acc, x) => acc + x.toString().length, 0)
287
+ const totalB = keyB.reduce((acc, x) => acc + x.toString().length, 0)
288
+ if (totalA !== totalB) return totalA - totalB
289
+ // Tertiary: Compare element-by-element using natural order.
290
+ for (let i = 0; i < keyA.length; i++) {
291
+ const elA = keyA[i]
292
+ const elB = keyB[i]
293
+
294
+ if (typeof elA === typeof elB) {
295
+ if (typeof elA === "number") {
296
+ if (elA !== elB) return elA - elB
297
+ } else if (typeof elA === "string") {
298
+ const cmp = elA.localeCompare(elB, undefined, { numeric: true })
299
+ if (cmp !== 0) return cmp
300
+ } else {
301
+ // Fallback: compare string representations.
302
+ const cmp = elA
303
+ .toString()
304
+ .localeCompare(elB.toString(), undefined, { numeric: true })
305
+ if (cmp !== 0) return cmp
306
+ }
307
+ } else {
308
+ // If types differ, compare string representations.
309
+ const cmp = elA
310
+ .toString()
311
+ .localeCompare(elB.toString(), undefined, { numeric: true })
312
+ if (cmp !== 0) return cmp
313
+ }
314
+ }
315
+
316
+ return 0
317
+ })
318
+
319
+ // --- Step 3. Build the dictionary.
320
+ // Each dictionary entry will be stored as an object with:
321
+ // - original: the original key (an array)
322
+ // - compressed: the computed compressed representation.
323
+ const dict = []
324
+
325
+ // Helper: For a given string, look for a previously defined simple key (an array of length 1).
326
+ function getPointerIndex(str) {
327
+ for (let i = 0; i < dict.length; i++) {
328
+ if (dict[i].original.length === 1 && dict[i].original[0] === str) return i
329
+ }
330
+ return -1
331
+ }
332
+
333
+ // Helper: Element-by-element compression.
334
+ // For each element in a composite key, if it is a string that already exists as a simple key,
335
+ // replace one or more consecutive occurrences with a pointer.
336
+ // A single occurrence becomes [dictIndex]; a group becomes [dictIndex, 0].
337
+ function compressElementByElement(key) {
338
+ const rep = []
339
+ let i = 0
340
+ while (i < key.length) {
341
+ const el = key[i]
342
+ if (typeof el === "string") {
343
+ const ptrIndex = getPointerIndex(el)
344
+ if (ptrIndex !== -1) {
345
+ let j = i
346
+ while (j < key.length && key[j] === el) {
347
+ j++
348
+ }
349
+ const groupLen = j - i
350
+ rep.push(groupLen === 1 ? [ptrIndex] : [ptrIndex, 0])
351
+ i = j
352
+ continue
353
+ }
354
+ }
355
+ rep.push(el)
356
+ i++
357
+ }
358
+ return rep
359
+ }
360
+
361
+ // Helper: Compute a "cost" for a given representation.
362
+ // Each literal (number or string) counts as 1; a pointer array counts as the number of numbers it holds.
363
+ function computeCost(rep) {
364
+ let cost = 0
365
+ for (const token of rep) cost += Array.isArray(token) ? token.length : 1
366
+ return cost
367
+ }
368
+
369
+ // Helper: Full segmentation compression.
370
+ // Try to segment the entire key as a concatenation of one or more previously defined dictionary entries.
371
+ // Uses dynamic programming over the key array.
372
+ // Returns an object { cost, seg } where seg is an array of dictionary indices.
373
+ function segmentKey(key) {
374
+ const n = key.length
375
+ const dp = Array(n + 1).fill(null)
376
+ dp[n] = { cost: 0, seg: [] }
377
+
378
+ for (let i = n - 1; i >= 0; i--) {
379
+ let best = null
380
+ // Try every dictionary entry.
381
+ for (let d = 0; d < dict.length; d++) {
382
+ const candidate = dict[d].original
383
+ const m = candidate.length
384
+ if (i + m <= n) {
385
+ let match = true
386
+ for (let k = 0; k < m; k++) {
387
+ if (key[i + k] !== candidate[k]) {
388
+ match = false
389
+ break
390
+ }
391
+ }
392
+ if (match && dp[i + m] !== null) {
393
+ const candidateCost = 1 + dp[i + m].cost // cost 1 for using this pointer.
394
+ if (best === null || candidateCost < best.cost) {
395
+ best = { cost: candidateCost, seg: [d].concat(dp[i + m].seg) }
396
+ }
397
+ }
398
+ }
399
+ }
400
+ dp[i] = best
401
+ }
402
+ return dp[0]
403
+ }
404
+
405
+ // Process each entry (in the sorted, deterministic order).
406
+ for (const entry of data) {
407
+ const key = entry.key
408
+ let compressed
409
+ if (key.length === 1) {
410
+ // For simple keys, copy as-is.
411
+ compressed = key.slice()
412
+ } else {
413
+ // Try element-by-element compression.
414
+ const repA = compressElementByElement(key)
415
+ let bestCost = computeCost(repA)
416
+ let bestRep = repA
417
+
418
+ // Also try full segmentation over the entire key.
419
+ const segRes = segmentKey(key)
420
+ if (segRes !== null) {
421
+ const repB = [segRes.seg] // Represent segmentation as a pointer.
422
+ const costB = segRes.cost
423
+ if (costB < bestCost) {
424
+ bestCost = costB
425
+ bestRep = repB
426
+ }
427
+ }
428
+
429
+ // Now try partial segmentation: try segmenting a prefix and then appending the literal remainder.
430
+ const n = key.length
431
+ for (let i = 1; i < n; i++) {
432
+ const prefixSeg = segmentKey(key.slice(0, i))
433
+ if (prefixSeg !== null) {
434
+ const literalPart = key.slice(i)
435
+ const candidateCost = prefixSeg.cost + computeCost(literalPart)
436
+ if (candidateCost < bestCost) {
437
+ bestCost = candidateCost
438
+ // Build candidate representation: pointer for the segmented prefix followed by literal remainder.
439
+ bestRep = [prefixSeg.seg].concat(literalPart)
440
+ }
441
+ }
442
+ }
443
+
444
+ compressed = bestRep
445
+ }
446
+ dict.push({ original: key, compressed })
447
+ }
448
+
449
+ // --- Step 4. Return the dictionary and key map.
450
+ // "dictionary" is an array of compressed keys.
451
+ // "keyMap" is the array of original keys (in the same, deterministic order).
452
+ return {
453
+ dictionary: dict.map(entry => {
454
+ return entry.compressed.length === 1 && !is(Array, entry.compressed[0])
455
+ ? entry.compressed[0]
456
+ : entry.compressed
457
+ }),
458
+ keyMap: dict.map(entry => entry.original),
459
+ }
460
+ }
461
+ const genDic = compose(buildDic, filterDic, sortKeys, countKeys, listKeys)
462
+
463
+ function listKeys(v, key = [], keys = []) {
464
+ if (Array.isArray(v)) {
465
+ let i = 0
466
+ for (const v2 of v) {
467
+ listKeys(v2, append(i, key), keys)
468
+ i++
469
+ }
470
+ } else if (typeof v === "object" && v !== null) {
471
+ for (const k in v) listKeys(v[k], append(k, key), keys)
472
+ } else {
473
+ keys.push(key)
474
+ }
475
+ return keys
476
+ }
477
+
478
+ function isPrefix(path, prefix) {
479
+ if (prefix.length > path.length) return false
480
+ for (let i = 0; i < prefix.length; i++) {
481
+ if (!equals(path[i], prefix[i])) return false
482
+ }
483
+ return true
484
+ }
485
+
486
+ function applyDicToPath(path, sortedDic) {
487
+ // Base case: if the path is empty, nothing to replace.
488
+ if (path.length === 0) return []
489
+ // Iterate over the dictionary entries in descending order.
490
+ for (const { entry, index } of sortedDic) {
491
+ if (isPrefix(path, entry)) {
492
+ // Found a match: remove the matched prefix.
493
+ const remainder = path.slice(entry.length)
494
+ // Recursively apply dictionary replacement on the remainder.
495
+ const replacedRemainder = applyDicToPath(remainder, sortedDic)
496
+ // If the remainder is completely replaced (i.e. replacedRemainder is a single dictionary reference array),
497
+ // then merge the current dictionary index with that.
498
+ if (replacedRemainder.length === 0) {
499
+ // No remainder: simply return the dictionary reference.
500
+ return [[index]]
501
+ }
502
+ if (Array.isArray(replacedRemainder[0])) {
503
+ // The first component is already a dictionary reference: merge the indices.
504
+ return [[index, ...replacedRemainder[0]]]
505
+ } else {
506
+ // Otherwise, return the dictionary reference for the prefix and then the literal remainder.
507
+ return [[index]].concat(replacedRemainder)
508
+ }
509
+ }
510
+ }
511
+ // If no dictionary entry applies, return the original literal path.
512
+ return path
513
+ }
514
+
515
+ function applyDic(arr, dic) {
516
+ // Build sorted dictionary entries in descending order by length.
517
+ const sortedDic = dic
518
+ .map((entry, index) => ({ entry, index }))
519
+ .sort((a, b) => b.entry.length - a.entry.length)
520
+ // For each pair, apply dictionary replacement to the path.
521
+ return arr.map(pair => {
522
+ const newPath = applyDicToPath(pair[0], sortedDic)
523
+ return [newPath, pair[1]]
524
+ })
525
+ }
526
+
527
+ function encodePaths(data, index = false) {
528
+ let i = 0
529
+ for (let v of data) {
530
+ let path = []
531
+ for (let v2 of v[0]) {
532
+ if (is(Number, v2)) {
533
+ path.push([0, 0, ...to128(v2)])
534
+ } else if (is(String, v2)) {
535
+ const key = v2.split("").map(c => c.charCodeAt(0))
536
+ let k = []
537
+ push(k, [key.length, ...(key.length == 0 ? [1] : key)])
538
+ path.push(k)
539
+ } else if (is(Array, v2)) {
540
+ if (v2.length === 1) path.push([0, 3, ...to128(v2[0])])
541
+ else path.push([0, 4, ...to128(v2.length), ...to128s(v2)])
542
+ }
543
+ }
544
+ v[0] = path
545
+ if (index) v.push(i)
546
+ i++
547
+ }
548
+ return data
549
+ }
550
+
551
+ function mapDic(dic, len) {
552
+ let _map = []
553
+ while (dic.length > 0) {
554
+ let dlen = shift(dic)
555
+ let _elms = []
556
+ while (dlen > 0) {
557
+ let type = dic.shift()
558
+ let elms = []
559
+ if (type == 7) {
560
+ let slen = shift(dic)
561
+ elms.push(slen)
562
+ for (let i = 0; i < slen; i++) elms.push(shift(dic))
563
+ _elms.push(elms)
564
+ } else if (type == 3) {
565
+ elms = concat(elms, [0, 0, shift(dic)])
566
+ _elms.push(elms)
567
+ } else if (type == 9) {
568
+ for (let v2 of _map[shift(dic)]) _elms.push(v2)
569
+ }
570
+ dlen--
571
+ }
572
+ _map.push(_elms)
573
+ if (_map.length === len) break
574
+ }
575
+ return _map
576
+ }
577
+
578
+ function encodeDic(dict) {
579
+ let enc = []
580
+ let offsets = []
581
+ let i = 0
582
+ for (let v of dict) {
583
+ let len = 1
584
+ let elms = []
585
+ if (!is(String, v)) {
586
+ len = 0
587
+ for (let v2 of v) {
588
+ if (is(Array, v2)) {
589
+ len += v2.length
590
+ for (let v3 of v2) push(elms, [9, v3])
591
+ } else {
592
+ len += 1
593
+ if (is(String, v2)) {
594
+ elms.push(7)
595
+ push(elms, v2.length)
596
+ push(
597
+ elms,
598
+ v2.split("").map(c => c.charCodeAt(0)),
599
+ )
600
+ } else {
601
+ push(elms, [3, v2])
602
+ }
603
+ }
604
+ }
605
+ } else {
606
+ elms.push(7)
607
+ push(elms, v.length)
608
+ push(
609
+ elms,
610
+ v.split("").map(c => c.charCodeAt(0)),
611
+ )
612
+ }
613
+ const _elms = [...to128(len), ...elms]
614
+ push(offsets, _elms.length)
615
+ enc = concat(enc, _elms)
616
+ i++
617
+ }
618
+ return { offsets, enc }
619
+ }
620
+ const addDicPos = ret => {
621
+ let dic_pos0 = to128(ret.length + 1)
622
+ let dic_pos = ret.length + dic_pos0.length
623
+ let dic_pos2 = to128(dic_pos)
624
+ if (dic_pos0.length !== dic_pos2.length) dic_pos += 1
625
+ unshift(ret, dic_pos) // if length > 256 offset changes
626
+ }
627
+
628
+ const sortEnc = (enc, sort) => {
629
+ if (!sort) return null
630
+ else {
631
+ let _enc = clone(enc)
632
+ _enc = encodePaths(_enc, true)
633
+ _enc.sort((a, b) => {
634
+ const isUndefined = v => typeof v == "undefined"
635
+ const max = Math.max(a[0].length, b[0].length)
636
+ if (max > 0) {
637
+ for (let i = 1; i < max; i++) {
638
+ const exA = !isUndefined(a[0][i])
639
+ const exB = !isUndefined(b[0][i])
640
+ if (exA && !exB) return 1
641
+ if (!exA && exB) return -1
642
+ const max2 = Math.max(a[0][i].length, b[0][i].length)
643
+ if (max2 > 0) {
644
+ for (let i2 = 0; i2 < max2; i2++) {
645
+ const vA = a[0][i][i2]
646
+ const vB = b[0][i][i2]
647
+ const exA = !isUndefined(vA)
648
+ const exB = !isUndefined(vB)
649
+ if (exA && !exB) return 1
650
+ if (!exA && exB) return -1
651
+ if (vA > vB) return 1
652
+ if (vA < vB) return -1
653
+ }
654
+ }
655
+ }
656
+ }
657
+ return 0
658
+ })
659
+ return _enc
660
+ }
661
+ }
662
+
663
+ const getDic = (json, enc, dict) => {
664
+ let dic = null
665
+ let dic_offsets = null
666
+ let diclen = 0
667
+ if (dict) {
668
+ let dictionary = []
669
+ let keyMap
670
+ ;({ dictionary, keyMap } = genDic(json))
671
+ if (dictionary.length > 0) {
672
+ ;({ enc: dic, offsets: dic_offsets } = encodeDic(dictionary))
673
+ }
674
+ if (dic) enc = applyDic(enc, keyMap)
675
+ diclen = dictionary.length
676
+ }
677
+ return { dic_offsets, diclen, dic, enc }
678
+ }
679
+
680
+ function encode(json, { dict = true, offset = true, sort = true } = {}) {
681
+ let enc = _encode(json)
682
+ let _enc = sortEnc(enc, sort)
683
+ let { dic_offsets, diclen, dic, enc: enc3 } = getDic(json, enc, dict)
684
+ enc = enc3
685
+ enc = encodePaths(enc)
686
+ enc = sort ? _enc.map(v => enc[v[2]]) : enc
687
+
688
+ // build encode
689
+ let ret = concat(
690
+ dic ?? [],
691
+ enc.reduce((arr, v) => arr.concat([...flattenPath(v[0]), ...v[1]]), []),
692
+ )
693
+ addDicPos(ret)
694
+
695
+ if (offset) {
696
+ // add dictionary offsets
697
+ if (diclen > 0) {
698
+ push(ret, diclen)
699
+ for (let v of dic_offsets) push(ret, v)
700
+ } else ret.push(0)
701
+
702
+ // add offset table
703
+ for (let v of enc) {
704
+ push(ret, flatten(v[0]).length + flatten(v[1]).length + 1)
705
+ }
706
+ }
707
+ return ret
708
+ }
709
+
710
+ function _decode(arr) {
711
+ let vals = []
712
+ let dic = []
713
+ let len = arr.length
714
+ let [offset, offset_len] = shift(arr, true)
715
+ let isDic = arr[offset - offset_len]
716
+ if (isDic > 0) dic = mapDic(arr, isDic)
717
+ while (len - offset + 1 < arr.length) {
718
+ let keylen = arr.shift() // key length
719
+ let keys = []
720
+ let val = null
721
+ while (keylen > 0) {
722
+ const plen2 = shift(arr)
723
+ if (plen2 == 0) {
724
+ const plen3 = arr.shift() // 02 is not used shift 3,4
725
+ if (plen3 == 1) {
726
+ // bare (01)
727
+ keys.push([plen2, plen3])
728
+ } else if (plen3 == 0) {
729
+ // array (00)
730
+ keys.push([plen2, plen3, shift(arr)])
731
+ } else if (plen3 == 3) {
732
+ // ref (03)
733
+ const _keys = dic[shift(arr)]
734
+ for (const k of _keys) keys.push(k)
735
+ } else if (plen3 == 4) {
736
+ // multi refs (04)
737
+ let key = []
738
+ let plen4 = shift(arr)
739
+ for (let i2 = 0; i2 < plen4; i2++) {
740
+ const _keys = dic[shift(arr)]
741
+ for (const k of _keys) keys.push(k)
742
+ }
743
+ }
744
+ } else if (plen2 != 0) {
745
+ // string
746
+ let key = []
747
+ move(arr, key, plen2)
748
+ keys.push([plen2, ...key])
749
+ }
750
+ keylen--
751
+ }
752
+ const type = arr.shift()
753
+ val = [type]
754
+ if (type == 5 || type == 6) {
755
+ move(arr, val)
756
+ val.push(arr.shift())
757
+ } else if (type == 3 || type == 4) {
758
+ move(arr, val)
759
+ } else if (type == 7) {
760
+ move(arr, val)
761
+ const strlen = val[val.length - 1]
762
+ move(arr, val, strlen)
763
+ }
764
+ vals.push([keys, val])
765
+ }
766
+ return vals
767
+ }
768
+
769
+ // 0: null, 1: true, 2: false, 3: positive integer, 4: negative integer, 5: positive float, 6: negative float, 7: string, 8: object, 9: ref
770
+
771
+ function encodeVal(v) {
772
+ let _vals = new u8()
773
+ let vals = []
774
+ if (typeof v == "number" || typeof v == "bigint") {
775
+ const int = Number.isInteger(v)
776
+ let moved = 0
777
+ let num = v
778
+ while (num % 1 != 0) {
779
+ num *= 10
780
+ moved += 1
781
+ }
782
+ let type = 3
783
+ if (v >= 0) {
784
+ if (moved > 0) type = 5
785
+ } else {
786
+ if (moved > 0) type = 6
787
+ else type = 4
788
+ }
789
+ vals.push(type)
790
+ if (moved > 0) vals.push(moved)
791
+ push(vals, v < 0 ? -num : num)
792
+ } else if (typeof v == "boolean") vals.push(v ? 1 : 2)
793
+ else if (v == null) vals = [0]
794
+ else if (typeof v == "string") {
795
+ vals = [7]
796
+ push(vals, v.length)
797
+ for (let v2 of v.split("")) push(vals, v2.charCodeAt(0))
798
+ } else vals = [8, ...encode(v)]
799
+ return vals
800
+ }
801
+
802
+ function decodeVal(arr) {
803
+ if (!is(Array, arr)) return
804
+ const type = arr[0]
805
+ const _val = arr[1]
806
+ let val = null
807
+ if (type == 0) {
808
+ val = null
809
+ } else if (type == 1) {
810
+ val = true
811
+ } else if (type == 2) {
812
+ val = false
813
+ } else if (type == 3) {
814
+ val = arr[1]
815
+ } else if (type == 4) {
816
+ val = arr[1] * -1
817
+ } else if (type == 5) {
818
+ val = arr[2]
819
+ for (let i = 0; i < arr[1]; i++) {
820
+ val /= 10
821
+ }
822
+ } else if (type == 6) {
823
+ val = arr[2] * -1
824
+ for (let i = 0; i < arr[1]; i++) {
825
+ val /= 10
826
+ }
827
+ } else if (type == 7) {
828
+ const _arr = arr.slice(2)
829
+ val = _arr.map(c => String.fromCharCode(Number(c))).join("")
830
+ } else if (type == 8) {
831
+ val = decode(arr.slice(1))
832
+ }
833
+ return val
834
+ }
835
+
836
+ function decode(_arr) {
837
+ let arr = Array.from(_arr)
838
+ const decoded = _decode(arr)
839
+ let json =
840
+ decoded[0]?.[0]?.[0]?.[0] == 0 && decoded[0]?.[0]?.[0]?.[1] == 0 ? [] : {}
841
+ for (const v of decoded) {
842
+ const keys = v[0].map(v2 => {
843
+ if (v2[0] == 0) {
844
+ if (v2[1] == 1) return ""
845
+ return v2[2]
846
+ } else {
847
+ return v2
848
+ .slice(1)
849
+ .map(c => String.fromCharCode(Number(c)))
850
+ .join("")
851
+ }
852
+ })
853
+ if (keys.length == 0) json = decodeVal(v[1])
854
+ else {
855
+ let obj = json
856
+ let i = 0
857
+ for (const k of keys) {
858
+ if (typeof k == "number") {
859
+ if (typeof keys[i + 1] == "undefined") {
860
+ obj[k] = decodeVal(v[1])
861
+ } else {
862
+ if (typeof obj[k] == "undefined") {
863
+ if (typeof keys[i + 1] == "string") {
864
+ obj[k] = {}
865
+ } else {
866
+ obj[k] = []
867
+ }
868
+ }
869
+ }
870
+ } else {
871
+ if (typeof obj[k] == "undefined") {
872
+ if (typeof keys[i + 1] == "undefined") {
873
+ obj[k] = decodeVal(v[1])
874
+ } else if (typeof keys[i + 1] == "string") {
875
+ obj[k] = {}
876
+ } else {
877
+ obj[k] = []
878
+ }
879
+ }
880
+ }
881
+ obj = obj[k]
882
+ i++
883
+ }
884
+ }
885
+ }
886
+ return json
887
+ }
888
+
889
+ const toIndex = str => {
890
+ return (
891
+ "1" +
892
+ str
893
+ .split("")
894
+ .map(s => base64Map[s])
895
+ .join("")
896
+ )
897
+ }
898
+
899
+ const fromIndex = id => {
900
+ let _id = id.toString().split("")
901
+ _id.shift()
902
+ return splitEvery(2, _id)
903
+ .map(s => {
904
+ return strMap[s.join("")]
905
+ })
906
+ .join("")
907
+ }
908
+
909
+ function toSignal(arr, uint_len = 75) {
910
+ const _arr = flatten(
911
+ arr.map(n => {
912
+ let str = splitEvery(8, n.toString().split(""))
913
+ let i = 0
914
+ str = str.map(s => {
915
+ const len = i == str.length - 1 ? s.length : 9
916
+ i++
917
+ return len.toString() + s.join("")
918
+ })
919
+ return str
920
+ }),
921
+ )
922
+ let _arr2 = []
923
+ let one = 0
924
+ let i = 0
925
+ let start = null
926
+ if (!uint_len) uint_len = _arr * 100
927
+ for (let v of _arr) {
928
+ _arr2.push(v)
929
+ if (v.length - 1 == 1) {
930
+ if (start == null) start = i
931
+ one += v.length - 1
932
+ if (one == 9) {
933
+ _arr2[start] = `0${one}${_arr2[start][1]}`
934
+ for (let i2 = start + 1; i2 <= i; i2++) _arr2[i2] = `${_arr2[i2][1]}`
935
+ one = 0
936
+ start = null
937
+ }
938
+ } else {
939
+ if (one > 2) {
940
+ _arr2[start] = `0${one}${_arr2[start][1]}`
941
+ for (let i2 = start + 1; i2 < i; i2++) _arr2[i2] = `${_arr2[i2][1]}`
942
+ }
943
+ one = 0
944
+ start = null
945
+ }
946
+ i++
947
+ }
948
+ if (one > 2) {
949
+ _arr2[start] = `0${one}${_arr2[start][1]}`
950
+ for (let i2 = start + 1; i2 <= i - 1; i2++) _arr2[i2] = `${_arr2[i2][1]}`
951
+ }
952
+ let _arr3 = []
953
+ let chain = null
954
+ let cur = 0
955
+ let num = ""
956
+ for (let v of _arr2) {
957
+ if (chain == null && +v[0] == 0) {
958
+ chain = +v[1]
959
+ cur = 1
960
+ num = v
961
+ } else if (chain != null) {
962
+ num += v
963
+ cur++
964
+ if (chain == cur) {
965
+ _arr3.push(num)
966
+ chain = null
967
+ num = ""
968
+ cur = 0
969
+ }
970
+ } else {
971
+ _arr3.push(v)
972
+ }
973
+ }
974
+ if (chain != null) _arr3.push(num)
975
+ let arrs2 = []
976
+ let len2 = 0
977
+ let str2 = ""
978
+ for (let v of _arr3) {
979
+ if (len2 + v.length > uint_len) {
980
+ arrs2.push("1" + str2)
981
+ if (+v[0] == 0) {
982
+ let len3 = uint_len - len2
983
+ if (len3 == 2 || len3 == 3) {
984
+ arrs2[arrs2.length - 1] += `1${v[2]}`
985
+ let new_len = +v[1] - 1
986
+ if (new_len == 2) {
987
+ v = `1${v[3]}1${v[4]}`
988
+ } else {
989
+ v = `0${new_len}${v.slice(3)}`
990
+ }
991
+ } else if (len3 > 3) {
992
+ let new_len = +v[1] - 2
993
+ let old_len = 2
994
+ if (len3 == 4) {
995
+ arrs2[arrs2.length - 1] += `1${v[2]}1${v[3]}`
996
+ } else {
997
+ old_len = len3 - 2
998
+ new_len = +v[1] - old_len
999
+ arrs2[arrs2.length - 1] += `0${old_len}${v.slice(2, 2 + old_len)}`
1000
+ }
1001
+ if (new_len == 1) {
1002
+ v = `1${v[old_len + 2]}`
1003
+ } else if (new_len == 2) {
1004
+ v = `1${v[old_len + 2]}1${v[old_len + 3]}`
1005
+ } else {
1006
+ v = `0${new_len}${v.slice(old_len + 2)}`
1007
+ }
1008
+ }
1009
+ }
1010
+ len2 = 0
1011
+ str2 = ""
1012
+ }
1013
+ len2 += v.length
1014
+ str2 += v
1015
+ }
1016
+ if (str2 != "") arrs2.push("1" + str2)
1017
+ return arrs2
1018
+ }
1019
+
1020
+ function fromSignal(arr) {
1021
+ let _arr = []
1022
+ let prev = ""
1023
+ for (let s of arr) {
1024
+ s = s.slice(1)
1025
+ let str = s.split("")
1026
+ while (str.length > 0) {
1027
+ const len = +str.shift()
1028
+ if (len == 0) {
1029
+ const len2 = +str.shift()
1030
+ for (let i2 = 0; i2 < len2; i2++) {
1031
+ _arr.push(+str[i2])
1032
+ }
1033
+ str = str.slice(len2)
1034
+ } else if (len == 9) {
1035
+ prev += str.slice(0, 8).join("")
1036
+ str = str.slice(8)
1037
+ } else {
1038
+ const nums = str.slice(0, len).join("")
1039
+ str = str.slice(len)
1040
+ _arr.push(+(prev + nums))
1041
+ prev = ""
1042
+ }
1043
+ }
1044
+ }
1045
+ return _arr
1046
+ }
1047
+
1048
+ const path = p => toSignal(encodePath(p))
1049
+ const val = v => toSignal(encodeVal(v))
1050
+ const query = v => toSignal(encodeQuery(v))
1051
+
1052
+ function encodeQuery(v) {
1053
+ if (!Array.isArray(v)) throw Error("query must be an array")
1054
+ const op = v[0]
1055
+ if (isNil(ops[op])) throw Error(`query not supported: ${op}`)
1056
+ return [ops[op], ...encodeVal(v[1])]
1057
+ }
1058
+
1059
+ function decodeQuery(v) {
1060
+ const op = opMap[v[0]]
1061
+ if (isNil(op)) throw Error("op doens't exist")
1062
+ return [op, decodeVal(v.slice(1))]
1063
+ }
1064
+
1065
+ function toUint8(sig) {
1066
+ let num = BigInt(sig)
1067
+ let byteArray = []
1068
+ while (num > 0) {
1069
+ byteArray.push(Number(num % 256n))
1070
+ num /= 256n
1071
+ }
1072
+ return new Uint8Array(byteArray.reverse())
1073
+ }
1074
+ function compress(arr) {
1075
+ let sig = toSignal(arr, false)
1076
+ return toUint8(sig)
1077
+ }
1078
+
1079
+ function decompress(arr) {
1080
+ const str = fromUint8(arr)
1081
+ return fromSignal([str])
1082
+ }
1083
+
1084
+ function fromUint8(arr) {
1085
+ let num = 0n
1086
+ for (let byte of arr) {
1087
+ num = num * 256n + BigInt(byte)
1088
+ }
1089
+ return num.toString()
1090
+ }
1091
+
1092
+ const get = (data, path) => decodeVal(getraw(data, encodePath(path)))
1093
+
1094
+ function getraw(_data, path) {
1095
+ const data = Array.from(_data)
1096
+ let dic = []
1097
+ let [offset, offset_len] = view(data) // only view
1098
+ let isDic = data[offset]
1099
+ if (isDic > 0) dic = mapDic(data.slice(offset_len), isDic) // handle this
1100
+ let cur = offset + 1
1101
+ let offsets = { dic: [], data: [] }
1102
+ let p = offset_len
1103
+ if (isDic > 0) {
1104
+ offsets.dic[0] = offset_len
1105
+ for (let i2 = 0; i2 < isDic; i2++) {
1106
+ const [o, len] = view(data, cur)
1107
+ p += o
1108
+ cur += len
1109
+ offsets.dic.push(p)
1110
+ }
1111
+ } else offsets.data[0] = 0
1112
+ while (cur < data.length) {
1113
+ offsets.data.push(p)
1114
+ const [o, len] = view(data, cur)
1115
+ p += o
1116
+ cur += len
1117
+ }
1118
+
1119
+ for (let i3 = 0; i3 < offsets.data.length; i3++) {
1120
+ let c = offsets.data[i3] // cursor
1121
+ let pc = 0 // keep track of path cursor
1122
+ let [klen, len] = view(data, c)
1123
+ c += len
1124
+ pc++
1125
+ let ok = true
1126
+ for (let i2 = 0; i2 < klen; i2++) {
1127
+ const [type, len] = view(data, c)
1128
+ c += len
1129
+
1130
+ if (type === 0) {
1131
+ const [subtype, sublen] = view(data, c)
1132
+ c += sublen
1133
+ if (subtype === 3) {
1134
+ // no check
1135
+ const [ref, reflen] = view(data, c)
1136
+ c += reflen
1137
+ let d = offsets.dic[ref]
1138
+ const getDic = x => {
1139
+ let [_len, len] = view(data, x)
1140
+ x += len
1141
+ let res = []
1142
+ for (let i = 0; i < _len; i++) {
1143
+ let [dtype, len] = view(data, x)
1144
+ x += len
1145
+ if (dtype === 9) {
1146
+ res = concat(res, getDic(offsets.dic[data[x++]]))
1147
+ } else if (dtype === 7) {
1148
+ let [slen, len] = view(data, x)
1149
+ x += len
1150
+ res.push(slen)
1151
+ for (let i2 = 0; i2 < slen; i2++) {
1152
+ let [y, len] = view(data, x)
1153
+ x += len
1154
+ res.push(y)
1155
+ }
1156
+ } else {
1157
+ res.push(0)
1158
+ res.push(0)
1159
+ let [y, len] = view(data, x)
1160
+ x += len
1161
+ res.push(y)
1162
+ }
1163
+ }
1164
+ return res
1165
+ }
1166
+ const dic = getDic(d)
1167
+ for (let v3 of dic) {
1168
+ if (path[pc++] !== v3) {
1169
+ ok = false
1170
+ break
1171
+ }
1172
+ }
1173
+ } else if (subtype === 0) {
1174
+ // check
1175
+ if (path[pc++] !== type) {
1176
+ ok = false
1177
+ break
1178
+ }
1179
+ if (path[pc++] !== subtype) {
1180
+ ok = false
1181
+ break
1182
+ }
1183
+ let [y, len] = view(data, c)
1184
+ c += len
1185
+ if (path[pc++] !== y) {
1186
+ ok = false
1187
+ break
1188
+ }
1189
+ }
1190
+ } else {
1191
+ // this is string
1192
+ const slen = type
1193
+ if (path[pc++] !== slen) {
1194
+ ok = false
1195
+ break
1196
+ }
1197
+ for (let i3 = 0; i3 < slen; i3++) {
1198
+ let [y, len] = view(data, c)
1199
+ c += len
1200
+ if (path[pc++] !== y) {
1201
+ ok = false
1202
+ break
1203
+ }
1204
+ }
1205
+ }
1206
+ }
1207
+ if (!ok) continue
1208
+ if (pc === path.length) {
1209
+ return from128s(data.slice(c, offsets.data[i3 + 1])).arr
1210
+ break
1211
+ }
1212
+ }
1213
+ return
1214
+ }
1215
+
1216
+ function to128(number) {
1217
+ const encoded = []
1218
+ while (number >= 128) {
1219
+ encoded.push((number & 0x7f) | 0x80)
1220
+ number >>= 7
1221
+ }
1222
+ encoded.push(number)
1223
+ return encoded
1224
+ }
1225
+
1226
+ function from128(bytes) {
1227
+ let value = 0
1228
+ let shift = 0
1229
+ for (const byte of bytes) {
1230
+ value |= (byte & 0x7f) << shift
1231
+ if ((byte & 0x80) === 0) break
1232
+ shift += 7
1233
+ }
1234
+ return value
1235
+ }
1236
+
1237
+ function from128s(bytes, limit) {
1238
+ const result = []
1239
+ let i = 0
1240
+ while (i < bytes.length && (limit === undefined || result.length < limit)) {
1241
+ const chunk = []
1242
+ // Collect bytes for one LH128-encoded number.
1243
+ while (i < bytes.length) {
1244
+ chunk.push(bytes[i])
1245
+ if ((bytes[i] & 0x80) === 0) {
1246
+ i++ // move past the terminating byte
1247
+ break
1248
+ }
1249
+ i++
1250
+ }
1251
+ result.push(from128(chunk))
1252
+ }
1253
+ return { arr: result, len: i }
1254
+ }
1255
+ function to128s(numbers) {
1256
+ const result = []
1257
+ for (const num of numbers) result.push(...to128(num))
1258
+ return result
1259
+ }
1260
+
1261
+ const shift = (arr, len = false) => {
1262
+ const res = from128s(arr, 1)
1263
+ arr.splice(0, res.len)
1264
+ return len ? [res.arr[0], res.len] : res.arr[0]
1265
+ }
1266
+
1267
+ const view = (arr, start = 0) => {
1268
+ const res = from128s(arr.slice(start), 1)
1269
+ return [res.arr[0], res.len]
1270
+ }
1271
+
1272
+ const move = (arr, val = [], limit = 1) => {
1273
+ const res = from128s(arr, limit)
1274
+ for (let v of res.arr) val.push(v)
1275
+ arr.splice(0, res.len)
1276
+ }
1277
+
1278
+ const push = (vals, _num) => {
1279
+ if (is(Array, _num)) {
1280
+ for (let v of _num) vals.splice(vals.length, 0, ...to128(v))
1281
+ } else {
1282
+ vals.splice(vals.length, 0, ...to128(_num))
1283
+ }
1284
+ }
1285
+
1286
+ const unshift = (vals, _num) => {
1287
+ let addedCount = 0
1288
+ if (is(Array, _num)) {
1289
+ let encodedBytes = []
1290
+ for (let v of _num) {
1291
+ encodedBytes = encodedBytes.concat(to128(v))
1292
+ }
1293
+ addedCount = encodedBytes.length
1294
+ vals.splice(0, 0, ...encodedBytes)
1295
+ } else {
1296
+ const encoded = to128(_num)
1297
+ addedCount = encoded.length
1298
+ vals.splice(0, 0, ...encoded)
1299
+ }
1300
+ return addedCount
1301
+ }
1302
+ module.exports = {
1303
+ from128s,
1304
+ to128s,
1305
+ to128,
1306
+ from128,
1307
+ get,
1308
+ encode,
1309
+ decode,
1310
+ encodePath,
1311
+ decodePath,
1312
+ encodeVal,
1313
+ decodeVal,
1314
+ pad,
1315
+ _encode,
1316
+ flattenPath,
1317
+ toSignal,
1318
+ fromSignal,
1319
+ toIndex,
1320
+ fromIndex,
1321
+ path,
1322
+ val,
1323
+ query,
1324
+ encodeQuery,
1325
+ decodeQuery,
1326
+ compress,
1327
+ decompress,
1328
+ toUint8,
1329
+ fromUint8,
1330
+ }