@marcuspuchalla/nachos 0.1.1 → 0.1.4

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 (62) hide show
  1. package/CHANGELOG.md +55 -0
  2. package/dist/{chunk-ZRPJUEIZ.js → chunk-5IWW5H47.js} +546 -227
  3. package/dist/chunk-5IWW5H47.js.map +1 -0
  4. package/dist/{chunk-2HBCILJS.cjs → chunk-RVG2BY32.cjs} +545 -226
  5. package/dist/chunk-RVG2BY32.cjs.map +1 -0
  6. package/dist/{chunk-2FUTHZQQ.cjs → chunk-S4RXO6IB.cjs} +244 -166
  7. package/dist/chunk-S4RXO6IB.cjs.map +1 -0
  8. package/dist/{chunk-7CFYWHS6.js → chunk-UMAX5MX5.js} +244 -166
  9. package/dist/chunk-UMAX5MX5.js.map +1 -0
  10. package/dist/encoder/index.cjs +13 -13
  11. package/dist/encoder/index.d.cts +2 -2
  12. package/dist/encoder/index.d.ts +2 -2
  13. package/dist/encoder/index.js +1 -1
  14. package/dist/index.cjs +32 -32
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.cts +28 -19
  17. package/dist/index.d.ts +28 -19
  18. package/dist/index.js +16 -16
  19. package/dist/index.js.map +1 -1
  20. package/dist/metafile-cjs.json +1 -1
  21. package/dist/metafile-esm.json +1 -1
  22. package/dist/parser/index.cjs +14 -14
  23. package/dist/parser/index.d.cts +3 -1
  24. package/dist/parser/index.d.ts +3 -1
  25. package/dist/parser/index.js +1 -1
  26. package/dist/{useCborSimpleEncoder-TVxzNJ_9.d.ts → useCborSimpleEncoder-BoKEmjP9.d.ts} +0 -2
  27. package/dist/{useCborSimpleEncoder-ButVU988.d.cts → useCborSimpleEncoder-C_OHxoB8.d.cts} +0 -2
  28. package/dist/{useCborTag-B_iaShG6.d.ts → useCborTag-BD6Sqp7p.d.ts} +11 -6
  29. package/dist/{useCborTag-BfTIV8HM.d.cts → useCborTag-QpZR-Er2.d.cts} +11 -6
  30. package/package.json +1 -1
  31. package/src/__tests__/public-api.test.ts +153 -0
  32. package/src/__tests__/roundtrip.test.ts +701 -0
  33. package/src/encoder/__tests__/cbor-collection-encoder.test.ts +129 -5
  34. package/src/encoder/__tests__/cbor-encoder-errors.test.ts +847 -0
  35. package/src/encoder/__tests__/cbor-simple-encoder.test.ts +126 -0
  36. package/src/encoder/__tests__/cbor-string-encoder.test.ts +14 -0
  37. package/src/encoder/composables/useCborCollectionEncoder.ts +56 -23
  38. package/src/encoder/composables/useCborEncoder.ts +27 -1
  39. package/src/encoder/composables/useCborSimpleEncoder.ts +40 -8
  40. package/src/encoder/composables/useCborStringEncoder.ts +23 -10
  41. package/src/encoder/types.ts +0 -2
  42. package/src/index.ts +29 -20
  43. package/src/parser/__tests__/buffer-native-parsing.test.ts +338 -0
  44. package/src/parser/__tests__/cbor-float-errors.test.ts +41 -0
  45. package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +97 -7
  46. package/src/parser/__tests__/cbor-security-dos-protection.test.ts +166 -33
  47. package/src/parser/__tests__/cbor-standard-tags.test.ts +104 -7
  48. package/src/parser/__tests__/cbor-string-errors.test.ts +4 -4
  49. package/src/parser/__tests__/cbor-tag-errors.test.ts +1 -1
  50. package/src/parser/__tests__/cbor-tag-reparse-fix.test.ts +268 -0
  51. package/src/parser/composables/useCborCollection.ts +45 -42
  52. package/src/parser/composables/useCborFloat.ts +95 -9
  53. package/src/parser/composables/useCborInteger.ts +24 -10
  54. package/src/parser/composables/useCborParser.ts +387 -216
  55. package/src/parser/composables/useCborString.ts +22 -4
  56. package/src/parser/composables/useCborTag.ts +149 -53
  57. package/src/parser/utils.ts +11 -0
  58. package/dist/chunk-2FUTHZQQ.cjs.map +0 -1
  59. package/dist/chunk-2HBCILJS.cjs.map +0 -1
  60. package/dist/chunk-7CFYWHS6.js.map +0 -1
  61. package/dist/chunk-ZRPJUEIZ.js.map +0 -1
  62. package/src/encoder/composables/#useCborTagEncoder.ts# +0 -158
@@ -158,6 +158,9 @@ function useCborStringEncoder(globalOptions) {
158
158
  const encodeByteString = (data, encodeOptions) => {
159
159
  const isIndefinite = isCborByteString(data) && data[INDEFINITE_SYMBOL] === true;
160
160
  if (encodeOptions?.indefinite || Array.isArray(data) || isIndefinite) {
161
+ if (options.allowIndefinite === false) {
162
+ throw new Error("Indefinite-length encoding is not allowed");
163
+ }
161
164
  if (options.canonical) {
162
165
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
163
166
  }
@@ -168,17 +171,20 @@ function useCborStringEncoder(globalOptions) {
168
171
  return encodeByteStringIndefinite(Array.isArray(bytes2) ? bytes2 : [bytes2]);
169
172
  }
170
173
  const bytes = isCborByteString(data) ? data.bytes : data;
174
+ if (bytes.length + 9 > options.maxOutputSize) {
175
+ throw new Error(`Encoded output exceeds maximum size`);
176
+ }
171
177
  const header = encodeLengthHeader(2, bytes.length);
172
178
  const result = concatenateUint8Arrays([header, bytes]);
173
- if (result.length > options.maxOutputSize) {
174
- throw new Error("Encoded output exceeds maximum size");
175
- }
176
179
  return {
177
180
  bytes: result,
178
181
  hex: bytesToHex(result)
179
182
  };
180
183
  };
181
184
  const encodeByteStringIndefinite = (chunks) => {
185
+ if (options.allowIndefinite === false) {
186
+ throw new Error("Indefinite-length encoding is not allowed");
187
+ }
182
188
  if (options.canonical) {
183
189
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
184
190
  }
@@ -198,6 +204,9 @@ function useCborStringEncoder(globalOptions) {
198
204
  const encodeTextString = (text, encodeOptions) => {
199
205
  const isIndefinite = isCborTextString(text) && text[INDEFINITE_SYMBOL] === true;
200
206
  if (encodeOptions?.indefinite || isIndefinite) {
207
+ if (options.allowIndefinite === false) {
208
+ throw new Error("Indefinite-length encoding is not allowed");
209
+ }
201
210
  if (options.canonical) {
202
211
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
203
212
  }
@@ -210,17 +219,20 @@ function useCborStringEncoder(globalOptions) {
210
219
  const textStr = isCborTextString(text) ? text.text : text;
211
220
  const encoder = new TextEncoder();
212
221
  const utf8Bytes = encoder.encode(textStr);
222
+ if (utf8Bytes.length + 9 > options.maxOutputSize) {
223
+ throw new Error(`Encoded output exceeds maximum size`);
224
+ }
213
225
  const header = encodeLengthHeader(3, utf8Bytes.length);
214
226
  const result = concatenateUint8Arrays([header, utf8Bytes]);
215
- if (result.length > options.maxOutputSize) {
216
- throw new Error("Encoded output exceeds maximum size");
217
- }
218
227
  return {
219
228
  bytes: result,
220
229
  hex: bytesToHex(result)
221
230
  };
222
231
  };
223
232
  const encodeTextStringIndefinite = (chunks) => {
233
+ if (options.allowIndefinite === false) {
234
+ throw new Error("Indefinite-length encoding is not allowed");
235
+ }
224
236
  if (options.canonical) {
225
237
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
226
238
  }
@@ -247,11 +259,172 @@ function useCborStringEncoder(globalOptions) {
247
259
  };
248
260
  }
249
261
 
262
+ // src/encoder/composables/useCborSimpleEncoder.ts
263
+ function useCborSimpleEncoder(_globalOptions) {
264
+ const { encodeInteger } = useCborIntegerEncoder();
265
+ const encodeSimple = (value) => {
266
+ let byte;
267
+ if (value === false) {
268
+ byte = 244;
269
+ } else if (value === true) {
270
+ byte = 245;
271
+ } else if (value === null) {
272
+ byte = 246;
273
+ } else if (value === void 0) {
274
+ byte = 247;
275
+ } else {
276
+ throw new Error(`Unsupported simple value: ${value}`);
277
+ }
278
+ return {
279
+ bytes: new Uint8Array([byte]),
280
+ hex: bytesToHex(new Uint8Array([byte]))
281
+ };
282
+ };
283
+ const encodeFloat16Bytes = (value) => {
284
+ if (Object.is(value, -0)) return new Uint8Array([128, 0]);
285
+ if (value === 0) return new Uint8Array([0, 0]);
286
+ if (Number.isNaN(value)) return new Uint8Array([126, 0]);
287
+ if (value === Infinity) return new Uint8Array([124, 0]);
288
+ if (value === -Infinity) return new Uint8Array([252, 0]);
289
+ const sign = value < 0 ? 1 : 0;
290
+ const absValue = Math.abs(value);
291
+ const buffer = new ArrayBuffer(8);
292
+ const view = new DataView(buffer);
293
+ view.setFloat64(0, absValue, false);
294
+ const bits = view.getBigUint64(0, false);
295
+ const exp64 = Number(bits >> 52n & 0x7ffn) - 1023;
296
+ const mant64 = Number(bits & 0xfffffffffffffn);
297
+ const mant64n = BigInt(mant64);
298
+ let exp16;
299
+ let mant16;
300
+ if (exp64 < -24) {
301
+ exp16 = 0;
302
+ mant16 = 0;
303
+ } else if (exp64 < -14) {
304
+ exp16 = 0;
305
+ const shift = -14 - exp64;
306
+ const fullMant = 1n << 10n | mant64n >> 42n;
307
+ const lostFromExtract = mant64n & (1n << 42n) - 1n;
308
+ const shiftN = BigInt(shift);
309
+ const guardBit = Number(fullMant >> shiftN - 1n & 1n);
310
+ const stickyBitsBelow = shiftN > 1n ? fullMant & (1n << shiftN - 1n) - 1n : 0n;
311
+ const sticky = stickyBitsBelow !== 0n || lostFromExtract !== 0n ? 1 : 0;
312
+ const truncated = Number(fullMant >> shiftN);
313
+ const lsb = truncated & 1;
314
+ mant16 = truncated + (guardBit & (sticky | lsb));
315
+ } else if (exp64 > 15) {
316
+ exp16 = 31;
317
+ mant16 = 0;
318
+ } else {
319
+ exp16 = exp64 + 15;
320
+ const truncated = Number(mant64n >> 42n);
321
+ const guardBit = Number(mant64n >> 41n & 1n);
322
+ const stickyBits = (mant64n & (1n << 41n) - 1n) !== 0n ? 1 : 0;
323
+ const lsb = truncated & 1;
324
+ mant16 = truncated + (guardBit & (stickyBits | lsb));
325
+ if (mant16 > 1023) {
326
+ mant16 = 0;
327
+ exp16 += 1;
328
+ }
329
+ }
330
+ const float16 = sign << 15 | exp16 << 10 | mant16;
331
+ return new Uint8Array([
332
+ float16 >> 8 & 255,
333
+ float16 & 255
334
+ ]);
335
+ };
336
+ const encodeFloat32Bytes = (value) => {
337
+ const buffer = new ArrayBuffer(4);
338
+ const view = new DataView(buffer);
339
+ view.setFloat32(0, value, false);
340
+ return new Uint8Array(buffer);
341
+ };
342
+ const encodeFloat64Bytes = (value) => {
343
+ const buffer = new ArrayBuffer(8);
344
+ const view = new DataView(buffer);
345
+ view.setFloat64(0, value, false);
346
+ return new Uint8Array(buffer);
347
+ };
348
+ const canBeFloat16 = (value) => {
349
+ if (!Number.isFinite(value) || Object.is(value, 0) || Object.is(value, -0)) {
350
+ return true;
351
+ }
352
+ const absValue = Math.abs(value);
353
+ if (absValue < 6103515625e-14 || absValue > 65504) {
354
+ return false;
355
+ }
356
+ const bytes = encodeFloat16Bytes(value);
357
+ const view = new DataView(bytes.buffer);
358
+ const bits = view.getUint16(0, false);
359
+ const sign = bits >> 15 & 1;
360
+ const exp = bits >> 10 & 31;
361
+ const mant = bits & 1023;
362
+ let decoded;
363
+ if (exp === 0) {
364
+ decoded = (sign ? -1 : 1) * Math.pow(2, -14) * (mant / 1024);
365
+ } else if (exp === 31) {
366
+ decoded = mant === 0 ? sign ? -Infinity : Infinity : NaN;
367
+ } else {
368
+ decoded = (sign ? -1 : 1) * Math.pow(2, exp - 15) * (1 + mant / 1024);
369
+ }
370
+ return decoded === value;
371
+ };
372
+ const canBeFloat32 = (value) => {
373
+ if (!Number.isFinite(value) || Object.is(value, 0) || Object.is(value, -0)) {
374
+ return true;
375
+ }
376
+ const buffer = new ArrayBuffer(4);
377
+ const view = new DataView(buffer);
378
+ view.setFloat32(0, value, false);
379
+ const decoded = view.getFloat32(0, false);
380
+ return decoded === value;
381
+ };
382
+ const isInteger = (value) => {
383
+ return Number.isInteger(value) && Number.isSafeInteger(value);
384
+ };
385
+ const encodeFloat = (value, precision) => {
386
+ let bytes;
387
+ if (isInteger(value) && !precision) {
388
+ return encodeInteger(value);
389
+ }
390
+ if (precision === 16) {
391
+ const floatBytes = encodeFloat16Bytes(value);
392
+ bytes = new Uint8Array([249, ...floatBytes]);
393
+ } else if (precision === 32) {
394
+ const floatBytes = encodeFloat32Bytes(value);
395
+ bytes = new Uint8Array([250, ...floatBytes]);
396
+ } else if (precision === 64) {
397
+ const floatBytes = encodeFloat64Bytes(value);
398
+ bytes = new Uint8Array([251, ...floatBytes]);
399
+ } else {
400
+ if (canBeFloat16(value)) {
401
+ const floatBytes = encodeFloat16Bytes(value);
402
+ bytes = new Uint8Array([249, ...floatBytes]);
403
+ } else if (canBeFloat32(value)) {
404
+ const floatBytes = encodeFloat32Bytes(value);
405
+ bytes = new Uint8Array([250, ...floatBytes]);
406
+ } else {
407
+ const floatBytes = encodeFloat64Bytes(value);
408
+ bytes = new Uint8Array([251, ...floatBytes]);
409
+ }
410
+ }
411
+ return {
412
+ bytes,
413
+ hex: bytesToHex(bytes)
414
+ };
415
+ };
416
+ return {
417
+ encodeSimple,
418
+ encodeFloat
419
+ };
420
+ }
421
+
250
422
  // src/encoder/composables/useCborCollectionEncoder.ts
251
423
  function useCborCollectionEncoder(globalOptions) {
252
424
  const options = { ...DEFAULT_ENCODE_OPTIONS, ...globalOptions };
253
425
  const { encodeInteger } = useCborIntegerEncoder();
254
426
  const { encodeTextString, encodeByteString } = useCborStringEncoder(globalOptions);
427
+ const { encodeFloat } = useCborSimpleEncoder();
255
428
  const { isCborByteString } = useCborByteString();
256
429
  const { isCborTextString } = useCborTextString();
257
430
  let mainEncode = null;
@@ -266,7 +439,15 @@ function useCborCollectionEncoder(globalOptions) {
266
439
  return new Uint8Array([246]);
267
440
  } else if (typeof value === "boolean") {
268
441
  return new Uint8Array([value ? 245 : 244]);
269
- } else if (typeof value === "number" || typeof value === "bigint") {
442
+ } else if (typeof value === "number") {
443
+ if (Object.is(value, -0)) {
444
+ return encodeFloat(value, 16).bytes;
445
+ }
446
+ if (Number.isInteger(value) && Number.isSafeInteger(value)) {
447
+ return encodeInteger(value).bytes;
448
+ }
449
+ return encodeFloat(value).bytes;
450
+ } else if (typeof value === "bigint") {
270
451
  return encodeInteger(value).bytes;
271
452
  } else if (typeof value === "string" || isCborTextString(value)) {
272
453
  return encodeTextString(value).bytes;
@@ -276,6 +457,9 @@ function useCborCollectionEncoder(globalOptions) {
276
457
  const isIndefinite = value[INDEFINITE_SYMBOL] === true;
277
458
  const newCtx = { ...ctx, depth: ctx.depth + 1 };
278
459
  if (isIndefinite) {
460
+ if (ctx.options.allowIndefinite === false) {
461
+ throw new Error("Indefinite-length encoding is not allowed");
462
+ }
279
463
  const parts = [new Uint8Array([159])];
280
464
  for (const item of value) {
281
465
  const encoded = encodeValue(item, newCtx);
@@ -295,6 +479,9 @@ function useCborCollectionEncoder(globalOptions) {
295
479
  const isIndefinite = value[INDEFINITE_SYMBOL] === true;
296
480
  const newCtx = { ...ctx, depth: ctx.depth + 1 };
297
481
  if (isIndefinite) {
482
+ if (ctx.options.allowIndefinite === false) {
483
+ throw new Error("Indefinite-length encoding is not allowed");
484
+ }
298
485
  const entries = value instanceof Map ? Array.from(value.entries()) : Object.entries(value);
299
486
  const parts = [new Uint8Array([191])];
300
487
  for (const [key, val] of entries) {
@@ -340,10 +527,6 @@ function useCborCollectionEncoder(globalOptions) {
340
527
  parts.push(encoded);
341
528
  }
342
529
  const result = concatenateUint8Arrays(parts);
343
- ctx.bytesWritten += result.length;
344
- if (ctx.bytesWritten > ctx.options.maxOutputSize) {
345
- throw new Error("Encoded output exceeds maximum size");
346
- }
347
530
  return {
348
531
  bytes: result,
349
532
  hex: bytesToHex(result)
@@ -352,6 +535,9 @@ function useCborCollectionEncoder(globalOptions) {
352
535
  const encodeArray = (array, encodeOptions) => {
353
536
  const isIndefinite = array[INDEFINITE_SYMBOL] === true;
354
537
  if (encodeOptions?.indefinite || isIndefinite) {
538
+ if (options.allowIndefinite === false) {
539
+ throw new Error("Indefinite-length encoding is not allowed");
540
+ }
355
541
  if (options.canonical) {
356
542
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
357
543
  }
@@ -359,19 +545,20 @@ function useCborCollectionEncoder(globalOptions) {
359
545
  }
360
546
  const ctx = {
361
547
  depth: 0,
362
- bytesWritten: 0,
363
548
  options
364
549
  };
365
550
  return encodeArrayInternal(array, ctx);
366
551
  };
367
552
  const encodeArrayIndefinite = (array) => {
553
+ if (options.allowIndefinite === false) {
554
+ throw new Error("Indefinite-length encoding is not allowed");
555
+ }
368
556
  if (options.canonical) {
369
557
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
370
558
  }
371
559
  const parts = [new Uint8Array([159])];
372
560
  const ctx = {
373
561
  depth: 0,
374
- bytesWritten: 0,
375
562
  options
376
563
  };
377
564
  for (const item of array) {
@@ -392,12 +579,27 @@ function useCborCollectionEncoder(globalOptions) {
392
579
  } else {
393
580
  entries = map instanceof Map ? Array.from(map.entries()) : Object.entries(map);
394
581
  }
582
+ let preEncodedKeys = null;
395
583
  if (ctx.options.canonical && !map[ALL_ENTRIES_SYMBOL]) {
396
- entries.sort((a, b) => {
397
- const keyA = encodeValue(a[0], { ...ctx, depth: ctx.depth + 1 });
398
- const keyB = encodeValue(b[0], { ...ctx, depth: ctx.depth + 1 });
399
- return compareBytes(keyA, keyB);
400
- });
584
+ const childCtx = { ...ctx, depth: ctx.depth + 1 };
585
+ const withEncodedKeys = entries.map((entry) => ({
586
+ encodedKey: encodeValue(entry[0], childCtx),
587
+ entry
588
+ }));
589
+ withEncodedKeys.sort((a, b) => compareBytes(a.encodedKey, b.encodedKey));
590
+ entries = withEncodedKeys.map((t) => t.entry);
591
+ preEncodedKeys = withEncodedKeys.map((t) => t.encodedKey);
592
+ }
593
+ if (ctx.options.rejectDuplicateKeys) {
594
+ const seen = /* @__PURE__ */ new Set();
595
+ const keysForDupCheck = preEncodedKeys ?? entries.map((e) => encodeValue(e[0], { ...ctx, depth: ctx.depth + 1 }));
596
+ for (const keyBytes of keysForDupCheck) {
597
+ const keyHex = bytesToHex(keyBytes);
598
+ if (seen.has(keyHex)) {
599
+ throw new Error("Duplicate map key detected");
600
+ }
601
+ seen.add(keyHex);
602
+ }
401
603
  }
402
604
  const header = encodeLengthHeader(5, entries.length);
403
605
  const parts = [header];
@@ -408,10 +610,6 @@ function useCborCollectionEncoder(globalOptions) {
408
610
  parts.push(encodedValue);
409
611
  }
410
612
  const result = concatenateUint8Arrays(parts);
411
- ctx.bytesWritten += result.length;
412
- if (ctx.bytesWritten > ctx.options.maxOutputSize) {
413
- throw new Error("Encoded output exceeds maximum size");
414
- }
415
613
  return {
416
614
  bytes: result,
417
615
  hex: bytesToHex(result)
@@ -420,6 +618,9 @@ function useCborCollectionEncoder(globalOptions) {
420
618
  const encodeMap = (map, encodeOptions) => {
421
619
  const isIndefinite = map[INDEFINITE_SYMBOL] === true;
422
620
  if (encodeOptions?.indefinite || isIndefinite) {
621
+ if (options.allowIndefinite === false) {
622
+ throw new Error("Indefinite-length encoding is not allowed");
623
+ }
423
624
  if (options.canonical) {
424
625
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
425
626
  }
@@ -427,12 +628,14 @@ function useCborCollectionEncoder(globalOptions) {
427
628
  }
428
629
  const ctx = {
429
630
  depth: 0,
430
- bytesWritten: 0,
431
631
  options
432
632
  };
433
633
  return encodeMapInternal(map, ctx);
434
634
  };
435
635
  const encodeMapIndefinite = (map) => {
636
+ if (options.allowIndefinite === false) {
637
+ throw new Error("Indefinite-length encoding is not allowed");
638
+ }
436
639
  if (options.canonical) {
437
640
  throw new Error("Indefinite-length encoding not allowed in canonical mode");
438
641
  }
@@ -440,7 +643,6 @@ function useCborCollectionEncoder(globalOptions) {
440
643
  const parts = [new Uint8Array([191])];
441
644
  const ctx = {
442
645
  depth: 0,
443
- bytesWritten: 0,
444
646
  options
445
647
  };
446
648
  for (const [key, value] of entries) {
@@ -465,145 +667,6 @@ function useCborCollectionEncoder(globalOptions) {
465
667
  };
466
668
  }
467
669
 
468
- // src/encoder/composables/useCborSimpleEncoder.ts
469
- function useCborSimpleEncoder(_globalOptions) {
470
- const { encodeInteger } = useCborIntegerEncoder();
471
- const encodeSimple = (value) => {
472
- let byte;
473
- if (value === false) {
474
- byte = 244;
475
- } else if (value === true) {
476
- byte = 245;
477
- } else if (value === null) {
478
- byte = 246;
479
- } else if (value === void 0) {
480
- byte = 247;
481
- } else {
482
- throw new Error(`Unsupported simple value: ${value}`);
483
- }
484
- return {
485
- bytes: new Uint8Array([byte]),
486
- hex: bytesToHex(new Uint8Array([byte]))
487
- };
488
- };
489
- const encodeFloat16Bytes = (value) => {
490
- if (value === 0) return new Uint8Array([0, 0]);
491
- if (value === -0) return new Uint8Array([128, 0]);
492
- if (Number.isNaN(value)) return new Uint8Array([126, 0]);
493
- if (value === Infinity) return new Uint8Array([124, 0]);
494
- if (value === -Infinity) return new Uint8Array([252, 0]);
495
- const sign = value < 0 ? 1 : 0;
496
- const absValue = Math.abs(value);
497
- const buffer = new ArrayBuffer(8);
498
- const view = new DataView(buffer);
499
- view.setFloat64(0, absValue, false);
500
- const bits = view.getBigUint64(0, false);
501
- const exp64 = Number(bits >> 52n & 0x7ffn) - 1023;
502
- const mant64 = Number(bits & 0xfffffffffffffn);
503
- let exp16;
504
- let mant16;
505
- if (exp64 < -14) {
506
- exp16 = 0;
507
- mant16 = 0;
508
- } else if (exp64 > 15) {
509
- exp16 = 31;
510
- mant16 = 0;
511
- } else {
512
- exp16 = exp64 + 15;
513
- mant16 = mant64 >> 42;
514
- }
515
- const float16 = sign << 15 | exp16 << 10 | mant16;
516
- return new Uint8Array([
517
- float16 >> 8 & 255,
518
- float16 & 255
519
- ]);
520
- };
521
- const encodeFloat32Bytes = (value) => {
522
- const buffer = new ArrayBuffer(4);
523
- const view = new DataView(buffer);
524
- view.setFloat32(0, value, false);
525
- return new Uint8Array(buffer);
526
- };
527
- const encodeFloat64Bytes = (value) => {
528
- const buffer = new ArrayBuffer(8);
529
- const view = new DataView(buffer);
530
- view.setFloat64(0, value, false);
531
- return new Uint8Array(buffer);
532
- };
533
- const canBeFloat16 = (value) => {
534
- if (!Number.isFinite(value) || value === 0 || value === -0) {
535
- return true;
536
- }
537
- const absValue = Math.abs(value);
538
- if (absValue < 6103515625e-14 || absValue > 65504) {
539
- return false;
540
- }
541
- const bytes = encodeFloat16Bytes(value);
542
- const view = new DataView(bytes.buffer);
543
- const bits = view.getUint16(0, false);
544
- const sign = bits >> 15 & 1;
545
- const exp = bits >> 10 & 31;
546
- const mant = bits & 1023;
547
- let decoded;
548
- if (exp === 0) {
549
- decoded = (sign ? -1 : 1) * Math.pow(2, -14) * (mant / 1024);
550
- } else if (exp === 31) {
551
- decoded = mant === 0 ? sign ? -Infinity : Infinity : NaN;
552
- } else {
553
- decoded = (sign ? -1 : 1) * Math.pow(2, exp - 15) * (1 + mant / 1024);
554
- }
555
- return decoded === value;
556
- };
557
- const canBeFloat32 = (value) => {
558
- if (!Number.isFinite(value) || value === 0 || value === -0) {
559
- return true;
560
- }
561
- const buffer = new ArrayBuffer(4);
562
- const view = new DataView(buffer);
563
- view.setFloat32(0, value, false);
564
- const decoded = view.getFloat32(0, false);
565
- return decoded === value;
566
- };
567
- const isInteger = (value) => {
568
- return Number.isInteger(value) && Number.isSafeInteger(value);
569
- };
570
- const encodeFloat = (value, precision) => {
571
- let bytes;
572
- if (isInteger(value) && !precision) {
573
- return encodeInteger(value);
574
- }
575
- if (precision === 16) {
576
- const floatBytes = encodeFloat16Bytes(value);
577
- bytes = new Uint8Array([249, ...floatBytes]);
578
- } else if (precision === 32) {
579
- const floatBytes = encodeFloat32Bytes(value);
580
- bytes = new Uint8Array([250, ...floatBytes]);
581
- } else if (precision === 64) {
582
- const floatBytes = encodeFloat64Bytes(value);
583
- bytes = new Uint8Array([251, ...floatBytes]);
584
- } else {
585
- if (canBeFloat16(value)) {
586
- const floatBytes = encodeFloat16Bytes(value);
587
- bytes = new Uint8Array([249, ...floatBytes]);
588
- } else if (canBeFloat32(value)) {
589
- const floatBytes = encodeFloat32Bytes(value);
590
- bytes = new Uint8Array([250, ...floatBytes]);
591
- } else {
592
- const floatBytes = encodeFloat64Bytes(value);
593
- bytes = new Uint8Array([251, ...floatBytes]);
594
- }
595
- }
596
- return {
597
- bytes,
598
- hex: bytesToHex(bytes)
599
- };
600
- };
601
- return {
602
- encodeSimple,
603
- encodeFloat
604
- };
605
- }
606
-
607
670
  // src/encoder/composables/useCborTagEncoder.ts
608
671
  function useCborTagEncoder() {
609
672
  const encodeTagNumber = (tagNumber) => {
@@ -657,6 +720,9 @@ function useCborTagEncoder() {
657
720
  // src/encoder/composables/useCborEncoder.ts
658
721
  function useCborEncoder(globalOptions) {
659
722
  const options = { ...DEFAULT_ENCODE_OPTIONS, ...globalOptions };
723
+ if (options.canonical && options.allowIndefinite) {
724
+ options.allowIndefinite = false;
725
+ }
660
726
  const { encodeInteger } = useCborIntegerEncoder();
661
727
  const { encodeTextString, encodeByteString } = useCborStringEncoder(options);
662
728
  const { encodeArray, encodeMap, setMainEncode } = useCborCollectionEncoder(options);
@@ -665,11 +731,23 @@ function useCborEncoder(globalOptions) {
665
731
  const { isCborByteString } = useCborByteString();
666
732
  const { isCborTextString } = useCborTextString();
667
733
  const encode = (value) => {
734
+ const result = encodeValue(value);
735
+ if (options.maxOutputSize && result.bytes.length > options.maxOutputSize) {
736
+ throw new Error(
737
+ `Encoded output size ${result.bytes.length} bytes exceeds limit of ${options.maxOutputSize} bytes`
738
+ );
739
+ }
740
+ return result;
741
+ };
742
+ const encodeValue = (value) => {
668
743
  if (value === null || value === void 0 || typeof value === "boolean") {
669
744
  return encodeSimple(value);
670
745
  }
671
746
  if (typeof value === "number") {
672
- if (Number.isInteger(value) && Number.isSafeInteger(value)) {
747
+ if (Object.is(value, -0)) {
748
+ return encodeFloat(value, 16);
749
+ }
750
+ if (Number.isSafeInteger(value)) {
673
751
  return encodeInteger(value);
674
752
  }
675
753
  return encodeFloat(value);
@@ -738,5 +816,5 @@ function useCborEncoder(globalOptions) {
738
816
  }
739
817
 
740
818
  export { DEFAULT_ENCODE_OPTIONS, bytesToHex, compareBytes, concatenateUint8Arrays, useCborCollectionEncoder, useCborEncoder, useCborIntegerEncoder, useCborSimpleEncoder, useCborStringEncoder, useCborTagEncoder, writeBigUint, writeUint };
741
- //# sourceMappingURL=chunk-7CFYWHS6.js.map
742
- //# sourceMappingURL=chunk-7CFYWHS6.js.map
819
+ //# sourceMappingURL=chunk-UMAX5MX5.js.map
820
+ //# sourceMappingURL=chunk-UMAX5MX5.js.map