compact-encoding 2.6.1 → 2.7.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/README.md +12 -1
- package/index.js +84 -26
- package/lexint.js +114 -0
- package/package.json +1 -1
- package/test.js +158 -0
package/README.md
CHANGED
|
@@ -79,13 +79,20 @@ to build others on top. Feel free to PR more that are missing.
|
|
|
79
79
|
* `cenc.uint16` - Encodes a fixed size uint16. Useful for things like ports.
|
|
80
80
|
* `cenc.uint24` - Encodes a fixed size uint24. Useful for message framing.
|
|
81
81
|
* `cenc.uint32` - Encodes a fixed size uint32. Useful for very large message framing.
|
|
82
|
+
* `cenc.uint40` - Encodes a fixed size uint40.
|
|
83
|
+
* `cenc.uint48` - Encodes a fixed size uint48.
|
|
84
|
+
* `cenc.uint56` - Encodes a fixed size uint56.
|
|
82
85
|
* `cenc.uint64` - Encodes a fixed size uint64.
|
|
83
86
|
* `cenc.int` - Encodes an int using `cenc.uint` with ZigZag encoding.
|
|
84
87
|
* `cenc.int8` - Encodes a fixed size int8 using `cenc.uint8` with ZigZag encoding.
|
|
85
88
|
* `cenc.int16` - Encodes a fixed size int16 using `cenc.uint16` with ZigZag encoding.
|
|
86
89
|
* `cenc.int24` - Encodes a fixed size int24 using `cenc.uint24` with ZigZag encoding.
|
|
87
90
|
* `cenc.int32` - Encodes a fixed size int32 using `cenc.uint32` with ZigZag encoding.
|
|
91
|
+
* `cenc.int40` - Encodes a fixed size int40 using `cenc.uint40` with ZigZag encoding.
|
|
92
|
+
* `cenc.int48` - Encodes a fixed size int48 using `cenc.uint48` with ZigZag encoding.
|
|
93
|
+
* `cenc.int56` - Encodes a fixed size int56 using `cenc.uint56` with ZigZag encoding.
|
|
88
94
|
* `cenc.int64` - Encodes a fixed size int64 using `cenc.uint64` with ZigZag encoding.
|
|
95
|
+
* `cenc.lexint` - Encodes an int using [lexicographic-integer](https://github.com/substack/lexicographic-integer) encoding so that encoded values are lexicographically sorted in ascending numerical order.
|
|
89
96
|
* `cenc.float32` - Encodes a fixed size float32.
|
|
90
97
|
* `cenc.float64` - Encodes a fixed size float64.
|
|
91
98
|
* `cenc.buffer` - Encodes a buffer with its length uint prefixed. When decoding an empty buffer, `null` is returned.
|
|
@@ -99,7 +106,11 @@ to build others on top. Feel free to PR more that are missing.
|
|
|
99
106
|
* `cenc.float32array` - Encodes a float32array with its element length uint prefixed.
|
|
100
107
|
* `cenc.float64array` - Encodes a float64array with its element length uint prefixed.
|
|
101
108
|
* `cenc.bool` - Encodes a boolean as 1 or 0.
|
|
102
|
-
* `cenc.string` - Encodes a utf-8 string, similar to buffer.
|
|
109
|
+
* `cenc.string`, `cenc.utf8` - Encodes a utf-8 string, similar to buffer.
|
|
110
|
+
* `cenc.ascii` - Encodes an ascii string.
|
|
111
|
+
* `cenc.hex` - Encodes a hex string.
|
|
112
|
+
* `cenc.base64` - Encodes a base64 string.
|
|
113
|
+
* `cenc.utf16le`, `cenc.ucs2` - Encodes a utf16le string.
|
|
103
114
|
* `cenc.fixed32` - Encodes a fixed 32 byte buffer.
|
|
104
115
|
* `cenc.fixed64` - Encodes a fixed 64 byte buffer.
|
|
105
116
|
* `cenc.fixed(n)` - Makes a fixed sized encoder.
|
package/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const b4a = require('b4a')
|
|
2
2
|
|
|
3
|
-
const LE = (new Uint8Array(new Uint16Array([
|
|
3
|
+
const LE = (new Uint8Array(new Uint16Array([0xff]).buffer))[0] === 0xff
|
|
4
4
|
const BE = !LE
|
|
5
5
|
|
|
6
6
|
exports.state = function () {
|
|
@@ -58,7 +58,7 @@ const uint16 = exports.uint16 = {
|
|
|
58
58
|
if (state.end - state.start < 2) throw new Error('Out of bounds')
|
|
59
59
|
return (
|
|
60
60
|
state.buffer[state.start++] +
|
|
61
|
-
state.buffer[state.start++] *
|
|
61
|
+
state.buffer[state.start++] * 0x100
|
|
62
62
|
)
|
|
63
63
|
}
|
|
64
64
|
}
|
|
@@ -76,8 +76,8 @@ const uint24 = exports.uint24 = {
|
|
|
76
76
|
if (state.end - state.start < 3) throw new Error('Out of bounds')
|
|
77
77
|
return (
|
|
78
78
|
state.buffer[state.start++] +
|
|
79
|
-
state.buffer[state.start++] *
|
|
80
|
-
state.buffer[state.start++] *
|
|
79
|
+
state.buffer[state.start++] * 0x100 +
|
|
80
|
+
state.buffer[state.start++] * 0x10000
|
|
81
81
|
)
|
|
82
82
|
}
|
|
83
83
|
}
|
|
@@ -96,25 +96,70 @@ const uint32 = exports.uint32 = {
|
|
|
96
96
|
if (state.end - state.start < 4) throw new Error('Out of bounds')
|
|
97
97
|
return (
|
|
98
98
|
state.buffer[state.start++] +
|
|
99
|
-
state.buffer[state.start++] *
|
|
100
|
-
state.buffer[state.start++] *
|
|
101
|
-
state.buffer[state.start++] *
|
|
99
|
+
state.buffer[state.start++] * 0x100 +
|
|
100
|
+
state.buffer[state.start++] * 0x10000 +
|
|
101
|
+
state.buffer[state.start++] * 0x1000000
|
|
102
102
|
)
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
const uint40 = exports.uint40 = {
|
|
107
|
+
preencode (state, n) {
|
|
108
|
+
state.end += 5
|
|
109
|
+
},
|
|
110
|
+
encode (state, n) {
|
|
111
|
+
const r = Math.floor(n / 0x100)
|
|
112
|
+
uint8.encode(state, n)
|
|
113
|
+
uint32.encode(state, r)
|
|
114
|
+
},
|
|
115
|
+
decode (state) {
|
|
116
|
+
if (state.end - state.start < 5) throw new Error('Out of bounds')
|
|
117
|
+
return uint8.decode(state) + 0x100 * uint32.decode(state)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const uint48 = exports.uint48 = {
|
|
122
|
+
preencode (state, n) {
|
|
123
|
+
state.end += 6
|
|
124
|
+
},
|
|
125
|
+
encode (state, n) {
|
|
126
|
+
const r = Math.floor(n / 0x10000)
|
|
127
|
+
uint16.encode(state, n)
|
|
128
|
+
uint32.encode(state, r)
|
|
129
|
+
},
|
|
130
|
+
decode (state) {
|
|
131
|
+
if (state.end - state.start < 6) throw new Error('Out of bounds')
|
|
132
|
+
return uint16.decode(state) + 0x10000 * uint32.decode(state)
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const uint56 = exports.uint56 = {
|
|
137
|
+
preencode (state, n) {
|
|
138
|
+
state.end += 7
|
|
139
|
+
},
|
|
140
|
+
encode (state, n) {
|
|
141
|
+
const r = Math.floor(n / 0x1000000)
|
|
142
|
+
uint24.encode(state, n)
|
|
143
|
+
uint32.encode(state, r)
|
|
144
|
+
},
|
|
145
|
+
decode (state) {
|
|
146
|
+
if (state.end - state.start < 7) throw new Error('Out of bounds')
|
|
147
|
+
return uint24.decode(state) + 0x1000000 * uint32.decode(state)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
106
151
|
const uint64 = exports.uint64 = {
|
|
107
152
|
preencode (state, n) {
|
|
108
153
|
state.end += 8
|
|
109
154
|
},
|
|
110
155
|
encode (state, n) {
|
|
111
|
-
const r = Math.floor(n /
|
|
156
|
+
const r = Math.floor(n / 0x100000000)
|
|
112
157
|
uint32.encode(state, n)
|
|
113
158
|
uint32.encode(state, r)
|
|
114
159
|
},
|
|
115
160
|
decode (state) {
|
|
116
161
|
if (state.end - state.start < 8) throw new Error('Out of bounds')
|
|
117
|
-
return uint32.decode(state) +
|
|
162
|
+
return uint32.decode(state) + 0x100000000 * uint32.decode(state)
|
|
118
163
|
}
|
|
119
164
|
}
|
|
120
165
|
|
|
@@ -123,8 +168,13 @@ exports.int8 = zigZag(uint8)
|
|
|
123
168
|
exports.int16 = zigZag(uint16)
|
|
124
169
|
exports.int24 = zigZag(uint24)
|
|
125
170
|
exports.int32 = zigZag(uint32)
|
|
171
|
+
exports.int40 = zigZag(uint40)
|
|
172
|
+
exports.int48 = zigZag(uint48)
|
|
173
|
+
exports.int56 = zigZag(uint56)
|
|
126
174
|
exports.int64 = zigZag(uint64)
|
|
127
175
|
|
|
176
|
+
exports.lexint = require('./lexint')
|
|
177
|
+
|
|
128
178
|
exports.float32 = {
|
|
129
179
|
preencode (state, n) {
|
|
130
180
|
state.end += 4
|
|
@@ -236,25 +286,33 @@ exports.int32array = typedarray(Int32Array, b4a.swap32)
|
|
|
236
286
|
exports.float32array = typedarray(Float32Array, b4a.swap32)
|
|
237
287
|
exports.float64array = typedarray(Float64Array, b4a.swap64)
|
|
238
288
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
289
|
+
function string (encoding) {
|
|
290
|
+
return {
|
|
291
|
+
preencode (state, s) {
|
|
292
|
+
const len = b4a.byteLength(s, encoding)
|
|
293
|
+
uint.preencode(state, len)
|
|
294
|
+
state.end += len
|
|
295
|
+
},
|
|
296
|
+
encode (state, s) {
|
|
297
|
+
const len = b4a.byteLength(s, encoding)
|
|
298
|
+
uint.encode(state, len)
|
|
299
|
+
b4a.write(state.buffer, s, state.start, encoding)
|
|
300
|
+
state.start += len
|
|
301
|
+
},
|
|
302
|
+
decode (state) {
|
|
303
|
+
const len = uint.decode(state)
|
|
304
|
+
if (state.end - state.start < len) throw new Error('Out of bounds')
|
|
305
|
+
return b4a.toString(state.buffer, encoding, state.start, (state.start += len))
|
|
306
|
+
}
|
|
255
307
|
}
|
|
256
308
|
}
|
|
257
309
|
|
|
310
|
+
exports.string = exports.utf8 = string('utf-8')
|
|
311
|
+
exports.ascii = string('ascii')
|
|
312
|
+
exports.hex = string('hex')
|
|
313
|
+
exports.base64 = string('base64')
|
|
314
|
+
exports.ucs2 = exports.utf16le = string('utf16le')
|
|
315
|
+
|
|
258
316
|
exports.bool = {
|
|
259
317
|
preencode (state, b) {
|
|
260
318
|
state.end++
|
|
@@ -311,7 +369,7 @@ exports.array = function array (enc) {
|
|
|
311
369
|
},
|
|
312
370
|
decode (state) {
|
|
313
371
|
const len = uint.decode(state)
|
|
314
|
-
if (len >
|
|
372
|
+
if (len > 0x100000) throw new Error('Array is too big')
|
|
315
373
|
const arr = new Array(len)
|
|
316
374
|
for (let i = 0; i < len; i++) arr[i] = enc.decode(state)
|
|
317
375
|
return arr
|
package/lexint.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
preencode,
|
|
3
|
+
encode,
|
|
4
|
+
decode
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
function preencode (state, num) {
|
|
8
|
+
if (num < 251) {
|
|
9
|
+
state.end++
|
|
10
|
+
} else if (num < 256) {
|
|
11
|
+
state.end += 2
|
|
12
|
+
} else if (num < 0x10000) {
|
|
13
|
+
state.end += 3
|
|
14
|
+
} else if (num < 0x1000000) {
|
|
15
|
+
state.end += 4
|
|
16
|
+
} else if (num < 0x100000000) {
|
|
17
|
+
state.end += 5
|
|
18
|
+
} else {
|
|
19
|
+
state.end++
|
|
20
|
+
const exp = Math.floor(Math.log(num) / Math.log(2)) - 32
|
|
21
|
+
preencode(state, exp)
|
|
22
|
+
state.end += 6
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function encode (state, num) {
|
|
27
|
+
const max = 251
|
|
28
|
+
const x = num - max
|
|
29
|
+
|
|
30
|
+
if (num < max) {
|
|
31
|
+
state.buffer[state.start++] = num
|
|
32
|
+
} else if (num < 256) {
|
|
33
|
+
state.buffer[state.start++] = max
|
|
34
|
+
state.buffer[state.start++] = x
|
|
35
|
+
} else if (num < 0x10000) {
|
|
36
|
+
state.buffer[state.start++] = max + 1
|
|
37
|
+
state.buffer[state.start++] = x >> 8 & 0xff
|
|
38
|
+
state.buffer[state.start++] = x & 0xff
|
|
39
|
+
} else if (num < 0x1000000) {
|
|
40
|
+
state.buffer[state.start++] = max + 2
|
|
41
|
+
state.buffer[state.start++] = x >> 16
|
|
42
|
+
state.buffer[state.start++] = x >> 8 & 0xff
|
|
43
|
+
state.buffer[state.start++] = x & 0xff
|
|
44
|
+
} else if (num < 0x100000000) {
|
|
45
|
+
state.buffer[state.start++] = max + 3
|
|
46
|
+
state.buffer[state.start++] = x >> 24
|
|
47
|
+
state.buffer[state.start++] = x >> 16 & 0xff
|
|
48
|
+
state.buffer[state.start++] = x >> 8 & 0xff
|
|
49
|
+
state.buffer[state.start++] = x & 0xff
|
|
50
|
+
} else {
|
|
51
|
+
// need to use Math here as bitwise ops are 32 bit
|
|
52
|
+
const exp = Math.floor(Math.log(x) / Math.log(2)) - 32
|
|
53
|
+
state.buffer[state.start++] = 0xff
|
|
54
|
+
|
|
55
|
+
encode(state, exp)
|
|
56
|
+
const rem = x / Math.pow(2, exp - 11)
|
|
57
|
+
|
|
58
|
+
for (let i = 5; i >= 0; i--) {
|
|
59
|
+
state.buffer[state.start++] = rem / Math.pow(2, 8 * i) & 0xff
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function decode (state) {
|
|
65
|
+
const max = 251
|
|
66
|
+
|
|
67
|
+
if (state.end - state.start < 1) throw new Error('Out of bounds')
|
|
68
|
+
|
|
69
|
+
const flag = state.buffer[state.start++]
|
|
70
|
+
|
|
71
|
+
if (flag < max) return flag
|
|
72
|
+
|
|
73
|
+
if (state.end - state.start < flag - max + 1) {
|
|
74
|
+
throw new Error('Out of bounds.')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (flag < 252) {
|
|
78
|
+
return state.buffer[state.start++] +
|
|
79
|
+
max
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (flag < 253) {
|
|
83
|
+
return (state.buffer[state.start++] << 8) +
|
|
84
|
+
state.buffer[state.start++] +
|
|
85
|
+
max
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (flag < 254) {
|
|
89
|
+
return (state.buffer[state.start++] << 16) +
|
|
90
|
+
(state.buffer[state.start++] << 8) +
|
|
91
|
+
state.buffer[state.start++] +
|
|
92
|
+
max
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// << 24 result may be interpreted as negative
|
|
96
|
+
if (flag < 255) {
|
|
97
|
+
return (state.buffer[state.start++] * 0x1000000) +
|
|
98
|
+
(state.buffer[state.start++] << 16) +
|
|
99
|
+
(state.buffer[state.start++] << 8) +
|
|
100
|
+
state.buffer[state.start++] +
|
|
101
|
+
max
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const exp = decode(state)
|
|
105
|
+
|
|
106
|
+
if (state.end - state.start < 6) throw new Error('Out of bounds')
|
|
107
|
+
|
|
108
|
+
let rem = 0
|
|
109
|
+
for (let i = 5; i >= 0; i--) {
|
|
110
|
+
rem += state.buffer[state.start++] * Math.pow(2, 8 * i)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return (rem * Math.pow(2, exp - 11)) + max
|
|
114
|
+
}
|
package/package.json
CHANGED
package/test.js
CHANGED
|
@@ -407,3 +407,161 @@ tape('array', function (t) {
|
|
|
407
407
|
|
|
408
408
|
t.exception(() => arr.decode(state))
|
|
409
409
|
})
|
|
410
|
+
|
|
411
|
+
tape('lexint: big numbers', function (t) {
|
|
412
|
+
t.plan(1)
|
|
413
|
+
|
|
414
|
+
let prev = enc.encode(enc.lexint, 0)
|
|
415
|
+
|
|
416
|
+
let n
|
|
417
|
+
let skip = 1
|
|
418
|
+
|
|
419
|
+
for (n = 1; n < Number.MAX_VALUE; n += skip) {
|
|
420
|
+
const cur = enc.encode(enc.lexint, n)
|
|
421
|
+
if (Buffer.compare(cur, prev) < 1) break
|
|
422
|
+
prev = cur
|
|
423
|
+
skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
|
|
424
|
+
}
|
|
425
|
+
t.is(n, Infinity)
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
tape('lexint: range precision', function (t) {
|
|
429
|
+
t.plan(2)
|
|
430
|
+
const a = 1e55
|
|
431
|
+
const b = 1.0000000000001e55
|
|
432
|
+
const ha = enc.encode(enc.lexint, a).toString('hex')
|
|
433
|
+
const hb = enc.encode(enc.lexint, b).toString('hex')
|
|
434
|
+
t.not(a, b)
|
|
435
|
+
t.not(ha, hb)
|
|
436
|
+
})
|
|
437
|
+
|
|
438
|
+
tape('lexint: range precision', function (t) {
|
|
439
|
+
let prev = enc.encode(enc.lexint, 0)
|
|
440
|
+
const skip = 0.000000001e55
|
|
441
|
+
for (let i = 0, n = 1e55; i < 1000; n = 1e55 + skip * ++i) {
|
|
442
|
+
const cur = enc.encode(enc.lexint, n)
|
|
443
|
+
if (Buffer.compare(cur, prev) < 1) t.fail('cur <= prev')
|
|
444
|
+
prev = cur
|
|
445
|
+
}
|
|
446
|
+
t.ok(true)
|
|
447
|
+
t.end()
|
|
448
|
+
})
|
|
449
|
+
|
|
450
|
+
tape('lexint: small numbers', function (t) {
|
|
451
|
+
let prev = enc.encode(enc.lexint, 0)
|
|
452
|
+
for (let n = 1; n < 256 * 256 * 16; n++) {
|
|
453
|
+
const cur = enc.encode(enc.lexint, n)
|
|
454
|
+
if (Buffer.compare(cur, prev) < 1) t.fail('cur <= prev')
|
|
455
|
+
prev = cur
|
|
456
|
+
}
|
|
457
|
+
t.ok(true)
|
|
458
|
+
t.end()
|
|
459
|
+
})
|
|
460
|
+
|
|
461
|
+
tape('lexint: throws', function (t) {
|
|
462
|
+
t.exception(() => {
|
|
463
|
+
enc.decode(enc.lexint, Buffer.alloc(1, 251))
|
|
464
|
+
})
|
|
465
|
+
|
|
466
|
+
let num = 252
|
|
467
|
+
|
|
468
|
+
const state = {
|
|
469
|
+
start: 0,
|
|
470
|
+
end: 0,
|
|
471
|
+
buffer: null
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
enc.lexint.preencode(state, num)
|
|
475
|
+
state.buffer = Buffer.alloc(state.end - state.start)
|
|
476
|
+
enc.lexint.encode(state, num)
|
|
477
|
+
|
|
478
|
+
t.exception(() => {
|
|
479
|
+
enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
|
|
480
|
+
})
|
|
481
|
+
|
|
482
|
+
num <<= 8
|
|
483
|
+
|
|
484
|
+
state.start = 0
|
|
485
|
+
state.end = 0
|
|
486
|
+
state.buffer = null
|
|
487
|
+
|
|
488
|
+
enc.lexint.preencode(state, num)
|
|
489
|
+
state.buffer = Buffer.alloc(state.end - state.start)
|
|
490
|
+
enc.lexint.encode(state, num)
|
|
491
|
+
|
|
492
|
+
t.exception(() => {
|
|
493
|
+
enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
|
|
494
|
+
})
|
|
495
|
+
|
|
496
|
+
num <<= 8
|
|
497
|
+
|
|
498
|
+
state.start = 0
|
|
499
|
+
state.end = 0
|
|
500
|
+
state.buffer = null
|
|
501
|
+
|
|
502
|
+
enc.lexint.preencode(state, num)
|
|
503
|
+
state.buffer = Buffer.alloc(state.end - state.start)
|
|
504
|
+
enc.lexint.encode(state, num)
|
|
505
|
+
|
|
506
|
+
t.exception(() => {
|
|
507
|
+
enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
num *= 256
|
|
511
|
+
|
|
512
|
+
state.start = 0
|
|
513
|
+
state.end = 0
|
|
514
|
+
state.buffer = null
|
|
515
|
+
|
|
516
|
+
enc.lexint.preencode(state, num)
|
|
517
|
+
state.buffer = Buffer.alloc(state.end - state.start)
|
|
518
|
+
enc.lexint.encode(state, num)
|
|
519
|
+
|
|
520
|
+
t.exception(() => {
|
|
521
|
+
enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
|
|
522
|
+
})
|
|
523
|
+
|
|
524
|
+
num *= 256 * 256
|
|
525
|
+
|
|
526
|
+
state.start = 0
|
|
527
|
+
state.end = 0
|
|
528
|
+
state.buffer = null
|
|
529
|
+
|
|
530
|
+
enc.lexint.preencode(state, num)
|
|
531
|
+
state.buffer = Buffer.alloc(state.end - state.start)
|
|
532
|
+
enc.lexint.encode(state, num)
|
|
533
|
+
|
|
534
|
+
t.exception(() => {
|
|
535
|
+
enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
|
|
536
|
+
})
|
|
537
|
+
|
|
538
|
+
t.end()
|
|
539
|
+
})
|
|
540
|
+
|
|
541
|
+
tape('lexint: unpack', function (t) {
|
|
542
|
+
let n
|
|
543
|
+
let skip = 1
|
|
544
|
+
|
|
545
|
+
for (n = 1; n < Number.MAX_VALUE; n += skip) {
|
|
546
|
+
const cur = enc.encode(enc.lexint, n)
|
|
547
|
+
compare(n, enc.decode(enc.lexint, cur))
|
|
548
|
+
skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
|
|
549
|
+
}
|
|
550
|
+
t.is(n, Infinity)
|
|
551
|
+
t.end()
|
|
552
|
+
|
|
553
|
+
function compare (a, b) {
|
|
554
|
+
const desc = a + ' !=~ ' + b
|
|
555
|
+
if (/e\+\d+$/.test(a) || /e\+\d+$/.test(b)) {
|
|
556
|
+
if (String(a).slice(0, 8) !== String(b).slice(0, 8) ||
|
|
557
|
+
/e\+(\d+)$/.exec(a)[1] !== /e\+(\d+)$/.exec(b)[1]) {
|
|
558
|
+
t.fail(desc)
|
|
559
|
+
}
|
|
560
|
+
} else {
|
|
561
|
+
if (String(a).slice(0, 8) !== String(b).slice(0, 8) ||
|
|
562
|
+
String(a).length !== String(b).length) {
|
|
563
|
+
t.fail(desc)
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
})
|