cbor-x 0.8.2 → 0.9.2

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/dist/test.js CHANGED
@@ -581,7 +581,7 @@
581
581
  outcomesScore: outcomesScore
582
582
  };
583
583
 
584
- //import inspector from 'inspector'; inspector.open(9330, null, true); debugger
584
+ //import inspector from 'inspector'; inspector.open(9229, null, true); debugger
585
585
  function tryRequire(module) {
586
586
  try {
587
587
  return require(module)
@@ -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);
@@ -676,6 +683,55 @@
676
683
  var deserialized = encoder.decode(serialized);
677
684
  assert.deepEqual(deserialized, data);
678
685
  });
686
+ test('encode/decode sample data with packing', function(){
687
+ var data = sampleData;
688
+ let encoder = new Encoder({ pack: true, useRecords: false });
689
+ var serialized = encoder.encode(data);
690
+ var deserialized = encoder.decode(serialized);
691
+ assert.deepEqual(deserialized, data);
692
+ });
693
+ test('encode/decode sample data with packing and records', function(){
694
+ var data = sampleData;
695
+ let structures = [];
696
+ let encoder = new Encoder({ structures, pack: true, useRecords: true });
697
+ var serialized = encoder.encode(data);
698
+ var deserialized = encoder.decode(serialized);
699
+ assert.deepEqual(deserialized, data);
700
+ });
701
+ test('encode/decode sample data with shared packing and records', function(){
702
+ let encoder = new Encoder({ useRecords: true });
703
+ let finishPack = encoder.findCommonStringsToPack();
704
+ for (let i = 0; i < 20; i++) {
705
+ let data = {
706
+ shouldShare: 'same each time',
707
+ shouldShare2: 'same each time 2',
708
+ shouldntShare: 'different each time ' + i
709
+ };
710
+ if (i == 10)
711
+ finishPack({});
712
+ var serialized = encoder.encode(data);
713
+ var deserialized = encoder.decode(serialized);
714
+ assert.deepEqual(deserialized, data);
715
+ }
716
+ });
717
+ test('encode/decode sample data with individual packing, shared packing and records', function(){
718
+ let encoder = new Encoder({ pack: true, useRecords: true });
719
+ let finishPack = encoder.findCommonStringsToPack();
720
+ for (let i = 0; i < 20; i++) {
721
+ let data = {
722
+ shouldShare: 'same each time',
723
+ shouldShare2: 'same each time',
724
+ shouldntShare: 'different each time ' + i,
725
+ shouldntShare2: 'different each time ' + i,
726
+ noPack: 'no packing ' + i,
727
+ };
728
+ if (i == 10)
729
+ finishPack({ threshold: 5 });
730
+ var serialized = encoder.encode(data);
731
+ var deserialized = encoder.decode(serialized);
732
+ assert.deepEqual(deserialized, data);
733
+ }
734
+ });
679
735
  if (typeof Buffer != 'undefined')
680
736
  test('replace data', function(){
681
737
  var data1 = {
@@ -787,10 +843,13 @@
787
843
  let fa = new Float32Array(b.buffer, 8, 2);
788
844
  fa[0] = 2.25;
789
845
  fa[1] = 6;
846
+ let map = new Map();
847
+ map.set('key', 'value');
790
848
  let object = {
791
849
  error: new Error('test'),
792
850
  set: new Set(['a', 'b']),
793
851
  regexp: /test/gi,
852
+ map,
794
853
  float32Array: fa,
795
854
  uint16Array: new Uint16Array([3,4])
796
855
  };
@@ -800,6 +859,7 @@
800
859
  var serialized = encoder.encode(object);
801
860
  var deserialized = encoder.decode(serialized);
802
861
  assert.deepEqual(Array.from(deserialized.set), Array.from(object.set));
862
+ assert.equal(deserialized.map.get('key'), 'value');
803
863
  assert.equal(deserialized.error.message, object.error.message);
804
864
  assert.equal(deserialized.regexp.test('TEST'), true);
805
865
  assert.equal(deserialized.float32Array.constructor.name, 'Float32Array');
@@ -810,6 +870,19 @@
810
870
  assert.equal(deserialized.uint16Array[1], 4);
811
871
  });
812
872
 
873
+ test('explicit maps and sets', function () {
874
+ let map = new Map();
875
+ map.set('key', { inside: 'value'});
876
+ let object = {
877
+ set: new Set(['a', 'b']),
878
+ map,
879
+ };
880
+ var serialized = encode(object); // default encoder
881
+ var deserialized = decode(serialized);
882
+ assert.deepEqual(Array.from(deserialized.set), Array.from(object.set));
883
+ assert.equal(deserialized.map.get('key').inside, 'value');
884
+ });
885
+
813
886
  test('object without prototype', function(){
814
887
  var data = Object.create(null);
815
888
  data.test = 3;
@@ -825,6 +898,13 @@
825
898
  var decoded = decode(encoded);
826
899
  assert.equal(decoded.length, size);
827
900
  });
901
+ test('little buffer', function() {
902
+ var data = typeof Buffer == 'undefined' ? new Uint8Array(0) : Buffer.alloc(0);
903
+ var encoded = encode(data);
904
+ assert.equal(encoded.length, 1); // make sure to use canonical form
905
+ var decoded = decode(encoded);
906
+ assert.equal(decoded.length, 0);
907
+ });
828
908
 
829
909
  test('random strings', function(){
830
910
  var data = [];
@@ -872,6 +952,7 @@
872
952
  let encoder = new Encoder({
873
953
  mapsAsObjects: true,
874
954
  useTimestamp32: true,
955
+ useTag259ForMaps: false,
875
956
  });
876
957
  var serialized = encoder.encode(data);
877
958
  var deserialized = encoder.decode(serialized);
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
@@ -10,6 +10,7 @@ const ByteArray = hasNodeBuffer ? Buffer : Uint8Array
10
10
  const RECORD_STARTING_ID_PREFIX = 0x69 // tag 105/0x69
11
11
  const MAX_STRUCTURES = 0x100
12
12
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000
13
+ let serializationId = 1
13
14
  let target
14
15
  let targetView
15
16
  let position = 0
@@ -25,6 +26,7 @@ export class Encoder extends Decoder {
25
26
  let hasSharedUpdate
26
27
  let structures
27
28
  let referenceMap
29
+ options = options || {}
28
30
  let lastSharedStructuresLength = 0
29
31
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
30
32
  return target.utf8Write(string, position, maxBytes)
@@ -35,19 +37,25 @@ export class Encoder extends Decoder {
35
37
 
36
38
  let encoder = this
37
39
  let maxSharedStructures = 64
38
- let isSequential = options && options.sequential
40
+ let isSequential = options.sequential
39
41
  if (isSequential) {
40
42
  maxSharedStructures = 0
41
43
  this.structures = []
42
44
  }
45
+ let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues
46
+ let sharedPackedObjectMap
47
+ if (sharedValues) {
48
+ sharedPackedObjectMap = Object.create(null)
49
+ for (let i = 0, l = sharedValues.length; i < l; i++) {
50
+ sharedPackedObjectMap[sharedValues[i]] = i
51
+ }
52
+
53
+ }
43
54
  let recordIdsToRemove = []
44
55
  let transitionsCount = 0
45
56
  let serializationsSinceTransitionRebuild = 0
46
- if (this.structures && this.structures.length > maxSharedStructures) {
47
- throw new Error('Too many shared structures')
48
- }
49
57
 
50
- this.encode = function(value) {
58
+ this.encode = function(value, encodeOptions) {
51
59
  if (!target) {
52
60
  target = new ByteArrayAllocate(8192)
53
61
  targetView = new DataView(target.buffer, 0, 8192)
@@ -60,7 +68,8 @@ export class Encoder extends Decoder {
60
68
  targetView = new DataView(target.buffer, 0, target.length)
61
69
  safeEnd = target.length - 10
62
70
  position = 0
63
- }
71
+ } else if (encodeOptions === REUSE_BUFFER_MODE)
72
+ position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
64
73
  start = position
65
74
  referenceMap = encoder.structuredClone ? new Map() : null
66
75
  sharedStructures = encoder.structures
@@ -68,7 +77,7 @@ export class Encoder extends Decoder {
68
77
  if (sharedStructures.uninitialized)
69
78
  encoder.structures = sharedStructures = encoder.getStructures()
70
79
  let sharedStructuresLength = sharedStructures.length
71
- if (sharedStructuresLength > maxSharedStructures && !isSequential)
80
+ if (sharedStructuresLength > maxSharedStructures && !isSequential)
72
81
  sharedStructuresLength = maxSharedStructures
73
82
  if (!sharedStructures.transitions) {
74
83
  // rebuild our structure transitions
@@ -78,8 +87,8 @@ export class Encoder extends Decoder {
78
87
  if (!keys)
79
88
  continue
80
89
  let nextTransition, transition = sharedStructures.transitions
81
- for (let i =0, l = keys.length; i < l; i++) {
82
- let key = keys[i]
90
+ for (let j = 0, l = keys.length; j < l; j++) {
91
+ let key = keys[j]
83
92
  nextTransition = transition[key]
84
93
  if (!nextTransition) {
85
94
  nextTransition = transition[key] = Object.create(null)
@@ -96,6 +105,29 @@ export class Encoder extends Decoder {
96
105
  if (hasSharedUpdate)
97
106
  hasSharedUpdate = false
98
107
  structures = sharedStructures || []
108
+ packedObjectMap = sharedPackedObjectMap
109
+ if (options.pack) {
110
+ let packedValues = new Map()
111
+ packedValues.values = []
112
+ packedValues.encoder = encoder
113
+ packedValues.maxValues = options.maxPrivatePackedValues || (sharedPackedObjectMap ? 16 : Infinity)
114
+ packedValues.objectMap = sharedPackedObjectMap || false
115
+ packedValues.samplingPackedValues = samplingPackedValues
116
+ findRepetitiveStrings(value, packedValues)
117
+ if (packedValues.values.length > 0) {
118
+ target[position++] = 0xd8 // one-byte tag
119
+ target[position++] = 51 // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
120
+ writeArrayHeader(4)
121
+ let valuesArray = packedValues.values
122
+ encode(valuesArray)
123
+ writeArrayHeader(0) // prefixes
124
+ writeArrayHeader(0) // suffixes
125
+ packedObjectMap = Object.create(sharedPackedObjectMap || null)
126
+ for (let i = 0, l = valuesArray.length; i < l; i++) {
127
+ packedObjectMap[valuesArray[i]] = i
128
+ }
129
+ }
130
+ }
99
131
  try {
100
132
  encode(value)
101
133
  encoder.offset = position // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
@@ -108,7 +140,12 @@ export class Encoder extends Decoder {
108
140
  referenceMap = null
109
141
  return serialized
110
142
  }
111
- return target.subarray(start, position) // position can change if we call encode again in saveStructures, so we get the buffer now
143
+ if (encodeOptions === REUSE_BUFFER_MODE) {
144
+ target.start = start
145
+ target.end = position
146
+ return target
147
+ }
148
+ return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
112
149
  } finally {
113
150
  if (sharedStructures) {
114
151
  if (serializationsSinceTransitionRebuild < 10)
@@ -122,7 +159,7 @@ export class Encoder extends Decoder {
122
159
  recordIdsToRemove = []
123
160
  } else if (recordIdsToRemove.length > 0 && !isSequential) {
124
161
  for (let i = 0, l = recordIdsToRemove.length; i < l; i++) {
125
- recordIdsToRemove[i][RECORD_SYMBOL] = 0
162
+ recordIdsToRemove[i][RECORD_SYMBOL] = undefined
126
163
  }
127
164
  recordIdsToRemove = []
128
165
  }
@@ -130,15 +167,41 @@ export class Encoder extends Decoder {
130
167
  if (encoder.structures.length > maxSharedStructures) {
131
168
  encoder.structures = encoder.structures.slice(0, maxSharedStructures)
132
169
  }
170
+ // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
171
+ let returnBuffer = target.subarray(start, position)
172
+ let shared = encoder.structures || []
173
+ if (sharedValues) {
174
+ shared = shared.concat(sharedValues)
175
+ }
133
176
 
134
177
  if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
135
178
  // get updated structures and try again if the update failed
136
179
  encoder.structures = encoder.getStructures() || []
137
180
  return encoder.encode(value)
138
181
  }
139
- lastSharedStructuresLength = encoder.structures.length
182
+ lastSharedStructuresLength = shared.length
183
+ return returnBuffer
184
+ }
185
+ }
186
+ }
187
+ }
188
+ this.findCommonStringsToPack = () => {
189
+ samplingPackedValues = new Map()
190
+ if (!sharedPackedObjectMap)
191
+ sharedPackedObjectMap = Object.create(null)
192
+ return ({ threshold }) => {
193
+ threshold = threshold || 4
194
+ let position = this.pack ? options.maxPrivatePackedValues || 16 : 0
195
+ if (!sharedValues)
196
+ sharedValues = this.sharedValues = []
197
+ for (let [ key, status ] of samplingPackedValues) {
198
+ if (status.count > threshold) {
199
+ sharedPackedObjectMap[key] = position++
200
+ sharedValues.push(key)
201
+ hasSharedUpdate = true
140
202
  }
141
203
  }
204
+ samplingPackedValues = null
142
205
  }
143
206
  }
144
207
  const encode = (value) => {
@@ -148,6 +211,43 @@ export class Encoder extends Decoder {
148
211
  var type = typeof value
149
212
  var length
150
213
  if (type === 'string') {
214
+ if (packedObjectMap) {
215
+ let packedPosition = packedObjectMap[value]
216
+ if (packedPosition >= 0) {
217
+ if (packedPosition < 16)
218
+ target[position++] = packedPosition + 0xe0 // simple values, defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
219
+ else {
220
+ target[position++] = 0xc6 // tag 6 defined in https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
221
+ if (packedPosition & 1)
222
+ encode((15 - packedPosition) >> 1)
223
+ else
224
+ encode((packedPosition - 16) >> 1)
225
+ }
226
+ return
227
+ /* } else if (packedStatus.serializationId != serializationId) {
228
+ packedStatus.serializationId = serializationId
229
+ packedStatus.count = 1
230
+ if (options.sharedPack) {
231
+ let sharedCount = packedStatus.sharedCount = (packedStatus.sharedCount || 0) + 1
232
+ if (shareCount > (options.sharedPack.threshold || 5)) {
233
+ let sharedPosition = packedStatus.position = packedStatus.nextSharedPosition
234
+ hasSharedUpdate = true
235
+ if (sharedPosition < 16)
236
+ target[position++] = sharedPosition + 0xc0
237
+
238
+ }
239
+ }
240
+ } // else any in-doc incrementation?*/
241
+ } else if (samplingPackedValues && !options.pack) {
242
+ let status = samplingPackedValues.get(value)
243
+ if (status)
244
+ status.count++
245
+ else
246
+ samplingPackedValues.set(value, {
247
+ count: 1,
248
+ })
249
+ }
250
+ }
151
251
  let strLength = value.length
152
252
  let headerSize
153
253
  // first we estimate the header size, so we can write to the correct location
@@ -257,7 +357,7 @@ export class Encoder extends Decoder {
257
357
  targetView.setFloat32(position, value)
258
358
  let xShifted
259
359
  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
360
+ // this checks for rounding of numbers that were encoded in 32-bit float to nearest significant decimal digit that could be preserved
261
361
  ((xShifted = value * mult10[((target[position] & 0x7f) << 1) | (target[position + 1] >> 7)]) >> 0) === xShifted) {
262
362
  position += 4
263
363
  return
@@ -303,6 +403,12 @@ export class Encoder extends Decoder {
303
403
  encode(value[i])
304
404
  }
305
405
  } else if (constructor === Map) {
406
+ if (this.mapsAsObjects ? this.useTag259ForMaps !== false : this.useTag259ForMaps) {
407
+ // use Tag 259 (https://github.com/shanewholloway/js-cbor-codec/blob/master/docs/CBOR-259-spec--explicit-maps.md) for maps if the user wants it that way
408
+ target[position++] = 0xd9
409
+ target[position++] = 1
410
+ target[position++] = 3
411
+ }
306
412
  length = value.size
307
413
  if (length < 0x18) {
308
414
  target[position++] = 0xa0 | length
@@ -380,10 +486,9 @@ export class Encoder extends Decoder {
380
486
  }
381
487
  position += 8
382
488
  } else if (type === 'undefined') {
383
- //target[position++] = 0xc1 // this is the "never-used" byte
384
489
  target[position++] = 0xf7
385
490
  } else {
386
- throw new Error('Unknown type ' + type)
491
+ throw new Error('Unknown type: ' + type)
387
492
  }
388
493
  }
389
494
 
@@ -472,7 +577,7 @@ export class Encoder extends Decoder {
472
577
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
473
578
  let newTransitions = 0
474
579
  let length = keys.length
475
- for (let i =0; i < length; i++) {
580
+ for (let i = 0; i < length; i++) {
476
581
  let key = keys[i]
477
582
  nextTransition = transition[key]
478
583
  if (!nextTransition) {
@@ -482,7 +587,7 @@ export class Encoder extends Decoder {
482
587
  transition = nextTransition
483
588
  }
484
589
  let recordId = transition[RECORD_SYMBOL]
485
- if (recordId) {
590
+ if (recordId !== undefined) {
486
591
  target[position++] = 0xd9 // tag two byte
487
592
  target[position++] = RECORD_STARTING_ID_PREFIX
488
593
  target[position++] = recordId
@@ -509,12 +614,9 @@ export class Encoder extends Decoder {
509
614
  transitionsCount += serializationsSinceTransitionRebuild * newTransitions
510
615
  // record the removal of the id, we can maintain our shared structure
511
616
  if (recordIdsToRemove.length >= MAX_STRUCTURES - maxSharedStructures)
512
- recordIdsToRemove.shift()[RECORD_SYMBOL] = 0 // we are cycling back through, and have to remove old ones
617
+ recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined // we are cycling back through, and have to remove old ones
513
618
  recordIdsToRemove.push(transition)
514
- if (length < 0x16)
515
- target[position++] = 0x82 + length // array header, length of values + 2
516
- else
517
- writeArrayHeader(length + 2)
619
+ writeArrayHeader(length + 2)
518
620
  encode(keys)
519
621
  target[position++] = 0x19 // uint16
520
622
  target[position++] = RECORD_STARTING_ID_PREFIX
@@ -570,7 +672,9 @@ function copyBinary(source, target, targetOffset, offset, endOffset) {
570
672
  }
571
673
 
572
674
  function writeArrayHeader(length) {
573
- if (length < 0x100) {
675
+ if (length < 0x18)
676
+ target[position++] = 0x80 | length
677
+ else if (length < 0x100) {
574
678
  target[position++] = 0x98
575
679
  target[position++] = length
576
680
  } else if (length < 0x10000) {
@@ -584,6 +688,56 @@ function writeArrayHeader(length) {
584
688
  }
585
689
  }
586
690
 
691
+ function findRepetitiveStrings(value, packedValues) {
692
+ switch(typeof value) {
693
+ case 'string':
694
+ if (value.length > 3) {
695
+ if (packedValues.objectMap[value] > -1 || packedValues.values.length >= packedValues.maxValues)
696
+ return
697
+ let packedStatus = packedValues.get(value)
698
+ if (packedStatus) {
699
+ if (++packedStatus.count == 2) {
700
+ packedValues.values.push(value)
701
+ }
702
+ } else {
703
+ packedValues.set(value, {
704
+ count: 1,
705
+ })
706
+ if (packedValues.samplingPackedValues) {
707
+ let status = packedValues.samplingPackedValues.get(value)
708
+ if (status)
709
+ status.count++
710
+ else
711
+ packedValues.samplingPackedValues.set(value, {
712
+ count: 1,
713
+ })
714
+ }
715
+ }
716
+ }
717
+ break
718
+ case 'object':
719
+ if (value) {
720
+ if (value instanceof Array) {
721
+ for (let i = 0, l = value.length; i < l; i++) {
722
+ findRepetitiveStrings(value[i], packedValues)
723
+ }
724
+
725
+ } else {
726
+ let includeKeys = !packedValues.encoder.useRecords
727
+ for (var key in value) {
728
+ if (value.hasOwnProperty(key)) {
729
+ if (includeKeys)
730
+ findRepetitiveStrings(key, packedValues)
731
+ findRepetitiveStrings(value[key], packedValues)
732
+ }
733
+ }
734
+ }
735
+ }
736
+ break
737
+ case 'function': console.log(value)
738
+ }
739
+ }
740
+
587
741
  extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, ByteArray,
588
742
  Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array, BigUint64Array, Int8Array, Int16Array, Int32Array, BigInt64Array,
589
743
  Float32Array, Float64Array]
@@ -655,7 +809,9 @@ function typedArrayEncoder(tag) {
655
809
  }
656
810
  function writeBuffer(buffer, makeRoom) {
657
811
  let length = buffer.byteLength
658
- if (length < 0x100) {
812
+ if (length < 0x18) {
813
+ target[position++] = 0x40 + length
814
+ } else if (length < 0x100) {
659
815
  target[position++] = 0x58
660
816
  target[position++] = length
661
817
  } else if (length < 0x10000) {
@@ -713,3 +869,4 @@ export const encode = defaultEncoder.encode
713
869
  export { FLOAT32_OPTIONS } from './decode.js'
714
870
  import { FLOAT32_OPTIONS } from './decode.js'
715
871
  export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
872
+ export const REUSE_BUFFER_MODE = 1000
package/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- export { Decoder, decode, addExtension, FLOAT32_OPTIONS } 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
- export as namespace msgpackr;
5
- export class DecoderStream {
5
+ export as namespace CBOR;
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 } from './decode.js'
2
+ export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './decode.js'
3
+ export { decodeIter, encodeIter } from './iterators.js'
3
4
  export const useRecords = false
4
5
  export const mapsAsObjects = true
5
-
package/iterators.js ADDED
@@ -0,0 +1,85 @@
1
+ import { Encoder } from './encode.js'
2
+ import { Decoder } from './decode.js'
3
+
4
+ /**
5
+ * Given an Iterable first argument, returns an Iterable where each value is encoded as a Buffer
6
+ * If the argument is only Async Iterable, the return value will be an Async Iterable.
7
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterator} objectIterator - iterable source, like a Readable object stream, an array, Set, or custom object
8
+ * @param {options} [options] - cbor-x Encoder options
9
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator>}
10
+ */
11
+ export function encodeIter (objectIterator, options = {}) {
12
+ if (!objectIterator || typeof objectIterator !== 'object') {
13
+ throw new Error('first argument must be an Iterable, Async Iterable, or a Promise for an Async Iterable')
14
+ } else if (typeof objectIterator[Symbol.iterator] === 'function') {
15
+ return encodeIterSync(objectIterator, options)
16
+ } else if (typeof objectIterator.then === 'function' || typeof objectIterator[Symbol.asyncIterator] === 'function') {
17
+ return encodeIterAsync(objectIterator, options)
18
+ } else {
19
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a Promise')
20
+ }
21
+ }
22
+
23
+ function * encodeIterSync (objectIterator, options) {
24
+ const encoder = new Encoder(options)
25
+ for (const value of objectIterator) {
26
+ yield encoder.encode(value)
27
+ }
28
+ }
29
+
30
+ async function * encodeIterAsync (objectIterator, options) {
31
+ const encoder = new Encoder(options)
32
+ for await (const value of objectIterator) {
33
+ yield encoder.encode(value)
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Given an Iterable/Iterator input which yields buffers, returns an IterableIterator which yields sync decoded objects
39
+ * Or, given an Async Iterable/Iterator which yields promises resolving in buffers, returns an AsyncIterableIterator.
40
+ * @param {Iterable|Iterator|AsyncIterable|AsyncIterableIterator} bufferIterator
41
+ * @param {object} [options] - Decoder options
42
+ * @returns {IterableIterator|Promise.<AsyncIterableIterator}
43
+ */
44
+ export function decodeIter (bufferIterator, options = {}) {
45
+ if (!bufferIterator || typeof bufferIterator !== 'object') {
46
+ throw new Error('first argument must be an Iterable, Async Iterable, Iterator, Async Iterator, or a promise')
47
+ }
48
+
49
+ const decoder = new Decoder(options)
50
+ let incomplete
51
+ const parser = (chunk) => {
52
+ let yields
53
+ // if there's incomplete data from previous chunk, concatinate and try again
54
+ if (incomplete) {
55
+ chunk = Buffer.concat([incomplete, chunk])
56
+ incomplete = undefined
57
+ }
58
+
59
+ try {
60
+ yields = decoder.decodeMultiple(chunk)
61
+ } catch (err) {
62
+ if (err.incomplete) {
63
+ incomplete = chunk.slice(err.lastPosition)
64
+ yields = err.values
65
+ } else {
66
+ throw err
67
+ }
68
+ }
69
+ return yields
70
+ }
71
+
72
+ if (typeof bufferIterator[Symbol.iterator] === 'function') {
73
+ return (function * iter () {
74
+ for (const value of bufferIterator) {
75
+ yield * parser(value)
76
+ }
77
+ })()
78
+ } else if (typeof bufferIterator[Symbol.asyncIterator] === 'function') {
79
+ return (async function * iter () {
80
+ for await (const value of bufferIterator) {
81
+ yield * parser(value)
82
+ }
83
+ })()
84
+ }
85
+ }
@@ -1,6 +1,7 @@
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
+ export { decodeIter, encodeIter } from './iterators.js'
4
5
  export const useRecords = false
5
6
  export const mapsAsObjects = true
6
7
  import { setExtractor } from './decode.js'
@@ -20,4 +21,4 @@ function tryRequire(moduleId) {
20
21
  else
21
22
  console.warn('For browser usage, directly use cbor-x/decode or cbor-x/encode modules. ' + error.message.split('\n')[0])
22
23
  }
23
- }
24
+ }