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.
@@ -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 32). 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).
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 use 32-bit when possible.
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
- cbor-x saves all JavaScript `Date`s using the standard CBOR date extension (tag 1).
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 2-4%, but YMMV).
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 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, resulting in less compact data than compressed JSON.
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
@@ -0,0 +1,11 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ | Version | Supported |
6
+ | ------- | ------------------ |
7
+ | 1.4.x | :white_check_mark: |
8
+
9
+ ## Reporting a Vulnerability
10
+
11
+ Please report security vulnerabilities to kriszyp@gmail.com.
@@ -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
- type: number
25
- pack(value: any): Buffer | Uint8Array
26
- unpack(messagePack: Buffer | Uint8Array): any
27
+ tag: number
28
+ encode(value: any): Buffer | Uint8Array
29
+ decode(messagePack: Buffer | Uint8Array): any
27
30
  }
28
- export class Unpackr {
31
+ export class Decoder {
29
32
  constructor(options?: Options)
30
- unpack(messagePack: Buffer | Uint8Array): any
31
33
  decode(messagePack: Buffer | Uint8Array): any
32
- unpackMultiple(messagePack: Buffer | Uint8Array, forEach?: (value: any) => any): [] | void
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 const C1: {}
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 let mult10 = new Array(147) // this is a table matching binary exponents to the multiplier to determine significant digit rounding
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
- let mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
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 > maxSharedStructures && !isSequential)
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 i =0, l = keys.length; i < l; i++) {
876
- let key = keys[i];
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
- return target.subarray(start, position$1) // position can change if we call encode again in saveStructures, so we get the buffer now
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
- // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
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?(ja[ma++]=152,ja[ma++]=a):65536>a?(ja[ma++]=153,ja[ma++]=a>>8,ja[ma++]=255&a):(ja[ma++]=154,ka.setUint32(ma,a),ma+=4)}function q(a){return{tag:a,encode:function(a,b){let c=a.byteLength,d=a.byteOffset||0,e=a.buffer||a;b(da?Buffer.from(e,d,c):new Uint8Array(e,d,c))}}}function r(a,b){let c=a.byteLength;24>c?ja[ma++]=64+c:256>c?(ja[ma++]=88,ja[ma++]=c):65536>c?(ja[ma++]=89,ja[ma++]=c>>8,ja[ma++]=255&c):(ja[ma++]=90,ka.setUint32(ma,c),ma+=4),ma+c>=ja.length&&b(ma+c),ja.set(a,ma),ma+=c}function s(a,b){// insert the ids that need to be referenced for structured clones
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");ca.unshift(a.Class),ba.unshift(a)}o(a)}function*u(a,b){const c=new oa(b);for(const d of a)yield c.encode(d)}async function*v(a,b){const c=new oa(b);for await(const d of a)yield c.encode(d)}/**
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]);let 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;try{aa=new TextEncoder}catch(a){}let ba,ca;const da="undefined"!=typeof Buffer,ea=da?Buffer.allocUnsafeSlow:Uint8Array,fa=da?Buffer:Uint8Array,ga=105,ha=256,ia=da?4294967296:2144337920;let ja,ka,la,ma=0;const na=Symbol("record-id");class oa extends N{constructor(a){super(a),this.offset=0;let b,c,d,e,f,g=0,h=fa.prototype.utf8Write?function(a,b,c){return ja.utf8Write(a,b,c)}:!!(aa&&aa.encodeInto)&&function(a,b){return aa.encodeInto(a,ja.subarray(b)).written},i=this,j=64,k=a&&a.sequential;k&&(j=0,this.structures=[]);let m=[],n=0,o=0;if(this.structures&&this.structures.length>j)throw new Error("Too many shared structures");this.encode=function(a){if(ja||(ja=new ea(8192),ka=new DataView(ja.buffer,0,8192),ma=0),la=ja.length-10,2048>la-ma&&(ja=new ea(ja.length),ka=new DataView(ja.buffer,0,ja.length),la=ja.length-10,ma=0),b=ma,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[na]=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=ma,f&&f.idsToInsert){ma+=8*f.idsToInsert.length,ma>la&&t(ma),i.offset=ma;let a=s(ja.subarray(b,ma),f.idsToInsert);return f=null,a}return ja.subarray(b,ma);// position can change if we call encode 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][na]=void 0;m=[]}if(d&&i.saveStructures){if(i.structures.length>j&&(i.structures=i.structures.slice(0,j)),!1===i.saveStructures(i.structures,g))return i.structures=i.getStructures()||[],i.encode(a);g=i.structures.length}}}};const q=a=>{ma>la&&(ja=t(ma));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(ma+e>la&&(ja=t(ma+e)),64>d||!h){let e,f,g,h=ma+b;for(e=0;e<d;e++)f=a.charCodeAt(e),128>f?ja[h++]=f:2048>f?(ja[h++]=192|f>>6,ja[h++]=128|63&f):55296==(64512&f)&&56320==(64512&(g=a.charCodeAt(e+1)))?(f=65536+((1023&f)<<10)+(1023&g),e++,ja[h++]=240|f>>18,ja[h++]=128|63&f>>12,ja[h++]=128|63&f>>6,ja[h++]=128|63&f):(ja[h++]=224|f>>12,ja[h++]=128|63&f>>6,ja[h++]=128|63&f);c=h-ma-b}else c=h(a,ma+b,e);24>c?ja[ma++]=96|c:256>c?(2>b&&ja.copyWithin(ma+2,ma+1,ma+1+c),ja[ma++]=120,ja[ma++]=c):65536>c?(3>b&&ja.copyWithin(ma+3,ma+2,ma+2+c),ja[ma++]=121,ja[ma++]=c>>8,ja[ma++]=255&c):(5>b&&ja.copyWithin(ma+5,ma+3,ma+3+c),ja[ma++]=122,ka.setUint32(ma,c),ma+=4),ma+=c}else if("number"===d){if(a>>>0===a)24>a?ja[ma++]=a:256>a?(ja[ma++]=24,ja[ma++]=a):65536>a?(ja[ma++]=25,ja[ma++]=a>>8,ja[ma++]=255&a):(ja[ma++]=26,ka.setUint32(ma,a),ma+=4);else if(a>>0===a)-24<=a?ja[ma++]=31-a:-256<=a?(ja[ma++]=56,ja[ma++]=~a):-65536<=a?(ja[ma++]=57,ka.setUint16(ma,~a),ma+=2):(ja[ma++]=58,ka.setUint32(ma,~a),ma+=4);else{let b;if(0<(b=this.useFloat32)&&4294967296>a&&-2147483648<=a){ja[ma++]=250,ka.setFloat32(ma,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
50
- (c=a*X[(127&ja[ma])<<1|ja[ma+1]>>7])>>0===c)return void(ma+=4);// move back into position for writing a double
51
- ma--}ja[ma++]=251,ka.setFloat64(ma,a),ma+=8}}else if("object"===d){if(!a)ja[ma++]=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 ja[ma++]=217,ja[ma++]=156,ja[ma++]=74,ja[ma++]=26,ka.setUint32(ma,c.id),void(ma+=4)}f.set(a,{offset:ma-b})}let d=a.constructor;if(d===Object)r(a,!0);else if(d===Array){c=a.length,24>c?ja[ma++]=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)&&(ja[ma++]=217,ja[ma++]=1,ja[ma++]=3),c=a.size,24>c?ja[ma++]=160|c:256>c?(ja[ma++]=184,ja[ma++]=c):65536>c?(ja[ma++]=185,ja[ma++]=c>>8,ja[ma++]=255&c):(ja[ma++]=186,ka.setUint32(ma,c),ma+=4);for(let[b,c]of a)q(b),q(c)}else{for(let b,c=0,d=ba.length;c<d;c++)if(b=ca[c],a instanceof b){let b=ba[c],d=b.tag;return 24>d?ja[ma++]=192|d:256>d?(ja[ma++]=216,ja[ma++]=d):65536>d?(ja[ma++]=217,ja[ma++]=d>>8,ja[ma++]=255&d):-1<d&&(ja[ma++]=218,ka.setUint32(ma,d),ma+=4),void b.encode.call(this,a,q,t)}if(a[Symbol.iterator]){ja[ma++]=159;// indefinite length array
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(ja[ma++]=255)}// no extension found, write as object
54
- r(a,!a.hasOwnProperty)}}}else if("boolean"===d)ja[ma++]=a?245:244;else if("bigint"===d){if(a<BigInt(1)<<BigInt(64)&&0<=a)ja[ma++]=27,ka.setBigUint64(ma,a);else if(a>-(BigInt(1)<<BigInt(64))&&0>a)ja[ma++]=59,ka.setBigUint64(ma,-a-BigInt(1));else// overflow
55
- if(this.largeBigIntToFloat)ja[ma++]=251,ka.setFloat64(ma,+a);else throw new RangeError(a+" was too large to fit in CBOR 64-bit integer format, set largeBigIntToFloat to convert to float-64");ma+=8}else if("undefined"===d)ja[ma++]=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)
56
- let b=Object.keys(a),c=b.length;24>c?ja[ma++]=160|c:256>c?(ja[ma++]=184,ja[ma++]=c):65536>c?(ja[ma++]=185,ja[ma++]=c>>8,ja[ma++]=255&c):(ja[ma++]=186,ka.setUint32(ma,c),ma+=4);let d;for(let e=0;e<c;e++)q(d=b[e]),q(a[d])}:(a,c)=>{ja[ma++]=185;// always use map 16, so we can preallocate and set the length afterwards
57
- let d=ma-b;ma+=2;let e=0;for(let b in a)(c||a.hasOwnProperty(b))&&(q(b),q(a[b]),e++);ja[d++ +b]=e>>8,ja[d+b]=255&e}:/* sharedStructures ? // For highly stable structures, using for-in can a little bit faster
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[na];if(void 0!==l)// tag two byte
97
- ja[ma++]=217,ja[ma++]=ga,ja[ma++]=l;else if(l=e.nextId++,l||(l=0,e.nextId=1),l>=ha&&(e.nextId=(l=j)+1),g[na]=l,e[l]=f,c&&c.length<=j)// tag two byte
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
- ja[ma++]=217,ja[ma++]=ga,ja[ma++]=l,d=!0;else{ja[ma++]=216,ja[ma++]=ga,h&&(n+=o*h),m.length>=ha-j&&(m.shift()[na]=void 0),m.push(g),22>k?ja[ma++]=130+k:// array header, length of values + 2
100
- p(k+2),q(f),ja[ma++]=25,ja[ma++]=ga,ja[ma++]=l;// now write the values
101
- for(let b=0;b<k;b++)q(a[f[b]]);return}24>k?ja[ma++]=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>ia)throw new Error("Encoded buffer would be larger than maximum buffer size");f=c(ia,4096*d(e((a-b)*(67108864<a?1.25:2),16777216)/4096))}else// faster handling for smaller buffers
103
- f=(e(a-b<<2,ja.length-1)>>12)+1<<12;let g=new ea(f);return ka=new DataView(g.buffer,0,f),ja.copy?ja.copy(g,0,b,a):g.set(ja.slice(b,a)),ma-=b,b=0,la=g.length-10,ja=g}}useBuffer(a){// this means we are finished using our own buffer and we can write over it safely
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 pa=new oa({useRecords:!1});const qa=pa.encode,{NEVER:ra,ALWAYS:sa,DECIMAL_ROUND:ta,DECIMAL_FIT:ua}=_;a.ALWAYS=sa,a.DECIMAL_FIT=ua,a.DECIMAL_ROUND=ta,a.Decoder=N,a.Encoder=oa,a.FLOAT32_OPTIONS=_,a.NEVER=ra,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=qa,a.encodeIter=/**
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
- let mult10 = new Array(147); // this is a table matching binary exponents to the multiplier to determine significant digit rounding
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 > maxSharedStructures && !isSequential)
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 i =0, l = keys.length; i < l; i++) {
919
- let key = keys[i];
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
- return target.subarray(start, position$1) // position can change if we call encode again in saveStructures, so we get the buffer now
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
- // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
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
- write(value) {
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
@@ -0,0 +1,6 @@
1
+ import { Decoder } from './decode'
2
+ export { addExtension, FLOAT32_OPTIONS } from './unpack'
3
+ export class Encoder extends Decoder {
4
+ encode(value: any): Buffer
5
+ }
6
+ export function encode(value: any): Buffer
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 > maxSharedStructures && !isSequential)
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 i =0, l = keys.length; i < l; i++) {
82
- let key = keys[i]
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
- return target.subarray(start, position) // position can change if we call encode again in saveStructures, so we get the buffer now
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
- // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
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
- write(value: any): void
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.8.3",
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.js",
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
- "./pack": {
36
+ "./encode": {
37
37
  "node": {
38
38
  "import": "./index.js",
39
39
  "require": "./dist/node.cjs"
40
40
  },
41
41
  "default": {
42
- "import": "./pack.js"
42
+ "import": "./encode.js"
43
43
  }
44
44
  },
45
- "./unpack": {
45
+ "./decode": {
46
46
  "node": {
47
47
  "import": "./index.js",
48
48
  "require": "./dist/node.cjs"
49
49
  },
50
50
  "default": {
51
- "import": "./unpack.js"
51
+ "import": "./decode.js"
52
52
  }
53
53
  }
54
54
  },
55
55
  "optionalDependencies": {
56
- "cbor-extract": "^0.3.1"
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
- write(value) {
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) {
@@ -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);
@@ -6,6 +6,7 @@ function tryRequire(module) {
6
6
  try {
7
7
  return require(module)
8
8
  } catch(error) {
9
+ console.log(error)
9
10
  }
10
11
  }
11
12
  //if (typeof chai === 'undefined') { chai = require('chai') }
@@ -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