hyperbee2 1.1.2 → 2.0.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/index.js +161 -22
- package/lib/cache.js +7 -0
- package/lib/{changes-stream.js → changes.js} +5 -2
- package/lib/compat.js +196 -13
- package/lib/compression.js +163 -0
- package/lib/context.js +50 -9
- package/lib/diff.js +142 -0
- package/lib/encoding.js +136 -6
- package/lib/ranges.js +144 -0
- package/lib/tree.js +97 -48
- package/lib/write.js +270 -101
- package/package.json +4 -2
- package/spec/hyperschema/index.js +356 -47
- package/spec/hyperschema/schema.json +208 -5
- package/lib/key-value-stream.js +0 -134
package/index.js
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
const Hypercore = require('hypercore')
|
|
3
|
-
const
|
|
4
|
-
const
|
|
3
|
+
const { RangeStream } = require('./lib/ranges.js')
|
|
4
|
+
const { DiffStream } = require('./lib/diff.js')
|
|
5
|
+
const { ChangesStream } = require('./lib/changes.js')
|
|
5
6
|
const NodeCache = require('./lib/cache.js')
|
|
6
7
|
const WriteBatch = require('./lib/write.js')
|
|
7
8
|
const CoreContext = require('./lib/context.js')
|
|
8
|
-
const {
|
|
9
|
+
const {
|
|
10
|
+
Pointer,
|
|
11
|
+
KeyPointer,
|
|
12
|
+
ValuePointer,
|
|
13
|
+
TreeNode,
|
|
14
|
+
TreeNodePointer,
|
|
15
|
+
EMPTY
|
|
16
|
+
} = require('./lib/tree.js')
|
|
17
|
+
const { DeltaOp, DeltaCohort, OP_COHORT } = require('./lib/compression.js')
|
|
9
18
|
|
|
10
19
|
class Hyperbee {
|
|
11
20
|
constructor(store, options = {}) {
|
|
12
21
|
const {
|
|
22
|
+
t = 128, // legacy number for now, should be 128 now
|
|
13
23
|
key = null,
|
|
14
24
|
encryption = null,
|
|
15
25
|
core = key ? store.get(key) : store.get({ key, name: 'bee', encryption }),
|
|
16
|
-
context = new CoreContext(store, core, core, encryption),
|
|
26
|
+
context = new CoreContext(store, core, core, encryption, t),
|
|
17
27
|
maxCacheSize = 4096,
|
|
18
28
|
cache = new NodeCache(maxCacheSize),
|
|
19
29
|
root = null,
|
|
@@ -110,8 +120,12 @@ class Hyperbee {
|
|
|
110
120
|
if (!this.view) await this.store.close()
|
|
111
121
|
}
|
|
112
122
|
|
|
113
|
-
createReadStream(
|
|
114
|
-
return new
|
|
123
|
+
createReadStream(options) {
|
|
124
|
+
return new RangeStream(this, options)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
createDiffStream(right, options) {
|
|
128
|
+
return new DiffStream(this, right, options)
|
|
115
129
|
}
|
|
116
130
|
|
|
117
131
|
createChangesStream(options) {
|
|
@@ -119,12 +133,21 @@ class Hyperbee {
|
|
|
119
133
|
}
|
|
120
134
|
|
|
121
135
|
async peek(range = {}) {
|
|
122
|
-
const rs = new
|
|
136
|
+
const rs = new RangeStream(this, { ...range, limit: 1 })
|
|
123
137
|
let entry = null
|
|
124
138
|
for await (const data of rs) entry = data
|
|
125
139
|
return entry
|
|
126
140
|
}
|
|
127
141
|
|
|
142
|
+
download(range = {}) {
|
|
143
|
+
const rs = new RangeStream(this, range)
|
|
144
|
+
rs.resume()
|
|
145
|
+
return new Promise((resolve, reject) => {
|
|
146
|
+
rs.once('error', reject)
|
|
147
|
+
rs.once('close', resolve)
|
|
148
|
+
})
|
|
149
|
+
}
|
|
150
|
+
|
|
128
151
|
bump(ptr) {
|
|
129
152
|
if (ptr.changed) return ptr.value
|
|
130
153
|
this.cache.bump(ptr)
|
|
@@ -132,40 +155,75 @@ class Hyperbee {
|
|
|
132
155
|
return ptr.value
|
|
133
156
|
}
|
|
134
157
|
|
|
158
|
+
// TODO: unslab these and parallize
|
|
135
159
|
async inflate(ptr, activeRequests = this.activeRequests) {
|
|
136
160
|
if (ptr.value) {
|
|
137
161
|
this.bump(ptr)
|
|
138
162
|
return ptr.value
|
|
139
163
|
}
|
|
140
164
|
|
|
141
|
-
const block = await
|
|
142
|
-
|
|
165
|
+
const [block, context] = await Promise.all([
|
|
166
|
+
ptr.context.getBlock(ptr.seq, ptr.core, activeRequests),
|
|
167
|
+
ptr.context.getContext(ptr.core, activeRequests)
|
|
168
|
+
])
|
|
169
|
+
|
|
143
170
|
const tree = block.tree[ptr.offset]
|
|
144
171
|
|
|
145
172
|
const keys = new Array(tree.keys.length)
|
|
146
173
|
const children = new Array(tree.children.length)
|
|
147
174
|
|
|
148
175
|
for (let i = 0; i < keys.length; i++) {
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
k.seq === ptr.seq && k.core === 0 && ptr.core === 0
|
|
152
|
-
? block
|
|
153
|
-
: await context.getBlock(k.seq, k.core, activeRequests)
|
|
154
|
-
const d = blk.data[k.offset]
|
|
155
|
-
keys[i] = new DataPointer(context, k.core, k.seq, k.offset, false, d.key, d.value)
|
|
176
|
+
const d = tree.keys[i]
|
|
177
|
+
keys[i] = inflateKey(context, d, ptr, block, activeRequests)
|
|
156
178
|
}
|
|
157
179
|
|
|
158
180
|
for (let i = 0; i < children.length; i++) {
|
|
159
|
-
const
|
|
160
|
-
children[i] =
|
|
181
|
+
const d = tree.children[i]
|
|
182
|
+
children[i] = inflateChild(context, d, ptr, block, activeRequests)
|
|
161
183
|
}
|
|
162
184
|
|
|
163
|
-
ptr.value = new TreeNode(keys, children)
|
|
185
|
+
ptr.value = new TreeNode(await Promise.all(keys), await Promise.all(children))
|
|
164
186
|
this.bump(ptr)
|
|
165
187
|
|
|
166
188
|
return ptr.value
|
|
167
189
|
}
|
|
168
190
|
|
|
191
|
+
async finalizeKeyPointer(key, activeRequests = this.activeRequests) {
|
|
192
|
+
const value = key.value || (await this.inflateValue(key, activeRequests))
|
|
193
|
+
|
|
194
|
+
return {
|
|
195
|
+
core: key.context.getCore(key.core),
|
|
196
|
+
offset: key.offset,
|
|
197
|
+
seq: key.seq,
|
|
198
|
+
key: key.key,
|
|
199
|
+
value
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
async inflateValue(key, activeRequests = this.activeRequests) {
|
|
204
|
+
if (key.value) return key.value
|
|
205
|
+
if (!key.valuePointer) return null
|
|
206
|
+
|
|
207
|
+
const ptr = key.valuePointer
|
|
208
|
+
|
|
209
|
+
if (ptr.split === 0) {
|
|
210
|
+
const block = await ptr.context.getBlock(ptr.seq, ptr.core, activeRequests)
|
|
211
|
+
return block.values[ptr.offset]
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const blockPromises = new Array(ptr.split + 1)
|
|
215
|
+
for (let i = 0; i < blockPromises.length; i++) {
|
|
216
|
+
blockPromises[i] = ptr.context.getBlock(ptr.seq - ptr.split + i, ptr.core, activeRequests)
|
|
217
|
+
}
|
|
218
|
+
const blocks = await Promise.all(blockPromises)
|
|
219
|
+
const splitValue = new Array(blockPromises.length)
|
|
220
|
+
for (let i = 0; i < splitValue.length - 1; i++) {
|
|
221
|
+
splitValue[i] = blocks[i].values[0]
|
|
222
|
+
}
|
|
223
|
+
splitValue[splitValue.length - 1] = blocks[blocks.length - 1].buffer[ptr.offset]
|
|
224
|
+
return b4a.concat(splitValue)
|
|
225
|
+
}
|
|
226
|
+
|
|
169
227
|
async bootstrap(activeRequests = this.activeRequests) {
|
|
170
228
|
if (!this.root) await this.ready()
|
|
171
229
|
if (this.unbatch) await this._rollback(activeRequests)
|
|
@@ -218,11 +276,11 @@ class Hyperbee {
|
|
|
218
276
|
|
|
219
277
|
while (s < e) {
|
|
220
278
|
const mid = (s + e) >> 1
|
|
221
|
-
const m = v.keys
|
|
279
|
+
const m = v.keys.get(mid)
|
|
222
280
|
|
|
223
281
|
c = b4a.compare(key, m.key)
|
|
224
282
|
|
|
225
|
-
if (c === 0) return m
|
|
283
|
+
if (c === 0) return this.finalizeKeyPointer(m, activeRequests)
|
|
226
284
|
|
|
227
285
|
if (c < 0) e = mid
|
|
228
286
|
else s = mid + 1
|
|
@@ -231,7 +289,7 @@ class Hyperbee {
|
|
|
231
289
|
if (!v.children.length) return null
|
|
232
290
|
|
|
233
291
|
const i = c < 0 ? e : s
|
|
234
|
-
ptr = v.children
|
|
292
|
+
ptr = v.children.get(i)
|
|
235
293
|
}
|
|
236
294
|
}
|
|
237
295
|
}
|
|
@@ -239,3 +297,84 @@ class Hyperbee {
|
|
|
239
297
|
module.exports = Hyperbee
|
|
240
298
|
|
|
241
299
|
function noop() {}
|
|
300
|
+
|
|
301
|
+
function inflateKey(context, d, ptr, block, activeRequests) {
|
|
302
|
+
if (d.type === OP_COHORT) return inflateKeyCohort(context, d, ptr, block, activeRequests)
|
|
303
|
+
return inflateKeyDelta(context, d, ptr, block, activeRequests)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async function inflateKeyDelta(context, d, ptr, block, activeRequests) {
|
|
307
|
+
const k = d.pointer
|
|
308
|
+
|
|
309
|
+
if (!k) return new DeltaOp(false, d.type, d.index, null)
|
|
310
|
+
|
|
311
|
+
const blk =
|
|
312
|
+
k.seq === ptr.seq && k.core === 0 && ptr.core === 0
|
|
313
|
+
? block
|
|
314
|
+
: await context.getBlock(k.seq, k.core, activeRequests)
|
|
315
|
+
|
|
316
|
+
const bk = blk.keys[k.offset]
|
|
317
|
+
|
|
318
|
+
let vp = null
|
|
319
|
+
|
|
320
|
+
if (bk.valuePointer) {
|
|
321
|
+
const p = bk.valuePointer
|
|
322
|
+
const ctx = await context.getContext(k.core, activeRequests)
|
|
323
|
+
vp = new ValuePointer(ctx, p.core, p.seq, p.offset, p.split)
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const kp = new KeyPointer(context, k.core, k.seq, k.offset, false, bk.key, bk.value, vp)
|
|
327
|
+
return new DeltaOp(false, d.type, d.index, kp)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function inflateKeyCohort(context, d, ptr, block, activeRequests) {
|
|
331
|
+
const co = d.pointer
|
|
332
|
+
|
|
333
|
+
const blk =
|
|
334
|
+
co.seq === ptr.seq && co.core === 0 && ptr.core === 0
|
|
335
|
+
? block
|
|
336
|
+
: await context.getBlock(co.seq, co.core, activeRequests)
|
|
337
|
+
|
|
338
|
+
const cohort = blk.cohorts[co.offset]
|
|
339
|
+
const promises = new Array(cohort.length)
|
|
340
|
+
|
|
341
|
+
for (let i = 0; i < cohort.length; i++) {
|
|
342
|
+
const p = cohort[i]
|
|
343
|
+
const k = inflateKeyDelta(context, p, co, blk, activeRequests)
|
|
344
|
+
promises[i] = k
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const p = new Pointer(context, co.core, co.seq, co.offset)
|
|
348
|
+
return new DeltaCohort(false, p, await Promise.all(promises))
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
function inflateChild(context, d, ptr, block, activeRequests) {
|
|
352
|
+
if (d.type === OP_COHORT) return inflateChildCohort(context, d, ptr, block, activeRequests)
|
|
353
|
+
return Promise.resolve(inflateChildDelta(context, d, ptr, block, activeRequests))
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
function inflateChildDelta(context, d, ptr, block, activeRequests) {
|
|
357
|
+
const p = d.pointer
|
|
358
|
+
const c = p && new TreeNodePointer(context, p.core, p.seq, p.offset, false, null)
|
|
359
|
+
return new DeltaOp(false, d.type, d.index, c)
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function inflateChildCohort(context, d, ptr, block, activeRequests) {
|
|
363
|
+
const co = d.pointer
|
|
364
|
+
|
|
365
|
+
const blk =
|
|
366
|
+
co.seq === ptr.seq && co.core === 0 && ptr.core === 0
|
|
367
|
+
? block
|
|
368
|
+
: await context.getBlock(co.seq, co.core, activeRequests)
|
|
369
|
+
|
|
370
|
+
const cohort = blk.cohorts[co.offset]
|
|
371
|
+
const deltas = new Array(cohort.length)
|
|
372
|
+
|
|
373
|
+
for (let i = 0; i < cohort.length; i++) {
|
|
374
|
+
const c = cohort[i]
|
|
375
|
+
deltas[i] = inflateChildDelta(context, c, co, blk, activeRequests)
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
const p = new Pointer(context, co.core, co.seq, co.offset)
|
|
379
|
+
return new DeltaCohort(false, p, deltas)
|
|
380
|
+
}
|
package/lib/cache.js
CHANGED
|
@@ -9,6 +9,13 @@ module.exports = class NodeCache {
|
|
|
9
9
|
return this.latest ? this.latest.next : null
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
empty() {
|
|
13
|
+
const maxSize = this.maxSize
|
|
14
|
+
this.maxSize = 0
|
|
15
|
+
this.gc()
|
|
16
|
+
this.maxSize = maxSize
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
gc() {
|
|
13
20
|
while (this.size > this.maxSize) {
|
|
14
21
|
const old = this.oldest()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const { Readable } = require('streamx')
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
class ChangesStream extends Readable {
|
|
4
4
|
constructor(tree, options = {}) {
|
|
5
|
-
|
|
5
|
+
const { highWaterMark } = options
|
|
6
|
+
super({ eagerOpen: true, highWaterMark })
|
|
6
7
|
|
|
7
8
|
const { head = null, activeRequests = tree.activeRequests } = options
|
|
8
9
|
|
|
@@ -76,3 +77,5 @@ module.exports = class ChangesStream extends Readable {
|
|
|
76
77
|
cb(null)
|
|
77
78
|
}
|
|
78
79
|
}
|
|
80
|
+
|
|
81
|
+
exports.ChangesStream = ChangesStream
|
package/lib/compat.js
CHANGED
|
@@ -1,35 +1,55 @@
|
|
|
1
1
|
// ported from the old protocol buffer impl in old bee
|
|
2
2
|
|
|
3
3
|
const encodings = require('protocol-buffers-encodings')
|
|
4
|
+
const b4a = require('b4a')
|
|
5
|
+
const { OP_COHORT, OP_INSERT } = require('./compression')
|
|
4
6
|
const varint = encodings.varint
|
|
5
7
|
const skip = encodings.skip
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
exports.decode = decodeCompat
|
|
10
|
+
exports.encode = encodeCompat
|
|
8
11
|
|
|
9
12
|
function decodeCompat(buffer, seq) {
|
|
10
|
-
const node = decodeNode(buffer)
|
|
11
|
-
const index = decodeYoloIndex(node.index)
|
|
13
|
+
const node = buffer.length > 1 ? decodeNode(buffer) : null
|
|
14
|
+
const index = node ? decodeYoloIndex(node.index) : { levels: [] }
|
|
12
15
|
const morphed = {
|
|
13
|
-
type:
|
|
16
|
+
type: 1,
|
|
14
17
|
checkpoint: 0,
|
|
15
18
|
batch: { start: 0, end: 0 },
|
|
16
19
|
previous: seq > 1 ? { core: 0, seq: seq - 1 } : null,
|
|
20
|
+
metadata: null,
|
|
17
21
|
tree: [],
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
keys: node ? [{ key: node.key, value: node.value, valuePointer: null }] : [],
|
|
23
|
+
values: [],
|
|
24
|
+
cohorts: []
|
|
20
25
|
}
|
|
21
26
|
|
|
22
27
|
for (const lvl of index.levels) {
|
|
23
28
|
const t = { keys: [], children: [] }
|
|
24
29
|
|
|
25
|
-
|
|
26
|
-
const
|
|
27
|
-
|
|
30
|
+
if (lvl.keys.length) {
|
|
31
|
+
const cohort = []
|
|
32
|
+
const offset = morphed.cohorts.push(cohort) - 1
|
|
33
|
+
|
|
34
|
+
for (let i = 0; i < lvl.keys.length; i++) {
|
|
35
|
+
const seq = lvl.keys[i]
|
|
36
|
+
cohort.push({ type: OP_INSERT, index: i, pointer: { core: 0, seq, offset: 0 } })
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
t.keys.push({ type: OP_COHORT, index: 0, pointer: { core: 0, seq, offset } })
|
|
28
40
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
41
|
+
|
|
42
|
+
if (lvl.children.length) {
|
|
43
|
+
const cohort = []
|
|
44
|
+
const offset = morphed.cohorts.push(cohort) - 1
|
|
45
|
+
|
|
46
|
+
for (let i = 0; i < lvl.children.length; i += 2) {
|
|
47
|
+
const seq = lvl.children[i]
|
|
48
|
+
const offset = lvl.children[i + 1]
|
|
49
|
+
cohort.push({ type: OP_INSERT, index: i / 2, pointer: { core: 0, seq, offset } })
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
t.children.push({ type: OP_COHORT, index: 0, pointer: { core: 0, seq, offset } })
|
|
33
53
|
}
|
|
34
54
|
|
|
35
55
|
morphed.tree.push(t)
|
|
@@ -38,6 +58,39 @@ function decodeCompat(buffer, seq) {
|
|
|
38
58
|
return morphed
|
|
39
59
|
}
|
|
40
60
|
|
|
61
|
+
function encodeCompat(node) {
|
|
62
|
+
const index = { levels: [] }
|
|
63
|
+
|
|
64
|
+
if (node.tree) {
|
|
65
|
+
for (const t of node.tree) {
|
|
66
|
+
const lvl = { keys: [], children: [] }
|
|
67
|
+
for (const k of t.keys) {
|
|
68
|
+
for (const kk of node.cohorts[k.pointer.offset]) {
|
|
69
|
+
lvl.keys.push(kk.pointer.seq)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
for (const c of t.children) {
|
|
73
|
+
for (const cc of node.cohorts[c.pointer.offset]) {
|
|
74
|
+
lvl.children.push(cc.pointer.seq, cc.pointer.offset)
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
index.levels.push(lvl)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const bufIndex = b4a.allocUnsafe(encodingLengthYoloIndex(index))
|
|
82
|
+
encodeYoloIndex(index, bufIndex, 0)
|
|
83
|
+
|
|
84
|
+
const n = {
|
|
85
|
+
key: node.keys[0].key,
|
|
86
|
+
value: node.keys[0].value,
|
|
87
|
+
index: bufIndex
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const buf = b4a.allocUnsafe(encodingLengthNode(n))
|
|
91
|
+
return encodeNode(n, buf, 0)
|
|
92
|
+
}
|
|
93
|
+
|
|
41
94
|
function decodeLevel(buf, offset, end) {
|
|
42
95
|
if (!offset) offset = 0
|
|
43
96
|
if (!end) end = buf.length
|
|
@@ -86,6 +139,74 @@ function decodeLevel(buf, offset, end) {
|
|
|
86
139
|
}
|
|
87
140
|
}
|
|
88
141
|
|
|
142
|
+
function encodingLengthLevel(obj) {
|
|
143
|
+
let length = 0
|
|
144
|
+
if (obj.keys) {
|
|
145
|
+
let packedLen = 0
|
|
146
|
+
for (let i = 0; i < obj.keys.length; i++) {
|
|
147
|
+
if (!obj.keys[i]) continue
|
|
148
|
+
const len = encodings.varint.encodingLength(obj.keys[i])
|
|
149
|
+
packedLen += len
|
|
150
|
+
}
|
|
151
|
+
if (packedLen) {
|
|
152
|
+
length += 1 + packedLen + varint.encodingLength(packedLen)
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (obj.children) {
|
|
156
|
+
let packedLen = 0
|
|
157
|
+
for (let i = 0; i < obj.children.length; i++) {
|
|
158
|
+
if (!obj.children[i]) continue
|
|
159
|
+
const len = encodings.varint.encodingLength(obj.children[i])
|
|
160
|
+
packedLen += len
|
|
161
|
+
}
|
|
162
|
+
if (packedLen) {
|
|
163
|
+
length += 1 + packedLen + varint.encodingLength(packedLen)
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return length
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function encodeLevel(obj, buf, offset) {
|
|
170
|
+
if (!offset) offset = 0
|
|
171
|
+
const oldOffset = offset
|
|
172
|
+
if (obj.keys) {
|
|
173
|
+
let packedLen = 0
|
|
174
|
+
for (let i = 0; i < obj.keys.length; i++) {
|
|
175
|
+
if (!obj.keys[i]) continue
|
|
176
|
+
packedLen += encodings.varint.encodingLength(obj.keys[i])
|
|
177
|
+
}
|
|
178
|
+
if (packedLen) {
|
|
179
|
+
buf[offset++] = 10
|
|
180
|
+
varint.encode(packedLen, buf, offset)
|
|
181
|
+
offset += varint.encode.bytes
|
|
182
|
+
}
|
|
183
|
+
for (let i = 0; i < obj.keys.length; i++) {
|
|
184
|
+
if (!obj.keys[i]) continue
|
|
185
|
+
encodings.varint.encode(obj.keys[i], buf, offset)
|
|
186
|
+
offset += encodings.varint.encode.bytes
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (obj.children) {
|
|
190
|
+
let packedLen = 0
|
|
191
|
+
for (let i = 0; i < obj.children.length; i++) {
|
|
192
|
+
if (!obj.children[i]) continue
|
|
193
|
+
packedLen += encodings.varint.encodingLength(obj.children[i])
|
|
194
|
+
}
|
|
195
|
+
if (packedLen) {
|
|
196
|
+
buf[offset++] = 18
|
|
197
|
+
varint.encode(packedLen, buf, offset)
|
|
198
|
+
offset += varint.encode.bytes
|
|
199
|
+
}
|
|
200
|
+
for (let i = 0; i < obj.children.length; i++) {
|
|
201
|
+
if (!obj.children[i]) continue
|
|
202
|
+
encodings.varint.encode(obj.children[i], buf, offset)
|
|
203
|
+
offset += encodings.varint.encode.bytes
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
encodeLevel.bytes = offset - oldOffset
|
|
207
|
+
return buf
|
|
208
|
+
}
|
|
209
|
+
|
|
89
210
|
function decodeYoloIndex(buf, offset, end) {
|
|
90
211
|
if (!offset) offset = 0
|
|
91
212
|
if (!end) end = buf.length
|
|
@@ -117,6 +238,37 @@ function decodeYoloIndex(buf, offset, end) {
|
|
|
117
238
|
}
|
|
118
239
|
}
|
|
119
240
|
|
|
241
|
+
function encodingLengthYoloIndex(obj) {
|
|
242
|
+
let length = 0
|
|
243
|
+
if (obj.levels) {
|
|
244
|
+
for (let i = 0; i < obj.levels.length; i++) {
|
|
245
|
+
if (!obj.levels[i]) continue
|
|
246
|
+
const len = encodingLengthLevel(obj.levels[i])
|
|
247
|
+
length += varint.encodingLength(len)
|
|
248
|
+
length += 1 + len
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return length
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function encodeYoloIndex(obj, buf, offset) {
|
|
255
|
+
if (!offset) offset = 0
|
|
256
|
+
const oldOffset = offset
|
|
257
|
+
if (obj.levels) {
|
|
258
|
+
for (let i = 0; i < obj.levels.length; i++) {
|
|
259
|
+
if (!obj.levels[i]) continue
|
|
260
|
+
buf[offset++] = 10
|
|
261
|
+
const len = encodingLengthLevel(obj.levels[i])
|
|
262
|
+
varint.encode(len, buf, offset)
|
|
263
|
+
offset += varint.encode.bytes
|
|
264
|
+
encodeLevel(obj.levels[i], buf, offset)
|
|
265
|
+
offset += encodeLevel.bytes
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
encodeYoloIndex.bytes = offset - oldOffset
|
|
269
|
+
return buf
|
|
270
|
+
}
|
|
271
|
+
|
|
120
272
|
function decodeNode(buf, offset, end) {
|
|
121
273
|
if (!offset) offset = 0
|
|
122
274
|
if (!end) end = buf.length
|
|
@@ -162,3 +314,34 @@ function decodeNode(buf, offset, end) {
|
|
|
162
314
|
}
|
|
163
315
|
}
|
|
164
316
|
}
|
|
317
|
+
|
|
318
|
+
function encodingLengthNode(obj) {
|
|
319
|
+
let length = 0
|
|
320
|
+
let len = encodings.bytes.encodingLength(obj.index)
|
|
321
|
+
length += 1 + len
|
|
322
|
+
len = encodings.bytes.encodingLength(obj.key)
|
|
323
|
+
length += 1 + len
|
|
324
|
+
if (obj.value) {
|
|
325
|
+
const len = encodings.bytes.encodingLength(obj.value)
|
|
326
|
+
length += 1 + len
|
|
327
|
+
}
|
|
328
|
+
return length
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function encodeNode(obj, buf, offset) {
|
|
332
|
+
if (!offset) offset = 0
|
|
333
|
+
const oldOffset = offset
|
|
334
|
+
buf[offset++] = 10
|
|
335
|
+
encodings.bytes.encode(obj.index, buf, offset)
|
|
336
|
+
offset += encodings.bytes.encode.bytes
|
|
337
|
+
buf[offset++] = 18
|
|
338
|
+
encodings.bytes.encode(obj.key, buf, offset)
|
|
339
|
+
offset += encodings.bytes.encode.bytes
|
|
340
|
+
if (obj.value) {
|
|
341
|
+
buf[offset++] = 26
|
|
342
|
+
encodings.bytes.encode(obj.value, buf, offset)
|
|
343
|
+
offset += encodings.bytes.encode.bytes
|
|
344
|
+
}
|
|
345
|
+
encodeNode.bytes = offset - oldOffset
|
|
346
|
+
return buf
|
|
347
|
+
}
|