cbor-x 0.9.4 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/encode.js CHANGED
@@ -7,7 +7,7 @@ let extensions, extensionClasses
7
7
  const hasNodeBuffer = typeof Buffer !== 'undefined'
8
8
  const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array
9
9
  const ByteArray = hasNodeBuffer ? Buffer : Uint8Array
10
- const RECORD_STARTING_ID_PREFIX = 0x69 // tag 105/0x69
10
+ const RECORD_INLINE_ID = 0xdfff // temporary first-come first-serve tag // proposed tag: 0x7265 // 're'
11
11
  const MAX_STRUCTURES = 0x100
12
12
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000
13
13
  let serializationId = 1
@@ -15,6 +15,9 @@ let target
15
15
  let targetView
16
16
  let position = 0
17
17
  let safeEnd
18
+ let bundledStrings = null
19
+ const MAX_BUNDLE_SIZE = 0xf000
20
+ const hasNonLatin = /[\u0080-\uFFFF]/
18
21
  const RECORD_SYMBOL = Symbol('record-id')
19
22
  export class Encoder extends Decoder {
20
23
  constructor(options) {
@@ -27,7 +30,6 @@ export class Encoder extends Decoder {
27
30
  let structures
28
31
  let referenceMap
29
32
  options = options || {}
30
- let lastSharedStructuresLength = 0
31
33
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
32
34
  return target.utf8Write(string, position, maxBytes)
33
35
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -36,12 +38,14 @@ export class Encoder extends Decoder {
36
38
  } : false
37
39
 
38
40
  let encoder = this
39
- let maxSharedStructures = 64
41
+ let maxSharedStructures = options.maxSharedStructures || 128
40
42
  let isSequential = options.sequential
41
43
  if (isSequential) {
42
44
  maxSharedStructures = 0
43
45
  this.structures = []
44
46
  }
47
+ if (this.saveStructures)
48
+ this.saveShared = this.saveStructures
45
49
  let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues
46
50
  let sharedPackedObjectMap
47
51
  if (sharedValues) {
@@ -49,13 +53,29 @@ export class Encoder extends Decoder {
49
53
  for (let i = 0, l = sharedValues.length; i < l; i++) {
50
54
  sharedPackedObjectMap[sharedValues[i]] = i
51
55
  }
52
-
53
56
  }
54
57
  let recordIdsToRemove = []
55
58
  let transitionsCount = 0
56
59
  let serializationsSinceTransitionRebuild = 0
57
-
58
- this.encode = function(value, encodeOptions) {
60
+
61
+ this.mapEncode = function(value, encodeOptions) {
62
+ // Experimental support for premapping keys using _keyMap instad of keyMap - not optiimised yet)
63
+ if (this._keyMap && !this._mapped) {
64
+ //console.log('encoding ', value)
65
+ switch (value.constructor.name) {
66
+ case 'Array':
67
+ value = value.map(r => this.encodeKeys(r))
68
+ break
69
+ //case 'Map':
70
+ // value = this.encodeKeys(value)
71
+ // break
72
+ }
73
+ //this._mapped = true
74
+ }
75
+ return this.encode(value, encodeOptions)
76
+ }
77
+
78
+ this.encode = function(value, encodeOptions) {
59
79
  if (!target) {
60
80
  target = new ByteArrayAllocate(8192)
61
81
  targetView = new DataView(target.buffer, 0, 8192)
@@ -72,10 +92,25 @@ export class Encoder extends Decoder {
72
92
  position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
73
93
  start = position
74
94
  referenceMap = encoder.structuredClone ? new Map() : null
95
+ if (encoder.bundleStrings && typeof value !== 'string') {
96
+ bundledStrings = []
97
+ bundledStrings.size = Infinity // force a new bundle start on first string
98
+ } else
99
+ bundledStrings = null
100
+
75
101
  sharedStructures = encoder.structures
76
102
  if (sharedStructures) {
77
- if (sharedStructures.uninitialized)
78
- encoder.structures = sharedStructures = encoder.getStructures()
103
+ if (sharedStructures.uninitialized) {
104
+ let sharedData = encoder.getShared() || {}
105
+ encoder.structures = sharedStructures = sharedData.structures || []
106
+ encoder.sharedVersion = sharedData.version
107
+ let sharedValues = encoder.sharedValues = sharedData.packedValues
108
+ if (sharedValues) {
109
+ sharedPackedObjectMap = {}
110
+ for (let i = 0, l = sharedValues.length; i < l; i++)
111
+ sharedPackedObjectMap[sharedValues[i]] = i
112
+ }
113
+ }
79
114
  let sharedStructuresLength = sharedStructures.length
80
115
  if (sharedStructuresLength > maxSharedStructures && !isSequential)
81
116
  sharedStructuresLength = maxSharedStructures
@@ -84,6 +119,7 @@ export class Encoder extends Decoder {
84
119
  sharedStructures.transitions = Object.create(null)
85
120
  for (let i = 0; i < sharedStructuresLength; i++) {
86
121
  let keys = sharedStructures[i]
122
+ //console.log('shared struct keys:', keys)
87
123
  if (!keys)
88
124
  continue
89
125
  let nextTransition, transition = sharedStructures.transitions
@@ -97,7 +133,6 @@ export class Encoder extends Decoder {
97
133
  }
98
134
  transition[RECORD_SYMBOL] = i
99
135
  }
100
- lastSharedStructuresLength = sharedStructures.length
101
136
  }
102
137
  if (!isSequential)
103
138
  sharedStructures.nextId = sharedStructuresLength
@@ -130,9 +165,12 @@ export class Encoder extends Decoder {
130
165
  }
131
166
  try {
132
167
  encode(value)
168
+ if (bundledStrings) {
169
+ writeBundles(start, encode)
170
+ }
133
171
  encoder.offset = position // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
134
172
  if (referenceMap && referenceMap.idsToInsert) {
135
- position += referenceMap.idsToInsert.length * 8
173
+ position += referenceMap.idsToInsert.length * 2
136
174
  if (position > safeEnd)
137
175
  makeRoom(position)
138
176
  encoder.offset = position
@@ -140,12 +178,12 @@ export class Encoder extends Decoder {
140
178
  referenceMap = null
141
179
  return serialized
142
180
  }
143
- if (encodeOptions === REUSE_BUFFER_MODE) {
181
+ if (encodeOptions & REUSE_BUFFER_MODE) {
144
182
  target.start = start
145
183
  target.end = position
146
184
  return target
147
185
  }
148
- return target.subarray(start, position) // position can change if we call pack again in saveStructures, so we get the buffer now
186
+ return target.subarray(start, position) // position can change if we call pack again in saveShared, so we get the buffer now
149
187
  } finally {
150
188
  if (sharedStructures) {
151
189
  if (serializationsSinceTransitionRebuild < 10)
@@ -163,34 +201,27 @@ export class Encoder extends Decoder {
163
201
  }
164
202
  recordIdsToRemove = []
165
203
  }
166
- if (hasSharedUpdate && encoder.saveStructures) {
167
- if (encoder.structures.length > maxSharedStructures) {
168
- encoder.structures = encoder.structures.slice(0, maxSharedStructures)
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
- }
176
-
177
- if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
178
- // get updated structures and try again if the update failed
179
- encoder.structures = encoder.getStructures() || []
180
- return encoder.encode(value)
181
- }
182
- lastSharedStructuresLength = shared.length
183
- return returnBuffer
204
+ }
205
+ if (hasSharedUpdate && encoder.saveShared) {
206
+ if (encoder.structures.length > maxSharedStructures) {
207
+ encoder.structures = encoder.structures.slice(0, maxSharedStructures)
184
208
  }
209
+ // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
210
+ let returnBuffer = target.subarray(start, position)
211
+ if (encoder.updateSharedData() === false)
212
+ return encoder.encode(value) // re-encode if it fails
213
+ return returnBuffer
185
214
  }
215
+ if (encodeOptions & RESET_BUFFER_MODE)
216
+ position = start
186
217
  }
187
218
  }
188
219
  this.findCommonStringsToPack = () => {
189
220
  samplingPackedValues = new Map()
190
221
  if (!sharedPackedObjectMap)
191
222
  sharedPackedObjectMap = Object.create(null)
192
- return ({ threshold }) => {
193
- threshold = threshold || 4
223
+ return (options) => {
224
+ let threshold = options && options.threshold || 4
194
225
  let position = this.pack ? options.maxPrivatePackedValues || 16 : 0
195
226
  if (!sharedValues)
196
227
  sharedValues = this.sharedValues = []
@@ -201,6 +232,7 @@ export class Encoder extends Decoder {
201
232
  hasSharedUpdate = true
202
233
  }
203
234
  }
235
+ while (this.saveShared && this.updateSharedData() === false) {}
204
236
  samplingPackedValues = null
205
237
  }
206
238
  }
@@ -249,6 +281,33 @@ export class Encoder extends Decoder {
249
281
  }
250
282
  }
251
283
  let strLength = value.length
284
+ if (bundledStrings && strLength >= 4 && strLength < 0x400) {
285
+ if ((bundledStrings.size += strLength) > MAX_BUNDLE_SIZE) {
286
+ let extStart
287
+ let maxBytes = (bundledStrings[0] ? bundledStrings[0].length * 3 + bundledStrings[1].length : 0) + 10
288
+ if (position + maxBytes > safeEnd)
289
+ target = makeRoom(position + maxBytes)
290
+ target[position++] = 0xd9 // tag 16-bit
291
+ target[position++] = 0xdf // tag 0xdff9
292
+ target[position++] = 0xf9
293
+ // TODO: If we only have one bundle with any string data, only write one string bundle
294
+ target[position++] = bundledStrings.position ? 0x84 : 0x82 // array of 4 or 2 elements depending on if we write bundles
295
+ target[position++] = 0x1a // 32-bit unsigned int
296
+ extStart = position - start
297
+ position += 4 // reserve for writing bundle reference
298
+ if (bundledStrings.position) {
299
+ writeBundles(start, encode) // write the last bundles
300
+ }
301
+ bundledStrings = ['', ''] // create new ones
302
+ bundledStrings.size = 0
303
+ bundledStrings.position = extStart
304
+ }
305
+ let twoByte = hasNonLatin.test(value)
306
+ bundledStrings[twoByte ? 0 : 1] += value
307
+ target[position++] = twoByte ? 0xce : 0xcf
308
+ encode(strLength);
309
+ return
310
+ }
252
311
  let headerSize
253
312
  // first we estimate the header size, so we can write to the correct location
254
313
  if (strLength < 0x20) {
@@ -375,16 +434,16 @@ export class Encoder extends Decoder {
375
434
  if (referenceMap) {
376
435
  let referee = referenceMap.get(value)
377
436
  if (referee) {
378
- if (!referee.id) {
437
+ target[position++] = 0xd8
438
+ target[position++] = 29 // http://cbor.schmorp.de/value-sharing
439
+ target[position++] = 0x19 // 16-bit uint
440
+ if (!referee.references) {
379
441
  let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = [])
380
- referee.id = idsToInsert.push(referee)
442
+ referee.references = []
443
+ idsToInsert.push(referee)
381
444
  }
382
- target[position++] = 0xd9
383
- target[position++] = 40010 >> 8
384
- target[position++] = 40010 & 0xff
385
- target[position++] = 0x1a // uint32
386
- targetView.setUint32(position, referee.id)
387
- position += 4
445
+ referee.references.push(position - start)
446
+ position += 2 // TODO: also support 32-bit
388
447
  return
389
448
  } else
390
449
  referenceMap.set(value, { offset: position - start })
@@ -424,16 +483,23 @@ export class Encoder extends Decoder {
424
483
  targetView.setUint32(position, length)
425
484
  position += 4
426
485
  }
427
- for (let [ key, entryValue ] of value) {
428
- encode(key)
429
- encode(entryValue)
486
+ if (encoder.keyMap) {
487
+ for (let [ key, entryValue ] of value) {
488
+ encode(encoder.encodeKey(key))
489
+ encode(entryValue)
490
+ }
491
+ } else {
492
+ for (let [ key, entryValue ] of value) {
493
+ encode(key)
494
+ encode(entryValue)
495
+ }
430
496
  }
431
- } else {
497
+ } else {
432
498
  for (let i = 0, l = extensions.length; i < l; i++) {
433
499
  let extensionClass = extensionClasses[i]
434
500
  if (value instanceof extensionClass) {
435
501
  let extension = extensions[i]
436
- let tag = extension.tag
502
+ let tag = extension.tag || extension.getTag && extension.getTag(value)
437
503
  if (tag < 0x18) {
438
504
  target[position++] = 0xc0 | tag
439
505
  } else if (tag < 0x100) {
@@ -495,6 +561,7 @@ export class Encoder extends Decoder {
495
561
  const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
496
562
  // this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
497
563
  let keys = Object.keys(object)
564
+ let vals = Object.values(object)
498
565
  let length = keys.length
499
566
  if (length < 0x18) {
500
567
  target[position++] = 0xa0 | length
@@ -511,9 +578,16 @@ export class Encoder extends Decoder {
511
578
  position += 4
512
579
  }
513
580
  let key
514
- for (let i = 0; i < length; i++) {
515
- encode(key = keys[i])
516
- encode(object[key])
581
+ if (encoder.keyMap) {
582
+ for (let i = 0; i < length; i++) {
583
+ encode(encodeKey(keys[i]))
584
+ encode(vals[i])
585
+ }
586
+ } else {
587
+ for (let i = 0; i < length; i++) {
588
+ encode(keys[i])
589
+ encode(vals[i])
590
+ }
517
591
  }
518
592
  } :
519
593
  (object, safePrototype) => {
@@ -521,12 +595,18 @@ export class Encoder extends Decoder {
521
595
  let objectOffset = position - start
522
596
  position += 2
523
597
  let size = 0
524
- for (let key in object) {
525
- if (safePrototype || object.hasOwnProperty(key)) {
526
- encode(key)
598
+ if (encoder.keyMap) {
599
+ for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
600
+ encode(encoder.encodeKey(key))
527
601
  encode(object[key])
528
602
  size++
529
603
  }
604
+ } else {
605
+ for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
606
+ encode(key)
607
+ encode(object[key])
608
+ size++
609
+ }
530
610
  }
531
611
  target[objectOffset++ + start] = size >> 8
532
612
  target[objectOffset + start] = size & 0xff
@@ -574,11 +654,16 @@ export class Encoder extends Decoder {
574
654
  }*/
575
655
  (object) => {
576
656
  let keys = Object.keys(object)
657
+ let vals = Object.values(object)
658
+ if (this.keyMap) keys = keys.map(k => this.encodeKey(k))
577
659
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
578
660
  let newTransitions = 0
579
661
  let length = keys.length
662
+ //let parentRecordId
580
663
  for (let i = 0; i < length; i++) {
664
+ //if (!parentRecordId)
581
665
  let key = keys[i]
666
+ // parentRecordId = transition[RECORD_SYMBOL]
582
667
  nextTransition = transition[key]
583
668
  if (!nextTransition) {
584
669
  nextTransition = transition[key] = Object.create(null)
@@ -588,9 +673,9 @@ export class Encoder extends Decoder {
588
673
  }
589
674
  let recordId = transition[RECORD_SYMBOL]
590
675
  if (recordId !== undefined) {
591
- target[position++] = 0xd9 // tag two byte
592
- target[position++] = RECORD_STARTING_ID_PREFIX
593
- target[position++] = recordId
676
+ target[position++] = 0xd9
677
+ target[position++] = (recordId >> 8) | 0xe0
678
+ target[position++] = recordId & 0xff
594
679
  } else {
595
680
  recordId = structures.nextId++
596
681
  if (!recordId) {
@@ -603,13 +688,13 @@ export class Encoder extends Decoder {
603
688
  transition[RECORD_SYMBOL] = recordId
604
689
  structures[recordId] = keys
605
690
  if (sharedStructures && sharedStructures.length <= maxSharedStructures) {
606
- target[position++] = 0xd9 // tag two byte
607
- target[position++] = RECORD_STARTING_ID_PREFIX
608
- target[position++] = recordId // tag number
691
+ target[position++] = 0xd9
692
+ target[position++] = (recordId >> 8) | 0xe0
693
+ target[position++] = recordId & 0xff
609
694
  hasSharedUpdate = true
610
695
  } else {
611
- target[position++] = 0xd8
612
- target[position++] = RECORD_STARTING_ID_PREFIX
696
+ targetView.setUint32(position, 0xd9dfff00) // tag two byte, then record definition id
697
+ position += 3
613
698
  if (newTransitions)
614
699
  transitionsCount += serializationsSinceTransitionRebuild * newTransitions
615
700
  // record the removal of the id, we can maintain our shared structure
@@ -617,13 +702,9 @@ export class Encoder extends Decoder {
617
702
  recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined // we are cycling back through, and have to remove old ones
618
703
  recordIdsToRemove.push(transition)
619
704
  writeArrayHeader(length + 2)
705
+ encode(0xe000 + recordId)
620
706
  encode(keys)
621
- target[position++] = 0x19 // uint16
622
- target[position++] = RECORD_STARTING_ID_PREFIX
623
- target[position++] = recordId
624
- // now write the values
625
- for (let i =0; i < length; i++)
626
- encode(object[keys[i]])
707
+ for (let v of Object.values(object)) encode(v)
627
708
  return
628
709
  }
629
710
  }
@@ -632,8 +713,7 @@ export class Encoder extends Decoder {
632
713
  } else {
633
714
  writeArrayHeader(length)
634
715
  }
635
- for (let i =0; i < length; i++)
636
- encode(object[keys[i]])
716
+ for (let i =0; i < length; i++) encode(vals[i])
637
717
  }
638
718
  const makeRoom = (end) => {
639
719
  let newSize
@@ -663,11 +743,32 @@ export class Encoder extends Decoder {
663
743
  targetView = new DataView(target.buffer, target.byteOffset, target.byteLength)
664
744
  position = 0
665
745
  }
746
+ clearSharedData() {
747
+ if (this.structures)
748
+ this.structures = []
749
+ if (this.sharedValues)
750
+ this.sharedValues = undefined
751
+ }
752
+ updateSharedData() {
753
+ let lastVersion = this.sharedVersion || 0
754
+ this.sharedVersion = lastVersion + 1
755
+ let saveResults = this.saveShared(new SharedData(this.structures, this.sharedValues, this.sharedVersion),
756
+ existingShared => (existingShared && existingShared.version || 0) == lastVersion)
757
+ if (saveResults === false) {
758
+ // get updated structures and try again if the update failed
759
+ let sharedData = this.getShared() || {}
760
+ this.structures = sharedData.structures || []
761
+ this.sharedValues = sharedData.packedValues
762
+ this.sharedVersion = sharedData.version
763
+ }
764
+ return saveResults
765
+ }
666
766
  }
667
-
668
- function copyBinary(source, target, targetOffset, offset, endOffset) {
669
- while (offset < endOffset) {
670
- target[targetOffset++] = source[offset++]
767
+ class SharedData {
768
+ constructor(structures, values, version) {
769
+ this.structures = structures
770
+ this.packedValues = values
771
+ this.version = version
671
772
  }
672
773
  }
673
774
 
@@ -738,11 +839,11 @@ function findRepetitiveStrings(value, packedValues) {
738
839
  }
739
840
  }
740
841
 
741
- extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, ByteArray,
842
+ extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer, ByteArray,
742
843
  Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
743
844
  typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
744
845
  typeof BigInt64Array == 'undefined' ? function() {} : BigInt64Array,
745
- Float32Array, Float64Array]
846
+ Float32Array, Float64Array, SharedData]
746
847
 
747
848
  //Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/
748
849
  extensions = [{
@@ -777,6 +878,13 @@ extensions = [{
777
878
  encode(regex, encode) {
778
879
  encode([ 'RegExp', regex.source, regex.flags ])
779
880
  }
881
+ }, {
882
+ getTag(tag) {
883
+ return tag.tag
884
+ },
885
+ encode(tag, encode) {
886
+ encode(tag.value)
887
+ }
780
888
  }, {
781
889
  encode(arrayBuffer, encode, makeRoom) {
782
890
  writeBuffer(arrayBuffer, makeRoom)
@@ -795,7 +903,35 @@ extensions = [{
795
903
  typedArrayEncoder(78),
796
904
  typedArrayEncoder(79),
797
905
  typedArrayEncoder(81),
798
- typedArrayEncoder(82)]
906
+ typedArrayEncoder(82),
907
+ {
908
+ encode(sharedData, encode) { // write SharedData
909
+ let packedValues = sharedData.packedValues || []
910
+ let sharedStructures = sharedData.structures || []
911
+ if (packedValues.values.length > 0) {
912
+ target[position++] = 0xd8 // one-byte tag
913
+ target[position++] = 51 // tag 51 for packed shared structures https://www.potaroo.net/ietf/ids/draft-ietf-cbor-packed-03.txt
914
+ writeArrayHeader(4)
915
+ let valuesArray = packedValues.values
916
+ encode(valuesArray)
917
+ writeArrayHeader(0) // prefixes
918
+ writeArrayHeader(0) // suffixes
919
+ packedObjectMap = Object.create(sharedPackedObjectMap || null)
920
+ for (let i = 0, l = valuesArray.length; i < l; i++) {
921
+ packedObjectMap[valuesArray[i]] = i
922
+ }
923
+ }
924
+ if (sharedStructures) {
925
+ targetView.setUint32(position, 0xd9dffe00)
926
+ position += 3
927
+ let definitions = sharedStructures.slice(0)
928
+ definitions.unshift(0xe000)
929
+ definitions.push(new Tag(sharedData.version, 0x53687264))
930
+ encode(definitions)
931
+ } else
932
+ encode(new Tag(sharedData.version, 0x53687264))
933
+ }
934
+ }]
799
935
 
800
936
  function typedArrayEncoder(tag) {
801
937
  return {
@@ -835,27 +971,35 @@ function writeBuffer(buffer, makeRoom) {
835
971
  function insertIds(serialized, idsToInsert) {
836
972
  // insert the ids that need to be referenced for structured clones
837
973
  let nextId
838
- let distanceToMove = idsToInsert.length * 8
974
+ let distanceToMove = idsToInsert.length * 2
839
975
  let lastEnd = serialized.length - distanceToMove
840
976
  idsToInsert.sort((a, b) => a.offset > b.offset ? 1 : -1)
977
+ for (let id = 0; id < idsToInsert.length; id++) {
978
+ let referee = idsToInsert[id]
979
+ referee.id = id
980
+ for (let position of referee.references) {
981
+ serialized[position++] = id >> 8
982
+ serialized[position] = id & 0xff
983
+ }
984
+ }
841
985
  while (nextId = idsToInsert.pop()) {
842
986
  let offset = nextId.offset
843
- let id = nextId.id
844
987
  serialized.copyWithin(offset + distanceToMove, offset, lastEnd)
845
- distanceToMove -= 8
988
+ distanceToMove -= 2
846
989
  let position = offset + distanceToMove
847
- serialized[position++] = 0xd9
848
- serialized[position++] = 40009 >> 8
849
- serialized[position++] = 40009 & 0xff
850
- serialized[position++] = 0x1a // uint32
851
- serialized[position++] = id >> 24
852
- serialized[position++] = (id >> 16) & 0xff
853
- serialized[position++] = (id >> 8) & 0xff
854
- serialized[position++] = id & 0xff
990
+ serialized[position++] = 0xd8
991
+ serialized[position++] = 28 // http://cbor.schmorp.de/value-sharing
855
992
  lastEnd = offset
856
993
  }
857
994
  return serialized
858
995
  }
996
+ function writeBundles(start, encode) {
997
+ targetView.setUint32(bundledStrings.position + start, position - bundledStrings.position - start + 1) // the offset to bundle
998
+ let writeStrings = bundledStrings
999
+ bundledStrings = null
1000
+ encode(writeStrings[0])
1001
+ encode(writeStrings[1])
1002
+ }
859
1003
 
860
1004
  export function addExtension(extension) {
861
1005
  if (extension.Class) {
@@ -871,4 +1015,6 @@ export const encode = defaultEncoder.encode
871
1015
  export { FLOAT32_OPTIONS } from './decode.js'
872
1016
  import { FLOAT32_OPTIONS } from './decode.js'
873
1017
  export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
874
- export const REUSE_BUFFER_MODE = 1000
1018
+ export const REUSE_BUFFER_MODE = 512
1019
+ export const RESET_BUFFER_MODE = 1024
1020
+
package/index.js CHANGED
@@ -1,5 +1,3 @@
1
1
  export { Encoder, addExtension, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT, REUSE_BUFFER_MODE } from './encode.js'
2
2
  export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32, isNativeAccelerationEnabled } from './decode.js'
3
3
  export { decodeIter, encodeIter } from './iterators.js'
4
- export const useRecords = false
5
- export const mapsAsObjects = true
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "cbor-x",
3
3
  "author": "Kris Zyp",
4
- "version": "0.9.4",
5
- "description": "Ultra-fast CBOR implementation with tag extensions for records and structured cloning",
4
+ "version": "1.0.0",
5
+ "description": "Ultra-fast and conformant CBOR (RFC 8949) implementation with support for numerous tag extensions including records and structured cloning",
6
6
  "license": "MIT",
7
7
  "types": "./index.d.ts",
8
8
  "main": "./dist/node.cjs",
@@ -52,10 +52,17 @@
52
52
  }
53
53
  }
54
54
  },
55
+ "files": [
56
+ "/dist",
57
+ "*.md",
58
+ "/*.js",
59
+ "/*.ts"
60
+ ],
55
61
  "optionalDependencies": {
56
- "cbor-extract": "^0.3.2"
62
+ "cbor-extract": "^1.0.0"
57
63
  },
58
64
  "devDependencies": {
65
+ "@rollup/plugin-json": "^4.1.0",
59
66
  "@types/node": "latest",
60
67
  "async": "^3",
61
68
  "cbor": "^5",
@@ -64,7 +71,9 @@
64
71
  "esm": "^3.2.25",
65
72
  "mocha": "^8.1.3",
66
73
  "rollup": "^1.20.3",
67
- "@rollup/plugin-json": "^4.1.0",
68
74
  "rollup-plugin-babel-minify": "^9.0.0"
75
+ },
76
+ "dependencies": {
77
+ "esbuild": "^0.13.15"
69
78
  }
70
79
  }
@@ -1,22 +0,0 @@
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
- }