cborg 4.5.8 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/dependabot.yml +4 -0
- package/.github/workflows/test-and-release.yml +2 -4
- package/CHANGELOG.md +44 -0
- package/README.md +213 -9
- package/cborg.js +4 -4
- package/example-extended.js +122 -0
- package/interface.ts +15 -3
- package/lib/0uint.js +2 -2
- package/lib/1negint.js +2 -2
- package/lib/2bytes.js +2 -2
- package/lib/3string.js +2 -2
- package/lib/4array.js +2 -2
- package/lib/5map.js +2 -2
- package/lib/6tag.js +2 -2
- package/lib/7float.js +5 -4
- package/lib/decode.js +94 -4
- package/lib/encode.js +7 -7
- package/lib/extended/extended.js +250 -0
- package/lib/json/decode.js +2 -2
- package/lib/json/encode.js +3 -3
- package/lib/jump.js +1 -1
- package/lib/length.js +3 -3
- package/lib/taglib.js +452 -0
- package/package.json +21 -17
- package/test/common.js +2 -1
- package/test/test-6tag.js +2 -1
- package/test/test-cbor-vectors.js +14 -6
- package/test/test-extended-vectors.js +293 -0
- package/test/test-extended.js +684 -0
- package/test/test-taglib.js +634 -0
- package/tsconfig.json +7 -11
- package/types/cborg.d.ts +4 -4
- package/types/cborg.d.ts.map +1 -1
- package/types/interface.d.ts +14 -3
- package/types/interface.d.ts.map +1 -1
- package/types/lib/0uint.d.ts +4 -4
- package/types/lib/0uint.d.ts.map +1 -1
- package/types/lib/1negint.d.ts +4 -4
- package/types/lib/1negint.d.ts.map +1 -1
- package/types/lib/2bytes.d.ts +2 -2
- package/types/lib/2bytes.d.ts.map +1 -1
- package/types/lib/3string.d.ts +2 -2
- package/types/lib/3string.d.ts.map +1 -1
- package/types/lib/4array.d.ts +2 -2
- package/types/lib/4array.d.ts.map +1 -1
- package/types/lib/5map.d.ts +2 -2
- package/types/lib/5map.d.ts.map +1 -1
- package/types/lib/6tag.d.ts +4 -4
- package/types/lib/6tag.d.ts.map +1 -1
- package/types/lib/7float.d.ts +6 -6
- package/types/lib/7float.d.ts.map +1 -1
- package/types/lib/byte-utils.d.ts +5 -2
- package/types/lib/byte-utils.d.ts.map +1 -1
- package/types/lib/decode.d.ts +4 -3
- package/types/lib/decode.d.ts.map +1 -1
- package/types/lib/encode.d.ts +8 -8
- package/types/lib/encode.d.ts.map +1 -1
- package/types/lib/extended/extended.d.ts +78 -0
- package/types/lib/extended/extended.d.ts.map +1 -0
- package/types/lib/json/decode.d.ts +5 -5
- package/types/lib/json/decode.d.ts.map +1 -1
- package/types/lib/json/encode.d.ts +3 -3
- package/types/lib/json/encode.d.ts.map +1 -1
- package/types/lib/jump.d.ts +1 -1
- package/types/lib/jump.d.ts.map +1 -1
- package/types/lib/length.d.ts +3 -3
- package/types/lib/length.d.ts.map +1 -1
- package/types/lib/taglib.d.ts +143 -0
- package/types/lib/taglib.d.ts.map +1 -0
- package/types/tsconfig.tsbuildinfo +1 -1
- package/taglib.js +0 -73
- package/types/taglib.d.ts +0 -18
- package/types/taglib.d.ts.map +0 -1
|
@@ -0,0 +1,634 @@
|
|
|
1
|
+
/* eslint-env mocha */
|
|
2
|
+
|
|
3
|
+
import * as chai from 'chai'
|
|
4
|
+
import { encode, decode } from '../cborg.js'
|
|
5
|
+
import {
|
|
6
|
+
// Tag constants
|
|
7
|
+
TAG_DATE_EPOCH,
|
|
8
|
+
TAG_BIGINT_POS,
|
|
9
|
+
TAG_BIGINT_NEG,
|
|
10
|
+
TAG_UINT8_ARRAY,
|
|
11
|
+
TAG_UINT8_CLAMPED_ARRAY,
|
|
12
|
+
TAG_INT8_ARRAY,
|
|
13
|
+
TAG_UINT16_ARRAY_LE,
|
|
14
|
+
TAG_UINT32_ARRAY_LE,
|
|
15
|
+
TAG_BIGUINT64_ARRAY_LE,
|
|
16
|
+
TAG_INT16_ARRAY_LE,
|
|
17
|
+
TAG_INT32_ARRAY_LE,
|
|
18
|
+
TAG_BIGINT64_ARRAY_LE,
|
|
19
|
+
TAG_FLOAT32_ARRAY_LE,
|
|
20
|
+
TAG_FLOAT64_ARRAY_LE,
|
|
21
|
+
TAG_SET,
|
|
22
|
+
TAG_MAP,
|
|
23
|
+
TAG_REGEXP,
|
|
24
|
+
|
|
25
|
+
// BigInt
|
|
26
|
+
bigIntEncoder,
|
|
27
|
+
bigIntDecoder,
|
|
28
|
+
bigNegIntDecoder,
|
|
29
|
+
structBigIntEncoder,
|
|
30
|
+
|
|
31
|
+
// Date
|
|
32
|
+
dateEncoder,
|
|
33
|
+
dateDecoder,
|
|
34
|
+
|
|
35
|
+
// RegExp
|
|
36
|
+
regExpEncoder,
|
|
37
|
+
regExpDecoder,
|
|
38
|
+
|
|
39
|
+
// Set
|
|
40
|
+
setEncoder,
|
|
41
|
+
setDecoder,
|
|
42
|
+
|
|
43
|
+
// Map
|
|
44
|
+
mapEncoder,
|
|
45
|
+
mapDecoder,
|
|
46
|
+
|
|
47
|
+
// TypedArrays
|
|
48
|
+
uint8ArrayEncoder,
|
|
49
|
+
uint8ArrayDecoder,
|
|
50
|
+
uint8ClampedArrayEncoder,
|
|
51
|
+
uint8ClampedArrayDecoder,
|
|
52
|
+
int8ArrayEncoder,
|
|
53
|
+
int8ArrayDecoder,
|
|
54
|
+
uint16ArrayEncoder,
|
|
55
|
+
uint16ArrayDecoder,
|
|
56
|
+
uint32ArrayEncoder,
|
|
57
|
+
uint32ArrayDecoder,
|
|
58
|
+
bigUint64ArrayEncoder,
|
|
59
|
+
bigUint64ArrayDecoder,
|
|
60
|
+
int16ArrayEncoder,
|
|
61
|
+
int16ArrayDecoder,
|
|
62
|
+
int32ArrayEncoder,
|
|
63
|
+
int32ArrayDecoder,
|
|
64
|
+
bigInt64ArrayEncoder,
|
|
65
|
+
bigInt64ArrayDecoder,
|
|
66
|
+
float32ArrayEncoder,
|
|
67
|
+
float32ArrayDecoder,
|
|
68
|
+
float64ArrayEncoder,
|
|
69
|
+
float64ArrayDecoder
|
|
70
|
+
} from '../lib/taglib.js'
|
|
71
|
+
|
|
72
|
+
const { assert } = chai
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Create a mock decode control for unit testing decoders
|
|
76
|
+
* @param {any} value - The value that decode() should return
|
|
77
|
+
* @param {Array<[any, any]>} [entries] - Optional entries for decode.entries()
|
|
78
|
+
* @returns {import('../interface').TagDecodeControl}
|
|
79
|
+
*/
|
|
80
|
+
function mockDecode (value, entries) {
|
|
81
|
+
const fn = () => value
|
|
82
|
+
fn.entries = () => entries || []
|
|
83
|
+
return fn
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
describe('taglib', () => {
|
|
87
|
+
describe('tag constants', () => {
|
|
88
|
+
it('has correct standard tag values', () => {
|
|
89
|
+
assert.strictEqual(TAG_DATE_EPOCH, 1)
|
|
90
|
+
assert.strictEqual(TAG_BIGINT_POS, 2)
|
|
91
|
+
assert.strictEqual(TAG_BIGINT_NEG, 3)
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('has correct TypedArray tag values', () => {
|
|
95
|
+
assert.strictEqual(TAG_UINT8_ARRAY, 64)
|
|
96
|
+
assert.strictEqual(TAG_UINT8_CLAMPED_ARRAY, 68)
|
|
97
|
+
assert.strictEqual(TAG_INT8_ARRAY, 72)
|
|
98
|
+
assert.strictEqual(TAG_UINT16_ARRAY_LE, 69)
|
|
99
|
+
assert.strictEqual(TAG_UINT32_ARRAY_LE, 70)
|
|
100
|
+
assert.strictEqual(TAG_BIGUINT64_ARRAY_LE, 71)
|
|
101
|
+
assert.strictEqual(TAG_INT16_ARRAY_LE, 77)
|
|
102
|
+
assert.strictEqual(TAG_INT32_ARRAY_LE, 78)
|
|
103
|
+
assert.strictEqual(TAG_BIGINT64_ARRAY_LE, 79)
|
|
104
|
+
assert.strictEqual(TAG_FLOAT32_ARRAY_LE, 85)
|
|
105
|
+
assert.strictEqual(TAG_FLOAT64_ARRAY_LE, 86)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('has correct extended tag values', () => {
|
|
109
|
+
assert.strictEqual(TAG_SET, 258)
|
|
110
|
+
assert.strictEqual(TAG_MAP, 259)
|
|
111
|
+
assert.strictEqual(TAG_REGEXP, 21066)
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
describe('BigInt', () => {
|
|
116
|
+
describe('bigIntDecoder', () => {
|
|
117
|
+
it('decodes zero', () => {
|
|
118
|
+
assert.strictEqual(bigIntDecoder(mockDecode(new Uint8Array([0]))), 0n)
|
|
119
|
+
})
|
|
120
|
+
|
|
121
|
+
it('decodes small positive', () => {
|
|
122
|
+
assert.strictEqual(bigIntDecoder(mockDecode(new Uint8Array([100]))), 100n)
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
it('decodes large positive', () => {
|
|
126
|
+
// 0x0100000000000000 = 72057594037927936
|
|
127
|
+
assert.strictEqual(
|
|
128
|
+
bigIntDecoder(mockDecode(new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0]))),
|
|
129
|
+
72057594037927936n
|
|
130
|
+
)
|
|
131
|
+
})
|
|
132
|
+
})
|
|
133
|
+
|
|
134
|
+
describe('bigNegIntDecoder', () => {
|
|
135
|
+
it('decodes -1', () => {
|
|
136
|
+
assert.strictEqual(bigNegIntDecoder(mockDecode(new Uint8Array([0]))), -1n)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('decodes negative', () => {
|
|
140
|
+
// -1 - 100 = -101
|
|
141
|
+
assert.strictEqual(bigNegIntDecoder(mockDecode(new Uint8Array([100]))), -101n)
|
|
142
|
+
})
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
describe('bigIntEncoder (IPLD compatible)', () => {
|
|
146
|
+
it('returns null for small values (within 64-bit range)', () => {
|
|
147
|
+
assert.strictEqual(bigIntEncoder(0n), null)
|
|
148
|
+
assert.strictEqual(bigIntEncoder(100n), null)
|
|
149
|
+
assert.strictEqual(bigIntEncoder(-100n), null)
|
|
150
|
+
assert.strictEqual(bigIntEncoder(BigInt('18446744073709551615')), null)
|
|
151
|
+
assert.strictEqual(bigIntEncoder(BigInt('-18446744073709551616')), null)
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('returns tokens for large positive values', () => {
|
|
155
|
+
const tokens = bigIntEncoder(BigInt('18446744073709551616'))
|
|
156
|
+
assert.ok(Array.isArray(tokens))
|
|
157
|
+
assert.strictEqual(tokens[0].value, TAG_BIGINT_POS)
|
|
158
|
+
})
|
|
159
|
+
|
|
160
|
+
it('returns tokens for large negative values', () => {
|
|
161
|
+
const tokens = bigIntEncoder(BigInt('-18446744073709551617'))
|
|
162
|
+
assert.ok(Array.isArray(tokens))
|
|
163
|
+
assert.strictEqual(tokens[0].value, TAG_BIGINT_NEG)
|
|
164
|
+
})
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
describe('structBigIntEncoder (always tags)', () => {
|
|
168
|
+
it('returns tokens for zero', () => {
|
|
169
|
+
const tokens = structBigIntEncoder(0n)
|
|
170
|
+
assert.ok(Array.isArray(tokens))
|
|
171
|
+
assert.strictEqual(tokens[0].value, TAG_BIGINT_POS)
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('returns tokens for small positive', () => {
|
|
175
|
+
const tokens = structBigIntEncoder(100n)
|
|
176
|
+
assert.ok(Array.isArray(tokens))
|
|
177
|
+
assert.strictEqual(tokens[0].value, TAG_BIGINT_POS)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it('returns tokens for small negative', () => {
|
|
181
|
+
const tokens = structBigIntEncoder(-1n)
|
|
182
|
+
assert.ok(Array.isArray(tokens))
|
|
183
|
+
assert.strictEqual(tokens[0].value, TAG_BIGINT_NEG)
|
|
184
|
+
})
|
|
185
|
+
})
|
|
186
|
+
|
|
187
|
+
describe('round-trip via encode/decode', () => {
|
|
188
|
+
const opts = {
|
|
189
|
+
typeEncoders: { bigint: structBigIntEncoder },
|
|
190
|
+
tags: { [TAG_BIGINT_POS]: bigIntDecoder, [TAG_BIGINT_NEG]: bigNegIntDecoder }
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
it('round-trips 0n', () => {
|
|
194
|
+
const result = decode(encode(0n, opts), opts)
|
|
195
|
+
assert.strictEqual(typeof result, 'bigint')
|
|
196
|
+
assert.strictEqual(result, 0n)
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
it('round-trips 100n', () => {
|
|
200
|
+
const result = decode(encode(100n, opts), opts)
|
|
201
|
+
assert.strictEqual(typeof result, 'bigint')
|
|
202
|
+
assert.strictEqual(result, 100n)
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
it('round-trips -1n', () => {
|
|
206
|
+
const result = decode(encode(-1n, opts), opts)
|
|
207
|
+
assert.strictEqual(typeof result, 'bigint')
|
|
208
|
+
assert.strictEqual(result, -1n)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
it('round-trips large positive', () => {
|
|
212
|
+
const n = BigInt('9007199254740993')
|
|
213
|
+
const result = decode(encode(n, opts), opts)
|
|
214
|
+
assert.strictEqual(result, n)
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
it('round-trips large negative', () => {
|
|
218
|
+
const n = BigInt('-18446744073709551617')
|
|
219
|
+
const result = decode(encode(n, opts), opts)
|
|
220
|
+
assert.strictEqual(result, n)
|
|
221
|
+
})
|
|
222
|
+
})
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
describe('Date', () => {
|
|
226
|
+
describe('dateEncoder', () => {
|
|
227
|
+
it('returns tag 1 with float seconds', () => {
|
|
228
|
+
const tokens = dateEncoder(new Date(1000))
|
|
229
|
+
assert.strictEqual(tokens[0].value, TAG_DATE_EPOCH)
|
|
230
|
+
assert.strictEqual(tokens[1].value, 1) // 1000ms = 1 second
|
|
231
|
+
})
|
|
232
|
+
|
|
233
|
+
it('handles milliseconds', () => {
|
|
234
|
+
const tokens = dateEncoder(new Date(1500))
|
|
235
|
+
assert.strictEqual(tokens[1].value, 1.5)
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
it('handles epoch', () => {
|
|
239
|
+
const tokens = dateEncoder(new Date(0))
|
|
240
|
+
assert.strictEqual(tokens[1].value, 0)
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
describe('dateDecoder', () => {
|
|
245
|
+
it('decodes seconds to Date', () => {
|
|
246
|
+
const date = dateDecoder(mockDecode(1))
|
|
247
|
+
assert.ok(date instanceof Date)
|
|
248
|
+
assert.strictEqual(date.getTime(), 1000)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('decodes float seconds', () => {
|
|
252
|
+
const date = dateDecoder(mockDecode(1.5))
|
|
253
|
+
assert.strictEqual(date.getTime(), 1500)
|
|
254
|
+
})
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
describe('round-trip via encode/decode', () => {
|
|
258
|
+
const opts = {
|
|
259
|
+
typeEncoders: { Date: dateEncoder },
|
|
260
|
+
tags: { [TAG_DATE_EPOCH]: dateDecoder }
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
it('round-trips a date', () => {
|
|
264
|
+
const d = new Date('2024-01-15T12:30:00.000Z')
|
|
265
|
+
const result = decode(encode(d, opts), opts)
|
|
266
|
+
assert.ok(result instanceof Date)
|
|
267
|
+
assert.strictEqual(result.getTime(), d.getTime())
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
it('round-trips date with milliseconds', () => {
|
|
271
|
+
const d = new Date('2024-01-15T12:30:00.123Z')
|
|
272
|
+
const result = decode(encode(d, opts), opts)
|
|
273
|
+
assert.strictEqual(result.getTime(), d.getTime())
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
it('round-trips epoch date', () => {
|
|
277
|
+
const d = new Date(0)
|
|
278
|
+
const result = decode(encode(d, opts), opts)
|
|
279
|
+
assert.strictEqual(result.getTime(), 0)
|
|
280
|
+
})
|
|
281
|
+
})
|
|
282
|
+
})
|
|
283
|
+
|
|
284
|
+
describe('RegExp', () => {
|
|
285
|
+
describe('regExpEncoder', () => {
|
|
286
|
+
it('encodes pattern without flags', () => {
|
|
287
|
+
const tokens = regExpEncoder(/foo/)
|
|
288
|
+
assert.strictEqual(tokens[0].value, TAG_REGEXP)
|
|
289
|
+
assert.strictEqual(tokens[1].value, 1) // array length 1
|
|
290
|
+
assert.strictEqual(tokens[2].value, 'foo')
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
it('encodes pattern with flags', () => {
|
|
294
|
+
const tokens = regExpEncoder(/foo/gi)
|
|
295
|
+
assert.strictEqual(tokens[0].value, TAG_REGEXP)
|
|
296
|
+
assert.strictEqual(tokens[1].value, 2) // array length 2
|
|
297
|
+
assert.strictEqual(tokens[2].value, 'foo')
|
|
298
|
+
assert.strictEqual(tokens[3].value, 'gi')
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
describe('regExpDecoder', () => {
|
|
303
|
+
it('decodes array with pattern only', () => {
|
|
304
|
+
const re = regExpDecoder(mockDecode(['foo']))
|
|
305
|
+
assert.ok(re instanceof RegExp)
|
|
306
|
+
assert.strictEqual(re.source, 'foo')
|
|
307
|
+
assert.strictEqual(re.flags, '')
|
|
308
|
+
})
|
|
309
|
+
|
|
310
|
+
it('decodes array with pattern and flags', () => {
|
|
311
|
+
const re = regExpDecoder(mockDecode(['foo', 'gi']))
|
|
312
|
+
assert.strictEqual(re.source, 'foo')
|
|
313
|
+
assert.strictEqual(re.flags, 'gi')
|
|
314
|
+
})
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
describe('round-trip via encode/decode', () => {
|
|
318
|
+
const opts = {
|
|
319
|
+
typeEncoders: { RegExp: regExpEncoder },
|
|
320
|
+
tags: { [TAG_REGEXP]: regExpDecoder }
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
it('round-trips pattern without flags', () => {
|
|
324
|
+
const re = /foo.*bar/
|
|
325
|
+
const result = decode(encode(re, opts), opts)
|
|
326
|
+
assert.ok(result instanceof RegExp)
|
|
327
|
+
assert.strictEqual(result.source, re.source)
|
|
328
|
+
assert.strictEqual(result.flags, re.flags)
|
|
329
|
+
})
|
|
330
|
+
|
|
331
|
+
it('round-trips pattern with flags', () => {
|
|
332
|
+
const re = /foo.*bar/gim
|
|
333
|
+
const result = decode(encode(re, opts), opts)
|
|
334
|
+
assert.strictEqual(result.source, re.source)
|
|
335
|
+
assert.strictEqual(result.flags, re.flags)
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
it('round-trips empty pattern', () => {
|
|
339
|
+
const re = /(?:)/
|
|
340
|
+
const result = decode(encode(re, opts), opts)
|
|
341
|
+
assert.strictEqual(result.source, '(?:)')
|
|
342
|
+
})
|
|
343
|
+
})
|
|
344
|
+
})
|
|
345
|
+
|
|
346
|
+
describe('Set', () => {
|
|
347
|
+
describe('setEncoder', () => {
|
|
348
|
+
it('encodes empty set', () => {
|
|
349
|
+
const tokens = setEncoder(new Set(), 'Set', {})
|
|
350
|
+
assert.strictEqual(tokens[0].value, TAG_SET)
|
|
351
|
+
assert.strictEqual(tokens[1].value, 0) // array length 0
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
describe('setDecoder', () => {
|
|
356
|
+
it('decodes array to Set', () => {
|
|
357
|
+
const s = setDecoder(mockDecode([1, 2, 3]))
|
|
358
|
+
assert.ok(s instanceof Set)
|
|
359
|
+
assert.strictEqual(s.size, 3)
|
|
360
|
+
assert.ok(s.has(1))
|
|
361
|
+
assert.ok(s.has(2))
|
|
362
|
+
assert.ok(s.has(3))
|
|
363
|
+
})
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
describe('round-trip via encode/decode', () => {
|
|
367
|
+
const opts = {
|
|
368
|
+
typeEncoders: { Set: setEncoder },
|
|
369
|
+
tags: { [TAG_SET]: setDecoder }
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
it('round-trips empty set', () => {
|
|
373
|
+
const s = new Set()
|
|
374
|
+
const result = decode(encode(s, opts), opts)
|
|
375
|
+
assert.ok(result instanceof Set)
|
|
376
|
+
assert.strictEqual(result.size, 0)
|
|
377
|
+
})
|
|
378
|
+
|
|
379
|
+
it('round-trips set with primitives', () => {
|
|
380
|
+
const s = new Set([1, 2, 3, 'a', 'b'])
|
|
381
|
+
const result = decode(encode(s, opts), opts)
|
|
382
|
+
assert.ok(result instanceof Set)
|
|
383
|
+
assert.strictEqual(result.size, 5)
|
|
384
|
+
assert.ok(result.has(1))
|
|
385
|
+
assert.ok(result.has('a'))
|
|
386
|
+
})
|
|
387
|
+
|
|
388
|
+
it('round-trips set with nested objects', () => {
|
|
389
|
+
const s = new Set([{ x: 1 }, { y: 2 }])
|
|
390
|
+
const result = decode(encode(s, opts), opts)
|
|
391
|
+
assert.strictEqual(result.size, 2)
|
|
392
|
+
const arr = [...result]
|
|
393
|
+
assert.deepStrictEqual(arr[0], { x: 1 })
|
|
394
|
+
assert.deepStrictEqual(arr[1], { y: 2 })
|
|
395
|
+
})
|
|
396
|
+
})
|
|
397
|
+
})
|
|
398
|
+
|
|
399
|
+
describe('Map (Tag 259)', () => {
|
|
400
|
+
describe('mapEncoder', () => {
|
|
401
|
+
it('encodes empty map', () => {
|
|
402
|
+
const tokens = mapEncoder(new Map(), 'Map', {})
|
|
403
|
+
assert.strictEqual(tokens[0].value, TAG_MAP)
|
|
404
|
+
assert.strictEqual(tokens[1].value, 0) // map length 0
|
|
405
|
+
})
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
describe('mapDecoder', () => {
|
|
409
|
+
it('decodes entries as Map', () => {
|
|
410
|
+
const result = mapDecoder(mockDecode(null, [['a', 1]]))
|
|
411
|
+
assert.ok(result instanceof Map)
|
|
412
|
+
assert.strictEqual(result.get('a'), 1)
|
|
413
|
+
})
|
|
414
|
+
|
|
415
|
+
it('decodes multiple entries as Map', () => {
|
|
416
|
+
const result = mapDecoder(mockDecode(null, [['a', 1], ['b', 2]]))
|
|
417
|
+
assert.ok(result instanceof Map)
|
|
418
|
+
assert.strictEqual(result.get('a'), 1)
|
|
419
|
+
assert.strictEqual(result.get('b'), 2)
|
|
420
|
+
})
|
|
421
|
+
|
|
422
|
+
it('preserves non-string keys', () => {
|
|
423
|
+
const result = mapDecoder(mockDecode(null, [[1, 'one'], [2, 'two']]))
|
|
424
|
+
assert.ok(result instanceof Map)
|
|
425
|
+
assert.strictEqual(result.get(1), 'one')
|
|
426
|
+
assert.strictEqual(result.get(2), 'two')
|
|
427
|
+
})
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
describe('round-trip via encode/decode', () => {
|
|
431
|
+
const opts = {
|
|
432
|
+
typeEncoders: { Map: mapEncoder },
|
|
433
|
+
tags: { [TAG_MAP]: mapDecoder }
|
|
434
|
+
// useMaps not needed - mapDecoder uses decode.entries() to preserve key types
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
it('round-trips empty map', () => {
|
|
438
|
+
const m = new Map()
|
|
439
|
+
const result = decode(encode(m, opts), opts)
|
|
440
|
+
assert.ok(result instanceof Map)
|
|
441
|
+
assert.strictEqual(result.size, 0)
|
|
442
|
+
})
|
|
443
|
+
|
|
444
|
+
it('round-trips map with string keys', () => {
|
|
445
|
+
const m = new Map([['a', 1], ['b', 2]])
|
|
446
|
+
const result = decode(encode(m, opts), opts)
|
|
447
|
+
assert.ok(result instanceof Map)
|
|
448
|
+
assert.strictEqual(result.get('a'), 1)
|
|
449
|
+
assert.strictEqual(result.get('b'), 2)
|
|
450
|
+
})
|
|
451
|
+
|
|
452
|
+
it('round-trips map with number keys', () => {
|
|
453
|
+
const m = new Map([[1, 'one'], [2, 'two']])
|
|
454
|
+
const result = decode(encode(m, opts), opts)
|
|
455
|
+
assert.ok(result instanceof Map)
|
|
456
|
+
assert.strictEqual(result.get(1), 'one')
|
|
457
|
+
assert.strictEqual(result.get(2), 'two')
|
|
458
|
+
})
|
|
459
|
+
})
|
|
460
|
+
})
|
|
461
|
+
|
|
462
|
+
describe('TypedArrays', () => {
|
|
463
|
+
describe('Uint8Array', () => {
|
|
464
|
+
const opts = {
|
|
465
|
+
typeEncoders: { Uint8Array: uint8ArrayEncoder },
|
|
466
|
+
tags: { [TAG_UINT8_ARRAY]: uint8ArrayDecoder }
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
it('encodes with tag 64', () => {
|
|
470
|
+
const tokens = uint8ArrayEncoder(new Uint8Array([1, 2, 3]))
|
|
471
|
+
assert.strictEqual(tokens[0].value, TAG_UINT8_ARRAY)
|
|
472
|
+
})
|
|
473
|
+
|
|
474
|
+
it('round-trips', () => {
|
|
475
|
+
const arr = new Uint8Array([1, 2, 3, 4, 5])
|
|
476
|
+
const result = decode(encode(arr, opts), opts)
|
|
477
|
+
assert.ok(result instanceof Uint8Array)
|
|
478
|
+
assert.deepStrictEqual([...result], [1, 2, 3, 4, 5])
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
it('round-trips view of larger buffer', () => {
|
|
482
|
+
const buffer = new ArrayBuffer(100)
|
|
483
|
+
const view = new Uint8Array(buffer, 10, 5)
|
|
484
|
+
view.set([1, 2, 3, 4, 5])
|
|
485
|
+
const result = decode(encode(view, opts), opts)
|
|
486
|
+
assert.strictEqual(result.length, 5)
|
|
487
|
+
assert.deepStrictEqual([...result], [1, 2, 3, 4, 5])
|
|
488
|
+
})
|
|
489
|
+
})
|
|
490
|
+
|
|
491
|
+
describe('Uint8ClampedArray', () => {
|
|
492
|
+
const opts = {
|
|
493
|
+
typeEncoders: { Uint8ClampedArray: uint8ClampedArrayEncoder },
|
|
494
|
+
tags: { [TAG_UINT8_CLAMPED_ARRAY]: uint8ClampedArrayDecoder }
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
it('round-trips', () => {
|
|
498
|
+
const arr = new Uint8ClampedArray([0, 128, 255])
|
|
499
|
+
const result = decode(encode(arr, opts), opts)
|
|
500
|
+
assert.ok(result instanceof Uint8ClampedArray)
|
|
501
|
+
assert.deepStrictEqual([...result], [0, 128, 255])
|
|
502
|
+
})
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
describe('Int8Array', () => {
|
|
506
|
+
const opts = {
|
|
507
|
+
typeEncoders: { Int8Array: int8ArrayEncoder },
|
|
508
|
+
tags: { [TAG_INT8_ARRAY]: int8ArrayDecoder }
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
it('round-trips', () => {
|
|
512
|
+
const arr = new Int8Array([-128, 0, 127])
|
|
513
|
+
const result = decode(encode(arr, opts), opts)
|
|
514
|
+
assert.ok(result instanceof Int8Array)
|
|
515
|
+
assert.deepStrictEqual([...result], [-128, 0, 127])
|
|
516
|
+
})
|
|
517
|
+
})
|
|
518
|
+
|
|
519
|
+
describe('Uint16Array', () => {
|
|
520
|
+
const opts = {
|
|
521
|
+
typeEncoders: { Uint16Array: uint16ArrayEncoder },
|
|
522
|
+
tags: { [TAG_UINT16_ARRAY_LE]: uint16ArrayDecoder }
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
it('round-trips', () => {
|
|
526
|
+
const arr = new Uint16Array([0, 256, 65535])
|
|
527
|
+
const result = decode(encode(arr, opts), opts)
|
|
528
|
+
assert.ok(result instanceof Uint16Array)
|
|
529
|
+
assert.deepStrictEqual([...result], [0, 256, 65535])
|
|
530
|
+
})
|
|
531
|
+
})
|
|
532
|
+
|
|
533
|
+
describe('Uint32Array', () => {
|
|
534
|
+
const opts = {
|
|
535
|
+
typeEncoders: { Uint32Array: uint32ArrayEncoder },
|
|
536
|
+
tags: { [TAG_UINT32_ARRAY_LE]: uint32ArrayDecoder }
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
it('round-trips', () => {
|
|
540
|
+
const arr = new Uint32Array([0, 65536, 4294967295])
|
|
541
|
+
const result = decode(encode(arr, opts), opts)
|
|
542
|
+
assert.ok(result instanceof Uint32Array)
|
|
543
|
+
assert.deepStrictEqual([...result], [0, 65536, 4294967295])
|
|
544
|
+
})
|
|
545
|
+
})
|
|
546
|
+
|
|
547
|
+
describe('Int16Array', () => {
|
|
548
|
+
const opts = {
|
|
549
|
+
typeEncoders: { Int16Array: int16ArrayEncoder },
|
|
550
|
+
tags: { [TAG_INT16_ARRAY_LE]: int16ArrayDecoder }
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
it('round-trips', () => {
|
|
554
|
+
const arr = new Int16Array([-32768, 0, 32767])
|
|
555
|
+
const result = decode(encode(arr, opts), opts)
|
|
556
|
+
assert.ok(result instanceof Int16Array)
|
|
557
|
+
assert.deepStrictEqual([...result], [-32768, 0, 32767])
|
|
558
|
+
})
|
|
559
|
+
})
|
|
560
|
+
|
|
561
|
+
describe('Int32Array', () => {
|
|
562
|
+
const opts = {
|
|
563
|
+
typeEncoders: { Int32Array: int32ArrayEncoder },
|
|
564
|
+
tags: { [TAG_INT32_ARRAY_LE]: int32ArrayDecoder }
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
it('round-trips', () => {
|
|
568
|
+
const arr = new Int32Array([-2147483648, 0, 2147483647])
|
|
569
|
+
const result = decode(encode(arr, opts), opts)
|
|
570
|
+
assert.ok(result instanceof Int32Array)
|
|
571
|
+
assert.deepStrictEqual([...result], [-2147483648, 0, 2147483647])
|
|
572
|
+
})
|
|
573
|
+
})
|
|
574
|
+
|
|
575
|
+
describe('Float32Array', () => {
|
|
576
|
+
const opts = {
|
|
577
|
+
typeEncoders: { Float32Array: float32ArrayEncoder },
|
|
578
|
+
tags: { [TAG_FLOAT32_ARRAY_LE]: float32ArrayDecoder }
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
it('round-trips', () => {
|
|
582
|
+
const arr = new Float32Array([1.5, -2.5, 3.14])
|
|
583
|
+
const result = decode(encode(arr, opts), opts)
|
|
584
|
+
assert.ok(result instanceof Float32Array)
|
|
585
|
+
// Float32 has limited precision
|
|
586
|
+
assert.strictEqual(result[0], 1.5)
|
|
587
|
+
assert.strictEqual(result[1], -2.5)
|
|
588
|
+
assert.ok(Math.abs(result[2] - 3.14) < 0.001)
|
|
589
|
+
})
|
|
590
|
+
})
|
|
591
|
+
|
|
592
|
+
describe('Float64Array', () => {
|
|
593
|
+
const opts = {
|
|
594
|
+
typeEncoders: { Float64Array: float64ArrayEncoder },
|
|
595
|
+
tags: { [TAG_FLOAT64_ARRAY_LE]: float64ArrayDecoder }
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
it('round-trips', () => {
|
|
599
|
+
const arr = new Float64Array([1.1, -2.2, Math.PI, Infinity, -Infinity])
|
|
600
|
+
const result = decode(encode(arr, opts), opts)
|
|
601
|
+
assert.ok(result instanceof Float64Array)
|
|
602
|
+
assert.deepStrictEqual([...result], [1.1, -2.2, Math.PI, Infinity, -Infinity])
|
|
603
|
+
})
|
|
604
|
+
})
|
|
605
|
+
|
|
606
|
+
describe('BigUint64Array', () => {
|
|
607
|
+
const opts = {
|
|
608
|
+
typeEncoders: { BigUint64Array: bigUint64ArrayEncoder },
|
|
609
|
+
tags: { [TAG_BIGUINT64_ARRAY_LE]: bigUint64ArrayDecoder }
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
it('round-trips', () => {
|
|
613
|
+
const arr = new BigUint64Array([0n, 1n, BigInt('18446744073709551615')])
|
|
614
|
+
const result = decode(encode(arr, opts), opts)
|
|
615
|
+
assert.ok(result instanceof BigUint64Array)
|
|
616
|
+
assert.deepStrictEqual([...result], [0n, 1n, BigInt('18446744073709551615')])
|
|
617
|
+
})
|
|
618
|
+
})
|
|
619
|
+
|
|
620
|
+
describe('BigInt64Array', () => {
|
|
621
|
+
const opts = {
|
|
622
|
+
typeEncoders: { BigInt64Array: bigInt64ArrayEncoder },
|
|
623
|
+
tags: { [TAG_BIGINT64_ARRAY_LE]: bigInt64ArrayDecoder }
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
it('round-trips', () => {
|
|
627
|
+
const arr = new BigInt64Array([BigInt('-9223372036854775808'), 0n, BigInt('9223372036854775807')])
|
|
628
|
+
const result = decode(encode(arr, opts), opts)
|
|
629
|
+
assert.ok(result instanceof BigInt64Array)
|
|
630
|
+
assert.deepStrictEqual([...result], [BigInt('-9223372036854775808'), 0n, BigInt('9223372036854775807')])
|
|
631
|
+
})
|
|
632
|
+
})
|
|
633
|
+
})
|
|
634
|
+
})
|
package/tsconfig.json
CHANGED
|
@@ -16,30 +16,26 @@
|
|
|
16
16
|
"strict": true,
|
|
17
17
|
"alwaysStrict": true,
|
|
18
18
|
"esModuleInterop": true,
|
|
19
|
-
"target": "
|
|
20
|
-
"
|
|
19
|
+
"target": "ES2020",
|
|
20
|
+
"module": "nodenext",
|
|
21
|
+
"moduleResolution": "nodenext",
|
|
21
22
|
"declaration": true,
|
|
22
23
|
"declarationMap": true,
|
|
23
24
|
"outDir": "types",
|
|
24
25
|
"skipLibCheck": true,
|
|
25
26
|
"stripInternal": true,
|
|
26
27
|
"resolveJsonModule": true,
|
|
27
|
-
"
|
|
28
|
-
"emitDeclarationOnly": true,
|
|
29
|
-
"paths": {
|
|
30
|
-
"cborg": [
|
|
31
|
-
"cborg.js"
|
|
32
|
-
]
|
|
33
|
-
}
|
|
28
|
+
"emitDeclarationOnly": true
|
|
34
29
|
},
|
|
35
30
|
"include": [
|
|
36
31
|
"cborg.js",
|
|
37
|
-
"example.js",
|
|
38
32
|
"taglib.js",
|
|
33
|
+
"interface.ts",
|
|
39
34
|
"lib/"
|
|
40
35
|
],
|
|
41
36
|
"exclude": [
|
|
42
|
-
"node_modules"
|
|
37
|
+
"node_modules",
|
|
38
|
+
"lib/bin.js"
|
|
43
39
|
],
|
|
44
40
|
"compileOnSave": false
|
|
45
41
|
}
|
package/types/cborg.d.ts
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* There was originally just `TypeEncoder` so don't break types by renaming or not exporting
|
|
3
3
|
*/
|
|
4
|
-
export type TagDecoder = import("./interface").TagDecoder;
|
|
4
|
+
export type TagDecoder = import("./interface.js").TagDecoder;
|
|
5
5
|
/**
|
|
6
6
|
* Export the types that were present in the original manual cborg.d.ts
|
|
7
7
|
*/
|
|
8
|
-
export type TypeEncoder = import("./interface").OptionalTypeEncoder;
|
|
8
|
+
export type TypeEncoder = import("./interface.js").OptionalTypeEncoder;
|
|
9
9
|
/**
|
|
10
10
|
* Export the types that were present in the original manual cborg.d.ts
|
|
11
11
|
*/
|
|
12
|
-
export type DecodeOptions = import("./interface").DecodeOptions;
|
|
12
|
+
export type DecodeOptions = import("./interface.js").DecodeOptions;
|
|
13
13
|
/**
|
|
14
14
|
* Export the types that were present in the original manual cborg.d.ts
|
|
15
15
|
*/
|
|
16
|
-
export type EncodeOptions = import("./interface").EncodeOptions;
|
|
16
|
+
export type EncodeOptions = import("./interface.js").EncodeOptions;
|
|
17
17
|
import { decode } from './lib/decode.js';
|
|
18
18
|
import { decodeFirst } from './lib/decode.js';
|
|
19
19
|
import { Tokeniser } from './lib/decode.js';
|
package/types/cborg.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cborg.d.ts","sourceRoot":"","sources":["../cborg.js"],"names":[],"mappings":";;;yBAMa,OAAO,
|
|
1
|
+
{"version":3,"file":"cborg.d.ts","sourceRoot":"","sources":["../cborg.js"],"names":[],"mappings":";;;yBAMa,OAAO,gBAAgB,EAAE,UAAU;;;;0BAEnC,OAAO,gBAAgB,EAAE,mBAAmB;;;;4BAC5C,OAAO,gBAAgB,EAAE,aAAa;;;;4BACtC,OAAO,gBAAgB,EAAE,aAAa;uBATY,iBAAiB;4BAAjB,iBAAiB;0BAAjB,iBAAiB;+BAAjB,iBAAiB;uBADvB,iBAAiB;2BAAjB,iBAAiB;qCAAjB,iBAAiB;sBAE9C,gBAAgB;qBAAhB,gBAAgB"}
|