cborg 4.4.1 → 4.5.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 (59) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +21 -0
  3. package/bench/README.md +115 -0
  4. package/bench/bench-comparative.js +133 -0
  5. package/bench/bench.js +414 -101
  6. package/bench/fixtures.js +558 -0
  7. package/bench/index.html +405 -0
  8. package/cborg.js +2 -1
  9. package/interface.ts +8 -2
  10. package/lib/0uint.js +11 -11
  11. package/lib/1negint.js +4 -4
  12. package/lib/2bytes.js +5 -5
  13. package/lib/3string.js +1 -1
  14. package/lib/4array.js +4 -4
  15. package/lib/5map.js +4 -4
  16. package/lib/6tag.js +4 -4
  17. package/lib/7float.js +10 -10
  18. package/lib/bl.js +46 -0
  19. package/lib/encode.js +40 -15
  20. package/lib/is.js +12 -31
  21. package/lib/json/encode.js +10 -10
  22. package/package.json +1 -1
  23. package/test/test-0uint.js +12 -1
  24. package/test/test-1negint.js +12 -1
  25. package/test/test-2bytes.js +11 -1
  26. package/test/test-3string.js +11 -1
  27. package/test/test-4array.js +11 -1
  28. package/test/test-5map.js +11 -3
  29. package/test/test-6tag.js +19 -1
  30. package/test/test-7float.js +11 -1
  31. package/test/test-cbor-vectors.js +13 -2
  32. package/test/test-encodeInto.js +246 -0
  33. package/types/cborg.d.ts +2 -1
  34. package/types/cborg.d.ts.map +1 -1
  35. package/types/interface.d.ts +7 -2
  36. package/types/interface.d.ts.map +1 -1
  37. package/types/lib/0uint.d.ts +6 -6
  38. package/types/lib/0uint.d.ts.map +1 -1
  39. package/types/lib/1negint.d.ts +4 -4
  40. package/types/lib/1negint.d.ts.map +1 -1
  41. package/types/lib/2bytes.d.ts +3 -3
  42. package/types/lib/2bytes.d.ts.map +1 -1
  43. package/types/lib/3string.d.ts +1 -1
  44. package/types/lib/3string.d.ts.map +1 -1
  45. package/types/lib/4array.d.ts +3 -3
  46. package/types/lib/4array.d.ts.map +1 -1
  47. package/types/lib/5map.d.ts +3 -3
  48. package/types/lib/5map.d.ts.map +1 -1
  49. package/types/lib/6tag.d.ts +4 -4
  50. package/types/lib/6tag.d.ts.map +1 -1
  51. package/types/lib/7float.d.ts +3 -3
  52. package/types/lib/7float.d.ts.map +1 -1
  53. package/types/lib/bl.d.ts +25 -0
  54. package/types/lib/bl.d.ts.map +1 -1
  55. package/types/lib/encode.d.ts +12 -1
  56. package/types/lib/encode.d.ts.map +1 -1
  57. package/types/lib/is.d.ts.map +1 -1
  58. package/types/lib/json/encode.d.ts +1 -1
  59. package/types/lib/json/encode.d.ts.map +1 -1
package/lib/7float.js CHANGED
@@ -6,7 +6,7 @@ import { decodeErrPrefix } from './common.js'
6
6
  import { encodeUint } from './0uint.js'
7
7
 
8
8
  /**
9
- * @typedef {import('./bl.js').Bl} Bl
9
+ * @typedef {import('../interface').ByteWriter} ByteWriter
10
10
  * @typedef {import('../interface').DecodeOptions} DecodeOptions
11
11
  * @typedef {import('../interface').EncodeOptions} EncodeOptions
12
12
  */
@@ -98,21 +98,21 @@ export function decodeFloat64 (data, pos, _minor, options) {
98
98
  }
99
99
 
100
100
  /**
101
- * @param {Bl} buf
101
+ * @param {ByteWriter} writer
102
102
  * @param {Token} token
103
103
  * @param {EncodeOptions} options
104
104
  */
105
- export function encodeFloat (buf, token, options) {
105
+ export function encodeFloat (writer, token, options) {
106
106
  const float = token.value
107
107
 
108
108
  if (float === false) {
109
- buf.push([Type.float.majorEncoded | MINOR_FALSE])
109
+ writer.push([Type.float.majorEncoded | MINOR_FALSE])
110
110
  } else if (float === true) {
111
- buf.push([Type.float.majorEncoded | MINOR_TRUE])
111
+ writer.push([Type.float.majorEncoded | MINOR_TRUE])
112
112
  } else if (float === null) {
113
- buf.push([Type.float.majorEncoded | MINOR_NULL])
113
+ writer.push([Type.float.majorEncoded | MINOR_NULL])
114
114
  } else if (float === undefined) {
115
- buf.push([Type.float.majorEncoded | MINOR_UNDEFINED])
115
+ writer.push([Type.float.majorEncoded | MINOR_UNDEFINED])
116
116
  } else {
117
117
  let decoded
118
118
  let success = false
@@ -121,14 +121,14 @@ export function encodeFloat (buf, token, options) {
121
121
  decoded = readFloat16(ui8a, 1)
122
122
  if (float === decoded || Number.isNaN(float)) {
123
123
  ui8a[0] = 0xf9
124
- buf.push(ui8a.slice(0, 3))
124
+ writer.push(ui8a.slice(0, 3))
125
125
  success = true
126
126
  } else {
127
127
  encodeFloat32(float)
128
128
  decoded = readFloat32(ui8a, 1)
129
129
  if (float === decoded) {
130
130
  ui8a[0] = 0xfa
131
- buf.push(ui8a.slice(0, 5))
131
+ writer.push(ui8a.slice(0, 5))
132
132
  success = true
133
133
  }
134
134
  }
@@ -137,7 +137,7 @@ export function encodeFloat (buf, token, options) {
137
137
  encodeFloat64(float)
138
138
  decoded = readFloat64(ui8a, 1)
139
139
  ui8a[0] = 0xfb
140
- buf.push(ui8a.slice(0, 9))
140
+ writer.push(ui8a.slice(0, 9))
141
141
  }
142
142
  }
143
143
  }
package/lib/bl.js CHANGED
@@ -122,3 +122,49 @@ export class Bl {
122
122
  return byts
123
123
  }
124
124
  }
125
+
126
+ /**
127
+ * U8Bl is a buffer list that writes directly to a user-provided Uint8Array.
128
+ * It provides the same interface as Bl but writes to a fixed destination.
129
+ */
130
+ export class U8Bl {
131
+ /**
132
+ * @param {Uint8Array} dest
133
+ */
134
+ constructor (dest) {
135
+ this.dest = dest
136
+ /** @type {number} */
137
+ this.cursor = 0
138
+ // chunks is for interface compatibility with Bl - encode.js checks chunks.length
139
+ // as a sanity check for pre-calculated sizes. For U8Bl this is always [dest].
140
+ /** @type {Uint8Array[]} */
141
+ this.chunks = [dest]
142
+ }
143
+
144
+ reset () {
145
+ this.cursor = 0
146
+ }
147
+
148
+ /**
149
+ * @param {Uint8Array|number[]} bytes
150
+ */
151
+ push (bytes) {
152
+ if (this.cursor + bytes.length > this.dest.length) {
153
+ throw new Error('write out of bounds, destination buffer is too small')
154
+ }
155
+ this.dest.set(bytes, this.cursor)
156
+ this.cursor += bytes.length
157
+ }
158
+
159
+ /**
160
+ * @param {boolean} [reset]
161
+ * @returns {Uint8Array}
162
+ */
163
+ toBytes (reset = false) {
164
+ const byts = this.dest.subarray(0, this.cursor)
165
+ if (reset) {
166
+ this.reset()
167
+ }
168
+ return byts
169
+ }
170
+ }
package/lib/encode.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { is } from './is.js'
2
2
  import { Token, Type } from './token.js'
3
- import { Bl } from './bl.js'
3
+ import { Bl, U8Bl } from './bl.js'
4
4
  import { encodeErrPrefix } from './common.js'
5
5
  import { quickEncodeToken } from './jump.js'
6
6
  import { asU8A, compare } from './byte-utils.js'
@@ -21,6 +21,7 @@ import { encodeFloat } from './7float.js'
21
21
  * @typedef {import('../interface').StrictTypeEncoder} StrictTypeEncoder
22
22
  * @typedef {import('../interface').TokenTypeEncoder} TokenTypeEncoder
23
23
  * @typedef {import('../interface').TokenOrNestedTokens} TokenOrNestedTokens
24
+ * @typedef {import('../interface').ByteWriter} ByteWriter
24
25
  */
25
26
 
26
27
  /** @type {EncodeOptions} */
@@ -53,7 +54,7 @@ export function makeCborEncoders () {
53
54
 
54
55
  const cborEncoders = makeCborEncoders()
55
56
 
56
- const buf = new Bl()
57
+ const defaultWriter = new Bl()
57
58
 
58
59
  /** @implements {Reference} */
59
60
  class Ref {
@@ -452,18 +453,18 @@ function encodeRfc8949 (data) {
452
453
  }
453
454
 
454
455
  /**
455
- * @param {Bl} buf
456
+ * @param {ByteWriter} writer
456
457
  * @param {TokenOrNestedTokens} tokens
457
458
  * @param {TokenTypeEncoder[]} encoders
458
459
  * @param {EncodeOptions} options
459
460
  */
460
- function tokensToEncoded (buf, tokens, encoders, options) {
461
+ function tokensToEncoded (writer, tokens, encoders, options) {
461
462
  if (Array.isArray(tokens)) {
462
463
  for (const token of tokens) {
463
- tokensToEncoded(buf, token, encoders, options)
464
+ tokensToEncoded(writer, token, encoders, options)
464
465
  }
465
466
  } else {
466
- encoders[tokens.type.major](buf, tokens, options)
467
+ encoders[tokens.type.major](writer, tokens, options)
467
468
  }
468
469
  }
469
470
 
@@ -471,31 +472,43 @@ function tokensToEncoded (buf, tokens, encoders, options) {
471
472
  * @param {any} data
472
473
  * @param {TokenTypeEncoder[]} encoders
473
474
  * @param {EncodeOptions} options
475
+ * @param {Uint8Array} [destination]
474
476
  * @returns {Uint8Array}
475
477
  */
476
- function encodeCustom (data, encoders, options) {
478
+ function encodeCustom (data, encoders, options, destination) {
479
+ // arg ordering is different to encodeInto for backward compatibility
480
+ const hasDest = destination instanceof Uint8Array
481
+ let writeTo = hasDest ? new U8Bl(destination) : defaultWriter
482
+
477
483
  const tokens = objectToTokens(data, options)
478
484
  if (!Array.isArray(tokens) && options.quickEncodeToken) {
479
485
  const quickBytes = options.quickEncodeToken(tokens)
480
486
  if (quickBytes) {
487
+ if (hasDest) {
488
+ // Copy quick bytes into destination buffer
489
+ writeTo.push(quickBytes)
490
+ return writeTo.toBytes()
491
+ }
481
492
  return quickBytes
482
493
  }
483
494
  const encoder = encoders[tokens.type.major]
484
495
  if (encoder.encodedSize) {
485
496
  const size = encoder.encodedSize(tokens, options)
486
- const buf = new Bl(size)
487
- encoder(buf, tokens, options)
497
+ if (!hasDest) {
498
+ writeTo = new Bl(size)
499
+ }
500
+ encoder(writeTo, tokens, options)
488
501
  /* c8 ignore next 4 */
489
502
  // this would be a problem with encodedSize() functions
490
- if (buf.chunks.length !== 1) {
503
+ if (writeTo.chunks.length !== 1) {
491
504
  throw new Error(`Unexpected error: pre-calculated length for ${tokens} was wrong`)
492
505
  }
493
- return asU8A(buf.chunks[0])
506
+ return hasDest ? writeTo.toBytes() : asU8A(writeTo.chunks[0])
494
507
  }
495
508
  }
496
- buf.reset()
497
- tokensToEncoded(buf, tokens, encoders, options)
498
- return buf.toBytes(true)
509
+ writeTo.reset()
510
+ tokensToEncoded(writeTo, tokens, encoders, options)
511
+ return writeTo.toBytes(true)
499
512
  }
500
513
 
501
514
  /**
@@ -508,4 +521,16 @@ function encode (data, options) {
508
521
  return encodeCustom(data, cborEncoders, options)
509
522
  }
510
523
 
511
- export { objectToTokens, encode, encodeCustom, Ref }
524
+ /**
525
+ * @param {any} data
526
+ * @param {Uint8Array} destination
527
+ * @param {EncodeOptions} [options]
528
+ * @returns {{ written: number }}
529
+ */
530
+ function encodeInto (data, destination, options) {
531
+ options = Object.assign({}, defaultEncodeOptions, options)
532
+ const result = encodeCustom(data, cborEncoders, options, destination)
533
+ return { written: result.length }
534
+ }
535
+
536
+ export { objectToTokens, encode, encodeCustom, encodeInto, Ref }
package/lib/is.js CHANGED
@@ -3,24 +3,10 @@
3
3
  // check is expensive, and unnecessary for our purposes. The values returned
4
4
  // are compatible with @sindresorhus/is, however.
5
5
 
6
- const typeofs = [
7
- 'string',
8
- 'number',
9
- 'bigint',
10
- 'symbol'
11
- ]
12
-
6
+ // Types that reach getObjectType() - excludes types with fast-paths above:
7
+ // primitives (typeof), Array (isArray), Uint8Array (instanceof), plain Object (constructor)
13
8
  const objectTypeNames = [
14
- 'Function',
15
- 'Generator',
16
- 'AsyncGenerator',
17
- 'GeneratorFunction',
18
- 'AsyncGeneratorFunction',
19
- 'AsyncFunction',
20
- 'Observable',
21
- 'Array',
22
- 'Buffer',
23
- 'Object',
9
+ 'Object', // for Object.create(null) and other non-plain objects
24
10
  'RegExp',
25
11
  'Date',
26
12
  'Error',
@@ -35,7 +21,6 @@ const objectTypeNames = [
35
21
  'URL',
36
22
  'HTMLElement',
37
23
  'Int8Array',
38
- 'Uint8Array',
39
24
  'Uint8ClampedArray',
40
25
  'Int16Array',
41
26
  'Uint16Array',
@@ -62,19 +47,23 @@ export function is (value) {
62
47
  return 'boolean'
63
48
  }
64
49
  const typeOf = typeof value
65
- if (typeofs.includes(typeOf)) {
50
+ if (typeOf === 'string' || typeOf === 'number' || typeOf === 'bigint' || typeOf === 'symbol') {
66
51
  return typeOf
67
52
  }
68
- /* c8 ignore next 4 */
69
- // not going to bother testing this, it's not going to be valid anyway
53
+ /* c8 ignore next 3 */
70
54
  if (typeOf === 'function') {
71
55
  return 'Function'
72
56
  }
73
57
  if (Array.isArray(value)) {
74
58
  return 'Array'
75
59
  }
76
- if (isBuffer(value)) {
77
- return 'Buffer'
60
+ // Also catches Node.js Buffer which extends Uint8Array
61
+ if (value instanceof Uint8Array) {
62
+ return 'Uint8Array'
63
+ }
64
+ // Fast path for plain objects (most common case after primitives/arrays/bytes)
65
+ if (value.constructor === Object) {
66
+ return 'Object'
78
67
  }
79
68
  const objectType = getObjectType(value)
80
69
  if (objectType) {
@@ -84,14 +73,6 @@ export function is (value) {
84
73
  return 'Object'
85
74
  }
86
75
 
87
- /**
88
- * @param {any} value
89
- * @returns {boolean}
90
- */
91
- function isBuffer (value) {
92
- return value && value.constructor && value.constructor.isBuffer && value.constructor.isBuffer.call(null, value)
93
- }
94
-
95
76
  /**
96
77
  * @param {any} value
97
78
  * @returns {string|undefined}
@@ -5,8 +5,8 @@ import { asU8A, fromString } from '../byte-utils.js'
5
5
 
6
6
  /**
7
7
  * @typedef {import('../../interface').EncodeOptions} EncodeOptions
8
+ * @typedef {import('../../interface').ByteWriter} ByteWriter
8
9
  * @typedef {import('../token').Token} Token
9
- * @typedef {import('../bl').Bl} Bl
10
10
  */
11
11
 
12
12
  class JSONEncoder extends Array {
@@ -17,7 +17,7 @@ class JSONEncoder extends Array {
17
17
  }
18
18
 
19
19
  /**
20
- * @param {Bl} buf
20
+ * @param {ByteWriter} buf
21
21
  */
22
22
  prefix (buf) {
23
23
  const recurs = this.inRecursive[this.inRecursive.length - 1]
@@ -42,7 +42,7 @@ class JSONEncoder extends Array {
42
42
  }
43
43
 
44
44
  /**
45
- * @param {Bl} buf
45
+ * @param {ByteWriter} buf
46
46
  * @param {Token} token
47
47
  */
48
48
  [Type.uint.major] (buf, token) {
@@ -56,7 +56,7 @@ class JSONEncoder extends Array {
56
56
  }
57
57
 
58
58
  /**
59
- * @param {Bl} buf
59
+ * @param {ByteWriter} buf
60
60
  * @param {Token} token
61
61
  */
62
62
  [Type.negint.major] (buf, token) {
@@ -65,7 +65,7 @@ class JSONEncoder extends Array {
65
65
  }
66
66
 
67
67
  /**
68
- * @param {Bl} _buf
68
+ * @param {ByteWriter} _buf
69
69
  * @param {Token} _token
70
70
  */
71
71
  [Type.bytes.major] (_buf, _token) {
@@ -73,7 +73,7 @@ class JSONEncoder extends Array {
73
73
  }
74
74
 
75
75
  /**
76
- * @param {Bl} buf
76
+ * @param {ByteWriter} buf
77
77
  * @param {Token} token
78
78
  */
79
79
  [Type.string.major] (buf, token) {
@@ -86,7 +86,7 @@ class JSONEncoder extends Array {
86
86
  }
87
87
 
88
88
  /**
89
- * @param {Bl} buf
89
+ * @param {ByteWriter} buf
90
90
  * @param {Token} _token
91
91
  */
92
92
  [Type.array.major] (buf, _token) {
@@ -96,7 +96,7 @@ class JSONEncoder extends Array {
96
96
  }
97
97
 
98
98
  /**
99
- * @param {Bl} buf
99
+ * @param {ByteWriter} buf
100
100
  * @param {Token} _token
101
101
  */
102
102
  [Type.map.major] (buf, _token) {
@@ -106,13 +106,13 @@ class JSONEncoder extends Array {
106
106
  }
107
107
 
108
108
  /**
109
- * @param {Bl} _buf
109
+ * @param {ByteWriter} _buf
110
110
  * @param {Token} _token
111
111
  */
112
112
  [Type.tag.major] (_buf, _token) {}
113
113
 
114
114
  /**
115
- * @param {Bl} buf
115
+ * @param {ByteWriter} buf
116
116
  * @param {Token} token
117
117
  */
118
118
  [Type.float.major] (buf, token) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cborg",
3
- "version": "4.4.1",
3
+ "version": "4.5.1",
4
4
  "description": "Fast CBOR with a focus on strictness",
5
5
  "main": "cborg.js",
6
6
  "type": "module",
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  // some from https://github.com/PJK/libcbor
11
17
 
12
18
  const fixtures = [
@@ -27,6 +33,8 @@ const fixtures = [
27
33
  { data: '1bffffffffffffffff', expected: BigInt('18446744073709551615'), type: 'uint64' }
28
34
  ]
29
35
 
36
+ const fixedDest = new Uint8Array(1024)
37
+
30
38
  describe('uint', () => {
31
39
  describe('decode', () => {
32
40
  for (const fixture of fixtures) {
@@ -53,8 +61,10 @@ describe('uint', () => {
53
61
  it(`should encode ${fixture.type}=${fixture.expected}`, () => {
54
62
  if (fixture.strict === false) {
55
63
  assert.notStrictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`)
64
+ assert.notStrictEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`)
56
65
  } else {
57
66
  assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`)
67
+ assert.strictEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`)
58
68
  }
59
69
  })
60
70
  }
@@ -66,6 +76,7 @@ describe('uint', () => {
66
76
  if (fixture.strict !== false) {
67
77
  it(`should roundtrip ${fixture.type}=${fixture.expected}`, () => {
68
78
  assert.ok(decode(encode(fixture.expected)) === fixture.expected, `roundtrip ${fixture.type}`)
79
+ assert.ok(decode(encodeIntoBytes(fixture.expected, fixedDest)) === fixture.expected, `roundtrip ${fixture.type}`)
69
80
  })
70
81
  }
71
82
  }
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  // some from https://github.com/PJK/libcbor
11
17
 
12
18
  const fixtures = [
@@ -28,6 +34,8 @@ const fixtures = [
28
34
  { data: '3bffffffffffffffff', expected: BigInt('-18446744073709551616'), type: 'negint64' }
29
35
  ]
30
36
 
37
+ const fixedDest = new Uint8Array(1024)
38
+
31
39
  describe('negint', () => {
32
40
  describe('decode', () => {
33
41
  for (const fixture of fixtures) {
@@ -48,8 +56,10 @@ describe('negint', () => {
48
56
  it(`should encode ${fixture.type}=${fixture.expected}`, () => {
49
57
  if (fixture.strict === false) {
50
58
  assert.notStrictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`)
59
+ assert.notStrictEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`)
51
60
  } else {
52
61
  assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`)
62
+ assert.strictEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`)
53
63
  }
54
64
  })
55
65
  }
@@ -60,6 +70,7 @@ describe('negint', () => {
60
70
  for (const fixture of fixtures) {
61
71
  it(`should roundtrip ${fixture.type}=${fixture.expected}`, () => {
62
72
  assert.ok(decode(encode(fixture.expected)) === fixture.expected, `roundtrip ${fixture.type}`)
73
+ assert.ok(decode(encodeIntoBytes(fixture.expected, fixedDest)) === fixture.expected, `roundtrip ${fixture.type}`)
63
74
  })
64
75
  }
65
76
  })
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { useBuffer, fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  // some from https://github.com/PJK/libcbor
11
17
 
12
18
  const fixtures = [
@@ -42,6 +48,8 @@ const fixtures = [
42
48
  }
43
49
  ]
44
50
 
51
+ const fixedDest = new Uint8Array(65536 + 8)
52
+
45
53
  // fill up byte arrays we can validate in strict mode, the minimal size for each
46
54
  // excluding 64-bit because 4G is just too big
47
55
  ;(() => {
@@ -111,8 +119,10 @@ describe('bytes', () => {
111
119
  assert.throws(() => encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/)
112
120
  } else if (fixture.strict === false) {
113
121
  assert.notStrictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type} !strict`)
122
+ assert.notStrictEqual(toHex(encodeIntoBytes(data, fixedDest)), expectedHex, `encode ${fixture.type} !strict`)
114
123
  } else {
115
124
  assert.strictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type}`)
125
+ assert.strictEqual(toHex(encodeIntoBytes(data, fixedDest)), expectedHex, `encode ${fixture.type}`)
116
126
  }
117
127
  })
118
128
  }
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  // some from https://github.com/PJK/libcbor
11
17
 
12
18
  const fixtures = [
@@ -52,6 +58,8 @@ const fixtures = [
52
58
  }
53
59
  ]
54
60
 
61
+ const fixedDest = new Uint8Array(65536 + 8)
62
+
55
63
  // fill up byte arrays converted to strings so we can validate in strict mode,
56
64
  // the minimal size for each excluding 64-bit because 4G is just too big
57
65
  ;(() => {
@@ -131,8 +139,10 @@ describe('string', () => {
131
139
  assert.throws(() => encode(data), Error, /^CBOR encode error: number too large to encode \(-\d+\)$/)
132
140
  } else if (fixture.strict === false) {
133
141
  assert.notStrictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type} !strict`)
142
+ assert.notStrictEqual(toHex(encodeIntoBytes(data, fixedDest)), expectedHex, `encode ${fixture.type} !strict`)
134
143
  } else {
135
144
  assert.strictEqual(toHex(encode(data)), expectedHex, `encode ${fixture.type}`)
145
+ assert.strictEqual(toHex(encodeIntoBytes(data, fixedDest)), expectedHex, `encode ${fixture.type}`)
136
146
  }
137
147
  })
138
148
 
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  const fixtures = [
11
17
  { data: '80', expected: [], type: 'array empty' },
12
18
  { data: '8102', expected: [2], type: 'array 1 compact uint' },
@@ -35,6 +41,8 @@ const fixtures = [
35
41
  { data: '9b000000000000000403040506', expected: [3, 4, 5, 6], type: 'array 4 ints, length64', strict: false }
36
42
  ]
37
43
 
44
+ const fixedDest = new Uint8Array(1024)
45
+
38
46
  describe('array', () => {
39
47
  describe('decode', () => {
40
48
  for (const fixture of fixtures) {
@@ -63,8 +71,10 @@ describe('array', () => {
63
71
  assert.throws(encode.bind(null, fixture.expected), Error, /^CBOR encode error: number too large to encode \(\d+\)$/)
64
72
  } else if (fixture.strict === false) {
65
73
  assert.notDeepEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type} !strict`)
74
+ assert.notDeepEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type} !strict`)
66
75
  } else {
67
76
  assert.strictEqual(toHex(encode(fixture.expected)), fixture.data, `encode ${fixture.type}`)
77
+ assert.strictEqual(toHex(encodeIntoBytes(fixture.expected, fixedDest)), fixture.data, `encode ${fixture.type}`)
68
78
  }
69
79
  })
70
80
  }
package/test/test-5map.js CHANGED
@@ -2,11 +2,17 @@
2
2
 
3
3
  import * as chai from 'chai'
4
4
 
5
- import { decode, encode } from '../cborg.js'
5
+ import { decode, encode, encodeInto } from '../cborg.js'
6
6
  import { fromHex, toHex } from '../lib/byte-utils.js'
7
7
 
8
8
  const { assert } = chai
9
9
 
10
+ // Helper to get encoded bytes from encodeInto (which returns { written })
11
+ const encodeIntoBytes = (data, dest) => {
12
+ const { written } = encodeInto(data, dest)
13
+ return dest.subarray(0, written)
14
+ }
15
+
10
16
  // TODO: reject duplicate keys from encoded form
11
17
 
12
18
  const fixtures = [
@@ -133,6 +139,8 @@ const fixtures = [
133
139
  { data: 'bb0000000000000001616101', expected: { a: 1 }, type: 'map 1 pair, length64', strict: false }
134
140
  ]
135
141
 
142
+ const fixedDest = new Uint8Array(1024)
143
+
136
144
  function toMap (arr) {
137
145
  const m = new Map()
138
146
  for (const [key, value] of arr) {
@@ -205,9 +213,9 @@ describe('map', () => {
205
213
  if (fixture.unsafe) {
206
214
  assert.throws(encode.bind(null, toEncode), Error, /^CBOR encode error: number too large to encode \(\d+\)$/)
207
215
  } else if (fixture.strict === false || fixture.roundtrip === false) {
208
- assert.notDeepEqual(toHex(encode(toEncode)), fixture.data, `encode ${fixture.type} !strict`)
216
+ assert.notDeepEqual(toHex(encodeIntoBytes(toEncode, fixedDest)), fixture.data, `encode ${fixture.type} !strict`)
209
217
  } else {
210
- assert.strictEqual(toHex(encode(toEncode)), fixture.data, `encode ${fixture.type}`)
218
+ assert.strictEqual(toHex(encodeIntoBytes(toEncode, fixedDest)), fixture.data, `encode ${fixture.type}`)
211
219
  }
212
220
  })
213
221
  }