cborg 4.5.2 → 4.5.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.
- package/CHANGELOG.md +4 -0
- package/lib/7float.js +4 -4
- package/lib/byte-utils.js +6 -2
- package/lib/encode.js +152 -3
- package/package.json +1 -1
- package/types/lib/7float.d.ts +9 -0
- package/types/lib/7float.d.ts.map +1 -1
- package/types/lib/byte-utils.d.ts.map +1 -1
- package/types/lib/encode.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
## [4.5.4](https://github.com/rvagg/cborg/compare/v4.5.3...v4.5.4) (2026-01-20)
|
|
2
|
+
|
|
3
|
+
## [4.5.3](https://github.com/rvagg/cborg/compare/v4.5.2...v4.5.3) (2026-01-20)
|
|
4
|
+
|
|
1
5
|
## [4.5.2](https://github.com/rvagg/cborg/compare/v4.5.1...v4.5.2) (2026-01-20)
|
|
2
6
|
|
|
3
7
|
## [4.5.1](https://github.com/rvagg/cborg/compare/v4.5.0...v4.5.1) (2026-01-20)
|
package/lib/7float.js
CHANGED
|
@@ -11,10 +11,10 @@ import { encodeUint } from './0uint.js'
|
|
|
11
11
|
* @typedef {import('../interface').EncodeOptions} EncodeOptions
|
|
12
12
|
*/
|
|
13
13
|
|
|
14
|
-
const MINOR_FALSE = 20
|
|
15
|
-
const MINOR_TRUE = 21
|
|
16
|
-
const MINOR_NULL = 22
|
|
17
|
-
const MINOR_UNDEFINED = 23
|
|
14
|
+
export const MINOR_FALSE = 20
|
|
15
|
+
export const MINOR_TRUE = 21
|
|
16
|
+
export const MINOR_NULL = 22
|
|
17
|
+
export const MINOR_UNDEFINED = 23
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* @param {Uint8Array} _data
|
package/lib/byte-utils.js
CHANGED
|
@@ -34,6 +34,10 @@ export function asU8A (buf) {
|
|
|
34
34
|
return isBuffer(buf) ? new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength) : buf
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// Threshold for switching between manual utf8Slice and native TextDecoder/Buffer
|
|
38
|
+
// Manual decoding has overhead from array building; native is fast for strings > 32 bytes
|
|
39
|
+
const UTF8_THRESHOLD = 32
|
|
40
|
+
|
|
37
41
|
export const toString = useBuffer
|
|
38
42
|
? // eslint-disable-line operator-linebreak
|
|
39
43
|
/**
|
|
@@ -42,7 +46,7 @@ export const toString = useBuffer
|
|
|
42
46
|
* @param {number} end
|
|
43
47
|
*/
|
|
44
48
|
(bytes, start, end) => {
|
|
45
|
-
return end - start >
|
|
49
|
+
return end - start > UTF8_THRESHOLD
|
|
46
50
|
? // eslint-disable-line operator-linebreak
|
|
47
51
|
// @ts-ignore
|
|
48
52
|
globalThis.Buffer.from(bytes.subarray(start, end)).toString('utf8')
|
|
@@ -56,7 +60,7 @@ export const toString = useBuffer
|
|
|
56
60
|
* @param {number} end
|
|
57
61
|
*/
|
|
58
62
|
(bytes, start, end) => {
|
|
59
|
-
return end - start >
|
|
63
|
+
return end - start > UTF8_THRESHOLD
|
|
60
64
|
? textDecoder.decode(bytes.subarray(start, end))
|
|
61
65
|
: utf8Slice(bytes, start, end)
|
|
62
66
|
}
|
package/lib/encode.js
CHANGED
|
@@ -3,16 +3,16 @@ import { Token, Type } from './token.js'
|
|
|
3
3
|
import { Bl, U8Bl } from './bl.js'
|
|
4
4
|
import { encodeErrPrefix } from './common.js'
|
|
5
5
|
import { quickEncodeToken } from './jump.js'
|
|
6
|
-
import { asU8A, compare } from './byte-utils.js'
|
|
6
|
+
import { asU8A, compare, fromString } from './byte-utils.js'
|
|
7
7
|
|
|
8
|
-
import { encodeUint } from './0uint.js'
|
|
8
|
+
import { encodeUint, encodeUintValue } from './0uint.js'
|
|
9
9
|
import { encodeNegint } from './1negint.js'
|
|
10
10
|
import { encodeBytes } from './2bytes.js'
|
|
11
11
|
import { encodeString } from './3string.js'
|
|
12
12
|
import { encodeArray } from './4array.js'
|
|
13
13
|
import { encodeMap } from './5map.js'
|
|
14
14
|
import { encodeTag } from './6tag.js'
|
|
15
|
-
import { encodeFloat } from './7float.js'
|
|
15
|
+
import { encodeFloat, MINOR_FALSE, MINOR_TRUE, MINOR_NULL, MINOR_UNDEFINED } from './7float.js'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* @typedef {import('../interface').EncodeOptions} EncodeOptions
|
|
@@ -468,6 +468,139 @@ function tokensToEncoded (writer, tokens, encoders, options) {
|
|
|
468
468
|
}
|
|
469
469
|
}
|
|
470
470
|
|
|
471
|
+
// CBOR major type prefixes, cached from Type for hot path performance
|
|
472
|
+
const MAJOR_UINT = Type.uint.majorEncoded
|
|
473
|
+
const MAJOR_NEGINT = Type.negint.majorEncoded
|
|
474
|
+
const MAJOR_BYTES = Type.bytes.majorEncoded
|
|
475
|
+
const MAJOR_STRING = Type.string.majorEncoded
|
|
476
|
+
const MAJOR_ARRAY = Type.array.majorEncoded
|
|
477
|
+
|
|
478
|
+
// Simple value bytes (CBOR major type 7 + minor value)
|
|
479
|
+
const SIMPLE_FALSE = Type.float.majorEncoded | MINOR_FALSE
|
|
480
|
+
const SIMPLE_TRUE = Type.float.majorEncoded | MINOR_TRUE
|
|
481
|
+
const SIMPLE_NULL = Type.float.majorEncoded | MINOR_NULL
|
|
482
|
+
const SIMPLE_UNDEFINED = Type.float.majorEncoded | MINOR_UNDEFINED
|
|
483
|
+
|
|
484
|
+
const neg1b = BigInt(-1)
|
|
485
|
+
const pos1b = BigInt(1)
|
|
486
|
+
|
|
487
|
+
/**
|
|
488
|
+
* Check if direct encoding can be used for the given options.
|
|
489
|
+
* Direct encoding bypasses token creation for most values.
|
|
490
|
+
* @param {EncodeOptions} options
|
|
491
|
+
* @returns {boolean}
|
|
492
|
+
*/
|
|
493
|
+
function canDirectEncode (options) {
|
|
494
|
+
// Cannot use direct encode with addBreakTokens (needs special break token handling).
|
|
495
|
+
// Direct encode checks typeEncoders per-value, falling back to tokens as needed.
|
|
496
|
+
// Maps fall back to token-based encoding for efficient key sorting.
|
|
497
|
+
return options.addBreakTokens !== true
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/**
|
|
501
|
+
* Direct encode a value to the writer, bypassing token creation for most types.
|
|
502
|
+
* Falls back to token-based encoding for custom type encoders.
|
|
503
|
+
* @param {ByteWriter} writer
|
|
504
|
+
* @param {any} data
|
|
505
|
+
* @param {EncodeOptions} options
|
|
506
|
+
* @param {Reference|undefined} refStack
|
|
507
|
+
*/
|
|
508
|
+
function directEncode (writer, data, options, refStack) {
|
|
509
|
+
const typ = is(data)
|
|
510
|
+
|
|
511
|
+
// Check for custom encoder for THIS specific type
|
|
512
|
+
const customEncoder = options.typeEncoders && options.typeEncoders[typ]
|
|
513
|
+
if (customEncoder) {
|
|
514
|
+
const tokens = customEncoder(data, typ, options, refStack)
|
|
515
|
+
if (tokens != null) {
|
|
516
|
+
// Custom encoder returned tokens, serialize immediately
|
|
517
|
+
tokensToEncoded(writer, tokens, cborEncoders, options)
|
|
518
|
+
return
|
|
519
|
+
}
|
|
520
|
+
// Custom encoder returned null, fall through to default handling
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
// Direct encode based on type
|
|
524
|
+
switch (typ) {
|
|
525
|
+
case 'null':
|
|
526
|
+
writer.push([SIMPLE_NULL])
|
|
527
|
+
return
|
|
528
|
+
|
|
529
|
+
case 'undefined':
|
|
530
|
+
writer.push([SIMPLE_UNDEFINED])
|
|
531
|
+
return
|
|
532
|
+
|
|
533
|
+
case 'boolean':
|
|
534
|
+
writer.push([data ? SIMPLE_TRUE : SIMPLE_FALSE])
|
|
535
|
+
return
|
|
536
|
+
|
|
537
|
+
case 'number':
|
|
538
|
+
if (!Number.isInteger(data) || !Number.isSafeInteger(data)) {
|
|
539
|
+
// Float, use token encoder for complex float encoding
|
|
540
|
+
encodeFloat(writer, new Token(Type.float, data), options)
|
|
541
|
+
} else if (data >= 0) {
|
|
542
|
+
encodeUintValue(writer, MAJOR_UINT, data)
|
|
543
|
+
} else {
|
|
544
|
+
// Negative integer
|
|
545
|
+
encodeUintValue(writer, MAJOR_NEGINT, data * -1 - 1)
|
|
546
|
+
}
|
|
547
|
+
return
|
|
548
|
+
|
|
549
|
+
case 'bigint':
|
|
550
|
+
if (data >= BigInt(0)) {
|
|
551
|
+
encodeUintValue(writer, MAJOR_UINT, data)
|
|
552
|
+
} else {
|
|
553
|
+
encodeUintValue(writer, MAJOR_NEGINT, data * neg1b - pos1b)
|
|
554
|
+
}
|
|
555
|
+
return
|
|
556
|
+
|
|
557
|
+
case 'string': {
|
|
558
|
+
const bytes = fromString(data)
|
|
559
|
+
encodeUintValue(writer, MAJOR_STRING, bytes.length)
|
|
560
|
+
writer.push(bytes)
|
|
561
|
+
return
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
case 'Uint8Array':
|
|
565
|
+
encodeUintValue(writer, MAJOR_BYTES, data.length)
|
|
566
|
+
writer.push(data)
|
|
567
|
+
return
|
|
568
|
+
|
|
569
|
+
case 'Array':
|
|
570
|
+
if (!data.length) {
|
|
571
|
+
writer.push([MAJOR_ARRAY]) // Empty array: 0x80
|
|
572
|
+
return
|
|
573
|
+
}
|
|
574
|
+
refStack = Ref.createCheck(refStack, data)
|
|
575
|
+
encodeUintValue(writer, MAJOR_ARRAY, data.length)
|
|
576
|
+
for (const elem of data) {
|
|
577
|
+
directEncode(writer, elem, options, refStack)
|
|
578
|
+
}
|
|
579
|
+
return
|
|
580
|
+
|
|
581
|
+
case 'Object':
|
|
582
|
+
case 'Map':
|
|
583
|
+
// Maps require key sorting, use token-based encoding for efficiency
|
|
584
|
+
// (pre-encoding all keys for sorting is expensive)
|
|
585
|
+
{
|
|
586
|
+
const tokens = typeEncoders.Object(data, typ, options, refStack)
|
|
587
|
+
tokensToEncoded(writer, tokens, cborEncoders, options)
|
|
588
|
+
}
|
|
589
|
+
return
|
|
590
|
+
|
|
591
|
+
default:
|
|
592
|
+
// Fall back to token-based encoding for other types (DataView, TypedArrays, etc.)
|
|
593
|
+
{
|
|
594
|
+
const typeEncoder = typeEncoders[typ]
|
|
595
|
+
if (!typeEncoder) {
|
|
596
|
+
throw new Error(`${encodeErrPrefix} unsupported type: ${typ}`)
|
|
597
|
+
}
|
|
598
|
+
const tokens = typeEncoder(data, typ, options, refStack)
|
|
599
|
+
tokensToEncoded(writer, tokens, cborEncoders, options)
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
471
604
|
/**
|
|
472
605
|
* @param {any} data
|
|
473
606
|
* @param {TokenTypeEncoder[]} encoders
|
|
@@ -518,6 +651,14 @@ function encodeCustom (data, encoders, options, destination) {
|
|
|
518
651
|
*/
|
|
519
652
|
function encode (data, options) {
|
|
520
653
|
options = Object.assign({}, defaultEncodeOptions, options)
|
|
654
|
+
|
|
655
|
+
// Use direct encode path when possible
|
|
656
|
+
if (canDirectEncode(options)) {
|
|
657
|
+
defaultWriter.reset()
|
|
658
|
+
directEncode(defaultWriter, data, options, undefined)
|
|
659
|
+
return defaultWriter.toBytes(true)
|
|
660
|
+
}
|
|
661
|
+
|
|
521
662
|
return encodeCustom(data, cborEncoders, options)
|
|
522
663
|
}
|
|
523
664
|
|
|
@@ -529,6 +670,14 @@ function encode (data, options) {
|
|
|
529
670
|
*/
|
|
530
671
|
function encodeInto (data, destination, options) {
|
|
531
672
|
options = Object.assign({}, defaultEncodeOptions, options)
|
|
673
|
+
|
|
674
|
+
// Use direct encode path when possible
|
|
675
|
+
if (canDirectEncode(options)) {
|
|
676
|
+
const writer = new U8Bl(destination)
|
|
677
|
+
directEncode(writer, data, options, undefined)
|
|
678
|
+
return { written: writer.toBytes().length }
|
|
679
|
+
}
|
|
680
|
+
|
|
532
681
|
const result = encodeCustom(data, cborEncoders, options, destination)
|
|
533
682
|
return { written: result.length }
|
|
534
683
|
}
|
package/package.json
CHANGED
package/types/lib/7float.d.ts
CHANGED
|
@@ -53,6 +53,15 @@ export namespace encodeFloat {
|
|
|
53
53
|
function encodedSize(token: Token, options: EncodeOptions): number;
|
|
54
54
|
let compareTokens: (tok1: Token, tok2: Token) => number;
|
|
55
55
|
}
|
|
56
|
+
/**
|
|
57
|
+
* @typedef {import('../interface').ByteWriter} ByteWriter
|
|
58
|
+
* @typedef {import('../interface').DecodeOptions} DecodeOptions
|
|
59
|
+
* @typedef {import('../interface').EncodeOptions} EncodeOptions
|
|
60
|
+
*/
|
|
61
|
+
export const MINOR_FALSE: 20;
|
|
62
|
+
export const MINOR_TRUE: 21;
|
|
63
|
+
export const MINOR_NULL: 22;
|
|
64
|
+
export const MINOR_UNDEFINED: 23;
|
|
56
65
|
export type ByteWriter = import("../interface").ByteWriter;
|
|
57
66
|
export type DecodeOptions = import("../interface").DecodeOptions;
|
|
58
67
|
export type EncodeOptions = import("../interface").EncodeOptions;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"7float.d.ts","sourceRoot":"","sources":["../../lib/7float.js"],"names":[],"mappings":"AAkBA;;;;;;GAMG;AACH,uCANW,UAAU,QACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CASjB;AAED;;;;;;GAMG;AACH,mCANW,UAAU,QACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAOjB;AAoBD;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;GAIG;AACH,oCAJW,UAAU,SACV,KAAK,WACL,aAAa,QAwCvB;;IAED;;;;OAIG;IACH,4BAJW,KAAK,WACL,aAAa,GACX,MAAM,CAsBlB;;;
|
|
1
|
+
{"version":3,"file":"7float.d.ts","sourceRoot":"","sources":["../../lib/7float.js"],"names":[],"mappings":"AAkBA;;;;;;GAMG;AACH,uCANW,UAAU,QACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CASjB;AAED;;;;;;GAMG;AACH,mCANW,UAAU,QACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAOjB;AAoBD;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;;;GAMG;AACH,oCANW,UAAU,OACV,MAAM,UACN,MAAM,WACN,aAAa,GACX,KAAK,CAIjB;AAED;;;;GAIG;AACH,oCAJW,UAAU,SACV,KAAK,WACL,aAAa,QAwCvB;;IAED;;;;OAIG;IACH,4BAJW,KAAK,WACL,aAAa,GACX,MAAM,CAsBlB;;;AAlKD;;;;GAIG;AAEH,0BAA2B,EAAE,CAAA;AAC7B,yBAA0B,EAAE,CAAA;AAC5B,yBAA0B,EAAE,CAAA;AAC5B,8BAA+B,EAAE,CAAA;yBARpB,OAAO,cAAc,EAAE,UAAU;4BACjC,OAAO,cAAc,EAAE,aAAa;4BACpC,OAAO,cAAc,EAAE,aAAa;sBAPrB,YAAY"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"byte-utils.d.ts","sourceRoot":"","sources":["../../lib/byte-utils.js"],"names":[],"mappings":"AAwBA;;;GAGG;AACH,2BAHW,UAAU,GAAC,MAAM,EAAE,GACjB,UAAU,CAQtB;
|
|
1
|
+
{"version":3,"file":"byte-utils.d.ts","sourceRoot":"","sources":["../../lib/byte-utils.js"],"names":[],"mappings":"AAwBA;;;GAGG;AACH,2BAHW,UAAU,GAAC,MAAM,EAAE,GACjB,UAAU,CAQtB;AAkOD;;;;GAIG;AACH,4BAJW,UAAU,MACV,UAAU,GACR,MAAM,CAgBlB;AA4HD;;;GAGG;AACH,kDAHW,MAAM,EAAE,GACN,MAAM,CAkBlB;AAnaD,gCAMkD;AAgC9C;;;;GAIG;AACH,gCAJW,UAAU,SACV,MAAM,OACN,MAAM,UAQhB;AAcL,mCAGe,MAAM,iDAYN,MAAM,yCAIhB;AAOE,+BAHI,MAAM,EAAE,GACN,UAAU,CAItB;AAIG;;;;GAIG;AACH,6BAJW,UAAU,SACV,MAAM,OACN,MAAM,2BAOhB;AAcD;;;;GAIG;AACH,+BAJW,UAAU,EAAE,UACZ,MAAM,GACJ,UAAU,CActB;AAwBD;;;GAGG;AACH,4BAHW,MAAM,GACJ,UAAU,CAMtB;AAaD;;;GAGG;AACH,yBAHW,UAAU,GACR,MAAM,CAQlB;AAiBH;;;GAGG;AACD,6BAHS,MAAM,GAAC,UAAU,GACf,UAAU,CAQpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../lib/encode.js"],"names":[],"mappings":"AAwCA,oCAAoC;AACpC,oCADc,gBAAgB,EAAE,CAY/B;AAnBD,4BAA4B;AAC5B,mCADW,aAAa,CAKtB;sBA+XW,KAAK,GAAG;IAAE,SAAS,CAAC,EAAE,UAAU,CAAA;CAAE;4BApZlC,OAAO,cAAc,EAAE,aAAa;kCACpC,OAAO,cAAc,EAAE,mBAAmB;wBAC1C,OAAO,cAAc,EAAE,SAAS;gCAChC,OAAO,cAAc,EAAE,iBAAiB;+BACxC,OAAO,cAAc,EAAE,gBAAgB;kCACvC,OAAO,cAAc,EAAE,mBAAmB;yBAC1C,OAAO,cAAc,EAAE,UAAU;AA0R9C;;;;;GAKG;AACH,oCALW,GAAG,YACH,aAAa,aACb,SAAS,GACP,mBAAmB,CAgB/B;
|
|
1
|
+
{"version":3,"file":"encode.d.ts","sourceRoot":"","sources":["../../lib/encode.js"],"names":[],"mappings":"AAwCA,oCAAoC;AACpC,oCADc,gBAAgB,EAAE,CAY/B;AAnBD,4BAA4B;AAC5B,mCADW,aAAa,CAKtB;sBA+XW,KAAK,GAAG;IAAE,SAAS,CAAC,EAAE,UAAU,CAAA;CAAE;4BApZlC,OAAO,cAAc,EAAE,aAAa;kCACpC,OAAO,cAAc,EAAE,mBAAmB;wBAC1C,OAAO,cAAc,EAAE,SAAS;gCAChC,OAAO,cAAc,EAAE,iBAAiB;+BACxC,OAAO,cAAc,EAAE,gBAAgB;kCACvC,OAAO,cAAc,EAAE,mBAAmB;yBAC1C,OAAO,cAAc,EAAE,UAAU;AA0R9C;;;;;GAKG;AACH,oCALW,GAAG,YACH,aAAa,aACb,SAAS,GACP,mBAAmB,CAgB/B;AAiUD;;;;GAIG;AACH,6BAJW,GAAG,YACH,aAAa,GACX,UAAU,CAatB;AA3DD;;;;;;GAMG;AACH,mCANW,GAAG,YACH,gBAAgB,EAAE,WAClB,aAAa,gBACb,UAAU,GACR,UAAU,CAoCtB;AAoBD;;;;;GAKG;AACH,iCALW,GAAG,eACH,UAAU,YACV,aAAa,GACX;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAc/B;AAhnBD,8BAA8B;AAC9B,4BADiB,SAAS;IA0BxB;;;;OAIG;IACH,0BAJW,SAAS,GAAC,SAAS,OACnB,MAAM,GAAC,GAAG,EAAE,GACV,SAAS,CAOrB;IAlCD;;;OAGG;IACH,iBAHW,MAAM,GAAC,GAAG,EAAE,UACZ,SAAS,GAAC,SAAS,EAK7B;IAFC,oBAAc;IACd,qDAAoB;IAGtB;;;OAGG;IACH,cAHW,MAAM,GAAC,GAAG,EAAE,GACV,OAAO,CAWnB;CAaF;sBA9F2B,YAAY"}
|