compact-encoding 2.14.0 → 2.15.1

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 +9 -1
  2. package/index.js +104 -15
  3. package/package.json +1 -1
  4. package/raw.js +3 -0
  5. package/test.js +127 -0
package/README.md CHANGED
@@ -94,7 +94,10 @@ to build others on top. Feel free to PR more that are missing.
94
94
  * `cenc.int48` - Encodes a fixed size int48 using `cenc.uint48` with ZigZag encoding.
95
95
  * `cenc.int56` - Encodes a fixed size int56 using `cenc.uint56` with ZigZag encoding.
96
96
  * `cenc.int64` - Encodes a fixed size int64 using `cenc.uint64` with ZigZag encoding.
97
- * `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.
97
+ * `cenc.biguint64` - Encodes a fixed size biguint64.
98
+ * `cenc.bigint64` - Encodes a fixed size bigint64 using `cenc.biguint64` with ZigZag encoding.
99
+ * `cenc.biguint` - Encodes a biguint with its word count uint prefixed.
100
+ * `cenc.bigint` - Encodes a bigint using `cenc.biguint` with ZigZag encoding.
98
101
  * `cenc.float32` - Encodes a fixed size float32.
99
102
  * `cenc.float64` - Encodes a fixed size float64.
100
103
  * `cenc.buffer` - Encodes a buffer with its length uint prefixed. When decoding an empty buffer, `null` is returned.
@@ -113,6 +116,10 @@ to build others on top. Feel free to PR more that are missing.
113
116
  * `cenc.raw.int16array` - Encodes a int16array without a length prefixed.
114
117
  * `cenc.int32array` - Encodes a int32array with its element length uint prefixed.
115
118
  * `cenc.raw.int32array` - Encodes a int32array without a length prefixed.
119
+ * `cenc.biguint64array` - Encodes a biguint64array with its element length uint prefixed.
120
+ * `cenc.raw.biguint64array` - Encodes a biguint64array without a length prefixed.
121
+ * `cenc.bigint64array` - Encodes a bigint64array with its element length uint prefixed.
122
+ * `cenc.raw.bigint64array` - Encodes a bigint64array without a length prefixed.
116
123
  * `cenc.float32array` - Encodes a float32array with its element length uint prefixed.
117
124
  * `cenc.raw.float32array` - Encodes a float32array without a length prefixed.
118
125
  * `cenc.float64array` - Encodes a float64array with its element length uint prefixed.
@@ -144,6 +151,7 @@ to build others on top. Feel free to PR more that are missing.
144
151
  * `cenc.raw.ndjson` - Encodes a JSON value as newline delimited utf-8 without a length prefixed.
145
152
  * `cenc.any` - Encodes any JSON representable value into a self described buffer. Like JSON + buffer, but using compact types. Useful for schemaless codecs.
146
153
  * `cenc.from(enc)` - Makes a compact encoder from a [codec](https://github.com/mafintosh/codecs) or [abstract-encoding](https://github.com/mafintosh/abstract-encoding).
154
+ * `cenc.none` - Helper for when you want to just express nothing
147
155
 
148
156
  ## License
149
157
 
package/index.js CHANGED
@@ -39,6 +39,7 @@ const uint8 = exports.uint8 = {
39
39
  state.end += 1
40
40
  },
41
41
  encode (state, n) {
42
+ validateUint(n)
42
43
  state.buffer[state.start++] = n
43
44
  },
44
45
  decode (state) {
@@ -52,6 +53,7 @@ const uint16 = exports.uint16 = {
52
53
  state.end += 2
53
54
  },
54
55
  encode (state, n) {
56
+ validateUint(n)
55
57
  state.buffer[state.start++] = n
56
58
  state.buffer[state.start++] = n >>> 8
57
59
  },
@@ -69,6 +71,7 @@ const uint24 = exports.uint24 = {
69
71
  state.end += 3
70
72
  },
71
73
  encode (state, n) {
74
+ validateUint(n)
72
75
  state.buffer[state.start++] = n
73
76
  state.buffer[state.start++] = n >>> 8
74
77
  state.buffer[state.start++] = n >>> 16
@@ -88,6 +91,7 @@ const uint32 = exports.uint32 = {
88
91
  state.end += 4
89
92
  },
90
93
  encode (state, n) {
94
+ validateUint(n)
91
95
  state.buffer[state.start++] = n
92
96
  state.buffer[state.start++] = n >>> 8
93
97
  state.buffer[state.start++] = n >>> 16
@@ -109,6 +113,7 @@ const uint40 = exports.uint40 = {
109
113
  state.end += 5
110
114
  },
111
115
  encode (state, n) {
116
+ validateUint(n)
112
117
  const r = Math.floor(n / 0x100)
113
118
  uint8.encode(state, n)
114
119
  uint32.encode(state, r)
@@ -124,6 +129,7 @@ const uint48 = exports.uint48 = {
124
129
  state.end += 6
125
130
  },
126
131
  encode (state, n) {
132
+ validateUint(n)
127
133
  const r = Math.floor(n / 0x10000)
128
134
  uint16.encode(state, n)
129
135
  uint32.encode(state, r)
@@ -139,6 +145,7 @@ const uint56 = exports.uint56 = {
139
145
  state.end += 7
140
146
  },
141
147
  encode (state, n) {
148
+ validateUint(n)
142
149
  const r = Math.floor(n / 0x1000000)
143
150
  uint24.encode(state, n)
144
151
  uint32.encode(state, r)
@@ -154,6 +161,7 @@ const uint64 = exports.uint64 = {
154
161
  state.end += 8
155
162
  },
156
163
  encode (state, n) {
164
+ validateUint(n)
157
165
  const r = Math.floor(n / 0x100000000)
158
166
  uint32.encode(state, n)
159
167
  uint32.encode(state, r)
@@ -164,15 +172,65 @@ const uint64 = exports.uint64 = {
164
172
  }
165
173
  }
166
174
 
167
- exports.int = zigZag(uint)
168
- exports.int8 = zigZag(uint8)
169
- exports.int16 = zigZag(uint16)
170
- exports.int24 = zigZag(uint24)
171
- exports.int32 = zigZag(uint32)
172
- exports.int40 = zigZag(uint40)
173
- exports.int48 = zigZag(uint48)
174
- exports.int56 = zigZag(uint56)
175
- exports.int64 = zigZag(uint64)
175
+ exports.int = zigZagInt(uint)
176
+ exports.int8 = zigZagInt(uint8)
177
+ exports.int16 = zigZagInt(uint16)
178
+ exports.int24 = zigZagInt(uint24)
179
+ exports.int32 = zigZagInt(uint32)
180
+ exports.int40 = zigZagInt(uint40)
181
+ exports.int48 = zigZagInt(uint48)
182
+ exports.int56 = zigZagInt(uint56)
183
+ exports.int64 = zigZagInt(uint64)
184
+
185
+ const biguint64 = exports.biguint64 = {
186
+ preencode (state, n) {
187
+ state.end += 8
188
+ },
189
+ encode (state, n) {
190
+ const view = new DataView(state.buffer.buffer, state.start + state.buffer.byteOffset, 8)
191
+ view.setBigUint64(0, n, true) // little endian
192
+ state.start += 8
193
+ },
194
+ decode (state) {
195
+ if (state.end - state.start < 8) throw new Error('Out of bounds')
196
+ const view = new DataView(state.buffer.buffer, state.start + state.buffer.byteOffset, 8)
197
+ const n = view.getBigUint64(0, true) // little endian
198
+ state.start += 8
199
+ return n
200
+ }
201
+ }
202
+
203
+ exports.bigint64 = zigZagBigInt(biguint64)
204
+
205
+ const biguint = exports.biguint = {
206
+ preencode (state, n) {
207
+ let len = 0
208
+ for (let m = n; m; m = m >> 64n) len++
209
+ uint.preencode(state, len)
210
+ state.end += 8 * len
211
+ },
212
+ encode (state, n) {
213
+ let len = 0
214
+ for (let m = n; m; m = m >> 64n) len++
215
+ uint.encode(state, len)
216
+ const view = new DataView(state.buffer.buffer, state.start + state.buffer.byteOffset, 8 * len)
217
+ for (let m = n, i = 0; m; m = m >> 64n, i += 8) {
218
+ view.setBigUint64(i, BigInt.asUintN(64, m), true) // little endian
219
+ }
220
+ state.start += 8 * len
221
+ },
222
+ decode (state) {
223
+ const len = uint.decode(state)
224
+ if (state.end - state.start < 8 * len) throw new Error('Out of bounds')
225
+ const view = new DataView(state.buffer.buffer, state.start + state.buffer.byteOffset, 8 * len)
226
+ let n = 0n
227
+ for (let i = len - 1; i >= 0; i--) n = (n << 64n) + view.getBigUint64(i * 8, true) // little endian
228
+ state.start += 8 * len
229
+ return n
230
+ }
231
+ }
232
+
233
+ exports.bigint = zigZagBigInt(biguint)
176
234
 
177
235
  exports.lexint = require('./lexint')
178
236
 
@@ -306,6 +364,9 @@ exports.int8array = typedarray(Int8Array)
306
364
  exports.int16array = typedarray(Int16Array, b4a.swap16)
307
365
  exports.int32array = typedarray(Int32Array, b4a.swap32)
308
366
 
367
+ exports.biguint64array = typedarray(BigUint64Array, b4a.swap64)
368
+ exports.bigint64array = typedarray(BigInt64Array, b4a.swap64)
369
+
309
370
  exports.float32array = typedarray(Float32Array, b4a.swap32)
310
371
  exports.float64array = typedarray(Float64Array, b4a.swap64)
311
372
 
@@ -367,6 +428,7 @@ exports.bool = {
367
428
  const fixed = exports.fixed = function fixed (n) {
368
429
  return {
369
430
  preencode (state, s) {
431
+ if (s.byteLength !== n) throw new Error('Incorrect buffer size')
370
432
  state.end += n
371
433
  },
372
434
  encode (state, s) {
@@ -639,25 +701,52 @@ exports.decode = function decode (enc, buffer) {
639
701
  return enc.decode(exports.state(0, buffer.byteLength, buffer))
640
702
  }
641
703
 
642
- function zigZag (enc) {
704
+ function zigZagInt (enc) {
643
705
  return {
644
706
  preencode (state, n) {
645
- enc.preencode(state, zigZagEncode(n))
707
+ enc.preencode(state, zigZagEncodeInt(n))
646
708
  },
647
709
  encode (state, n) {
648
- enc.encode(state, zigZagEncode(n))
710
+ enc.encode(state, zigZagEncodeInt(n))
649
711
  },
650
712
  decode (state) {
651
- return zigZagDecode(enc.decode(state))
713
+ return zigZagDecodeInt(enc.decode(state))
652
714
  }
653
715
  }
654
716
  }
655
717
 
656
- function zigZagDecode (n) {
718
+ function zigZagDecodeInt (n) {
657
719
  return n === 0 ? n : (n & 1) === 0 ? n / 2 : -(n + 1) / 2
658
720
  }
659
721
 
660
- function zigZagEncode (n) {
722
+ function zigZagEncodeInt (n) {
661
723
  // 0, -1, 1, -2, 2, ...
662
724
  return n < 0 ? (2 * -n) - 1 : n === 0 ? 0 : 2 * n
663
725
  }
726
+
727
+ function zigZagBigInt (enc) {
728
+ return {
729
+ preencode (state, n) {
730
+ enc.preencode(state, zigZagEncodeBigInt(n))
731
+ },
732
+ encode (state, n) {
733
+ enc.encode(state, zigZagEncodeBigInt(n))
734
+ },
735
+ decode (state) {
736
+ return zigZagDecodeBigInt(enc.decode(state))
737
+ }
738
+ }
739
+ }
740
+
741
+ function zigZagDecodeBigInt (n) {
742
+ return n === 0n ? n : (n & 1n) === 0n ? n / 2n : -(n + 1n) / 2n
743
+ }
744
+
745
+ function zigZagEncodeBigInt (n) {
746
+ // 0, -1, 1, -2, 2, ...
747
+ return n < 0n ? (2n * -n) - 1n : n === 0n ? 0n : 2n * n
748
+ }
749
+
750
+ function validateUint (n) {
751
+ if ((n >= 0) === false /* Handles NaN as well */) throw new Error('uint must be positive')
752
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "compact-encoding",
3
- "version": "2.14.0",
3
+ "version": "2.15.1",
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/raw.js CHANGED
@@ -104,6 +104,9 @@ exports.int8array = typedarray(Int8Array)
104
104
  exports.int16array = typedarray(Int16Array, b4a.swap16)
105
105
  exports.int32array = typedarray(Int32Array, b4a.swap32)
106
106
 
107
+ exports.biguint64array = typedarray(BigUint64Array, b4a.swap64)
108
+ exports.bigint64array = typedarray(BigInt64Array, b4a.swap64)
109
+
107
110
  exports.float32array = typedarray(Float32Array, b4a.swap32)
108
111
  exports.float64array = typedarray(Float64Array, b4a.swap64)
109
112
 
package/test.js CHANGED
@@ -146,6 +146,82 @@ test('float64', function (t) {
146
146
  t.is(state.start, state.end)
147
147
  })
148
148
 
149
+ test('biguint64', function (t) {
150
+ const state = enc.state()
151
+
152
+ const n = 0x0102030405060708n
153
+
154
+ enc.biguint64.preencode(state, n)
155
+ t.alike(state, enc.state(0, 8))
156
+
157
+ state.buffer = b4a.alloc(state.end)
158
+ enc.biguint64.encode(state, n)
159
+ t.alike(state, enc.state(8, 8, b4a.from([0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1])))
160
+
161
+ state.start = 0
162
+ t.is(enc.biguint64.decode(state), n)
163
+ t.is(state.start, state.end)
164
+
165
+ t.exception(() => enc.biguint64.decode(state))
166
+ })
167
+
168
+ test('bigint64', function (t) {
169
+ const state = enc.state()
170
+
171
+ const n = -0x0102030405060708n
172
+
173
+ enc.bigint64.preencode(state, n)
174
+ t.alike(state, enc.state(0, 8))
175
+
176
+ state.buffer = b4a.alloc(state.end)
177
+ enc.bigint64.encode(state, n)
178
+ t.alike(state, enc.state(8, 8, b4a.from([0xf, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2])))
179
+
180
+ state.start = 0
181
+ t.is(enc.bigint64.decode(state), n)
182
+ t.is(state.start, state.end)
183
+
184
+ t.exception(() => enc.bigint64.decode(state))
185
+ })
186
+
187
+ test('biguint', function (t) {
188
+ const state = enc.state()
189
+
190
+ const n = 0x0102030405060708090a0b0cn
191
+
192
+ enc.biguint.preencode(state, n)
193
+ t.alike(state, enc.state(0, 17))
194
+
195
+ state.buffer = b4a.alloc(state.end)
196
+ enc.biguint.encode(state, n)
197
+ t.alike(state, enc.state(17, 17, b4a.from([2, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0])))
198
+
199
+ state.start = 0
200
+ t.is(enc.biguint.decode(state), n)
201
+ t.is(state.start, state.end)
202
+
203
+ t.exception(() => enc.biguint.decode(state))
204
+ })
205
+
206
+ test('bigint', function (t) {
207
+ const state = enc.state()
208
+
209
+ const n = -0x0102030405060708090a0b0cn
210
+
211
+ enc.bigint.preencode(state, n)
212
+ t.alike(state, enc.state(0, 17))
213
+
214
+ state.buffer = b4a.alloc(state.end)
215
+ enc.bigint.encode(state, n)
216
+ t.alike(state, enc.state(17, 17, b4a.from([2, 0x17, 0x16, 0x14, 0x12, 0x10, 0xe, 0xc, 0xa, 0x8, 0x6, 0x4, 0x2, 0x0, 0x0, 0x0, 0x0])))
217
+
218
+ state.start = 0
219
+ t.is(enc.bigint.decode(state), n)
220
+ t.is(state.start, state.end)
221
+
222
+ t.exception(() => enc.bigint.decode(state))
223
+ })
224
+
149
225
  test('buffer', function (t) {
150
226
  const state = enc.state()
151
227
 
@@ -308,6 +384,44 @@ test('int32array', function (t) {
308
384
  t.exception(() => enc.int32array.decode(state))
309
385
  })
310
386
 
387
+ test('biguint64array', function (t) {
388
+ const state = enc.state()
389
+
390
+ const arr = new BigUint64Array([0x01020304n, 0x05060708n, 0x090a0b0cn])
391
+
392
+ enc.biguint64array.preencode(state, arr)
393
+ t.alike(state, enc.state(0, 25))
394
+
395
+ state.buffer = b4a.alloc(state.end)
396
+ enc.biguint64array.encode(state, arr)
397
+ t.alike(state, enc.state(25, 25, b4a.from([3, 0x4, 0x3, 0x2, 0x1, 0x0, 0x0, 0x0, 0x0, 0x8, 0x7, 0x6, 0x5, 0x0, 0x0, 0x0, 0x0, 0xc, 0xb, 0xa, 0x9, 0x0, 0x0, 0x0, 0x0])))
398
+
399
+ state.start = 0
400
+ t.alike(enc.biguint64array.decode(state), arr)
401
+ t.is(state.start, state.end)
402
+
403
+ t.exception(() => enc.biguint64array.decode(state))
404
+ })
405
+
406
+ test('bigint64array', function (t) {
407
+ const state = enc.state()
408
+
409
+ const arr = new BigInt64Array([-0x01020304n, 0x05060708n, -0x090a0b0cn])
410
+
411
+ enc.bigint64array.preencode(state, arr)
412
+ t.alike(state, enc.state(0, 25))
413
+
414
+ state.buffer = b4a.alloc(state.end)
415
+ enc.bigint64array.encode(state, arr)
416
+ t.alike(state, enc.state(25, 25, b4a.from([3, 0xfc, 0xfc, 0xfd, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x8, 0x7, 0x6, 0x5, 0x0, 0x0, 0x0, 0x0, 0xf4, 0xf4, 0xf5, 0xf6, 0xff, 0xff, 0xff, 0xff])))
417
+
418
+ state.start = 0
419
+ t.alike(enc.bigint64array.decode(state), arr)
420
+ t.is(state.start, state.end)
421
+
422
+ t.exception(() => enc.bigint64array.decode(state))
423
+ })
424
+
311
425
  test('float32array', function (t) {
312
426
  const state = enc.state()
313
427
 
@@ -451,6 +565,19 @@ test('fixed n', function (t) {
451
565
  t.exception(() => fixed.decode(state))
452
566
  })
453
567
 
568
+ test('error for incorrect buffer sizes when encoding fixed-length buffers', function (t) {
569
+ const smallbuf = b4a.from('aa', 'hex')
570
+ const bigBuf = b4a.from('aa'.repeat(500), 'hex')
571
+
572
+ t.exception(() => enc.encode(enc.fixed32, smallbuf), /Incorrect buffer size/)
573
+ t.exception(() => enc.encode(enc.fixed64, smallbuf), /Incorrect buffer size/)
574
+ t.exception(() => enc.encode(enc.fixed(100), smallbuf), /Incorrect buffer size/)
575
+
576
+ t.exception(() => enc.encode(enc.fixed32, bigBuf), /Incorrect buffer size/)
577
+ t.exception(() => enc.encode(enc.fixed64, bigBuf), /Incorrect buffer size/)
578
+ t.exception(() => enc.encode(enc.fixed(100), bigBuf), /Incorrect buffer size/)
579
+ })
580
+
454
581
  test('array', function (t) {
455
582
  const state = enc.state()
456
583
  const arr = enc.array(enc.bool)