cbor-x 0.8.3 → 0.9.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/.vscode/launch.json +22 -0
- package/README.md +34 -5
- package/SECURITY.md +11 -0
- package/{unpack.d.ts → decode.d.ts} +11 -11
- package/decode.js +8 -1
- package/dist/index.js +30 -16
- package/dist/index.min.js +24 -24
- package/dist/node.cjs +37 -25
- package/dist/test.js +7 -0
- package/encode.d.ts +6 -0
- package/encode.js +19 -13
- package/index.d.ts +6 -5
- package/index.js +1 -1
- package/node-index.js +2 -2
- package/package.json +11 -11
- package/stream.js +5 -9
- package/tests/benchmark.cjs +13 -7
- package/tests/test-compatibility.cjs +1 -0
- package/tests/test-node-stream.js +10 -0
- package/tests/test.js +7 -0
- package/pack.d.ts +0 -9
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "pwa-node",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Run cbor-x tests",
|
|
11
|
+
"runtimeArgs": [
|
|
12
|
+
"test"
|
|
13
|
+
],
|
|
14
|
+
"runtimeExecutable": "npm",
|
|
15
|
+
"skipFiles": [
|
|
16
|
+
"<node_internals>/**"
|
|
17
|
+
],
|
|
18
|
+
"console": "internalConsole",
|
|
19
|
+
"outputCapture": "std"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
package/README.md
CHANGED
|
@@ -96,6 +96,8 @@ Another way to further leverage the benefits of the cbor-x record structures is
|
|
|
96
96
|
|
|
97
97
|
When creating a new `Encoder`, `EncoderStream`, or `DecoderStream` instance, we can enable or disable the record structure extension with the `objectsAsMaps` property. When this is `true`, the record structure extension will be disabled, and all objects will revert to being serialized using MessageMap `map`s, and all `map`s will be deserialized to JS `Object`s as properties (like the standalone `encode` and `decode` functions).
|
|
98
98
|
|
|
99
|
+
Streaming with record structures works by encoding a structure the first time it is seen in a stream and referencing the structure in later messages that are sent across that stream. When an encoder can expect a decoder to understand previous structure references, this can be configured using the `sequential: true` flag, which is auto-enabled by streams, but can also be used with Packr instances.
|
|
100
|
+
|
|
99
101
|
### Shared Record Structures
|
|
100
102
|
Another useful way of using cbor-x, and the record extension, is for storing data in a databases, files, or other storage systems. If a number of objects with common data structures are being stored, a shared structure can be used to greatly improve data storage and deserialization efficiency. In the simplest form, provide a `structures` array, which is updated if any new object structure is encountered:
|
|
101
103
|
|
|
@@ -119,7 +121,7 @@ let encoder = new Encoder({
|
|
|
119
121
|
structures: []
|
|
120
122
|
});
|
|
121
123
|
```
|
|
122
|
-
Cbor-x will automatically add and saves structures as it encounters any new object structures (up to a limit of
|
|
124
|
+
Cbor-x will automatically add and saves structures as it encounters any new object structures (up to a limit of 64). It will always add structures in incremental/compatible way: Any object encoded with an earlier structure can be decoded with a later version (as long as it is persisted).
|
|
123
125
|
|
|
124
126
|
### Reading Multiple Values
|
|
125
127
|
If you have a buffer with multiple values sequentially encoded, you can choose to parse and read multiple values. This can be done using the `unpackMultiple` function/method, which can return an array of all the values it can sequentially parse within the provided buffer. For example:
|
|
@@ -147,6 +149,7 @@ The following options properties can be provided to the Encoder or Decoder const
|
|
|
147
149
|
* `variableMapSize` - This will use varying map size definition (from single-byte to full 32-bit representation) based on the number of keys when encoding objects, which yields slightly more compact encodings (for small objects), but is typically 5-10% slower during encoding. This is only relevant when record extension is disabled.
|
|
148
150
|
* `copyBuffers` - When decoding a CBOR message with binary data (Buffers are encoded as binary data), copy the buffer rather than providing a slice/view of the buffer. If you want your input data to be collected or modified while the decoded embedded buffer continues to live on, you can use this option (there is extra overhead to copying).
|
|
149
151
|
* `useTimestamp32` - Encode JS `Date`s in 32-bit format when possible by dropping the milliseconds. This is a more efficient encoding of dates. You can also cause dates to use 32-bit format by manually setting the milliseconds to zero (`date.setMilliseconds(0)`).
|
|
152
|
+
* `sequential` - Encode structures in serialized data, and reference previously encoded structures with expectation that decoder will read the encoded structures in the same order as encoded, with `unpackMultiple`.
|
|
150
153
|
* `largeBigIntToFloat` - If a bigint needs to be encoded that is larger than will fit in 64-bit integers, it will be encoded as a float-64 (otherwise will throw a RangeError).
|
|
151
154
|
* `useTag259ForMaps` - This flag indicates if [tag 259 (explicit maps)](https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md) should be used to encode JS `Map`s. When using records is enabled, this is disabled by default, since plain objects are encoded with record structures and unambigiously differentiated from `Map`s, which are encoded as CBOR maps. Without using records, this enabled by default and is necessary to distinguish plain objects from `Map`s (but can be disabled by setting this to `false`).
|
|
152
155
|
|
|
@@ -158,10 +161,12 @@ import { ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from 'cbor-x'
|
|
|
158
161
|
|
|
159
162
|
* `ALWAYS` (1) - Always will encode non-integers (absolute less than 2147483648) as 32-bit float.
|
|
160
163
|
* `DECIMAL_ROUND` (3) - Always will encode non-integers as 32-bit float, and when decoding 32-bit float, round to the significant decimal digits (usually 7, but 6 or 8 digits for some ranges).
|
|
161
|
-
* `DECIMAL_FIT` (4) - Only encode non-integers as 32-bit float if all significant digits (usually up to 7) can be unamiguously encoded as a 32-bit float, and decode with decimal rounding (same as above). This will ensure round-trip encoding/decoding without loss in precision and
|
|
164
|
+
* `DECIMAL_FIT` (4) - Only encode non-integers as 32-bit float if all significant digits (usually up to 7) can be unamiguously encoded as a 32-bit float, and decode with decimal rounding (same as above). This will ensure round-trip encoding/decoding without loss in precision and uses 32-bit when possible.
|
|
162
165
|
|
|
163
166
|
Note, that the performance is decreased with decimal rounding by about 20-25%, although if only 5% of your values are floating point, that will only have about a 1% impact overall.
|
|
164
167
|
|
|
168
|
+
In addition, msgpackr exports a `roundFloat32(number)` function that can be used to round floating point numbers to the maximum significant decimal digits that can be stored in 32-bit float, just as DECIMAL_ROUND does when decoding. This can be useful for determining how a number will be decoded prior to encoding it.
|
|
169
|
+
|
|
165
170
|
## Performance
|
|
166
171
|
Cbor-x is fast. Really fast. Here is comparison with the next fastest JS projects using the benchmark tool from `msgpack-lite` (and the sample data is from some clinical research data we use that has a good mix of different value types and structures). It also includes comparison to V8 native JSON functionality, and JavaScript Avro (`avsc`, a very optimized Avro implementation):
|
|
167
172
|
|
|
@@ -244,14 +249,38 @@ During the serialization process, data is written to buffers. Again, allocating
|
|
|
244
249
|
Cbor-x currently uses tag id 105 and 26880-27135 for its [proposed extension for records](https://github.com/kriszyp/cbor-records).
|
|
245
250
|
|
|
246
251
|
### Dates
|
|
247
|
-
|
|
252
|
+
Cbor-x saves all JavaScript `Date`s using the standard CBOR date extension (tag 1).
|
|
248
253
|
|
|
249
254
|
### Structured Cloning
|
|
250
255
|
With structured cloning enabled, cbor-x will also use tags/extensions to store Set, Map, Error, RegExp, ArrayBufferView objects and preserve their types.
|
|
251
256
|
|
|
257
|
+
### List of supported tags for decoding
|
|
258
|
+
Here is a list of CBOR tags that are supported for decoding:
|
|
259
|
+
|
|
260
|
+
* 0 - String date
|
|
261
|
+
* 1 - Numeric Date
|
|
262
|
+
* 2 - BigInt
|
|
263
|
+
* 3 - Negative BigInt
|
|
264
|
+
* 27 - Generic named objects (used for Error, RegExp)
|
|
265
|
+
* 64 - Uint8Array
|
|
266
|
+
* 68 - Uint8ClampedArray
|
|
267
|
+
* 69 - Uint16Array
|
|
268
|
+
* 70 - Uint32Array
|
|
269
|
+
* 71 - BigUint64Array
|
|
270
|
+
* 72 - Int8Array
|
|
271
|
+
* 77 - Int16Array
|
|
272
|
+
* 78 - Int32Array
|
|
273
|
+
* 79 - BigInt64Array
|
|
274
|
+
* 81 - Float32Array
|
|
275
|
+
* 82 - Float64Array
|
|
276
|
+
* 105 - Records
|
|
277
|
+
* 258 - Set
|
|
278
|
+
* 259 - Map
|
|
279
|
+
* 40009, 40010 - Pointers for cycles
|
|
280
|
+
|
|
252
281
|
## Alternate Encoding/Package
|
|
253
282
|
The high-performance serialization and deserialization algorithms in this package are also available in the [msgpackr](https://github.com/kriszyp/msgpackr) for the MessagePack format, with the same API and design. A quick summary of the pros and cons of using MessagePack vs CBOR are:
|
|
254
|
-
* MessagePack has wider adoption, and, at least with this implementation is slightly more efficient (by roughly
|
|
283
|
+
* MessagePack has wider adoption, and, at least with this implementation is slightly more efficient (by roughly 1%, but YMMV).
|
|
255
284
|
* CBOR has an [official IETF standardization track](https://www.rfc-editor.org/rfc/rfc8949.html), and the record extensions is conceptually/philosophically a better fit for CBOR tags.
|
|
256
285
|
|
|
257
286
|
## License
|
|
@@ -259,7 +288,7 @@ The high-performance serialization and deserialization algorithms in this packag
|
|
|
259
288
|
MIT
|
|
260
289
|
|
|
261
290
|
### Browser Consideration
|
|
262
|
-
CBOR can be a great choice for high-performance data delivery to browsers, as reasonable data size is possible without compression. And CBOR
|
|
291
|
+
CBOR can be a great choice for high-performance data delivery to browsers, as reasonable data size is possible without compression. And CBOR works very well in modern browsers. However, it is worth noting that if you want highly compact data, brotli or gzip are most effective in compressing, and CBOR's character frequency tends to defeat Huffman encoding used by these standard compression algorithms, often resulting in less compact data than compressed JSON.
|
|
263
292
|
|
|
264
293
|
### Credits
|
|
265
294
|
|
package/SECURITY.md
ADDED
|
@@ -5,7 +5,7 @@ export enum FLOAT32_OPTIONS {
|
|
|
5
5
|
DECIMAL_FIT = 4
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
interface Options {
|
|
8
|
+
export interface Options {
|
|
9
9
|
useFloat32?: FLOAT32_OPTIONS
|
|
10
10
|
useRecords?: boolean
|
|
11
11
|
structures?: {}[]
|
|
@@ -16,24 +16,24 @@ interface Options {
|
|
|
16
16
|
useTimestamp32?: boolean
|
|
17
17
|
largeBigIntToFloat?: boolean
|
|
18
18
|
encodeUndefinedAsNil?: boolean
|
|
19
|
+
maxSharedStructures?: number
|
|
20
|
+
maxOwnStructures?: number
|
|
21
|
+
shouldShareStructure?: (keys: string[]) => boolean
|
|
19
22
|
getStructures?(): {}[]
|
|
20
23
|
saveStructures?(structures: {}[]): boolean | void
|
|
21
24
|
}
|
|
22
25
|
interface Extension {
|
|
23
26
|
Class: Function
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
tag: number
|
|
28
|
+
encode(value: any): Buffer | Uint8Array
|
|
29
|
+
decode(messagePack: Buffer | Uint8Array): any
|
|
27
30
|
}
|
|
28
|
-
export class
|
|
31
|
+
export class Decoder {
|
|
29
32
|
constructor(options?: Options)
|
|
30
|
-
unpack(messagePack: Buffer | Uint8Array): any
|
|
31
33
|
decode(messagePack: Buffer | Uint8Array): any
|
|
32
|
-
|
|
34
|
+
decodeMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
|
|
33
35
|
}
|
|
34
|
-
export class Decoder extends Unpackr {}
|
|
35
|
-
export function unpack(messagePack: Buffer | Uint8Array): any
|
|
36
|
-
export function unpackMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
|
|
37
36
|
export function decode(messagePack: Buffer | Uint8Array): any
|
|
37
|
+
export function decodeMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
|
|
38
38
|
export function addExtension(extension: Extension): void
|
|
39
|
-
export
|
|
39
|
+
export function roundFloat32(float32Number: number): number
|
package/decode.js
CHANGED
|
@@ -835,7 +835,7 @@ export function addExtension(extension) {
|
|
|
835
835
|
currentExtensions[extension.tag] = extension.decode
|
|
836
836
|
}
|
|
837
837
|
|
|
838
|
-
export
|
|
838
|
+
export const mult10 = new Array(147) // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
839
839
|
for (let i = 0; i < 256; i++) {
|
|
840
840
|
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103))
|
|
841
841
|
}
|
|
@@ -850,3 +850,10 @@ export const FLOAT32_OPTIONS = {
|
|
|
850
850
|
DECIMAL_ROUND: 3,
|
|
851
851
|
DECIMAL_FIT: 4
|
|
852
852
|
}
|
|
853
|
+
let f32Array = new Float32Array(1)
|
|
854
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4)
|
|
855
|
+
export function roundFloat32(float32Number) {
|
|
856
|
+
f32Array[0] = float32Number
|
|
857
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)]
|
|
858
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
859
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -780,7 +780,7 @@
|
|
|
780
780
|
currentExtensions[extension.tag] = extension.decode;
|
|
781
781
|
}
|
|
782
782
|
|
|
783
|
-
|
|
783
|
+
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
784
784
|
for (let i = 0; i < 256; i++) {
|
|
785
785
|
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
|
786
786
|
}
|
|
@@ -792,7 +792,14 @@
|
|
|
792
792
|
ALWAYS: 1,
|
|
793
793
|
DECIMAL_ROUND: 3,
|
|
794
794
|
DECIMAL_FIT: 4
|
|
795
|
-
};
|
|
795
|
+
};
|
|
796
|
+
let f32Array = new Float32Array(1);
|
|
797
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
798
|
+
function roundFloat32(float32Number) {
|
|
799
|
+
f32Array[0] = float32Number;
|
|
800
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
801
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
802
|
+
}
|
|
796
803
|
|
|
797
804
|
let textEncoder;
|
|
798
805
|
try {
|
|
@@ -837,11 +844,8 @@
|
|
|
837
844
|
let recordIdsToRemove = [];
|
|
838
845
|
let transitionsCount = 0;
|
|
839
846
|
let serializationsSinceTransitionRebuild = 0;
|
|
840
|
-
if (this.structures && this.structures.length > maxSharedStructures) {
|
|
841
|
-
throw new Error('Too many shared structures')
|
|
842
|
-
}
|
|
843
847
|
|
|
844
|
-
this.encode = function(value) {
|
|
848
|
+
this.encode = function(value, encodeOptions) {
|
|
845
849
|
if (!target) {
|
|
846
850
|
target = new ByteArrayAllocate(8192);
|
|
847
851
|
targetView = new DataView(target.buffer, 0, 8192);
|
|
@@ -854,7 +858,8 @@
|
|
|
854
858
|
targetView = new DataView(target.buffer, 0, target.length);
|
|
855
859
|
safeEnd = target.length - 10;
|
|
856
860
|
position$1 = 0;
|
|
857
|
-
}
|
|
861
|
+
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
862
|
+
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
858
863
|
start = position$1;
|
|
859
864
|
referenceMap = encoder.structuredClone ? new Map() : null;
|
|
860
865
|
sharedStructures = encoder.structures;
|
|
@@ -862,7 +867,7 @@
|
|
|
862
867
|
if (sharedStructures.uninitialized)
|
|
863
868
|
encoder.structures = sharedStructures = encoder.getStructures();
|
|
864
869
|
let sharedStructuresLength = sharedStructures.length;
|
|
865
|
-
if (sharedStructuresLength >
|
|
870
|
+
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
866
871
|
sharedStructuresLength = maxSharedStructures;
|
|
867
872
|
if (!sharedStructures.transitions) {
|
|
868
873
|
// rebuild our structure transitions
|
|
@@ -872,8 +877,8 @@
|
|
|
872
877
|
if (!keys)
|
|
873
878
|
continue
|
|
874
879
|
let nextTransition, transition = sharedStructures.transitions;
|
|
875
|
-
for (let
|
|
876
|
-
let key = keys[
|
|
880
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
881
|
+
let key = keys[j];
|
|
877
882
|
nextTransition = transition[key];
|
|
878
883
|
if (!nextTransition) {
|
|
879
884
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -902,7 +907,12 @@
|
|
|
902
907
|
referenceMap = null;
|
|
903
908
|
return serialized
|
|
904
909
|
}
|
|
905
|
-
|
|
910
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
911
|
+
target.start = start;
|
|
912
|
+
target.end = position$1;
|
|
913
|
+
return target
|
|
914
|
+
}
|
|
915
|
+
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
906
916
|
} finally {
|
|
907
917
|
if (sharedStructures) {
|
|
908
918
|
if (serializationsSinceTransitionRebuild < 10)
|
|
@@ -924,13 +934,15 @@
|
|
|
924
934
|
if (encoder.structures.length > maxSharedStructures) {
|
|
925
935
|
encoder.structures = encoder.structures.slice(0, maxSharedStructures);
|
|
926
936
|
}
|
|
927
|
-
|
|
937
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
938
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
928
939
|
if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
|
|
929
940
|
// get updated structures and try again if the update failed
|
|
930
941
|
encoder.structures = encoder.getStructures() || [];
|
|
931
942
|
return encoder.encode(value)
|
|
932
943
|
}
|
|
933
944
|
lastSharedStructuresLength = encoder.structures.length;
|
|
945
|
+
return returnBuffer
|
|
934
946
|
}
|
|
935
947
|
}
|
|
936
948
|
}
|
|
@@ -1051,7 +1063,7 @@
|
|
|
1051
1063
|
targetView.setFloat32(position$1, value);
|
|
1052
1064
|
let xShifted;
|
|
1053
1065
|
if (useFloat32 < 4 ||
|
|
1054
|
-
|
|
1066
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1055
1067
|
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1056
1068
|
position$1 += 4;
|
|
1057
1069
|
return
|
|
@@ -1182,7 +1194,7 @@
|
|
|
1182
1194
|
} else if (type === 'undefined') {
|
|
1183
1195
|
target[position$1++] = 0xf7;
|
|
1184
1196
|
} else {
|
|
1185
|
-
throw new Error('Unknown type ' + type)
|
|
1197
|
+
throw new Error('Unknown type: ' + type)
|
|
1186
1198
|
}
|
|
1187
1199
|
};
|
|
1188
1200
|
|
|
@@ -1271,7 +1283,7 @@
|
|
|
1271
1283
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1272
1284
|
let newTransitions = 0;
|
|
1273
1285
|
let length = keys.length;
|
|
1274
|
-
for (let i =0; i < length; i++) {
|
|
1286
|
+
for (let i = 0; i < length; i++) {
|
|
1275
1287
|
let key = keys[i];
|
|
1276
1288
|
nextTransition = transition[key];
|
|
1277
1289
|
if (!nextTransition) {
|
|
@@ -1505,7 +1517,8 @@
|
|
|
1505
1517
|
}
|
|
1506
1518
|
let defaultEncoder = new Encoder({ useRecords: false });
|
|
1507
1519
|
const encode = defaultEncoder.encode;
|
|
1508
|
-
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1520
|
+
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1521
|
+
const REUSE_BUFFER_MODE = 1000;
|
|
1509
1522
|
|
|
1510
1523
|
/**
|
|
1511
1524
|
* Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
|
|
@@ -1609,6 +1622,7 @@
|
|
|
1609
1622
|
exports.encode = encode;
|
|
1610
1623
|
exports.encodeIter = encodeIter;
|
|
1611
1624
|
exports.mapsAsObjects = mapsAsObjects;
|
|
1625
|
+
exports.roundFloat32 = roundFloat32;
|
|
1612
1626
|
exports.useRecords = useRecords;
|
|
1613
1627
|
|
|
1614
1628
|
Object.defineProperty(exports, '__esModule', { value: true });
|
package/dist/index.min.js
CHANGED
|
@@ -29,9 +29,9 @@ const b=63&x[z++],c=63&x[z++],e=63&x[z++];let f=(7&a)<<18|b<<12|c<<6|e;65535<f&&
|
|
|
29
29
|
Uint8Array.prototype.slice.call(x,z,z+=a):x.subarray(z,z+=a)}function j(){var a=Math.exp;let b,c=x[z++],d=x[z++],e=(c<<8)+d,f=31&e>>10,g=1023&e;return b=0==f?a(g,-24):31==f?0==g?1/0:NaN:a(g+1024,f-25),32768&e?-b:b}function k(){let a=x[z++];if(96<=a&&120>a){if(a-=96,J>=z)// if it has been extracted, must use it (and faster anyway)
|
|
30
30
|
return D.slice(z-I,(z+=a)-I);if(!(0==J&&180>y))return P(a)}else return z--,c();let b,d=4095&(a<<5^(1<a?F.getUint16(z):0<a?x[z]:0)),e=R[d],f=z,j=z+a-3,k=0;if(e&&e.bytes==a){for(;f<j;){if(b=F.getUint32(f),b!=e[k++]){f=1879048192;break}f+=4}for(j+=3;f<j;)if(b=x[f++],b!=e[k++]){f=1879048192;break}if(f===j)return z=f,e.string;j-=3,f=z}for(e=[],R[d]=e,e.bytes=a;f<j;)b=F.getUint32(f),e.push(b),f+=4;for(j+=3;f<j;)b=x[f++],e.push(b);// for small blocks, avoiding the overhead of the extract call is helpful
|
|
31
31
|
let l=16>a?h(a):g(a);return null==l?e.string=P(a):e.string=l}function l(a,b){K[b]=b=>{if(!a)throw new Error("Could not find typed array for code "+typeCode);// we have to always slice/copy here to get a new ArrayBuffer that is word/byte aligned
|
|
32
|
-
return new T[a](Uint8Array.prototype.slice.call(b,0).buffer)}}function m(a){let b=y,c=z,d=I,e=J,f=D,g=E,h=new Uint8Array(x.slice(0,y)),i=C,j=H,k=M,l=a();return y=b,z=c,I=d,J=e,D=f,E=g,x=h,M=k,C=i,H=j,F=new DataView(x.buffer,x.byteOffset,x.byteLength),l}function n(){x=null,E=null,C=null}function o(a){K[a.tag]=a.decode}function p(a){256>a?(
|
|
32
|
+
return new T[a](Uint8Array.prototype.slice.call(b,0).buffer)}}function m(a){let b=y,c=z,d=I,e=J,f=D,g=E,h=new Uint8Array(x.slice(0,y)),i=C,j=H,k=M,l=a();return y=b,z=c,I=d,J=e,D=f,E=g,x=h,M=k,C=i,H=j,F=new DataView(x.buffer,x.byteOffset,x.byteLength),l}function n(){x=null,E=null,C=null}function o(a){K[a.tag]=a.decode}function p(a){256>a?(la[oa++]=152,la[oa++]=a):65536>a?(la[oa++]=153,la[oa++]=a>>8,la[oa++]=255&a):(la[oa++]=154,ma.setUint32(oa,a),oa+=4)}function q(a){return{tag:a,encode:function(a,b){let c=a.byteLength,d=a.byteOffset||0,e=a.buffer||a;b(fa?Buffer.from(e,d,c):new Uint8Array(e,d,c))}}}function r(a,b){let c=a.byteLength;24>c?la[oa++]=64+c:256>c?(la[oa++]=88,la[oa++]=c):65536>c?(la[oa++]=89,la[oa++]=c>>8,la[oa++]=255&c):(la[oa++]=90,ma.setUint32(oa,c),oa+=4),oa+c>=la.length&&b(oa+c),la.set(a,oa),oa+=c}function s(a,b){// insert the ids that need to be referenced for structured clones
|
|
33
33
|
let c,d=8*b.length,e=a.length-d;for(b.sort((c,a)=>c.offset>a.offset?1:-1);c=b.pop();){let b=c.offset,f=c.id;a.copyWithin(b+d,b,e),d-=8;let g=b+d;// uint32
|
|
34
|
-
a[g++]=217,a[g++]=156,a[g++]=73,a[g++]=26,a[g++]=f>>24,a[g++]=255&f>>16,a[g++]=255&f>>8,a[g++]=255&f,e=b}return a}function t(a){if(a.Class){if(!a.encode)throw new Error("Extension has no encode function");
|
|
34
|
+
a[g++]=217,a[g++]=156,a[g++]=73,a[g++]=26,a[g++]=f>>24,a[g++]=255&f>>16,a[g++]=255&f>>8,a[g++]=255&f,e=b}return a}function t(a){if(a.Class){if(!a.encode)throw new Error("Extension has no encode function");ea.unshift(a.Class),da.unshift(a)}o(a)}function*u(a,b){const c=new qa(b);for(const d of a)yield c.encode(d)}async function*v(a,b){const c=new qa(b);for await(const d of a)yield c.encode(d)}/**
|
|
35
35
|
* Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
|
|
36
36
|
* Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
|
|
37
37
|
* @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
|
|
@@ -43,18 +43,19 @@ const U=()=>{let a=c(),b=a[0],e=a[1];C[255&e]=b,b.read=d(b);let f={};for(let c,d
|
|
|
43
43
|
E.set(a,e);let f=c();// read the next value as the target object to id
|
|
44
44
|
return e.used?Object.assign(b,f):(e.target=f,f);// no cycle, can just use the returned read object
|
|
45
45
|
},K[40010]=a=>{// pointer extension (for structured clones)
|
|
46
|
-
let b=E.get(a);return b.used=!0,b.target},K[258]=a=>new Set(a),(K[259]=a=>(H.mapsAsObjects&&(H.mapsAsObjects=!1,G=!0),a())).handlesRead=!0;const V=["Uint8","Uint8Clamped","Uint16","Uint32","BigUint64","Int8","Int16","Int32","BigInt64","Float32","Float64"].map(a=>a+"Array"),W=[64,68,69,70,71,72,77,78,79,81,82];for(let b=0;b<V.length;b++)l(V[b],W[b]);
|
|
47
|
-
for(let b=0;256>b;b++)X[b]=+("1e"+Math.floor(45.15-.30103*b));let Y=new N({useRecords:!1});const Z=Y.decode,$=Y.decodeMultiple,_={NEVER:0,ALWAYS:1,DECIMAL_ROUND:3,DECIMAL_FIT:4};let aa;try{aa=new TextEncoder}catch(a){}let
|
|
48
|
-
if(q(a),i.offset=
|
|
49
|
-
}finally{if(c){if(10>o&&o++,1e4<n)c.transitions=null,o=0,n=0,0<m.length&&(m=[]);else if(0<m.length&&!k){for(let a=0,b=m.length;a<b;a++)m[a][
|
|
50
|
-
(c=a*
|
|
51
|
-
|
|
46
|
+
let b=E.get(a);return b.used=!0,b.target},K[258]=a=>new Set(a),(K[259]=a=>(H.mapsAsObjects&&(H.mapsAsObjects=!1,G=!0),a())).handlesRead=!0;const V=["Uint8","Uint8Clamped","Uint16","Uint32","BigUint64","Int8","Int16","Int32","BigInt64","Float32","Float64"].map(a=>a+"Array"),W=[64,68,69,70,71,72,77,78,79,81,82];for(let b=0;b<V.length;b++)l(V[b],W[b]);const X=Array(147);// this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
47
|
+
for(let b=0;256>b;b++)X[b]=+("1e"+Math.floor(45.15-.30103*b));let Y=new N({useRecords:!1});const Z=Y.decode,$=Y.decodeMultiple,_={NEVER:0,ALWAYS:1,DECIMAL_ROUND:3,DECIMAL_FIT:4};let aa,ba=new Float32Array(1),ca=new Uint8Array(ba.buffer,0,4);try{aa=new TextEncoder}catch(a){}let da,ea;const fa="undefined"!=typeof Buffer,ga=fa?Buffer.allocUnsafeSlow:Uint8Array,ha=fa?Buffer:Uint8Array,ia=105,ja=256,ka=fa?4294967296:2144337920;let la,ma,na,oa=0;const pa=Symbol("record-id");class qa extends N{constructor(a){super(a),this.offset=0;let b,c,d,e,f,g=0,h=ha.prototype.utf8Write?function(a,b,c){return la.utf8Write(a,b,c)}:!!(aa&&aa.encodeInto)&&function(a,b){return aa.encodeInto(a,la.subarray(b)).written},i=this,j=64,k=a&&a.sequential;k&&(j=0,this.structures=[]);let m=[],n=0,o=0;this.encode=function(a,h){if(la||(la=new ga(8192),ma=new DataView(la.buffer,0,8192),oa=0),na=la.length-10,2048>na-oa?(la=new ga(la.length),ma=new DataView(la.buffer,0,la.length),na=la.length-10,oa=0):h===xa&&(oa=2147483640&oa+7),b=oa,f=i.structuredClone?new Map:null,c=i.structures,c){c.uninitialized&&(i.structures=c=i.getStructures());let a=c.length;if(a>j&&!k&&(a=j),!c.transitions){c.transitions=Object.create(null);for(let b,d=0;d<a;d++){if(b=c[d],!b)continue;let a,e=c.transitions;for(let c,d=0,f=b.length;d<f;d++)c=b[d],a=e[c],a||(a=e[c]=Object.create(null)),e=a;e[pa]=d}g=c.length}k||(c.nextId=a)}d&&(d=!1),e=c||[];try{// update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
|
|
48
|
+
if(q(a),i.offset=oa,f&&f.idsToInsert){oa+=8*f.idsToInsert.length,oa>na&&t(oa),i.offset=oa;let a=s(la.subarray(b,oa),f.idsToInsert);return f=null,a}return h===xa?(la.start=b,la.end=oa,la):la.subarray(b,oa);// position can change if we call pack again in saveStructures, so we get the buffer now
|
|
49
|
+
}finally{if(c){if(10>o&&o++,1e4<n)c.transitions=null,o=0,n=0,0<m.length&&(m=[]);else if(0<m.length&&!k){for(let a=0,b=m.length;a<b;a++)m[a][pa]=void 0;m=[]}if(d&&i.saveStructures){i.structures.length>j&&(i.structures=i.structures.slice(0,j));// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
50
|
+
let c=la.subarray(b,oa);return!1===i.saveStructures(i.structures,g)?(i.structures=i.getStructures()||[],i.encode(a)):(g=i.structures.length,c)}}}};const q=a=>{oa>na&&(la=t(oa));var c,d=typeof a;if("string"==d){let b,d=a.length;b=32>d?1:256>d?2:65536>d?3:5;let e=3*d;if(oa+e>na&&(la=t(oa+e)),64>d||!h){let e,f,g,h=oa+b;for(e=0;e<d;e++)f=a.charCodeAt(e),128>f?la[h++]=f:2048>f?(la[h++]=192|f>>6,la[h++]=128|63&f):55296==(64512&f)&&56320==(64512&(g=a.charCodeAt(e+1)))?(f=65536+((1023&f)<<10)+(1023&g),e++,la[h++]=240|f>>18,la[h++]=128|63&f>>12,la[h++]=128|63&f>>6,la[h++]=128|63&f):(la[h++]=224|f>>12,la[h++]=128|63&f>>6,la[h++]=128|63&f);c=h-oa-b}else c=h(a,oa+b,e);24>c?la[oa++]=96|c:256>c?(2>b&&la.copyWithin(oa+2,oa+1,oa+1+c),la[oa++]=120,la[oa++]=c):65536>c?(3>b&&la.copyWithin(oa+3,oa+2,oa+2+c),la[oa++]=121,la[oa++]=c>>8,la[oa++]=255&c):(5>b&&la.copyWithin(oa+5,oa+3,oa+3+c),la[oa++]=122,ma.setUint32(oa,c),oa+=4),oa+=c}else if("number"===d){if(a>>>0===a)24>a?la[oa++]=a:256>a?(la[oa++]=24,la[oa++]=a):65536>a?(la[oa++]=25,la[oa++]=a>>8,la[oa++]=255&a):(la[oa++]=26,ma.setUint32(oa,a),oa+=4);else if(a>>0===a)-24<=a?la[oa++]=31-a:-256<=a?(la[oa++]=56,la[oa++]=~a):-65536<=a?(la[oa++]=57,ma.setUint16(oa,~a),oa+=2):(la[oa++]=58,ma.setUint32(oa,~a),oa+=4);else{let b;if(0<(b=this.useFloat32)&&4294967296>a&&-2147483648<=a){la[oa++]=250,ma.setFloat32(oa,a);let c;if(4>b||// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
51
|
+
(c=a*X[(127&la[oa])<<1|la[oa+1]>>7])>>0===c)return void(oa+=4);// move back into position for writing a double
|
|
52
|
+
oa--}la[oa++]=251,ma.setFloat64(oa,a),oa+=8}}else if("object"===d){if(!a)la[oa++]=246;else{if(f){let c=f.get(a);if(c){if(!c.id){let a=f.idsToInsert||(f.idsToInsert=[]);c.id=a.push(c)}return la[oa++]=217,la[oa++]=156,la[oa++]=74,la[oa++]=26,ma.setUint32(oa,c.id),void(oa+=4)}f.set(a,{offset:oa-b})}let d=a.constructor;if(d===Object)r(a,!0);else if(d===Array){c=a.length,24>c?la[oa++]=128|c:p(c);for(let b=0;b<c;b++)q(a[b])}else if(d===Map){(this.mapsAsObjects?!1!==this.useTag259ForMaps:this.useTag259ForMaps)&&(la[oa++]=217,la[oa++]=1,la[oa++]=3),c=a.size,24>c?la[oa++]=160|c:256>c?(la[oa++]=184,la[oa++]=c):65536>c?(la[oa++]=185,la[oa++]=c>>8,la[oa++]=255&c):(la[oa++]=186,ma.setUint32(oa,c),oa+=4);for(let[b,c]of a)q(b),q(c)}else{for(let b,c=0,d=da.length;c<d;c++)if(b=ea[c],a instanceof b){let b=da[c],d=b.tag;return 24>d?la[oa++]=192|d:256>d?(la[oa++]=216,la[oa++]=d):65536>d?(la[oa++]=217,la[oa++]=d>>8,la[oa++]=255&d):-1<d&&(la[oa++]=218,ma.setUint32(oa,d),oa+=4),void b.encode.call(this,a,q,t)}if(a[Symbol.iterator]){la[oa++]=159;// indefinite length array
|
|
52
53
|
for(let b of a)q(b);// stop-code
|
|
53
|
-
return void(
|
|
54
|
-
r(a,!a.hasOwnProperty)}}}else if("boolean"===d)
|
|
55
|
-
if(this.largeBigIntToFloat)
|
|
56
|
-
let b=Object.keys(a),c=b.length;24>c?
|
|
57
|
-
let d=
|
|
54
|
+
return void(la[oa++]=255)}// no extension found, write as object
|
|
55
|
+
r(a,!a.hasOwnProperty)}}}else if("boolean"===d)la[oa++]=a?245:244;else if("bigint"===d){if(a<BigInt(1)<<BigInt(64)&&0<=a)la[oa++]=27,ma.setBigUint64(oa,a);else if(a>-(BigInt(1)<<BigInt(64))&&0>a)la[oa++]=59,ma.setBigUint64(oa,-a-BigInt(1));else// overflow
|
|
56
|
+
if(this.largeBigIntToFloat)la[oa++]=251,ma.setFloat64(oa,+a);else throw new RangeError(a+" was too large to fit in CBOR 64-bit integer format, set largeBigIntToFloat to convert to float-64");oa+=8}else if("undefined"===d)la[oa++]=247;else throw new Error("Unknown type: "+d)},r=!1===this.useRecords?this.variableMapSize?a=>{// this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
|
|
57
|
+
let b=Object.keys(a),c=b.length;24>c?la[oa++]=160|c:256>c?(la[oa++]=184,la[oa++]=c):65536>c?(la[oa++]=185,la[oa++]=c>>8,la[oa++]=255&c):(la[oa++]=186,ma.setUint32(oa,c),oa+=4);let d;for(let e=0;e<c;e++)q(d=b[e]),q(a[d])}:(a,c)=>{la[oa++]=185;// always use map 16, so we can preallocate and set the length afterwards
|
|
58
|
+
let d=oa-b;oa+=2;let e=0;for(let b in a)(c||a.hasOwnProperty(b))&&(q(b),q(a[b]),e++);la[d++ +b]=e>>8,la[d+b]=255&e}:/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
|
|
58
59
|
(object, safePrototype) => {
|
|
59
60
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
60
61
|
let objectOffset = position++ - start
|
|
@@ -93,22 +94,21 @@ let d=ma-b;ma+=2;let e=0;for(let b in a)(c||a.hasOwnProperty(b))&&(q(b),q(a[b]),
|
|
|
93
94
|
sharedStructures.onUpdate(id, transition.__keys__)
|
|
94
95
|
}
|
|
95
96
|
target[objectOffset + start] = id
|
|
96
|
-
}*/a=>{let b,f=Object.keys(a),g=e.transitions||(e.transitions=Object.create(null)),h=0,k=f.length;for(let c,d=0;d<k;d++)c=f[d],b=g[c],b||(b=g[c]=Object.create(null),h++),g=b;let l=g[
|
|
97
|
-
|
|
97
|
+
}*/a=>{let b,f=Object.keys(a),g=e.transitions||(e.transitions=Object.create(null)),h=0,k=f.length;for(let c,d=0;d<k;d++)c=f[d],b=g[c],b||(b=g[c]=Object.create(null),h++),g=b;let l=g[pa];if(void 0!==l)// tag two byte
|
|
98
|
+
la[oa++]=217,la[oa++]=ia,la[oa++]=l;else if(l=e.nextId++,l||(l=0,e.nextId=1),l>=ja&&(e.nextId=(l=j)+1),g[pa]=l,e[l]=f,c&&c.length<=j)// tag two byte
|
|
98
99
|
// tag number
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
ja=a,ka=new DataView(ja.buffer,ja.byteOffset,ja.byteLength),ma=0}}ca=[Date,Set,Error,RegExp,ArrayBuffer,fa,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,BigUint64Array,Int8Array,Int16Array,Int32Array,BigInt64Array,Float32Array,Float64Array],ba=[{tag:1,encode(a){let b=a.getTime()/1e3;(this.useTimestamp32||0===a.getMilliseconds())&&0<=b&&4294967296>b?(ja[ma++]=26,ka.setUint32(ma,b),ma+=4):(ja[ma++]=251,ka.setFloat64(ma,b),ma+=8)}},{tag:258,// https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
100
|
+
la[oa++]=217,la[oa++]=ia,la[oa++]=l,d=!0;else{la[oa++]=216,la[oa++]=ia,h&&(n+=o*h),m.length>=ja-j&&(m.shift()[pa]=void 0),m.push(g),22>k?la[oa++]=130+k:p(k+2),q(f),la[oa++]=25,la[oa++]=ia,la[oa++]=l;// now write the values
|
|
101
|
+
for(let b=0;b<k;b++)q(a[f[b]]);return}24>k?la[oa++]=128|k:p(k);for(let b=0;b<k;b++)q(a[f[b]])},t=a=>{var c=Math.min,d=Math.round,e=Math.max;let f;if(16777216<a){// special handling for really large buffers
|
|
102
|
+
if(a-b>ka)throw new Error("Encoded buffer would be larger than maximum buffer size");f=c(ka,4096*d(e((a-b)*(67108864<a?1.25:2),16777216)/4096))}else// faster handling for smaller buffers
|
|
103
|
+
f=(e(a-b<<2,la.length-1)>>12)+1<<12;let g=new ga(f);return ma=new DataView(g.buffer,0,f),la.copy?la.copy(g,0,b,a):g.set(la.slice(b,a)),oa-=b,b=0,na=g.length-10,la=g}}useBuffer(a){// this means we are finished using our own buffer and we can write over it safely
|
|
104
|
+
la=a,ma=new DataView(la.buffer,la.byteOffset,la.byteLength),oa=0}}ea=[Date,Set,Error,RegExp,ArrayBuffer,ha,Uint8Array,Uint8ClampedArray,Uint16Array,Uint32Array,BigUint64Array,Int8Array,Int16Array,Int32Array,BigInt64Array,Float32Array,Float64Array],da=[{tag:1,encode(a){let b=a.getTime()/1e3;(this.useTimestamp32||0===a.getMilliseconds())&&0<=b&&4294967296>b?(la[oa++]=26,ma.setUint32(oa,b),oa+=4):(la[oa++]=251,ma.setFloat64(oa,b),oa+=8)}},{tag:258,// https://github.com/input-output-hk/cbor-sets-spec/blob/master/CBOR_SETS.md
|
|
105
105
|
encode(a,b){let c=Array.from(a);b(c)}},{tag:27,// http://cbor.schmorp.de/generic-object
|
|
106
106
|
encode(a,b){b([a.name,a.message])}},{tag:27,// http://cbor.schmorp.de/generic-object
|
|
107
|
-
encode(a,b){b(["RegExp",a.source,a.flags])}},{encode(a,b,c){r(a,c)}},{encode(a,b,c){r(a,c)}},q(64),q(68),q(69),q(70),q(71),q(72),q(77),q(78),q(79),q(81),q(82)];let
|
|
108
|
-
d&&(a=Buffer.concat([d,a]),d=void 0);try{b=c.decodeMultiple(a)}catch(c){if(c.incomplete)d=a.slice(c.lastPosition),b=c.values;else throw c}return b};if("function"==typeof a[Symbol.iterator])return function*(){for(const b of a)yield*e(b)}();return"function"==typeof a[Symbol.asyncIterator]?async function*(){for await(const b of a)yield*e(b)}():void 0},a.decodeMultiple=$,a.encode=
|
|
107
|
+
encode(a,b){b(["RegExp",a.source,a.flags])}},{encode(a,b,c){r(a,c)}},{encode(a,b,c){r(a,c)}},q(64),q(68),q(69),q(70),q(71),q(72),q(77),q(78),q(79),q(81),q(82)];let ra=new qa({useRecords:!1});const sa=ra.encode,{NEVER:ta,ALWAYS:ua,DECIMAL_ROUND:va,DECIMAL_FIT:wa}=_,xa=1e3;a.ALWAYS=ua,a.DECIMAL_FIT=wa,a.DECIMAL_ROUND=va,a.Decoder=N,a.Encoder=qa,a.FLOAT32_OPTIONS=_,a.NEVER=ta,a.Tag=S,a.addExtension=t,a.clearSource=n,a.decode=Z,a.decodeIter=function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise");const c=new N(b);let d;const e=a=>{let b;// if there's incomplete data from previous chunk, concatinate and try again
|
|
108
|
+
d&&(a=Buffer.concat([d,a]),d=void 0);try{b=c.decodeMultiple(a)}catch(c){if(c.incomplete)d=a.slice(c.lastPosition),b=c.values;else throw c}return b};if("function"==typeof a[Symbol.iterator])return function*(){for(const b of a)yield*e(b)}();return"function"==typeof a[Symbol.asyncIterator]?async function*(){for await(const b of a)yield*e(b)}():void 0},a.decodeMultiple=$,a.encode=sa,a.encodeIter=/**
|
|
109
109
|
* Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
|
|
110
110
|
* If the argument is only Async Iterable, the return value will be an Async Iterable.
|
|
111
111
|
* @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
|
|
112
112
|
* @param {options} [options] - cbor-x Encoder options
|
|
113
113
|
* @returns {IterableIterator|Promise.<AsyncIterableIterator>}
|
|
114
|
-
*/function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable");else{if("function"==typeof a[Symbol.iterator])return u(a,b);if("function"==typeof a.then||"function"==typeof a[Symbol.asyncIterator])return v(a,b);throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise")}},a.mapsAsObjects=!0,a.useRecords=!1,Object.defineProperty(a,"__esModule",{value:!0})});
|
|
114
|
+
*/function(a,b={}){if(!a||"object"!=typeof a)throw new Error("first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable");else{if("function"==typeof a[Symbol.iterator])return u(a,b);if("function"==typeof a.then||"function"==typeof a[Symbol.asyncIterator])return v(a,b);throw new Error("first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise")}},a.mapsAsObjects=!0,a.roundFloat32=function(a){ba[0]=a;let b=X[(127&ca[3])<<1|ca[2]>>7];return(b*a+(0<a?.5:-.5)>>0)/b},a.useRecords=!1,Object.defineProperty(a,"__esModule",{value:!0})});
|
package/dist/node.cjs
CHANGED
|
@@ -823,7 +823,7 @@ function addExtension(extension) {
|
|
|
823
823
|
currentExtensions[extension.tag] = extension.decode;
|
|
824
824
|
}
|
|
825
825
|
|
|
826
|
-
|
|
826
|
+
const mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
|
|
827
827
|
for (let i = 0; i < 256; i++) {
|
|
828
828
|
mult10[i] = +('1e' + Math.floor(45.15 - i * 0.30103));
|
|
829
829
|
}
|
|
@@ -835,7 +835,14 @@ const FLOAT32_OPTIONS = {
|
|
|
835
835
|
ALWAYS: 1,
|
|
836
836
|
DECIMAL_ROUND: 3,
|
|
837
837
|
DECIMAL_FIT: 4
|
|
838
|
-
};
|
|
838
|
+
};
|
|
839
|
+
let f32Array = new Float32Array(1);
|
|
840
|
+
let u8Array = new Uint8Array(f32Array.buffer, 0, 4);
|
|
841
|
+
function roundFloat32(float32Number) {
|
|
842
|
+
f32Array[0] = float32Number;
|
|
843
|
+
let multiplier = mult10[((u8Array[3] & 0x7f) << 1) | (u8Array[2] >> 7)];
|
|
844
|
+
return ((multiplier * float32Number + (float32Number > 0 ? 0.5 : -0.5)) >> 0) / multiplier
|
|
845
|
+
}
|
|
839
846
|
|
|
840
847
|
let textEncoder;
|
|
841
848
|
try {
|
|
@@ -880,11 +887,8 @@ class Encoder extends Decoder {
|
|
|
880
887
|
let recordIdsToRemove = [];
|
|
881
888
|
let transitionsCount = 0;
|
|
882
889
|
let serializationsSinceTransitionRebuild = 0;
|
|
883
|
-
if (this.structures && this.structures.length > maxSharedStructures) {
|
|
884
|
-
throw new Error('Too many shared structures')
|
|
885
|
-
}
|
|
886
890
|
|
|
887
|
-
this.encode = function(value) {
|
|
891
|
+
this.encode = function(value, encodeOptions) {
|
|
888
892
|
if (!target) {
|
|
889
893
|
target = new ByteArrayAllocate(8192);
|
|
890
894
|
targetView = new DataView(target.buffer, 0, 8192);
|
|
@@ -897,7 +901,8 @@ class Encoder extends Decoder {
|
|
|
897
901
|
targetView = new DataView(target.buffer, 0, target.length);
|
|
898
902
|
safeEnd = target.length - 10;
|
|
899
903
|
position$1 = 0;
|
|
900
|
-
}
|
|
904
|
+
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
905
|
+
position$1 = (position$1 + 7) & 0x7ffffff8; // Word align to make any future copying of this buffer faster
|
|
901
906
|
start = position$1;
|
|
902
907
|
referenceMap = encoder.structuredClone ? new Map() : null;
|
|
903
908
|
sharedStructures = encoder.structures;
|
|
@@ -905,7 +910,7 @@ class Encoder extends Decoder {
|
|
|
905
910
|
if (sharedStructures.uninitialized)
|
|
906
911
|
encoder.structures = sharedStructures = encoder.getStructures();
|
|
907
912
|
let sharedStructuresLength = sharedStructures.length;
|
|
908
|
-
if (sharedStructuresLength >
|
|
913
|
+
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
909
914
|
sharedStructuresLength = maxSharedStructures;
|
|
910
915
|
if (!sharedStructures.transitions) {
|
|
911
916
|
// rebuild our structure transitions
|
|
@@ -915,8 +920,8 @@ class Encoder extends Decoder {
|
|
|
915
920
|
if (!keys)
|
|
916
921
|
continue
|
|
917
922
|
let nextTransition, transition = sharedStructures.transitions;
|
|
918
|
-
for (let
|
|
919
|
-
let key = keys[
|
|
923
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
924
|
+
let key = keys[j];
|
|
920
925
|
nextTransition = transition[key];
|
|
921
926
|
if (!nextTransition) {
|
|
922
927
|
nextTransition = transition[key] = Object.create(null);
|
|
@@ -945,7 +950,12 @@ class Encoder extends Decoder {
|
|
|
945
950
|
referenceMap = null;
|
|
946
951
|
return serialized
|
|
947
952
|
}
|
|
948
|
-
|
|
953
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
954
|
+
target.start = start;
|
|
955
|
+
target.end = position$1;
|
|
956
|
+
return target
|
|
957
|
+
}
|
|
958
|
+
return target.subarray(start, position$1) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
949
959
|
} finally {
|
|
950
960
|
if (sharedStructures) {
|
|
951
961
|
if (serializationsSinceTransitionRebuild < 10)
|
|
@@ -967,13 +977,15 @@ class Encoder extends Decoder {
|
|
|
967
977
|
if (encoder.structures.length > maxSharedStructures) {
|
|
968
978
|
encoder.structures = encoder.structures.slice(0, maxSharedStructures);
|
|
969
979
|
}
|
|
970
|
-
|
|
980
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
981
|
+
let returnBuffer = target.subarray(start, position$1);
|
|
971
982
|
if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
|
|
972
983
|
// get updated structures and try again if the update failed
|
|
973
984
|
encoder.structures = encoder.getStructures() || [];
|
|
974
985
|
return encoder.encode(value)
|
|
975
986
|
}
|
|
976
987
|
lastSharedStructuresLength = encoder.structures.length;
|
|
988
|
+
return returnBuffer
|
|
977
989
|
}
|
|
978
990
|
}
|
|
979
991
|
}
|
|
@@ -1094,7 +1106,7 @@ class Encoder extends Decoder {
|
|
|
1094
1106
|
targetView.setFloat32(position$1, value);
|
|
1095
1107
|
let xShifted;
|
|
1096
1108
|
if (useFloat32 < 4 ||
|
|
1097
|
-
|
|
1109
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
1098
1110
|
((xShifted = value * mult10[((target[position$1] & 0x7f) << 1) | (target[position$1 + 1] >> 7)]) >> 0) === xShifted) {
|
|
1099
1111
|
position$1 += 4;
|
|
1100
1112
|
return
|
|
@@ -1225,7 +1237,7 @@ class Encoder extends Decoder {
|
|
|
1225
1237
|
} else if (type === 'undefined') {
|
|
1226
1238
|
target[position$1++] = 0xf7;
|
|
1227
1239
|
} else {
|
|
1228
|
-
throw new Error('Unknown type ' + type)
|
|
1240
|
+
throw new Error('Unknown type: ' + type)
|
|
1229
1241
|
}
|
|
1230
1242
|
};
|
|
1231
1243
|
|
|
@@ -1314,7 +1326,7 @@ class Encoder extends Decoder {
|
|
|
1314
1326
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null));
|
|
1315
1327
|
let newTransitions = 0;
|
|
1316
1328
|
let length = keys.length;
|
|
1317
|
-
for (let i =0; i < length; i++) {
|
|
1329
|
+
for (let i = 0; i < length; i++) {
|
|
1318
1330
|
let key = keys[i];
|
|
1319
1331
|
nextTransition = transition[key];
|
|
1320
1332
|
if (!nextTransition) {
|
|
@@ -1548,24 +1560,21 @@ function addExtension$1(extension) {
|
|
|
1548
1560
|
}
|
|
1549
1561
|
let defaultEncoder = new Encoder({ useRecords: false });
|
|
1550
1562
|
const encode = defaultEncoder.encode;
|
|
1551
|
-
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1563
|
+
const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS;
|
|
1564
|
+
const REUSE_BUFFER_MODE = 1000;
|
|
1552
1565
|
|
|
1553
1566
|
class EncoderStream extends stream.Transform {
|
|
1554
1567
|
constructor(options) {
|
|
1555
1568
|
if (!options)
|
|
1556
1569
|
options = {};
|
|
1570
|
+
options.writableObjectMode = true;
|
|
1557
1571
|
super(options);
|
|
1558
1572
|
options.sequential = true;
|
|
1559
|
-
this.encoder = new Encoder(options);
|
|
1573
|
+
this.encoder = options.encoder || new Encoder(options);
|
|
1560
1574
|
}
|
|
1561
|
-
|
|
1575
|
+
_transform(value, encoding, callback) {
|
|
1562
1576
|
this.push(this.encoder.encode(value));
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
end(value) {
|
|
1566
|
-
if (value != null)
|
|
1567
|
-
this.push(this.encoder.encode(value));
|
|
1568
|
-
this.push(null);
|
|
1577
|
+
callback();
|
|
1569
1578
|
}
|
|
1570
1579
|
}
|
|
1571
1580
|
|
|
@@ -1576,7 +1585,7 @@ class DecoderStream extends stream.Transform {
|
|
|
1576
1585
|
options.objectMode = true;
|
|
1577
1586
|
super(options);
|
|
1578
1587
|
options.structures = [];
|
|
1579
|
-
this.decoder = new Decoder(options);
|
|
1588
|
+
this.decoder = options.decoder || new Decoder(options);
|
|
1580
1589
|
}
|
|
1581
1590
|
_transform(chunk, encoding, callback) {
|
|
1582
1591
|
if (this.incompleteBuffer) {
|
|
@@ -1718,12 +1727,15 @@ exports.Encoder = Encoder;
|
|
|
1718
1727
|
exports.EncoderStream = EncoderStream;
|
|
1719
1728
|
exports.FLOAT32_OPTIONS = FLOAT32_OPTIONS;
|
|
1720
1729
|
exports.NEVER = NEVER;
|
|
1730
|
+
exports.REUSE_BUFFER_MODE = REUSE_BUFFER_MODE;
|
|
1721
1731
|
exports.Tag = Tag;
|
|
1722
1732
|
exports.addExtension = addExtension$1;
|
|
1733
|
+
exports.clearSource = clearSource;
|
|
1723
1734
|
exports.decode = decode;
|
|
1724
1735
|
exports.decodeIter = decodeIter;
|
|
1725
1736
|
exports.decodeMultiple = decodeMultiple;
|
|
1726
1737
|
exports.encode = encode;
|
|
1727
1738
|
exports.encodeIter = encodeIter;
|
|
1728
1739
|
exports.mapsAsObjects = mapsAsObjects;
|
|
1740
|
+
exports.roundFloat32 = roundFloat32;
|
|
1729
1741
|
exports.useRecords = useRecords;
|
package/dist/test.js
CHANGED
|
@@ -659,6 +659,13 @@
|
|
|
659
659
|
assert.deepEqual(deserialized, data);
|
|
660
660
|
});
|
|
661
661
|
|
|
662
|
+
test('255 chars', function() {
|
|
663
|
+
const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W';
|
|
664
|
+
var serialized = CBOR.encode(data);
|
|
665
|
+
var deserialized = CBOR.decode(serialized);
|
|
666
|
+
assert.equal(deserialized, data);
|
|
667
|
+
});
|
|
668
|
+
|
|
662
669
|
test('encode/decode sample data', function(){
|
|
663
670
|
var data = sampleData;
|
|
664
671
|
var serialized = CBOR.encode(data);
|
package/encode.d.ts
ADDED
package/encode.js
CHANGED
|
@@ -43,11 +43,8 @@ export class Encoder extends Decoder {
|
|
|
43
43
|
let recordIdsToRemove = []
|
|
44
44
|
let transitionsCount = 0
|
|
45
45
|
let serializationsSinceTransitionRebuild = 0
|
|
46
|
-
if (this.structures && this.structures.length > maxSharedStructures) {
|
|
47
|
-
throw new Error('Too many shared structures')
|
|
48
|
-
}
|
|
49
46
|
|
|
50
|
-
this.encode = function(value) {
|
|
47
|
+
this.encode = function(value, encodeOptions) {
|
|
51
48
|
if (!target) {
|
|
52
49
|
target = new ByteArrayAllocate(8192)
|
|
53
50
|
targetView = new DataView(target.buffer, 0, 8192)
|
|
@@ -60,7 +57,8 @@ export class Encoder extends Decoder {
|
|
|
60
57
|
targetView = new DataView(target.buffer, 0, target.length)
|
|
61
58
|
safeEnd = target.length - 10
|
|
62
59
|
position = 0
|
|
63
|
-
}
|
|
60
|
+
} else if (encodeOptions === REUSE_BUFFER_MODE)
|
|
61
|
+
position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
|
|
64
62
|
start = position
|
|
65
63
|
referenceMap = encoder.structuredClone ? new Map() : null
|
|
66
64
|
sharedStructures = encoder.structures
|
|
@@ -68,7 +66,7 @@ export class Encoder extends Decoder {
|
|
|
68
66
|
if (sharedStructures.uninitialized)
|
|
69
67
|
encoder.structures = sharedStructures = encoder.getStructures()
|
|
70
68
|
let sharedStructuresLength = sharedStructures.length
|
|
71
|
-
if (sharedStructuresLength >
|
|
69
|
+
if (sharedStructuresLength > maxSharedStructures && !isSequential)
|
|
72
70
|
sharedStructuresLength = maxSharedStructures
|
|
73
71
|
if (!sharedStructures.transitions) {
|
|
74
72
|
// rebuild our structure transitions
|
|
@@ -78,8 +76,8 @@ export class Encoder extends Decoder {
|
|
|
78
76
|
if (!keys)
|
|
79
77
|
continue
|
|
80
78
|
let nextTransition, transition = sharedStructures.transitions
|
|
81
|
-
for (let
|
|
82
|
-
let key = keys[
|
|
79
|
+
for (let j = 0, l = keys.length; j < l; j++) {
|
|
80
|
+
let key = keys[j]
|
|
83
81
|
nextTransition = transition[key]
|
|
84
82
|
if (!nextTransition) {
|
|
85
83
|
nextTransition = transition[key] = Object.create(null)
|
|
@@ -108,7 +106,12 @@ export class Encoder extends Decoder {
|
|
|
108
106
|
referenceMap = null
|
|
109
107
|
return serialized
|
|
110
108
|
}
|
|
111
|
-
|
|
109
|
+
if (encodeOptions === REUSE_BUFFER_MODE) {
|
|
110
|
+
target.start = start
|
|
111
|
+
target.end = position
|
|
112
|
+
return target
|
|
113
|
+
}
|
|
114
|
+
return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
|
|
112
115
|
} finally {
|
|
113
116
|
if (sharedStructures) {
|
|
114
117
|
if (serializationsSinceTransitionRebuild < 10)
|
|
@@ -130,13 +133,15 @@ export class Encoder extends Decoder {
|
|
|
130
133
|
if (encoder.structures.length > maxSharedStructures) {
|
|
131
134
|
encoder.structures = encoder.structures.slice(0, maxSharedStructures)
|
|
132
135
|
}
|
|
133
|
-
|
|
136
|
+
// we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
|
|
137
|
+
let returnBuffer = target.subarray(start, position)
|
|
134
138
|
if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
|
|
135
139
|
// get updated structures and try again if the update failed
|
|
136
140
|
encoder.structures = encoder.getStructures() || []
|
|
137
141
|
return encoder.encode(value)
|
|
138
142
|
}
|
|
139
143
|
lastSharedStructuresLength = encoder.structures.length
|
|
144
|
+
return returnBuffer
|
|
140
145
|
}
|
|
141
146
|
}
|
|
142
147
|
}
|
|
@@ -257,7 +262,7 @@ export class Encoder extends Decoder {
|
|
|
257
262
|
targetView.setFloat32(position, value)
|
|
258
263
|
let xShifted
|
|
259
264
|
if (useFloat32 < 4 ||
|
|
260
|
-
|
|
265
|
+
// this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
|
|
261
266
|
((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
|
|
262
267
|
position += 4
|
|
263
268
|
return
|
|
@@ -388,7 +393,7 @@ export class Encoder extends Decoder {
|
|
|
388
393
|
} else if (type === 'undefined') {
|
|
389
394
|
target[position++] = 0xf7
|
|
390
395
|
} else {
|
|
391
|
-
throw new Error('Unknown type ' + type)
|
|
396
|
+
throw new Error('Unknown type: ' + type)
|
|
392
397
|
}
|
|
393
398
|
}
|
|
394
399
|
|
|
@@ -477,7 +482,7 @@ export class Encoder extends Decoder {
|
|
|
477
482
|
let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
|
|
478
483
|
let newTransitions = 0
|
|
479
484
|
let length = keys.length
|
|
480
|
-
for (let i =0; i < length; i++) {
|
|
485
|
+
for (let i = 0; i < length; i++) {
|
|
481
486
|
let key = keys[i]
|
|
482
487
|
nextTransition = transition[key]
|
|
483
488
|
if (!nextTransition) {
|
|
@@ -720,3 +725,4 @@ export const encode = defaultEncoder.encode
|
|
|
720
725
|
export { FLOAT32_OPTIONS } from './decode.js'
|
|
721
726
|
import { FLOAT32_OPTIONS } from './decode.js'
|
|
722
727
|
export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
|
|
728
|
+
export const REUSE_BUFFER_MODE = 1000
|
package/index.d.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
export { Decoder, decode, addExtension, FLOAT32_OPTIONS, clearSource } from './decode.js'
|
|
1
|
+
export { Decoder, decode, addExtension, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './decode.js'
|
|
2
2
|
export { Encoder, encode } from './encode.js'
|
|
3
|
+
import { Transform, Readable } from 'stream'
|
|
3
4
|
|
|
4
5
|
export as namespace CBOR;
|
|
5
|
-
export class DecoderStream {
|
|
6
|
+
export class DecoderStream extends Transform {
|
|
7
|
+
constructor(options?: Options | { highWaterMark: number, emitClose: boolean, allowHalfOpen: boolean })
|
|
6
8
|
}
|
|
7
|
-
export class EncoderStream {
|
|
8
|
-
|
|
9
|
-
end(value?: any): void
|
|
9
|
+
export class EncoderStream extends Transform {
|
|
10
|
+
constructor(options?: Options | { highWaterMark: number, emitClose: boolean, allowHalfOpen: boolean })
|
|
10
11
|
}
|
package/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Encoder, addExtension, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './encode.js'
|
|
2
|
-
export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource } from './decode.js'
|
|
2
|
+
export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './decode.js'
|
|
3
3
|
export { decodeIter, encodeIter } from './iterators.js'
|
|
4
4
|
export const useRecords = false
|
|
5
5
|
export const mapsAsObjects = true
|
package/node-index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { Encoder, addExtension, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './encode.js'
|
|
2
|
-
export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS } from './decode.js'
|
|
1
|
+
export { Encoder, addExtension, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT, REUSE_BUFFER_MODE } from './encode.js'
|
|
2
|
+
export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './decode.js'
|
|
3
3
|
export { EncoderStream, DecoderStream } from './stream.js'
|
|
4
4
|
export { decodeIter, encodeIter } from './iterators.js'
|
|
5
5
|
export const useRecords = false
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cbor-x",
|
|
3
3
|
"author": "Kris Zyp",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.9.0",
|
|
5
5
|
"description": "Ultra-fast CBOR implementation with tag extensions for records and structured cloning",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"types": "./index.d.ts",
|
|
8
|
+
"main": "./dist/node.cjs",
|
|
9
|
+
"module": "./index.js",
|
|
8
10
|
"keywords": [
|
|
9
11
|
"CBOR",
|
|
10
12
|
"performance",
|
|
@@ -16,44 +18,42 @@
|
|
|
16
18
|
"url": "http://github.com/kriszyp/cbor-x"
|
|
17
19
|
},
|
|
18
20
|
"scripts": {
|
|
19
|
-
"benchmark": "node ./tests/benchmark.
|
|
21
|
+
"benchmark": "node ./tests/benchmark.cjs",
|
|
20
22
|
"build": "rollup -c",
|
|
23
|
+
"dry-run": "npm publish --dry-run",
|
|
21
24
|
"prepare": "npm run build",
|
|
22
25
|
"test": "mocha tests/test**.*js -u tdd --experimental-json-modules"
|
|
23
26
|
},
|
|
24
27
|
"type": "module",
|
|
25
|
-
"main": "./dist/node.cjs",
|
|
26
28
|
"exports": {
|
|
27
29
|
".": {
|
|
28
30
|
"node": {
|
|
29
31
|
"require": "./dist/node.cjs",
|
|
30
32
|
"import": "./node-index.js"
|
|
31
33
|
},
|
|
32
|
-
"default":
|
|
33
|
-
"import": "./index.js"
|
|
34
|
-
}
|
|
34
|
+
"default": "./index.js"
|
|
35
35
|
},
|
|
36
|
-
"./
|
|
36
|
+
"./encode": {
|
|
37
37
|
"node": {
|
|
38
38
|
"import": "./index.js",
|
|
39
39
|
"require": "./dist/node.cjs"
|
|
40
40
|
},
|
|
41
41
|
"default": {
|
|
42
|
-
"import": "./
|
|
42
|
+
"import": "./encode.js"
|
|
43
43
|
}
|
|
44
44
|
},
|
|
45
|
-
"./
|
|
45
|
+
"./decode": {
|
|
46
46
|
"node": {
|
|
47
47
|
"import": "./index.js",
|
|
48
48
|
"require": "./dist/node.cjs"
|
|
49
49
|
},
|
|
50
50
|
"default": {
|
|
51
|
-
"import": "./
|
|
51
|
+
"import": "./decode.js"
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
},
|
|
55
55
|
"optionalDependencies": {
|
|
56
|
-
"cbor-extract": "^0.3.
|
|
56
|
+
"cbor-extract": "^0.3.2"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "latest",
|
package/stream.js
CHANGED
|
@@ -7,18 +7,14 @@ export class EncoderStream extends Transform {
|
|
|
7
7
|
constructor(options) {
|
|
8
8
|
if (!options)
|
|
9
9
|
options = {}
|
|
10
|
+
options.writableObjectMode = true
|
|
10
11
|
super(options)
|
|
11
12
|
options.sequential = true
|
|
12
|
-
this.encoder = new Encoder(options)
|
|
13
|
+
this.encoder = options.encoder || new Encoder(options)
|
|
13
14
|
}
|
|
14
|
-
|
|
15
|
+
_transform(value, encoding, callback) {
|
|
15
16
|
this.push(this.encoder.encode(value))
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
end(value) {
|
|
19
|
-
if (value != null)
|
|
20
|
-
this.push(this.encoder.encode(value))
|
|
21
|
-
this.push(null)
|
|
17
|
+
callback()
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
20
|
|
|
@@ -29,7 +25,7 @@ export class DecoderStream extends Transform {
|
|
|
29
25
|
options.objectMode = true
|
|
30
26
|
super(options)
|
|
31
27
|
options.structures = []
|
|
32
|
-
this.decoder = new Decoder(options)
|
|
28
|
+
this.decoder = options.decoder || new Decoder(options)
|
|
33
29
|
}
|
|
34
30
|
_transform(chunk, encoding, callback) {
|
|
35
31
|
if (this.incompleteBuffer) {
|
package/tests/benchmark.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var cborX = tryRequire("
|
|
1
|
+
var cborX = tryRequire("../dist/node.cjs");
|
|
2
2
|
var msgpack_node = tryRequire("msgpack");
|
|
3
3
|
var msgpack_msgpack = tryRequire("@msgpack/msgpack");
|
|
4
4
|
var msgpack_lite = tryRequire("msgpack-lite");
|
|
@@ -43,12 +43,6 @@ console.log(rpad("", COL1, "-"), "|", lpad(":", COL2, "-"), "|", lpad(":", COL3,
|
|
|
43
43
|
|
|
44
44
|
var buf, obj;
|
|
45
45
|
|
|
46
|
-
if (JSON) {
|
|
47
|
-
buf = bench('buf = Buffer(JSON.stringify(obj));', JSON_stringify, data);
|
|
48
|
-
obj = bench('obj = JSON.parse(buf);', JSON.parse, buf);
|
|
49
|
-
test(obj);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
46
|
if (cborX) {
|
|
53
47
|
// let packr = new msgpackr.Packr({ objectsAsMaps: true })
|
|
54
48
|
buf = bench('require("cbor-x").encode(obj);', cborX.encode, data);
|
|
@@ -63,6 +57,18 @@ if (cborX) {
|
|
|
63
57
|
obj = bench('cbor-x w/ shared structures: encoder.decode(buf);', encoder.decode.bind(encoder), buf);
|
|
64
58
|
test(obj);
|
|
65
59
|
}
|
|
60
|
+
if (JSON) {
|
|
61
|
+
buf = bench('buf = Buffer(JSON.stringify(obj));', JSON_stringify, data);
|
|
62
|
+
obj = bench('obj = JSON.parse(buf);', JSON.parse, buf);
|
|
63
|
+
test(obj);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
if (JSON) {
|
|
68
|
+
buf = bench('buf = Buffer(JSON.stringify(obj));', JSON_stringify, data);
|
|
69
|
+
obj = bench('obj = JSON.parse(buf);', JSON.parse, buf);
|
|
70
|
+
test(obj);
|
|
71
|
+
}
|
|
66
72
|
|
|
67
73
|
if (msgpack_lite) {
|
|
68
74
|
buf = bench('buf = require("msgpack-lite").encode(obj);', msgpack_lite.encode, data);
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { EncoderStream, DecoderStream } from '../node-index.js'
|
|
2
2
|
import stream from 'stream'
|
|
3
3
|
import chai from 'chai'
|
|
4
|
+
import util from 'util'
|
|
5
|
+
import fs from 'fs'
|
|
6
|
+
const finished = util.promisify(stream.finished)
|
|
4
7
|
var assert = chai.assert
|
|
5
8
|
|
|
6
9
|
suite('cbor-x node stream tests', function(){
|
|
@@ -47,4 +50,11 @@ suite('cbor-x node stream tests', function(){
|
|
|
47
50
|
bufferStream.push(new Uint8Array([1, 2]))
|
|
48
51
|
bufferStream.push(null)
|
|
49
52
|
}))
|
|
53
|
+
|
|
54
|
+
teardown(function() {
|
|
55
|
+
try {
|
|
56
|
+
fs.unlinkSync('test-output.msgpack')
|
|
57
|
+
}catch(error){}
|
|
58
|
+
})
|
|
50
59
|
})
|
|
60
|
+
|
package/tests/test.js
CHANGED
|
@@ -84,6 +84,13 @@ suite('CBOR basic tests', function(){
|
|
|
84
84
|
assert.deepEqual(deserialized, data)
|
|
85
85
|
})
|
|
86
86
|
|
|
87
|
+
test('255 chars', function() {
|
|
88
|
+
const data = 'RRZG9A6I7xupPeOZhxcOcioFsuhszGOdyDUcbRf4Zef2kdPIfC9RaLO4jTM5JhuZvTsF09fbRHMGtqk7YAgu3vespeTe9l61ziZ6VrMnYu2CamK96wCkmz0VUXyqaiUoTPgzk414LS9yYrd5uh7w18ksJF5SlC2e91rukWvNqAZJjYN3jpkqHNOFchCwFrhbxq2Lrv1kSJPYCx9blRg2hGmYqTbElLTZHv20iNqwZeQbRMgSBPT6vnbCBPnOh1W'
|
|
89
|
+
var serialized = CBOR.encode(data)
|
|
90
|
+
var deserialized = CBOR.decode(serialized)
|
|
91
|
+
assert.equal(deserialized, data)
|
|
92
|
+
})
|
|
93
|
+
|
|
87
94
|
test('encode/decode sample data', function(){
|
|
88
95
|
var data = sampleData
|
|
89
96
|
var serialized = CBOR.encode(data)
|
package/pack.d.ts
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { Unpackr } from './unpack'
|
|
2
|
-
export { addExtension, FLOAT32_OPTIONS } from './unpack'
|
|
3
|
-
export class Packr extends Unpackr {
|
|
4
|
-
pack(value: any): Buffer
|
|
5
|
-
encode(value: any): Buffer
|
|
6
|
-
}
|
|
7
|
-
export class Encoder extends Packr {}
|
|
8
|
-
export function pack(value: any): Buffer
|
|
9
|
-
export function encode(value: any): Buffer
|