compact-encoding 2.6.1 → 2.9.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.
Files changed (5) hide show
  1. package/README.md +18 -4
  2. package/index.js +112 -30
  3. package/lexint.js +114 -0
  4. package/package.json +1 -1
  5. package/test.js +236 -63
package/README.md CHANGED
@@ -11,13 +11,13 @@ npm install compact-encoding
11
11
  ``` js
12
12
  const cenc = require('compact-encoding')
13
13
 
14
- const state = { start: 0, end: 0, buffer: null }
14
+ const state = cenc.state()
15
15
 
16
16
  // use preencode to figure out how big a buffer is needed
17
17
  cenc.uint.preencode(state, 42)
18
18
  cenc.string.preencode(state, 'hi')
19
19
 
20
- console.log(state) // { start: 0, end: 4, buffer: null }
20
+ console.log(state) // { start: 0, end: 4, buffer: null, cache: null }
21
21
 
22
22
  state.buffer = Buffer.allocUnsafe(state.end)
23
23
 
@@ -36,13 +36,14 @@ cenc.string.decode(state) // 'hi'
36
36
 
37
37
  #### `state`
38
38
 
39
- Should be an object that looks like this `{ start, end, buffer }`.
39
+ Should be an object that looks like this `{ start, end, buffer, cache }`.
40
40
 
41
41
  You can also get a blank state object using `cenc.state()`.
42
42
 
43
43
  * `start` is the byte offset to start encoding/decoding at.
44
44
  * `end` is the byte offset indicating the end of the buffer.
45
45
  * `buffer` should be either a Node.js Buffer or Uint8Array.
46
+ * `cache` is used internally be codecs, starts out as `null`.
46
47
 
47
48
  #### `enc.preencode(state, val)`
48
49
 
@@ -79,13 +80,20 @@ to build others on top. Feel free to PR more that are missing.
79
80
  * `cenc.uint16` - Encodes a fixed size uint16. Useful for things like ports.
80
81
  * `cenc.uint24` - Encodes a fixed size uint24. Useful for message framing.
81
82
  * `cenc.uint32` - Encodes a fixed size uint32. Useful for very large message framing.
83
+ * `cenc.uint40` - Encodes a fixed size uint40.
84
+ * `cenc.uint48` - Encodes a fixed size uint48.
85
+ * `cenc.uint56` - Encodes a fixed size uint56.
82
86
  * `cenc.uint64` - Encodes a fixed size uint64.
83
87
  * `cenc.int` - Encodes an int using `cenc.uint` with ZigZag encoding.
84
88
  * `cenc.int8` - Encodes a fixed size int8 using `cenc.uint8` with ZigZag encoding.
85
89
  * `cenc.int16` - Encodes a fixed size int16 using `cenc.uint16` with ZigZag encoding.
86
90
  * `cenc.int24` - Encodes a fixed size int24 using `cenc.uint24` with ZigZag encoding.
87
91
  * `cenc.int32` - Encodes a fixed size int32 using `cenc.uint32` with ZigZag encoding.
92
+ * `cenc.int40` - Encodes a fixed size int40 using `cenc.uint40` with ZigZag encoding.
93
+ * `cenc.int48` - Encodes a fixed size int48 using `cenc.uint48` with ZigZag encoding.
94
+ * `cenc.int56` - Encodes a fixed size int56 using `cenc.uint56` with ZigZag encoding.
88
95
  * `cenc.int64` - Encodes a fixed size int64 using `cenc.uint64` with ZigZag encoding.
96
+ * `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
97
  * `cenc.float32` - Encodes a fixed size float32.
90
98
  * `cenc.float64` - Encodes a fixed size float64.
91
99
  * `cenc.buffer` - Encodes a buffer with its length uint prefixed. When decoding an empty buffer, `null` is returned.
@@ -99,11 +107,17 @@ to build others on top. Feel free to PR more that are missing.
99
107
  * `cenc.float32array` - Encodes a float32array with its element length uint prefixed.
100
108
  * `cenc.float64array` - Encodes a float64array with its element length uint prefixed.
101
109
  * `cenc.bool` - Encodes a boolean as 1 or 0.
102
- * `cenc.string` - Encodes a utf-8 string, similar to buffer.
110
+ * `cenc.string`, `cenc.utf8` - Encodes a utf-8 string, similar to buffer.
111
+ * `cenc.ascii` - Encodes an ascii string.
112
+ * `cenc.hex` - Encodes a hex string.
113
+ * `cenc.base64` - Encodes a base64 string.
114
+ * `cenc.utf16le`, `cenc.ucs2` - Encodes a utf16le string.
103
115
  * `cenc.fixed32` - Encodes a fixed 32 byte buffer.
104
116
  * `cenc.fixed64` - Encodes a fixed 64 byte buffer.
105
117
  * `cenc.fixed(n)` - Makes a fixed sized encoder.
106
118
  * `cenc.array(enc)` - Makes an array encoder from another encoder. Arrays are uint prefixed with their length.
119
+ * `cenc.json` - Encodes a JSON value as utf-8.
120
+ * `cenc.ndjson` - Encodes a JSON value as newline delimited utf-8.
107
121
  * `cenc.from(enc)` - Makes a compact encoder from a [codec](https://github.com/mafintosh/codecs) or [abstract-encoding](https://github.com/mafintosh/abstract-encoding).
108
122
 
109
123
  ## License
package/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  const b4a = require('b4a')
2
2
 
3
- const LE = (new Uint8Array(new Uint16Array([255]).buffer))[0] === 0xff
3
+ const LE = (new Uint8Array(new Uint16Array([0xff]).buffer))[0] === 0xff
4
4
  const BE = !LE
5
5
 
6
- exports.state = function () {
7
- return { start: 0, end: 0, buffer: null }
6
+ exports.state = function (start = 0, end = 0, buffer = null) {
7
+ return { start, end, buffer, cache: null }
8
8
  }
9
9
 
10
10
  const uint = exports.uint = {
@@ -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++] * 256
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++] * 256 +
80
- state.buffer[state.start++] * 65536
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++] * 256 +
100
- state.buffer[state.start++] * 65536 +
101
- state.buffer[state.start++] * 16777216
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 / 4294967296)
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) + 4294967296 * 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
- exports.string = {
240
- preencode (state, s) {
241
- const len = b4a.byteLength(s)
242
- uint.preencode(state, len)
243
- state.end += len
244
- },
245
- encode (state, s) {
246
- const len = b4a.byteLength(s)
247
- uint.encode(state, len)
248
- b4a.write(state.buffer, s, state.start)
249
- state.start += len
250
- },
251
- decode (state) {
252
- const len = uint.decode(state)
253
- if (state.end - state.start < len) throw new Error('Out of bounds')
254
- return b4a.toString(state.buffer, 'utf-8', state.start, (state.start += len))
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
+ const utf8 = 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 > 1048576) throw new Error('Array is too big')
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
@@ -319,6 +377,30 @@ exports.array = function array (enc) {
319
377
  }
320
378
  }
321
379
 
380
+ exports.json = {
381
+ preencode (state, v) {
382
+ utf8.preencode(state, JSON.stringify(v))
383
+ },
384
+ encode (state, v) {
385
+ utf8.encode(state, JSON.stringify(v))
386
+ },
387
+ decode (state) {
388
+ return JSON.parse(utf8.decode(state))
389
+ }
390
+ }
391
+
392
+ exports.ndjson = {
393
+ preencode (state, v) {
394
+ utf8.preencode(state, JSON.stringify(v) + '\n')
395
+ },
396
+ encode (state, v) {
397
+ utf8.encode(state, JSON.stringify(v) + '\n')
398
+ },
399
+ decode (state) {
400
+ return JSON.parse(utf8.decode(state))
401
+ }
402
+ }
403
+
322
404
  exports.from = function from (enc) {
323
405
  if (enc.preencode) return enc
324
406
  if (enc.encodingLength) return fromAbstractEncoder(enc)
@@ -363,7 +445,7 @@ function fromAbstractEncoder (enc) {
363
445
  }
364
446
 
365
447
  exports.encode = function encode (enc, m) {
366
- const state = { start: 0, end: 0, buffer: null }
448
+ const state = exports.state()
367
449
  enc.preencode(state, m)
368
450
  state.buffer = b4a.allocUnsafe(state.end)
369
451
  enc.encode(state, m)
@@ -371,7 +453,7 @@ exports.encode = function encode (enc, m) {
371
453
  }
372
454
 
373
455
  exports.decode = function decode (enc, buffer) {
374
- return enc.decode({ start: 0, end: buffer.byteLength, buffer })
456
+ return enc.decode(exports.state(0, buffer.byteLength, buffer))
375
457
  }
376
458
 
377
459
  function zigZag (enc) {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compact-encoding",
3
- "version": "2.6.1",
3
+ "version": "2.9.0",
4
4
  "description": "A series of compact encoding schemes for building small and fast parsers and serializers",
5
5
  "main": "index.js",
6
6
  "dependencies": {
package/test.js CHANGED
@@ -5,19 +5,19 @@ tape('uint', function (t) {
5
5
  const state = enc.state()
6
6
 
7
7
  enc.uint.preencode(state, 42)
8
- t.alike(state, { start: 0, end: 1, buffer: null })
8
+ t.alike(state, enc.state(0, 1))
9
9
  enc.uint.preencode(state, 4200)
10
- t.alike(state, { start: 0, end: 4, buffer: null })
10
+ t.alike(state, enc.state(0, 4))
11
11
  enc.uint.preencode(state, Number.MAX_SAFE_INTEGER)
12
- t.alike(state, { start: 0, end: 13, buffer: null })
12
+ t.alike(state, enc.state(0, 13))
13
13
 
14
14
  state.buffer = Buffer.alloc(state.end)
15
15
  enc.uint.encode(state, 42)
16
- t.alike(state, { start: 1, end: 13, buffer: Buffer.from([42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) })
16
+ t.alike(state, enc.state(1, 13, Buffer.from([42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])))
17
17
  enc.uint.encode(state, 4200)
18
- t.alike(state, { start: 4, end: 13, buffer: Buffer.from([42, 0xfd, 104, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0]) })
18
+ t.alike(state, enc.state(4, 13, Buffer.from([42, 0xfd, 104, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0])))
19
19
  enc.uint.encode(state, Number.MAX_SAFE_INTEGER)
20
- t.alike(state, { start: 13, end: 13, buffer: Buffer.from([42, 0xfd, 104, 16, 0xff, 255, 255, 255, 255, 255, 255, 31, 0]) })
20
+ t.alike(state, enc.state(13, 13, Buffer.from([42, 0xfd, 104, 16, 0xff, 255, 255, 255, 255, 255, 255, 31, 0])))
21
21
 
22
22
  state.start = 0
23
23
  t.is(enc.uint.decode(state), 42)
@@ -32,15 +32,15 @@ tape('int', function (t) {
32
32
  const state = enc.state()
33
33
 
34
34
  enc.int.preencode(state, 42)
35
- t.alike(state, { start: 0, end: 1, buffer: null })
35
+ t.alike(state, enc.state(0, 1))
36
36
  enc.int.preencode(state, -4200)
37
- t.alike(state, { start: 0, end: 4, buffer: null })
37
+ t.alike(state, enc.state(0, 4))
38
38
 
39
39
  state.buffer = Buffer.alloc(state.end)
40
40
  enc.int.encode(state, 42)
41
- t.alike(state, { start: 1, end: 4, buffer: Buffer.from([84, 0, 0, 0]) })
41
+ t.alike(state, enc.state(1, 4, Buffer.from([84, 0, 0, 0])))
42
42
  enc.int.encode(state, -4200)
43
- t.alike(state, { start: 4, end: 4, buffer: Buffer.from([84, 0xfd, 207, 32]) })
43
+ t.alike(state, enc.state(4, 4, Buffer.from([84, 0xfd, 207, 32])))
44
44
 
45
45
  state.start = 0
46
46
  t.is(enc.int.decode(state), 42)
@@ -54,12 +54,12 @@ tape('float64', function (t) {
54
54
  const state = enc.state()
55
55
 
56
56
  enc.float64.preencode(state, 162.2377294)
57
- t.alike(state, { start: 0, end: 8, buffer: null })
57
+ t.alike(state, enc.state(0, 8))
58
58
 
59
59
  state.buffer = Buffer.alloc(state.end)
60
- t.alike(state, { start: 0, end: 8, buffer: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]) })
60
+ t.alike(state, enc.state(0, 8, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0])))
61
61
  enc.float64.encode(state, 162.2377294)
62
- t.alike(state, { start: 8, end: 8, buffer: Buffer.from([0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]) })
62
+ t.alike(state, enc.state(8, 8, Buffer.from([0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40])))
63
63
 
64
64
  state.start = 0
65
65
  t.is(enc.float64.decode(state), 162.2377294)
@@ -74,13 +74,13 @@ tape('float64', function (t) {
74
74
 
75
75
  enc.int.preencode(state, 0)
76
76
  enc.float64.preencode(state, 162.2377294)
77
- t.alike(state, { start: 0, end: 9, buffer: null })
77
+ t.alike(state, enc.state(0, 9))
78
78
 
79
79
  state.buffer = Buffer.alloc(state.end)
80
- t.alike(state, { start: 0, end: 9, buffer: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0]) })
80
+ t.alike(state, enc.state(0, 9, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0])))
81
81
  enc.int.encode(state, 0)
82
82
  enc.float64.encode(state, 162.2377294)
83
- t.alike(state, { start: 9, end: 9, buffer: Buffer.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]) })
83
+ t.alike(state, enc.state(9, 9, Buffer.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40])))
84
84
 
85
85
  state.start = 0
86
86
  t.is(enc.int.decode(state), 0)
@@ -91,10 +91,10 @@ tape('float64', function (t) {
91
91
  const buf = Buffer.alloc(10)
92
92
  state.start = 0
93
93
  state.buffer = buf.subarray(1)
94
- t.alike(state, { start: 0, end: 9, buffer: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0]) })
94
+ t.alike(state, enc.state(0, 9, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0])))
95
95
  enc.int.encode(state, 0)
96
96
  enc.float64.encode(state, 162.2377294)
97
- t.alike(state, { start: 9, end: 9, buffer: Buffer.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]) })
97
+ t.alike(state, enc.state(9, 9, Buffer.from([0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40])))
98
98
  t.alike(buf, Buffer.from([0, 0, 0x87, 0xc9, 0xaf, 0x7a, 0x9b, 0x47, 0x64, 0x40]))
99
99
 
100
100
  state.start = 0
@@ -110,7 +110,7 @@ tape('float64', function (t) {
110
110
  enc.float64.preencode(state, 162.2377294)
111
111
  state.buffer = Buffer.alloc(state.end)
112
112
  enc.float64.encode(state, 0)
113
- t.alike(state, { start: 8, end: 8, buffer: Buffer.from([0, 0, 0, 0, 0, 0, 0, 0]) })
113
+ t.alike(state, enc.state(8, 8, Buffer.from([0, 0, 0, 0, 0, 0, 0, 0])))
114
114
 
115
115
  state.start = 0
116
116
  t.is(enc.float64.decode(state), 0)
@@ -124,7 +124,7 @@ tape('float64', function (t) {
124
124
  enc.float64.preencode(state, Infinity)
125
125
  state.buffer = Buffer.alloc(state.end)
126
126
  enc.float64.encode(state, Infinity)
127
- t.alike(state, { start: 8, end: 8, buffer: Buffer.from([0, 0, 0, 0, 0, 0, 0xf0, 0x7f]) })
127
+ t.alike(state, enc.state(8, 8, Buffer.from([0, 0, 0, 0, 0, 0, 0xf0, 0x7f])))
128
128
 
129
129
  state.start = 0
130
130
  t.is(enc.float64.decode(state), Infinity)
@@ -138,7 +138,7 @@ tape('float64', function (t) {
138
138
  enc.float64.preencode(state, 0.1 + 0.2)
139
139
  state.buffer = Buffer.alloc(state.end)
140
140
  enc.float64.encode(state, 0.1 + 0.2)
141
- t.alike(state, { start: 8, end: 8, buffer: Buffer.from([0x34, 0x33, 0x33, 0x33, 0x33, 0x33, 0xd3, 0x3f]) })
141
+ t.alike(state, enc.state(8, 8, Buffer.from([0x34, 0x33, 0x33, 0x33, 0x33, 0x33, 0xd3, 0x3f])))
142
142
 
143
143
  state.start = 0
144
144
  t.is(enc.float64.decode(state), 0.1 + 0.2)
@@ -149,19 +149,19 @@ tape('buffer', function (t) {
149
149
  const state = enc.state()
150
150
 
151
151
  enc.buffer.preencode(state, Buffer.from('hi'))
152
- t.alike(state, { start: 0, end: 3, buffer: null })
152
+ t.alike(state, enc.state(0, 3))
153
153
  enc.buffer.preencode(state, Buffer.from('hello'))
154
- t.alike(state, { start: 0, end: 9, buffer: null })
154
+ t.alike(state, enc.state(0, 9))
155
155
  enc.buffer.preencode(state, null)
156
- t.alike(state, { start: 0, end: 10, buffer: null })
156
+ t.alike(state, enc.state(0, 10))
157
157
 
158
158
  state.buffer = Buffer.alloc(state.end)
159
159
  enc.buffer.encode(state, Buffer.from('hi'))
160
- t.alike(state, { start: 3, end: 10, buffer: Buffer.from('\x02hi\x00\x00\x00\x00\x00\x00\x00') })
160
+ t.alike(state, enc.state(3, 10, Buffer.from('\x02hi\x00\x00\x00\x00\x00\x00\x00')))
161
161
  enc.buffer.encode(state, Buffer.from('hello'))
162
- t.alike(state, { start: 9, end: 10, buffer: Buffer.from('\x02hi\x05hello\x00') })
162
+ t.alike(state, enc.state(9, 10, Buffer.from('\x02hi\x05hello\x00')))
163
163
  enc.buffer.encode(state, null)
164
- t.alike(state, { start: 10, end: 10, buffer: Buffer.from('\x02hi\x05hello\x00') })
164
+ t.alike(state, enc.state(10, 10, Buffer.from('\x02hi\x05hello\x00')))
165
165
 
166
166
  state.start = 0
167
167
  t.alike(enc.buffer.decode(state), Buffer.from('hi'))
@@ -176,11 +176,11 @@ tape('raw', function (t) {
176
176
  const state = enc.state()
177
177
 
178
178
  enc.raw.preencode(state, Buffer.from('hi'))
179
- t.alike(state, { start: 0, end: 2, buffer: null })
179
+ t.alike(state, enc.state(0, 2))
180
180
 
181
181
  state.buffer = Buffer.alloc(state.end)
182
182
  enc.raw.encode(state, Buffer.from('hi'))
183
- t.alike(state, { start: 2, end: 2, buffer: Buffer.from('hi') })
183
+ t.alike(state, enc.state(2, 2, Buffer.from('hi')))
184
184
 
185
185
  state.start = 0
186
186
  t.alike(enc.raw.decode(state), Buffer.from('hi'))
@@ -191,11 +191,11 @@ tape('uint16array', function (t) {
191
191
  const state = enc.state()
192
192
 
193
193
  enc.uint16array.preencode(state, new Uint16Array([1, 2, 3]))
194
- t.alike(state, { start: 0, end: 7, buffer: null })
194
+ t.alike(state, enc.state(0, 7))
195
195
 
196
196
  state.buffer = Buffer.alloc(state.end)
197
197
  enc.uint16array.encode(state, new Uint16Array([1, 2, 3]))
198
- t.alike(state, { start: 7, end: 7, buffer: Buffer.from([3, 1, 0, 2, 0, 3, 0]) })
198
+ t.alike(state, enc.state(7, 7, Buffer.from([3, 1, 0, 2, 0, 3, 0])))
199
199
 
200
200
  state.start = 0
201
201
  t.alike(enc.uint16array.decode(state), new Uint16Array([1, 2, 3]))
@@ -208,15 +208,15 @@ tape('uint32array', function (t) {
208
208
  const state = enc.state()
209
209
 
210
210
  enc.uint32array.preencode(state, new Uint32Array([1]))
211
- t.alike(state, { start: 0, end: 5, buffer: null })
211
+ t.alike(state, enc.state(0, 5))
212
212
  enc.uint32array.preencode(state, new Uint32Array([42, 43]))
213
- t.alike(state, { start: 0, end: 14, buffer: null })
213
+ t.alike(state, enc.state(0, 14))
214
214
 
215
215
  state.buffer = Buffer.alloc(state.end)
216
216
  enc.uint32array.encode(state, new Uint32Array([1]))
217
- t.alike(state, { start: 5, end: 14, buffer: Buffer.from([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) })
217
+ t.alike(state, enc.state(5, 14, Buffer.from([1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])))
218
218
  enc.uint32array.encode(state, new Uint32Array([42, 43]))
219
- t.alike(state, { start: 14, end: 14, buffer: Buffer.from([1, 1, 0, 0, 0, 2, 42, 0, 0, 0, 43, 0, 0, 0]) })
219
+ t.alike(state, enc.state(14, 14, Buffer.from([1, 1, 0, 0, 0, 2, 42, 0, 0, 0, 43, 0, 0, 0])))
220
220
 
221
221
  state.start = 0
222
222
  t.alike(enc.uint32array.decode(state), new Uint32Array([1]))
@@ -230,11 +230,11 @@ tape('int16array', function (t) {
230
230
  const state = enc.state()
231
231
 
232
232
  enc.int16array.preencode(state, new Int16Array([1, -2, 3]))
233
- t.alike(state, { start: 0, end: 7, buffer: null })
233
+ t.alike(state, enc.state(0, 7))
234
234
 
235
235
  state.buffer = Buffer.alloc(state.end)
236
236
  enc.int16array.encode(state, new Int16Array([1, -2, 3]))
237
- t.alike(state, { start: 7, end: 7, buffer: Buffer.from([3, 1, 0, 0xfe, 0xff, 3, 0]) })
237
+ t.alike(state, enc.state(7, 7, Buffer.from([3, 1, 0, 0xfe, 0xff, 3, 0])))
238
238
 
239
239
  state.start = 0
240
240
  t.alike(enc.int16array.decode(state), new Int16Array([1, -2, 3]))
@@ -247,11 +247,11 @@ tape('int32array', function (t) {
247
247
  const state = enc.state()
248
248
 
249
249
  enc.int32array.preencode(state, new Int32Array([1, -2, 3]))
250
- t.alike(state, { start: 0, end: 13, buffer: null })
250
+ t.alike(state, enc.state(0, 13))
251
251
 
252
252
  state.buffer = Buffer.alloc(state.end)
253
253
  enc.int32array.encode(state, new Int32Array([1, -2, 3]))
254
- t.alike(state, { start: 13, end: 13, buffer: Buffer.from([3, 1, 0, 0, 0, 0xfe, 0xff, 0xff, 0xff, 3, 0, 0, 0]) })
254
+ t.alike(state, enc.state(13, 13, Buffer.from([3, 1, 0, 0, 0, 0xfe, 0xff, 0xff, 0xff, 3, 0, 0, 0])))
255
255
 
256
256
  state.start = 0
257
257
  t.alike(enc.int32array.decode(state), new Int32Array([1, -2, 3]))
@@ -264,11 +264,11 @@ tape('float32array', function (t) {
264
264
  const state = enc.state()
265
265
 
266
266
  enc.float32array.preencode(state, new Float32Array([1.1, -2.2, 3.3]))
267
- t.alike(state, { start: 0, end: 13, buffer: null })
267
+ t.alike(state, enc.state(0, 13))
268
268
 
269
269
  state.buffer = Buffer.alloc(state.end)
270
270
  enc.float32array.encode(state, new Float32Array([1.1, -2.2, 3.3]))
271
- t.alike(state, { start: 13, end: 13, buffer: Buffer.from([3, 0xcd, 0xcc, 0x8c, 0x3f, 0xcd, 0xcc, 0x0c, 0xc0, 0x33, 0x33, 0x53, 0x40]) })
271
+ t.alike(state, enc.state(13, 13, Buffer.from([3, 0xcd, 0xcc, 0x8c, 0x3f, 0xcd, 0xcc, 0x0c, 0xc0, 0x33, 0x33, 0x53, 0x40])))
272
272
 
273
273
  state.start = 0
274
274
  t.alike(enc.float32array.decode(state), new Float32Array([1.1, -2.2, 3.3]))
@@ -281,11 +281,11 @@ tape('float64array', function (t) {
281
281
  const state = enc.state()
282
282
 
283
283
  enc.float64array.preencode(state, new Float64Array([1.1, -2.2, 3.3]))
284
- t.alike(state, { start: 0, end: 25, buffer: null })
284
+ t.alike(state, enc.state(0, 25))
285
285
 
286
286
  state.buffer = Buffer.alloc(state.end)
287
287
  enc.float64array.encode(state, new Float64Array([1.1, -2.2, 3.3]))
288
- t.alike(state, { start: 25, end: 25, buffer: Buffer.from([3, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xf1, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x01, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0a, 0x40]) })
288
+ t.alike(state, enc.state(25, 25, Buffer.from([3, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0xf1, 0x3f, 0x9a, 0x99, 0x99, 0x99, 0x99, 0x99, 0x01, 0xc0, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x0a, 0x40])))
289
289
 
290
290
  state.start = 0
291
291
  t.alike(enc.float64array.decode(state), new Float64Array([1.1, -2.2, 3.3]))
@@ -298,15 +298,15 @@ tape('string', function (t) {
298
298
  const state = enc.state()
299
299
 
300
300
  enc.string.preencode(state, '🌾')
301
- t.alike(state, { start: 0, end: 5, buffer: null })
301
+ t.alike(state, enc.state(0, 5))
302
302
  enc.string.preencode(state, 'høsten er fin')
303
- t.alike(state, { start: 0, end: 20, buffer: null })
303
+ t.alike(state, enc.state(0, 20))
304
304
 
305
305
  state.buffer = Buffer.alloc(state.end)
306
306
  enc.string.encode(state, '🌾')
307
- t.alike(state, { start: 5, end: 20, buffer: Buffer.from('\x04🌾\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') })
307
+ t.alike(state, enc.state(5, 20, Buffer.from('\x04🌾\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')))
308
308
  enc.string.encode(state, 'høsten er fin')
309
- t.alike(state, { start: 20, end: 20, buffer: Buffer.from('\x04🌾\x0ehøsten er fin') })
309
+ t.alike(state, enc.state(20, 20, Buffer.from('\x04🌾\x0ehøsten er fin')))
310
310
 
311
311
  state.start = 0
312
312
  t.is(enc.string.decode(state), '🌾')
@@ -320,15 +320,15 @@ tape('fixed32', function (t) {
320
320
  const state = enc.state()
321
321
 
322
322
  enc.fixed32.preencode(state, Buffer.alloc(32).fill('a'))
323
- t.alike(state, { start: 0, end: 32, buffer: null })
323
+ t.alike(state, enc.state(0, 32))
324
324
  enc.fixed32.preencode(state, Buffer.alloc(32).fill('b'))
325
- t.alike(state, { start: 0, end: 64, buffer: null })
325
+ t.alike(state, enc.state(0, 64))
326
326
 
327
327
  state.buffer = Buffer.alloc(state.end)
328
328
  enc.fixed32.encode(state, Buffer.alloc(32).fill('a'))
329
- t.alike(state, { start: 32, end: 64, buffer: Buffer.alloc(64).fill('a', 0, 32) })
329
+ t.alike(state, enc.state(32, 64, Buffer.alloc(64).fill('a', 0, 32)))
330
330
  enc.fixed32.encode(state, Buffer.alloc(32).fill('b'))
331
- t.alike(state, { start: 64, end: 64, buffer: Buffer.alloc(64).fill('a', 0, 32).fill('b', 32, 64) })
331
+ t.alike(state, enc.state(64, 64, Buffer.alloc(64).fill('a', 0, 32).fill('b', 32, 64)))
332
332
 
333
333
  state.start = 0
334
334
  t.alike(enc.fixed32.decode(state), Buffer.alloc(32).fill('a'))
@@ -342,15 +342,15 @@ tape('fixed64', function (t) {
342
342
  const state = enc.state()
343
343
 
344
344
  enc.fixed64.preencode(state, Buffer.alloc(64).fill('a'))
345
- t.alike(state, { start: 0, end: 64, buffer: null })
345
+ t.alike(state, enc.state(0, 64))
346
346
  enc.fixed64.preencode(state, Buffer.alloc(64).fill('b'))
347
- t.alike(state, { start: 0, end: 128, buffer: null })
347
+ t.alike(state, enc.state(0, 128))
348
348
 
349
349
  state.buffer = Buffer.alloc(state.end)
350
350
  enc.fixed64.encode(state, Buffer.alloc(64).fill('a'))
351
- t.alike(state, { start: 64, end: 128, buffer: Buffer.alloc(128).fill('a', 0, 64) })
351
+ t.alike(state, enc.state(64, 128, Buffer.alloc(128).fill('a', 0, 64)))
352
352
  enc.fixed64.encode(state, Buffer.alloc(64).fill('b'))
353
- t.alike(state, { start: 128, end: 128, buffer: Buffer.alloc(128).fill('a', 0, 64).fill('b', 64, 128) })
353
+ t.alike(state, enc.state(128, 128, Buffer.alloc(128).fill('a', 0, 64).fill('b', 64, 128)))
354
354
 
355
355
  state.start = 0
356
356
  t.alike(enc.fixed64.decode(state), Buffer.alloc(64).fill('a'))
@@ -365,15 +365,15 @@ tape('fixed n', function (t) {
365
365
  const fixed = enc.fixed(3)
366
366
 
367
367
  fixed.preencode(state, Buffer.alloc(3).fill('a'))
368
- t.alike(state, { start: 0, end: 3, buffer: null })
368
+ t.alike(state, enc.state(0, 3))
369
369
  fixed.preencode(state, Buffer.alloc(3).fill('b'))
370
- t.alike(state, { start: 0, end: 6, buffer: null })
370
+ t.alike(state, enc.state(0, 6))
371
371
 
372
372
  state.buffer = Buffer.alloc(state.end)
373
373
  fixed.encode(state, Buffer.alloc(3).fill('a'))
374
- t.alike(state, { start: 3, end: 6, buffer: Buffer.alloc(6).fill('a', 0, 3) })
374
+ t.alike(state, enc.state(3, 6, Buffer.alloc(6).fill('a', 0, 3)))
375
375
  fixed.encode(state, Buffer.alloc(3).fill('b'))
376
- t.alike(state, { start: 6, end: 6, buffer: Buffer.alloc(6).fill('a', 0, 3).fill('b', 3, 6) })
376
+ t.alike(state, enc.state(6, 6, Buffer.alloc(6).fill('a', 0, 3).fill('b', 3, 6)))
377
377
 
378
378
  state.start = 0
379
379
  t.alike(fixed.decode(state), Buffer.alloc(3).fill('a'))
@@ -390,15 +390,15 @@ tape('array', function (t) {
390
390
  const arr = enc.array(enc.bool)
391
391
 
392
392
  arr.preencode(state, [true, false, true])
393
- t.alike(state, { start: 0, end: 4, buffer: null })
393
+ t.alike(state, enc.state(0, 4))
394
394
  arr.preencode(state, [false, false, true, true])
395
- t.alike(state, { start: 0, end: 9, buffer: null })
395
+ t.alike(state, enc.state(0, 9))
396
396
 
397
397
  state.buffer = Buffer.alloc(state.end)
398
398
  arr.encode(state, [true, false, true])
399
- t.alike(state, { start: 4, end: 9, buffer: Buffer.from([3, 1, 0, 1, 0, 0, 0, 0, 0]) })
399
+ t.alike(state, enc.state(4, 9, Buffer.from([3, 1, 0, 1, 0, 0, 0, 0, 0])))
400
400
  arr.encode(state, [false, false, true, true])
401
- t.alike(state, { start: 9, end: 9, buffer: Buffer.from([3, 1, 0, 1, 4, 0, 0, 1, 1]) })
401
+ t.alike(state, enc.state(9, 9, Buffer.from([3, 1, 0, 1, 4, 0, 0, 1, 1])))
402
402
 
403
403
  state.start = 0
404
404
  t.alike(arr.decode(state), [true, false, true])
@@ -407,3 +407,176 @@ tape('array', function (t) {
407
407
 
408
408
  t.exception(() => arr.decode(state))
409
409
  })
410
+
411
+ tape('json', function (t) {
412
+ const state = enc.state()
413
+
414
+ enc.json.preencode(state, { a: 1, b: 2 })
415
+ t.alike(state, enc.state(0, 14))
416
+
417
+ state.buffer = Buffer.alloc(state.end)
418
+ enc.json.encode(state, { a: 1, b: 2 })
419
+ t.alike(state, enc.state(14, 14, Buffer.concat([
420
+ Buffer.from([13]),
421
+ Buffer.from('{"a":1,"b":2}')
422
+ ])))
423
+
424
+ state.start = 0
425
+ t.alike(enc.json.decode(state), { a: 1, b: 2 })
426
+
427
+ t.exception(() => enc.json.decode(state))
428
+ })
429
+
430
+ tape('lexint: big numbers', function (t) {
431
+ t.plan(1)
432
+
433
+ let prev = enc.encode(enc.lexint, 0)
434
+
435
+ let n
436
+ let skip = 1
437
+
438
+ for (n = 1; n < Number.MAX_VALUE; n += skip) {
439
+ const cur = enc.encode(enc.lexint, n)
440
+ if (Buffer.compare(cur, prev) < 1) break
441
+ prev = cur
442
+ skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
443
+ }
444
+ t.is(n, Infinity)
445
+ })
446
+
447
+ tape('lexint: range precision', function (t) {
448
+ t.plan(2)
449
+ const a = 1e55
450
+ const b = 1.0000000000001e55
451
+ const ha = enc.encode(enc.lexint, a).toString('hex')
452
+ const hb = enc.encode(enc.lexint, b).toString('hex')
453
+ t.not(a, b)
454
+ t.not(ha, hb)
455
+ })
456
+
457
+ tape('lexint: range precision', function (t) {
458
+ let prev = enc.encode(enc.lexint, 0)
459
+ const skip = 0.000000001e55
460
+ for (let i = 0, n = 1e55; i < 1000; n = 1e55 + skip * ++i) {
461
+ const cur = enc.encode(enc.lexint, n)
462
+ if (Buffer.compare(cur, prev) < 1) t.fail('cur <= prev')
463
+ prev = cur
464
+ }
465
+ t.ok(true)
466
+ t.end()
467
+ })
468
+
469
+ tape('lexint: small numbers', function (t) {
470
+ let prev = enc.encode(enc.lexint, 0)
471
+ for (let n = 1; n < 256 * 256 * 16; n++) {
472
+ const cur = enc.encode(enc.lexint, n)
473
+ if (Buffer.compare(cur, prev) < 1) t.fail('cur <= prev')
474
+ prev = cur
475
+ }
476
+ t.ok(true)
477
+ t.end()
478
+ })
479
+
480
+ tape('lexint: throws', function (t) {
481
+ t.exception(() => {
482
+ enc.decode(enc.lexint, Buffer.alloc(1, 251))
483
+ })
484
+
485
+ let num = 252
486
+
487
+ const state = enc.state()
488
+
489
+ enc.lexint.preencode(state, num)
490
+ state.buffer = Buffer.alloc(state.end - state.start)
491
+ enc.lexint.encode(state, num)
492
+
493
+ t.exception(() => {
494
+ enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
495
+ })
496
+
497
+ num <<= 8
498
+
499
+ state.start = 0
500
+ state.end = 0
501
+ state.buffer = null
502
+
503
+ enc.lexint.preencode(state, num)
504
+ state.buffer = Buffer.alloc(state.end - state.start)
505
+ enc.lexint.encode(state, num)
506
+
507
+ t.exception(() => {
508
+ enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
509
+ })
510
+
511
+ num <<= 8
512
+
513
+ state.start = 0
514
+ state.end = 0
515
+ state.buffer = null
516
+
517
+ enc.lexint.preencode(state, num)
518
+ state.buffer = Buffer.alloc(state.end - state.start)
519
+ enc.lexint.encode(state, num)
520
+
521
+ t.exception(() => {
522
+ enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
523
+ })
524
+
525
+ num *= 256
526
+
527
+ state.start = 0
528
+ state.end = 0
529
+ state.buffer = null
530
+
531
+ enc.lexint.preencode(state, num)
532
+ state.buffer = Buffer.alloc(state.end - state.start)
533
+ enc.lexint.encode(state, num)
534
+
535
+ t.exception(() => {
536
+ enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
537
+ })
538
+
539
+ num *= 256 * 256
540
+
541
+ state.start = 0
542
+ state.end = 0
543
+ state.buffer = null
544
+
545
+ enc.lexint.preencode(state, num)
546
+ state.buffer = Buffer.alloc(state.end - state.start)
547
+ enc.lexint.encode(state, num)
548
+
549
+ t.exception(() => {
550
+ enc.decode(enc.lexint, state.buffer.subarray(0, state.buffer.byteLength - 2))
551
+ })
552
+
553
+ t.end()
554
+ })
555
+
556
+ tape('lexint: unpack', function (t) {
557
+ let n
558
+ let skip = 1
559
+
560
+ for (n = 1; n < Number.MAX_VALUE; n += skip) {
561
+ const cur = enc.encode(enc.lexint, n)
562
+ compare(n, enc.decode(enc.lexint, cur))
563
+ skip = 1 + Math.pow(245, Math.ceil(Math.log(n) / Math.log(256)))
564
+ }
565
+ t.is(n, Infinity)
566
+ t.end()
567
+
568
+ function compare (a, b) {
569
+ const desc = a + ' !=~ ' + b
570
+ if (/e\+\d+$/.test(a) || /e\+\d+$/.test(b)) {
571
+ if (String(a).slice(0, 8) !== String(b).slice(0, 8) ||
572
+ /e\+(\d+)$/.exec(a)[1] !== /e\+(\d+)$/.exec(b)[1]) {
573
+ t.fail(desc)
574
+ }
575
+ } else {
576
+ if (String(a).slice(0, 8) !== String(b).slice(0, 8) ||
577
+ String(a).length !== String(b).length) {
578
+ t.fail(desc)
579
+ }
580
+ }
581
+ }
582
+ })