cbor-x 0.9.1 → 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
@@ -1,4 +1,3 @@
1
- import { write } from 'fs'
2
1
  import { Decoder, mult10, Tag, typedArrays, addExtension as decodeAddExtension } from './decode.js'
3
2
  let textEncoder
4
3
  try {
@@ -8,7 +7,7 @@ let extensions, extensionClasses
8
7
  const hasNodeBuffer = typeof Buffer !== 'undefined'
9
8
  const ByteArrayAllocate = hasNodeBuffer ? Buffer.allocUnsafeSlow : Uint8Array
10
9
  const ByteArray = hasNodeBuffer ? Buffer : Uint8Array
11
- 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'
12
11
  const MAX_STRUCTURES = 0x100
13
12
  const MAX_BUFFER_SIZE = hasNodeBuffer ? 0x100000000 : 0x7fd00000
14
13
  let serializationId = 1
@@ -16,6 +15,9 @@ let target
16
15
  let targetView
17
16
  let position = 0
18
17
  let safeEnd
18
+ let bundledStrings = null
19
+ const MAX_BUNDLE_SIZE = 0xf000
20
+ const hasNonLatin = /[\u0080-\uFFFF]/
19
21
  const RECORD_SYMBOL = Symbol('record-id')
20
22
  export class Encoder extends Decoder {
21
23
  constructor(options) {
@@ -28,7 +30,6 @@ export class Encoder extends Decoder {
28
30
  let structures
29
31
  let referenceMap
30
32
  options = options || {}
31
- let lastSharedStructuresLength = 0
32
33
  let encodeUtf8 = ByteArray.prototype.utf8Write ? function(string, position, maxBytes) {
33
34
  return target.utf8Write(string, position, maxBytes)
34
35
  } : (textEncoder && textEncoder.encodeInto) ?
@@ -37,12 +38,14 @@ export class Encoder extends Decoder {
37
38
  } : false
38
39
 
39
40
  let encoder = this
40
- let maxSharedStructures = 64
41
+ let maxSharedStructures = options.maxSharedStructures || 128
41
42
  let isSequential = options.sequential
42
43
  if (isSequential) {
43
44
  maxSharedStructures = 0
44
45
  this.structures = []
45
46
  }
47
+ if (this.saveStructures)
48
+ this.saveShared = this.saveStructures
46
49
  let samplingPackedValues, packedObjectMap, sharedValues = options.sharedValues
47
50
  let sharedPackedObjectMap
48
51
  if (sharedValues) {
@@ -50,13 +53,29 @@ export class Encoder extends Decoder {
50
53
  for (let i = 0, l = sharedValues.length; i < l; i++) {
51
54
  sharedPackedObjectMap[sharedValues[i]] = i
52
55
  }
53
-
54
56
  }
55
57
  let recordIdsToRemove = []
56
58
  let transitionsCount = 0
57
59
  let serializationsSinceTransitionRebuild = 0
58
-
59
- 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) {
60
79
  if (!target) {
61
80
  target = new ByteArrayAllocate(8192)
62
81
  targetView = new DataView(target.buffer, 0, 8192)
@@ -73,10 +92,25 @@ export class Encoder extends Decoder {
73
92
  position = (position + 7) & 0x7ffffff8 // Word align to make any future copying of this buffer faster
74
93
  start = position
75
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
+
76
101
  sharedStructures = encoder.structures
77
102
  if (sharedStructures) {
78
- if (sharedStructures.uninitialized)
79
- 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
+ }
80
114
  let sharedStructuresLength = sharedStructures.length
81
115
  if (sharedStructuresLength > maxSharedStructures && !isSequential)
82
116
  sharedStructuresLength = maxSharedStructures
@@ -85,6 +119,7 @@ export class Encoder extends Decoder {
85
119
  sharedStructures.transitions = Object.create(null)
86
120
  for (let i = 0; i < sharedStructuresLength; i++) {
87
121
  let keys = sharedStructures[i]
122
+ //console.log('shared struct keys:', keys)
88
123
  if (!keys)
89
124
  continue
90
125
  let nextTransition, transition = sharedStructures.transitions
@@ -98,7 +133,6 @@ export class Encoder extends Decoder {
98
133
  }
99
134
  transition[RECORD_SYMBOL] = i
100
135
  }
101
- lastSharedStructuresLength = sharedStructures.length
102
136
  }
103
137
  if (!isSequential)
104
138
  sharedStructures.nextId = sharedStructuresLength
@@ -131,9 +165,12 @@ export class Encoder extends Decoder {
131
165
  }
132
166
  try {
133
167
  encode(value)
168
+ if (bundledStrings) {
169
+ writeBundles(start, encode)
170
+ }
134
171
  encoder.offset = position // update the offset so next serialization doesn't write over our buffer, but can continue writing to same buffer sequentially
135
172
  if (referenceMap && referenceMap.idsToInsert) {
136
- position += referenceMap.idsToInsert.length * 8
173
+ position += referenceMap.idsToInsert.length * 2
137
174
  if (position > safeEnd)
138
175
  makeRoom(position)
139
176
  encoder.offset = position
@@ -141,12 +178,12 @@ export class Encoder extends Decoder {
141
178
  referenceMap = null
142
179
  return serialized
143
180
  }
144
- if (encodeOptions === REUSE_BUFFER_MODE) {
181
+ if (encodeOptions & REUSE_BUFFER_MODE) {
145
182
  target.start = start
146
183
  target.end = position
147
184
  return target
148
185
  }
149
- 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
150
187
  } finally {
151
188
  if (sharedStructures) {
152
189
  if (serializationsSinceTransitionRebuild < 10)
@@ -164,34 +201,27 @@ export class Encoder extends Decoder {
164
201
  }
165
202
  recordIdsToRemove = []
166
203
  }
167
- if (hasSharedUpdate && encoder.saveStructures) {
168
- if (encoder.structures.length > maxSharedStructures) {
169
- encoder.structures = encoder.structures.slice(0, maxSharedStructures)
170
- }
171
- // we can't rely on start/end with REUSE_BUFFER_MODE since they will (probably) change when we save
172
- let returnBuffer = target.subarray(start, position)
173
- let shared = encoder.structures || []
174
- if (sharedValues) {
175
- shared = shared.concat(sharedValues)
176
- }
177
-
178
- if (encoder.saveStructures(encoder.structures, lastSharedStructuresLength) === false) {
179
- // get updated structures and try again if the update failed
180
- encoder.structures = encoder.getStructures() || []
181
- return encoder.encode(value)
182
- }
183
- lastSharedStructuresLength = shared.length
184
- return returnBuffer
204
+ }
205
+ if (hasSharedUpdate && encoder.saveShared) {
206
+ if (encoder.structures.length > maxSharedStructures) {
207
+ encoder.structures = encoder.structures.slice(0, maxSharedStructures)
185
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
186
214
  }
215
+ if (encodeOptions & RESET_BUFFER_MODE)
216
+ position = start
187
217
  }
188
218
  }
189
219
  this.findCommonStringsToPack = () => {
190
220
  samplingPackedValues = new Map()
191
221
  if (!sharedPackedObjectMap)
192
222
  sharedPackedObjectMap = Object.create(null)
193
- return ({ threshold }) => {
194
- threshold = threshold || 4
223
+ return (options) => {
224
+ let threshold = options && options.threshold || 4
195
225
  let position = this.pack ? options.maxPrivatePackedValues || 16 : 0
196
226
  if (!sharedValues)
197
227
  sharedValues = this.sharedValues = []
@@ -202,6 +232,7 @@ export class Encoder extends Decoder {
202
232
  hasSharedUpdate = true
203
233
  }
204
234
  }
235
+ while (this.saveShared && this.updateSharedData() === false) {}
205
236
  samplingPackedValues = null
206
237
  }
207
238
  }
@@ -250,6 +281,33 @@ export class Encoder extends Decoder {
250
281
  }
251
282
  }
252
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
+ }
253
311
  let headerSize
254
312
  // first we estimate the header size, so we can write to the correct location
255
313
  if (strLength < 0x20) {
@@ -376,16 +434,16 @@ export class Encoder extends Decoder {
376
434
  if (referenceMap) {
377
435
  let referee = referenceMap.get(value)
378
436
  if (referee) {
379
- 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) {
380
441
  let idsToInsert = referenceMap.idsToInsert || (referenceMap.idsToInsert = [])
381
- referee.id = idsToInsert.push(referee)
442
+ referee.references = []
443
+ idsToInsert.push(referee)
382
444
  }
383
- target[position++] = 0xd9
384
- target[position++] = 40010 >> 8
385
- target[position++] = 40010 & 0xff
386
- target[position++] = 0x1a // uint32
387
- targetView.setUint32(position, referee.id)
388
- position += 4
445
+ referee.references.push(position - start)
446
+ position += 2 // TODO: also support 32-bit
389
447
  return
390
448
  } else
391
449
  referenceMap.set(value, { offset: position - start })
@@ -425,16 +483,23 @@ export class Encoder extends Decoder {
425
483
  targetView.setUint32(position, length)
426
484
  position += 4
427
485
  }
428
- for (let [ key, entryValue ] of value) {
429
- encode(key)
430
- 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
+ }
431
496
  }
432
- } else {
497
+ } else {
433
498
  for (let i = 0, l = extensions.length; i < l; i++) {
434
499
  let extensionClass = extensionClasses[i]
435
500
  if (value instanceof extensionClass) {
436
501
  let extension = extensions[i]
437
- let tag = extension.tag
502
+ let tag = extension.tag || extension.getTag && extension.getTag(value)
438
503
  if (tag < 0x18) {
439
504
  target[position++] = 0xc0 | tag
440
505
  } else if (tag < 0x100) {
@@ -496,6 +561,7 @@ export class Encoder extends Decoder {
496
561
  const writeObject = this.useRecords === false ? this.variableMapSize ? (object) => {
497
562
  // this method is slightly slower, but generates "preferred serialization" (optimally small for smaller objects)
498
563
  let keys = Object.keys(object)
564
+ let vals = Object.values(object)
499
565
  let length = keys.length
500
566
  if (length < 0x18) {
501
567
  target[position++] = 0xa0 | length
@@ -512,9 +578,16 @@ export class Encoder extends Decoder {
512
578
  position += 4
513
579
  }
514
580
  let key
515
- for (let i = 0; i < length; i++) {
516
- encode(key = keys[i])
517
- 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
+ }
518
591
  }
519
592
  } :
520
593
  (object, safePrototype) => {
@@ -522,12 +595,18 @@ export class Encoder extends Decoder {
522
595
  let objectOffset = position - start
523
596
  position += 2
524
597
  let size = 0
525
- for (let key in object) {
526
- if (safePrototype || object.hasOwnProperty(key)) {
527
- encode(key)
598
+ if (encoder.keyMap) {
599
+ for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
600
+ encode(encoder.encodeKey(key))
528
601
  encode(object[key])
529
602
  size++
530
603
  }
604
+ } else {
605
+ for (let key in object) if (safePrototype || object.hasOwnProperty(key)) {
606
+ encode(key)
607
+ encode(object[key])
608
+ size++
609
+ }
531
610
  }
532
611
  target[objectOffset++ + start] = size >> 8
533
612
  target[objectOffset + start] = size & 0xff
@@ -575,11 +654,16 @@ export class Encoder extends Decoder {
575
654
  }*/
576
655
  (object) => {
577
656
  let keys = Object.keys(object)
657
+ let vals = Object.values(object)
658
+ if (this.keyMap) keys = keys.map(k => this.encodeKey(k))
578
659
  let nextTransition, transition = structures.transitions || (structures.transitions = Object.create(null))
579
660
  let newTransitions = 0
580
661
  let length = keys.length
662
+ //let parentRecordId
581
663
  for (let i = 0; i < length; i++) {
664
+ //if (!parentRecordId)
582
665
  let key = keys[i]
666
+ // parentRecordId = transition[RECORD_SYMBOL]
583
667
  nextTransition = transition[key]
584
668
  if (!nextTransition) {
585
669
  nextTransition = transition[key] = Object.create(null)
@@ -589,9 +673,9 @@ export class Encoder extends Decoder {
589
673
  }
590
674
  let recordId = transition[RECORD_SYMBOL]
591
675
  if (recordId !== undefined) {
592
- target[position++] = 0xd9 // tag two byte
593
- target[position++] = RECORD_STARTING_ID_PREFIX
594
- target[position++] = recordId
676
+ target[position++] = 0xd9
677
+ target[position++] = (recordId >> 8) | 0xe0
678
+ target[position++] = recordId & 0xff
595
679
  } else {
596
680
  recordId = structures.nextId++
597
681
  if (!recordId) {
@@ -604,13 +688,13 @@ export class Encoder extends Decoder {
604
688
  transition[RECORD_SYMBOL] = recordId
605
689
  structures[recordId] = keys
606
690
  if (sharedStructures && sharedStructures.length <= maxSharedStructures) {
607
- target[position++] = 0xd9 // tag two byte
608
- target[position++] = RECORD_STARTING_ID_PREFIX
609
- target[position++] = recordId // tag number
691
+ target[position++] = 0xd9
692
+ target[position++] = (recordId >> 8) | 0xe0
693
+ target[position++] = recordId & 0xff
610
694
  hasSharedUpdate = true
611
695
  } else {
612
- target[position++] = 0xd8
613
- target[position++] = RECORD_STARTING_ID_PREFIX
696
+ targetView.setUint32(position, 0xd9dfff00) // tag two byte, then record definition id
697
+ position += 3
614
698
  if (newTransitions)
615
699
  transitionsCount += serializationsSinceTransitionRebuild * newTransitions
616
700
  // record the removal of the id, we can maintain our shared structure
@@ -618,13 +702,9 @@ export class Encoder extends Decoder {
618
702
  recordIdsToRemove.shift()[RECORD_SYMBOL] = undefined // we are cycling back through, and have to remove old ones
619
703
  recordIdsToRemove.push(transition)
620
704
  writeArrayHeader(length + 2)
705
+ encode(0xe000 + recordId)
621
706
  encode(keys)
622
- target[position++] = 0x19 // uint16
623
- target[position++] = RECORD_STARTING_ID_PREFIX
624
- target[position++] = recordId
625
- // now write the values
626
- for (let i =0; i < length; i++)
627
- encode(object[keys[i]])
707
+ for (let v of Object.values(object)) encode(v)
628
708
  return
629
709
  }
630
710
  }
@@ -633,8 +713,7 @@ export class Encoder extends Decoder {
633
713
  } else {
634
714
  writeArrayHeader(length)
635
715
  }
636
- for (let i =0; i < length; i++)
637
- encode(object[keys[i]])
716
+ for (let i =0; i < length; i++) encode(vals[i])
638
717
  }
639
718
  const makeRoom = (end) => {
640
719
  let newSize
@@ -643,7 +722,7 @@ export class Encoder extends Decoder {
643
722
  if ((end - start) > MAX_BUFFER_SIZE)
644
723
  throw new Error('Encoded buffer would be larger than maximum buffer size')
645
724
  newSize = Math.min(MAX_BUFFER_SIZE,
646
- Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x1000000) / 0x1000) * 0x1000)
725
+ Math.round(Math.max((end - start) * (end > 0x4000000 ? 1.25 : 2), 0x400000) / 0x1000) * 0x1000)
647
726
  } else // faster handling for smaller buffers
648
727
  newSize = ((Math.max((end - start) << 2, target.length - 1) >> 12) + 1) << 12
649
728
  let newBuffer = new ByteArrayAllocate(newSize)
@@ -664,11 +743,32 @@ export class Encoder extends Decoder {
664
743
  targetView = new DataView(target.buffer, target.byteOffset, target.byteLength)
665
744
  position = 0
666
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
+ }
667
766
  }
668
-
669
- function copyBinary(source, target, targetOffset, offset, endOffset) {
670
- while (offset < endOffset) {
671
- target[targetOffset++] = source[offset++]
767
+ class SharedData {
768
+ constructor(structures, values, version) {
769
+ this.structures = structures
770
+ this.packedValues = values
771
+ this.version = version
672
772
  }
673
773
  }
674
774
 
@@ -739,9 +839,11 @@ function findRepetitiveStrings(value, packedValues) {
739
839
  }
740
840
  }
741
841
 
742
- extensionClasses = [ Date, Set, Error, RegExp, ArrayBuffer, ByteArray,
743
- Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array, BigUint64Array, Int8Array, Int16Array, Int32Array, BigInt64Array,
744
- Float32Array, Float64Array]
842
+ extensionClasses = [ Date, Set, Error, RegExp, Tag, ArrayBuffer, ByteArray,
843
+ Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array,
844
+ typeof BigUint64Array == 'undefined' ? function() {} : BigUint64Array, Int8Array, Int16Array, Int32Array,
845
+ typeof BigInt64Array == 'undefined' ? function() {} : BigInt64Array,
846
+ Float32Array, Float64Array, SharedData]
745
847
 
746
848
  //Object.getPrototypeOf(Uint8Array.prototype).constructor /*TypedArray*/
747
849
  extensions = [{
@@ -776,6 +878,13 @@ extensions = [{
776
878
  encode(regex, encode) {
777
879
  encode([ 'RegExp', regex.source, regex.flags ])
778
880
  }
881
+ }, {
882
+ getTag(tag) {
883
+ return tag.tag
884
+ },
885
+ encode(tag, encode) {
886
+ encode(tag.value)
887
+ }
779
888
  }, {
780
889
  encode(arrayBuffer, encode, makeRoom) {
781
890
  writeBuffer(arrayBuffer, makeRoom)
@@ -794,7 +903,35 @@ extensions = [{
794
903
  typedArrayEncoder(78),
795
904
  typedArrayEncoder(79),
796
905
  typedArrayEncoder(81),
797
- 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
+ }]
798
935
 
799
936
  function typedArrayEncoder(tag) {
800
937
  return {
@@ -834,27 +971,35 @@ function writeBuffer(buffer, makeRoom) {
834
971
  function insertIds(serialized, idsToInsert) {
835
972
  // insert the ids that need to be referenced for structured clones
836
973
  let nextId
837
- let distanceToMove = idsToInsert.length * 8
974
+ let distanceToMove = idsToInsert.length * 2
838
975
  let lastEnd = serialized.length - distanceToMove
839
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
+ }
840
985
  while (nextId = idsToInsert.pop()) {
841
986
  let offset = nextId.offset
842
- let id = nextId.id
843
987
  serialized.copyWithin(offset + distanceToMove, offset, lastEnd)
844
- distanceToMove -= 8
988
+ distanceToMove -= 2
845
989
  let position = offset + distanceToMove
846
- serialized[position++] = 0xd9
847
- serialized[position++] = 40009 >> 8
848
- serialized[position++] = 40009 & 0xff
849
- serialized[position++] = 0x1a // uint32
850
- serialized[position++] = id >> 24
851
- serialized[position++] = (id >> 16) & 0xff
852
- serialized[position++] = (id >> 8) & 0xff
853
- serialized[position++] = id & 0xff
990
+ serialized[position++] = 0xd8
991
+ serialized[position++] = 28 // http://cbor.schmorp.de/value-sharing
854
992
  lastEnd = offset
855
993
  }
856
994
  return serialized
857
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
+ }
858
1003
 
859
1004
  export function addExtension(extension) {
860
1005
  if (extension.Class) {
@@ -870,4 +1015,6 @@ export const encode = defaultEncoder.encode
870
1015
  export { FLOAT32_OPTIONS } from './decode.js'
871
1016
  import { FLOAT32_OPTIONS } from './decode.js'
872
1017
  export const { NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } = FLOAT32_OPTIONS
873
- export const REUSE_BUFFER_MODE = 1000
1018
+ export const REUSE_BUFFER_MODE = 512
1019
+ export const RESET_BUFFER_MODE = 1024
1020
+
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { Decoder, decode, addExtension, FLOAT32_OPTIONS, clearSource, roundFloat32 } from './decode.js'
1
+ export { Decoder, decode, addExtension, FLOAT32_OPTIONS, clearSource, roundFloat32, isNativeAccelerationEnabled } from './decode.js'
2
2
  export { Encoder, encode } from './encode.js'
3
3
  import { Transform, Readable } from 'stream'
4
4
 
package/index.js CHANGED
@@ -1,5 +1,3 @@
1
- export { Encoder, addExtension, encode, NEVER, ALWAYS, DECIMAL_ROUND, DECIMAL_FIT } from './encode.js'
2
- export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32 } 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, isNativeAccelerationEnabled } from './decode.js'
3
3
  export { decodeIter, encodeIter } from './iterators.js'
4
- export const useRecords = false
5
- export const mapsAsObjects = true
package/node-index.js CHANGED
@@ -1,5 +1,5 @@
1
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'
2
+ export { Tag, Decoder, decodeMultiple, decode, FLOAT32_OPTIONS, clearSource, roundFloat32, isNativeAccelerationEnabled } 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
@@ -16,9 +16,7 @@ function tryRequire(moduleId) {
16
16
  let require = createRequire(import.meta.url)
17
17
  return require(moduleId)
18
18
  } catch (error) {
19
- if (typeof window == 'undefined')
20
- console.warn('Native extraction module not loaded, cbor-x will still run, but with decreased performance. ' + error.message.split('\n')[0])
21
- else
19
+ if (typeof window != 'undefined')
22
20
  console.warn('For browser usage, directly use cbor-x/decode or cbor-x/encode modules. ' + error.message.split('\n')[0])
23
21
  }
24
22
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "cbor-x",
3
3
  "author": "Kris Zyp",
4
- "version": "0.9.1",
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
- }