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