@atproto/lex-cbor 0.0.8 → 0.0.9

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/index.cjs CHANGED
@@ -1,23 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const lexData = require("@atproto/lex-data");
4
- const typeofs = [
5
- "string",
6
- "number",
7
- "bigint",
8
- "symbol"
9
- ];
10
4
  const objectTypeNames = [
11
- "Function",
12
- "Generator",
13
- "AsyncGenerator",
14
- "GeneratorFunction",
15
- "AsyncGeneratorFunction",
16
- "AsyncFunction",
17
- "Observable",
18
- "Array",
19
- "Buffer",
20
5
  "Object",
6
+ // for Object.create(null) and other non-plain objects
21
7
  "RegExp",
22
8
  "Date",
23
9
  "Error",
@@ -32,7 +18,6 @@ const objectTypeNames = [
32
18
  "URL",
33
19
  "HTMLElement",
34
20
  "Int8Array",
35
- "Uint8Array",
36
21
  "Uint8ClampedArray",
37
22
  "Int16Array",
38
23
  "Uint16Array",
@@ -54,7 +39,7 @@ function is(value) {
54
39
  return "boolean";
55
40
  }
56
41
  const typeOf = typeof value;
57
- if (typeofs.includes(typeOf)) {
42
+ if (typeOf === "string" || typeOf === "number" || typeOf === "bigint" || typeOf === "symbol") {
58
43
  return typeOf;
59
44
  }
60
45
  if (typeOf === "function") {
@@ -63,8 +48,11 @@ function is(value) {
63
48
  if (Array.isArray(value)) {
64
49
  return "Array";
65
50
  }
66
- if (isBuffer$1(value)) {
67
- return "Buffer";
51
+ if (value instanceof Uint8Array) {
52
+ return "Uint8Array";
53
+ }
54
+ if (value.constructor === Object) {
55
+ return "Object";
68
56
  }
69
57
  const objectType = getObjectType(value);
70
58
  if (objectType) {
@@ -72,9 +60,6 @@ function is(value) {
72
60
  }
73
61
  return "Object";
74
62
  }
75
- function isBuffer$1(value) {
76
- return value && value.constructor && value.constructor.isBuffer && value.constructor.isBuffer.call(null, value);
77
- }
78
63
  function getObjectType(value) {
79
64
  const objectTypeName = Object.prototype.toString.call(value).slice(8, -1);
80
65
  if (objectTypeNames.includes(objectTypeName)) {
@@ -105,6 +90,17 @@ class Type {
105
90
  compare(typ) {
106
91
  return this.major < typ.major ? -1 : this.major > typ.major ? 1 : 0;
107
92
  }
93
+ /**
94
+ * Check equality between two Type instances. Safe to use across different
95
+ * copies of the Type class (e.g., when bundlers duplicate the module).
96
+ * (major, name) uniquely identifies a Type; terminal is implied by these.
97
+ * @param {Type} a
98
+ * @param {Type} b
99
+ * @returns {boolean}
100
+ */
101
+ static equals(a, b) {
102
+ return a === b || a.major === b.major && a.name === b.name;
103
+ }
108
104
  }
109
105
  Type.uint = new Type(0, "uint", true);
110
106
  Type.negint = new Type(1, "negint", true);
@@ -141,49 +137,25 @@ const useBuffer = globalThis.process && // @ts-ignore
141
137
  !globalThis.process.browser && // @ts-ignore
142
138
  globalThis.Buffer && // @ts-ignore
143
139
  typeof globalThis.Buffer.isBuffer === "function";
144
- const textDecoder = new TextDecoder();
145
140
  const textEncoder = new TextEncoder();
146
- function isBuffer(buf2) {
147
- return useBuffer && globalThis.Buffer.isBuffer(buf2);
141
+ function isBuffer(buf) {
142
+ return useBuffer && globalThis.Buffer.isBuffer(buf);
148
143
  }
149
- function asU8A(buf2) {
150
- if (!(buf2 instanceof Uint8Array)) {
151
- return Uint8Array.from(buf2);
144
+ function asU8A(buf) {
145
+ if (!(buf instanceof Uint8Array)) {
146
+ return Uint8Array.from(buf);
152
147
  }
153
- return isBuffer(buf2) ? new Uint8Array(buf2.buffer, buf2.byteOffset, buf2.byteLength) : buf2;
148
+ return isBuffer(buf) ? new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength) : buf;
154
149
  }
155
- const toString = useBuffer ? (
156
- // eslint-disable-line operator-linebreak
157
- /**
158
- * @param {Uint8Array} bytes
159
- * @param {number} start
160
- * @param {number} end
161
- */
162
- (bytes, start, end) => {
163
- return end - start > 64 ? (
164
- // eslint-disable-line operator-linebreak
165
- // @ts-ignore
166
- globalThis.Buffer.from(bytes.subarray(start, end)).toString("utf8")
167
- ) : utf8Slice(bytes, start, end);
168
- }
169
- ) : (
170
- // eslint-disable-line operator-linebreak
171
- /**
172
- * @param {Uint8Array} bytes
173
- * @param {number} start
174
- * @param {number} end
175
- */
176
- (bytes, start, end) => {
177
- return end - start > 64 ? textDecoder.decode(bytes.subarray(start, end)) : utf8Slice(bytes, start, end);
178
- }
179
- );
150
+ const FROM_STRING_THRESHOLD_BUFFER = 24;
151
+ const FROM_STRING_THRESHOLD_TEXTENCODER = 200;
180
152
  const fromString = useBuffer ? (
181
153
  // eslint-disable-line operator-linebreak
182
154
  /**
183
155
  * @param {string} string
184
156
  */
185
157
  (string) => {
186
- return string.length > 64 ? (
158
+ return string.length >= FROM_STRING_THRESHOLD_BUFFER ? (
187
159
  // eslint-disable-line operator-linebreak
188
160
  // @ts-ignore
189
161
  globalThis.Buffer.from(string)
@@ -195,7 +167,7 @@ const fromString = useBuffer ? (
195
167
  * @param {string} string
196
168
  */
197
169
  (string) => {
198
- return string.length > 64 ? textEncoder.encode(string) : utf8ToBytes(string);
170
+ return string.length >= FROM_STRING_THRESHOLD_TEXTENCODER ? textEncoder.encode(string) : utf8ToBytes(string);
199
171
  }
200
172
  );
201
173
  const fromArray = (arr) => {
@@ -208,6 +180,7 @@ const slice = useBuffer ? (
208
180
  * @param {number} start
209
181
  * @param {number} end
210
182
  */
183
+ // Buffer.slice() returns a view, not a copy, so we need special handling
211
184
  (bytes, start, end) => {
212
185
  if (isBuffer(bytes)) {
213
186
  return new Uint8Array(bytes.subarray(start, end));
@@ -308,6 +281,9 @@ function utf8ToBytes(str) {
308
281
  out[p++] = c >> 6 & 63 | 128;
309
282
  out[p++] = c & 63 | 128;
310
283
  } else {
284
+ if (c >= 55296 && c <= 57343) {
285
+ c = 65533;
286
+ }
311
287
  out[p++] = c >> 12 | 224;
312
288
  out[p++] = c >> 6 & 63 | 128;
313
289
  out[p++] = c & 63 | 128;
@@ -315,80 +291,6 @@ function utf8ToBytes(str) {
315
291
  }
316
292
  return out;
317
293
  }
318
- function utf8Slice(buf2, offset, end) {
319
- const res = [];
320
- while (offset < end) {
321
- const firstByte = buf2[offset];
322
- let codePoint = null;
323
- let bytesPerSequence = firstByte > 239 ? 4 : firstByte > 223 ? 3 : firstByte > 191 ? 2 : 1;
324
- if (offset + bytesPerSequence <= end) {
325
- let secondByte, thirdByte, fourthByte, tempCodePoint;
326
- switch (bytesPerSequence) {
327
- case 1:
328
- if (firstByte < 128) {
329
- codePoint = firstByte;
330
- }
331
- break;
332
- case 2:
333
- secondByte = buf2[offset + 1];
334
- if ((secondByte & 192) === 128) {
335
- tempCodePoint = (firstByte & 31) << 6 | secondByte & 63;
336
- if (tempCodePoint > 127) {
337
- codePoint = tempCodePoint;
338
- }
339
- }
340
- break;
341
- case 3:
342
- secondByte = buf2[offset + 1];
343
- thirdByte = buf2[offset + 2];
344
- if ((secondByte & 192) === 128 && (thirdByte & 192) === 128) {
345
- tempCodePoint = (firstByte & 15) << 12 | (secondByte & 63) << 6 | thirdByte & 63;
346
- if (tempCodePoint > 2047 && (tempCodePoint < 55296 || tempCodePoint > 57343)) {
347
- codePoint = tempCodePoint;
348
- }
349
- }
350
- break;
351
- case 4:
352
- secondByte = buf2[offset + 1];
353
- thirdByte = buf2[offset + 2];
354
- fourthByte = buf2[offset + 3];
355
- if ((secondByte & 192) === 128 && (thirdByte & 192) === 128 && (fourthByte & 192) === 128) {
356
- tempCodePoint = (firstByte & 15) << 18 | (secondByte & 63) << 12 | (thirdByte & 63) << 6 | fourthByte & 63;
357
- if (tempCodePoint > 65535 && tempCodePoint < 1114112) {
358
- codePoint = tempCodePoint;
359
- }
360
- }
361
- }
362
- }
363
- if (codePoint === null) {
364
- codePoint = 65533;
365
- bytesPerSequence = 1;
366
- } else if (codePoint > 65535) {
367
- codePoint -= 65536;
368
- res.push(codePoint >>> 10 & 1023 | 55296);
369
- codePoint = 56320 | codePoint & 1023;
370
- }
371
- res.push(codePoint);
372
- offset += bytesPerSequence;
373
- }
374
- return decodeCodePointsArray(res);
375
- }
376
- const MAX_ARGUMENTS_LENGTH = 4096;
377
- function decodeCodePointsArray(codePoints) {
378
- const len = codePoints.length;
379
- if (len <= MAX_ARGUMENTS_LENGTH) {
380
- return String.fromCharCode.apply(String, codePoints);
381
- }
382
- let res = "";
383
- let i = 0;
384
- while (i < len) {
385
- res += String.fromCharCode.apply(
386
- String,
387
- codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
388
- );
389
- }
390
- return res;
391
- }
392
294
  const defaultChunkSize = 256;
393
295
  class Bl {
394
296
  /**
@@ -468,6 +370,40 @@ class Bl {
468
370
  return byts;
469
371
  }
470
372
  }
373
+ class U8Bl {
374
+ /**
375
+ * @param {Uint8Array} dest
376
+ */
377
+ constructor(dest) {
378
+ this.dest = dest;
379
+ this.cursor = 0;
380
+ this.chunks = [dest];
381
+ }
382
+ reset() {
383
+ this.cursor = 0;
384
+ }
385
+ /**
386
+ * @param {Uint8Array|number[]} bytes
387
+ */
388
+ push(bytes) {
389
+ if (this.cursor + bytes.length > this.dest.length) {
390
+ throw new Error("write out of bounds, destination buffer is too small");
391
+ }
392
+ this.dest.set(bytes, this.cursor);
393
+ this.cursor += bytes.length;
394
+ }
395
+ /**
396
+ * @param {boolean} [reset]
397
+ * @returns {Uint8Array}
398
+ */
399
+ toBytes(reset = false) {
400
+ const byts = this.dest.subarray(0, this.cursor);
401
+ if (reset) {
402
+ this.reset();
403
+ }
404
+ return byts;
405
+ }
406
+ }
471
407
  const decodeErrPrefix = "CBOR decode error:";
472
408
  const encodeErrPrefix = "CBOR encode error:";
473
409
  function assertEnoughData(data, pos, need) {
@@ -528,22 +464,22 @@ function decodeUint32(data, pos, _minor, options) {
528
464
  function decodeUint64(data, pos, _minor, options) {
529
465
  return new Token(Type.uint, readUint64(data, pos + 1, options), 9);
530
466
  }
531
- function encodeUint(buf2, token) {
532
- return encodeUintValue(buf2, 0, token.value);
467
+ function encodeUint(writer, token) {
468
+ return encodeUintValue(writer, 0, token.value);
533
469
  }
534
- function encodeUintValue(buf2, major, uint) {
470
+ function encodeUintValue(writer, major, uint) {
535
471
  if (uint < uintBoundaries[0]) {
536
472
  const nuint = Number(uint);
537
- buf2.push([major | nuint]);
473
+ writer.push([major | nuint]);
538
474
  } else if (uint < uintBoundaries[1]) {
539
475
  const nuint = Number(uint);
540
- buf2.push([major | 24, nuint]);
476
+ writer.push([major | 24, nuint]);
541
477
  } else if (uint < uintBoundaries[2]) {
542
478
  const nuint = Number(uint);
543
- buf2.push([major | 25, nuint >>> 8, nuint & 255]);
479
+ writer.push([major | 25, nuint >>> 8, nuint & 255]);
544
480
  } else if (uint < uintBoundaries[3]) {
545
481
  const nuint = Number(uint);
546
- buf2.push([major | 26, nuint >>> 24 & 255, nuint >>> 16 & 255, nuint >>> 8 & 255, nuint & 255]);
482
+ writer.push([major | 26, nuint >>> 24 & 255, nuint >>> 16 & 255, nuint >>> 8 & 255, nuint & 255]);
547
483
  } else {
548
484
  const buint = BigInt(uint);
549
485
  if (buint < uintBoundaries[4]) {
@@ -564,7 +500,7 @@ function encodeUintValue(buf2, major, uint) {
564
500
  set[2] = hi & 255;
565
501
  hi = hi >> 8;
566
502
  set[1] = hi & 255;
567
- buf2.push(set);
503
+ writer.push(set);
568
504
  } else {
569
505
  throw new Error(`${decodeErrPrefix} encountered BigInt larger than allowable range`);
570
506
  }
@@ -603,8 +539,8 @@ function decodeNegint16(data, pos, _minor, options) {
603
539
  function decodeNegint32(data, pos, _minor, options) {
604
540
  return new Token(Type.negint, -1 - readUint32(data, pos + 1, options), 5);
605
541
  }
606
- const neg1b = BigInt(-1);
607
- const pos1b = BigInt(1);
542
+ const neg1b$1 = BigInt(-1);
543
+ const pos1b$1 = BigInt(1);
608
544
  function decodeNegint64(data, pos, _minor, options) {
609
545
  const int = readUint64(data, pos + 1, options);
610
546
  if (typeof int !== "bigint") {
@@ -616,16 +552,16 @@ function decodeNegint64(data, pos, _minor, options) {
616
552
  if (options.allowBigInt !== true) {
617
553
  throw new Error(`${decodeErrPrefix} integers outside of the safe integer range are not supported`);
618
554
  }
619
- return new Token(Type.negint, neg1b - BigInt(int), 9);
555
+ return new Token(Type.negint, neg1b$1 - BigInt(int), 9);
620
556
  }
621
- function encodeNegint(buf2, token) {
557
+ function encodeNegint(writer, token) {
622
558
  const negint = token.value;
623
- const unsigned = typeof negint === "bigint" ? negint * neg1b - pos1b : negint * -1 - 1;
624
- encodeUintValue(buf2, token.type.majorEncoded, unsigned);
559
+ const unsigned = typeof negint === "bigint" ? negint * neg1b$1 - pos1b$1 : negint * -1 - 1;
560
+ encodeUintValue(writer, token.type.majorEncoded, unsigned);
625
561
  }
626
562
  encodeNegint.encodedSize = function encodedSize3(token) {
627
563
  const negint = token.value;
628
- const unsigned = typeof negint === "bigint" ? negint * neg1b - pos1b : negint * -1 - 1;
564
+ const unsigned = typeof negint === "bigint" ? negint * neg1b$1 - pos1b$1 : negint * -1 - 1;
629
565
  if (unsigned < uintBoundaries[0]) {
630
566
  return 1;
631
567
  }
@@ -648,8 +584,8 @@ encodeNegint.compareTokens = function compareTokens2(tok1, tok2) {
648
584
  };
649
585
  function toToken$3(data, pos, prefix, length) {
650
586
  assertEnoughData(data, pos, prefix + length);
651
- const buf2 = slice(data, pos + prefix, pos + prefix + length);
652
- return new Token(Type.bytes, buf2, prefix + length);
587
+ const buf = data.slice(pos + prefix, pos + prefix + length);
588
+ return new Token(Type.bytes, buf, prefix + length);
653
589
  }
654
590
  function decodeBytesCompact(data, pos, minor, _options) {
655
591
  return toToken$3(data, pos, 1, minor);
@@ -672,14 +608,14 @@ function decodeBytes64(data, pos, _minor, options) {
672
608
  }
673
609
  function tokenBytes(token) {
674
610
  if (token.encodedBytes === void 0) {
675
- token.encodedBytes = token.type === Type.string ? fromString(token.value) : token.value;
611
+ token.encodedBytes = Type.equals(token.type, Type.string) ? fromString(token.value) : token.value;
676
612
  }
677
613
  return token.encodedBytes;
678
614
  }
679
- function encodeBytes(buf2, token) {
615
+ function encodeBytes(writer, token) {
680
616
  const bytes = tokenBytes(token);
681
- encodeUintValue(buf2, token.type.majorEncoded, bytes.length);
682
- buf2.push(bytes);
617
+ encodeUintValue(writer, token.type.majorEncoded, bytes.length);
618
+ writer.push(bytes);
683
619
  }
684
620
  encodeBytes.encodedSize = function encodedSize4(token) {
685
621
  const bytes = tokenBytes(token);
@@ -691,12 +627,29 @@ encodeBytes.compareTokens = function compareTokens3(tok1, tok2) {
691
627
  function compareBytes(b1, b2) {
692
628
  return b1.length < b2.length ? -1 : b1.length > b2.length ? 1 : compare(b1, b2);
693
629
  }
630
+ const textDecoder = new TextDecoder();
631
+ const ASCII_THRESHOLD = 32;
632
+ function toStr(bytes, start, end) {
633
+ const len = end - start;
634
+ if (len < ASCII_THRESHOLD) {
635
+ let str = "";
636
+ for (let i = start; i < end; i++) {
637
+ const c = bytes[i];
638
+ if (c & 128) {
639
+ return textDecoder.decode(bytes.subarray(start, end));
640
+ }
641
+ str += String.fromCharCode(c);
642
+ }
643
+ return str;
644
+ }
645
+ return textDecoder.decode(bytes.subarray(start, end));
646
+ }
694
647
  function toToken$2(data, pos, prefix, length, options) {
695
648
  const totLength = prefix + length;
696
649
  assertEnoughData(data, pos, totLength);
697
- const tok = new Token(Type.string, toString(data, pos + prefix, pos + totLength), totLength);
650
+ const tok = new Token(Type.string, toStr(data, pos + prefix, pos + totLength), totLength);
698
651
  if (options.retainStringBytes === true) {
699
- tok.byteValue = slice(data, pos + prefix, pos + totLength);
652
+ tok.byteValue = data.slice(pos + prefix, pos + totLength);
700
653
  }
701
654
  return tok;
702
655
  }
@@ -748,8 +701,8 @@ function decodeArrayIndefinite(data, pos, _minor, options) {
748
701
  }
749
702
  return toToken$1(data, pos, 1, Infinity);
750
703
  }
751
- function encodeArray(buf2, token) {
752
- encodeUintValue(buf2, Type.array.majorEncoded, token.value);
704
+ function encodeArray(writer, token) {
705
+ encodeUintValue(writer, Type.array.majorEncoded, token.value);
753
706
  }
754
707
  encodeArray.compareTokens = encodeUint.compareTokens;
755
708
  encodeArray.encodedSize = function encodedSize5(token) {
@@ -783,8 +736,8 @@ function decodeMapIndefinite(data, pos, _minor, options) {
783
736
  }
784
737
  return toToken(data, pos, 1, Infinity);
785
738
  }
786
- function encodeMap(buf2, token) {
787
- encodeUintValue(buf2, Type.map.majorEncoded, token.value);
739
+ function encodeMap(writer, token) {
740
+ encodeUintValue(writer, Type.map.majorEncoded, token.value);
788
741
  }
789
742
  encodeMap.compareTokens = encodeUint.compareTokens;
790
743
  encodeMap.encodedSize = function encodedSize6(token) {
@@ -805,8 +758,8 @@ function decodeTag32(data, pos, _minor, options) {
805
758
  function decodeTag64(data, pos, _minor, options) {
806
759
  return new Token(Type.tag, readUint64(data, pos + 1, options), 9);
807
760
  }
808
- function encodeTag(buf2, token) {
809
- encodeUintValue(buf2, Type.tag.majorEncoded, token.value);
761
+ function encodeTag(writer, token) {
762
+ encodeUintValue(writer, Type.tag.majorEncoded, token.value);
810
763
  }
811
764
  encodeTag.compareTokens = encodeUint.compareTokens;
812
765
  encodeTag.encodedSize = function encodedSize7(token) {
@@ -850,16 +803,16 @@ function decodeFloat32(data, pos, _minor, options) {
850
803
  function decodeFloat64(data, pos, _minor, options) {
851
804
  return createToken(readFloat64(data, pos + 1), 9, options);
852
805
  }
853
- function encodeFloat(buf2, token, options) {
806
+ function encodeFloat(writer, token, options) {
854
807
  const float = token.value;
855
808
  if (float === false) {
856
- buf2.push([Type.float.majorEncoded | MINOR_FALSE]);
809
+ writer.push([Type.float.majorEncoded | MINOR_FALSE]);
857
810
  } else if (float === true) {
858
- buf2.push([Type.float.majorEncoded | MINOR_TRUE]);
811
+ writer.push([Type.float.majorEncoded | MINOR_TRUE]);
859
812
  } else if (float === null) {
860
- buf2.push([Type.float.majorEncoded | MINOR_NULL]);
813
+ writer.push([Type.float.majorEncoded | MINOR_NULL]);
861
814
  } else if (float === void 0) {
862
- buf2.push([Type.float.majorEncoded | MINOR_UNDEFINED]);
815
+ writer.push([Type.float.majorEncoded | MINOR_UNDEFINED]);
863
816
  } else {
864
817
  let decoded;
865
818
  let success = false;
@@ -868,14 +821,14 @@ function encodeFloat(buf2, token, options) {
868
821
  decoded = readFloat16(ui8a, 1);
869
822
  if (float === decoded || Number.isNaN(float)) {
870
823
  ui8a[0] = 249;
871
- buf2.push(ui8a.slice(0, 3));
824
+ writer.push(ui8a.slice(0, 3));
872
825
  success = true;
873
826
  } else {
874
827
  encodeFloat32(float);
875
828
  decoded = readFloat32(ui8a, 1);
876
829
  if (float === decoded) {
877
830
  ui8a[0] = 250;
878
- buf2.push(ui8a.slice(0, 5));
831
+ writer.push(ui8a.slice(0, 5));
879
832
  success = true;
880
833
  }
881
834
  }
@@ -884,7 +837,7 @@ function encodeFloat(buf2, token, options) {
884
837
  encodeFloat64(float);
885
838
  decoded = readFloat64(ui8a, 1);
886
839
  ui8a[0] = 251;
887
- buf2.push(ui8a.slice(0, 9));
840
+ writer.push(ui8a.slice(0, 9));
888
841
  }
889
842
  }
890
843
  }
@@ -1158,7 +1111,7 @@ function makeCborEncoders() {
1158
1111
  return encoders;
1159
1112
  }
1160
1113
  const cborEncoders = makeCborEncoders();
1161
- const buf = new Bl();
1114
+ const defaultWriter = new Bl();
1162
1115
  class Ref {
1163
1116
  /**
1164
1117
  * @param {object|any[]} obj
@@ -1337,27 +1290,38 @@ const typeEncoders = {
1337
1290
  Object(obj, typ, options, refStack) {
1338
1291
  const isMap = typ !== "Object";
1339
1292
  const keys = isMap ? obj.keys() : Object.keys(obj);
1340
- const length = isMap ? obj.size : keys.length;
1341
- if (!length) {
1293
+ const maxLength = isMap ? obj.size : keys.length;
1294
+ let entries;
1295
+ if (maxLength) {
1296
+ entries = new Array(maxLength);
1297
+ refStack = Ref.createCheck(refStack, obj);
1298
+ const skipUndefined = !isMap && options.ignoreUndefinedProperties;
1299
+ let i = 0;
1300
+ for (const key of keys) {
1301
+ const value = isMap ? obj.get(key) : obj[key];
1302
+ if (skipUndefined && value === void 0) {
1303
+ continue;
1304
+ }
1305
+ entries[i++] = [
1306
+ objectToTokens(key, options, refStack),
1307
+ objectToTokens(value, options, refStack)
1308
+ ];
1309
+ }
1310
+ if (i < maxLength) {
1311
+ entries.length = i;
1312
+ }
1313
+ }
1314
+ if (!(entries == null ? void 0 : entries.length)) {
1342
1315
  if (options.addBreakTokens === true) {
1343
1316
  return [simpleTokens.emptyMap, new Token(Type.break)];
1344
1317
  }
1345
1318
  return simpleTokens.emptyMap;
1346
1319
  }
1347
- refStack = Ref.createCheck(refStack, obj);
1348
- const entries = [];
1349
- let i = 0;
1350
- for (const key of keys) {
1351
- entries[i++] = [
1352
- objectToTokens(key, options, refStack),
1353
- objectToTokens(isMap ? obj.get(key) : obj[key], options, refStack)
1354
- ];
1355
- }
1356
1320
  sortMapEntries(entries, options);
1357
1321
  if (options.addBreakTokens) {
1358
- return [new Token(Type.map, length), entries, new Token(Type.break)];
1322
+ return [new Token(Type.map, entries.length), entries, new Token(Type.break)];
1359
1323
  }
1360
- return [new Token(Type.map, length), entries];
1324
+ return [new Token(Type.map, entries.length), entries];
1361
1325
  }
1362
1326
  };
1363
1327
  typeEncoders.Map = typeEncoders.Object;
@@ -1399,39 +1363,140 @@ function mapSorter(e1, e2) {
1399
1363
  }
1400
1364
  return tcmp;
1401
1365
  }
1402
- function tokensToEncoded(buf2, tokens, encoders, options) {
1366
+ function tokensToEncoded(writer, tokens, encoders, options) {
1403
1367
  if (Array.isArray(tokens)) {
1404
1368
  for (const token of tokens) {
1405
- tokensToEncoded(buf2, token, encoders, options);
1369
+ tokensToEncoded(writer, token, encoders, options);
1406
1370
  }
1407
1371
  } else {
1408
- encoders[tokens.type.major](buf2, tokens, options);
1372
+ encoders[tokens.type.major](writer, tokens, options);
1373
+ }
1374
+ }
1375
+ const MAJOR_UINT = Type.uint.majorEncoded;
1376
+ const MAJOR_NEGINT = Type.negint.majorEncoded;
1377
+ const MAJOR_BYTES = Type.bytes.majorEncoded;
1378
+ const MAJOR_STRING = Type.string.majorEncoded;
1379
+ const MAJOR_ARRAY = Type.array.majorEncoded;
1380
+ const SIMPLE_FALSE = Type.float.majorEncoded | MINOR_FALSE;
1381
+ const SIMPLE_TRUE = Type.float.majorEncoded | MINOR_TRUE;
1382
+ const SIMPLE_NULL = Type.float.majorEncoded | MINOR_NULL;
1383
+ const SIMPLE_UNDEFINED = Type.float.majorEncoded | MINOR_UNDEFINED;
1384
+ const neg1b = BigInt(-1);
1385
+ const pos1b = BigInt(1);
1386
+ function canDirectEncode(options) {
1387
+ return options.addBreakTokens !== true;
1388
+ }
1389
+ function directEncode(writer, data, options, refStack) {
1390
+ const typ = is(data);
1391
+ const customEncoder = options.typeEncoders && options.typeEncoders[typ];
1392
+ if (customEncoder) {
1393
+ const tokens = customEncoder(data, typ, options, refStack);
1394
+ if (tokens != null) {
1395
+ tokensToEncoded(writer, tokens, cborEncoders, options);
1396
+ return;
1397
+ }
1398
+ }
1399
+ switch (typ) {
1400
+ case "null":
1401
+ writer.push([SIMPLE_NULL]);
1402
+ return;
1403
+ case "undefined":
1404
+ writer.push([SIMPLE_UNDEFINED]);
1405
+ return;
1406
+ case "boolean":
1407
+ writer.push([data ? SIMPLE_TRUE : SIMPLE_FALSE]);
1408
+ return;
1409
+ case "number":
1410
+ if (!Number.isInteger(data) || !Number.isSafeInteger(data)) {
1411
+ encodeFloat(writer, new Token(Type.float, data), options);
1412
+ } else if (data >= 0) {
1413
+ encodeUintValue(writer, MAJOR_UINT, data);
1414
+ } else {
1415
+ encodeUintValue(writer, MAJOR_NEGINT, data * -1 - 1);
1416
+ }
1417
+ return;
1418
+ case "bigint":
1419
+ if (data >= BigInt(0)) {
1420
+ encodeUintValue(writer, MAJOR_UINT, data);
1421
+ } else {
1422
+ encodeUintValue(writer, MAJOR_NEGINT, data * neg1b - pos1b);
1423
+ }
1424
+ return;
1425
+ case "string": {
1426
+ const bytes = fromString(data);
1427
+ encodeUintValue(writer, MAJOR_STRING, bytes.length);
1428
+ writer.push(bytes);
1429
+ return;
1430
+ }
1431
+ case "Uint8Array":
1432
+ encodeUintValue(writer, MAJOR_BYTES, data.length);
1433
+ writer.push(data);
1434
+ return;
1435
+ case "Array":
1436
+ if (!data.length) {
1437
+ writer.push([MAJOR_ARRAY]);
1438
+ return;
1439
+ }
1440
+ refStack = Ref.createCheck(refStack, data);
1441
+ encodeUintValue(writer, MAJOR_ARRAY, data.length);
1442
+ for (const elem of data) {
1443
+ directEncode(writer, elem, options, refStack);
1444
+ }
1445
+ return;
1446
+ case "Object":
1447
+ case "Map":
1448
+ {
1449
+ const tokens = typeEncoders.Object(data, typ, options, refStack);
1450
+ tokensToEncoded(writer, tokens, cborEncoders, options);
1451
+ }
1452
+ return;
1453
+ default: {
1454
+ const typeEncoder = typeEncoders[typ];
1455
+ if (!typeEncoder) {
1456
+ throw new Error(`${encodeErrPrefix} unsupported type: ${typ}`);
1457
+ }
1458
+ const tokens = typeEncoder(data, typ, options, refStack);
1459
+ tokensToEncoded(writer, tokens, cborEncoders, options);
1460
+ }
1409
1461
  }
1410
1462
  }
1411
- function encodeCustom(data, encoders, options) {
1463
+ function encodeCustom(data, encoders, options, destination) {
1464
+ const hasDest = destination instanceof Uint8Array;
1465
+ let writeTo = hasDest ? new U8Bl(destination) : defaultWriter;
1412
1466
  const tokens = objectToTokens(data, options);
1413
1467
  if (!Array.isArray(tokens) && options.quickEncodeToken) {
1414
1468
  const quickBytes = options.quickEncodeToken(tokens);
1415
1469
  if (quickBytes) {
1470
+ if (hasDest) {
1471
+ writeTo.push(quickBytes);
1472
+ return writeTo.toBytes();
1473
+ }
1416
1474
  return quickBytes;
1417
1475
  }
1418
1476
  const encoder = encoders[tokens.type.major];
1419
1477
  if (encoder.encodedSize) {
1420
1478
  const size = encoder.encodedSize(tokens, options);
1421
- const buf2 = new Bl(size);
1422
- encoder(buf2, tokens, options);
1423
- if (buf2.chunks.length !== 1) {
1479
+ if (!hasDest) {
1480
+ writeTo = new Bl(size);
1481
+ }
1482
+ encoder(writeTo, tokens, options);
1483
+ if (writeTo.chunks.length !== 1) {
1424
1484
  throw new Error(`Unexpected error: pre-calculated length for ${tokens} was wrong`);
1425
1485
  }
1426
- return asU8A(buf2.chunks[0]);
1486
+ return hasDest ? writeTo.toBytes() : asU8A(writeTo.chunks[0]);
1427
1487
  }
1428
1488
  }
1429
- buf.reset();
1430
- tokensToEncoded(buf, tokens, encoders, options);
1431
- return buf.toBytes(true);
1489
+ writeTo.reset();
1490
+ tokensToEncoded(writeTo, tokens, encoders, options);
1491
+ return writeTo.toBytes(true);
1432
1492
  }
1433
1493
  function encode$1(data, options) {
1434
1494
  options = Object.assign({}, defaultEncodeOptions, options);
1495
+ if (canDirectEncode(options)) {
1496
+ defaultWriter.reset();
1497
+ directEncode(defaultWriter, data, options, void 0);
1498
+ return defaultWriter.toBytes(true);
1499
+ }
1435
1500
  return encodeCustom(data, cborEncoders, options);
1436
1501
  }
1437
1502
  const defaultDecodeOptions = {
@@ -1492,6 +1557,7 @@ function tokenToArray(token, tokeniser, options) {
1492
1557
  }
1493
1558
  function tokenToMap(token, tokeniser, options) {
1494
1559
  const useMaps = options.useMaps === true;
1560
+ const rejectDuplicateMapKeys = options.rejectDuplicateMapKeys === true;
1495
1561
  const obj = useMaps ? void 0 : {};
1496
1562
  const m = useMaps ? /* @__PURE__ */ new Map() : void 0;
1497
1563
  for (let i = 0; i < token.value; i++) {
@@ -1505,11 +1571,11 @@ function tokenToMap(token, tokeniser, options) {
1505
1571
  if (key === DONE) {
1506
1572
  throw new Error(`${decodeErrPrefix} found map but not enough entries (got ${i} [no key], expected ${token.value})`);
1507
1573
  }
1508
- if (useMaps !== true && typeof key !== "string") {
1574
+ if (!useMaps && typeof key !== "string") {
1509
1575
  throw new Error(`${decodeErrPrefix} non-string keys not supported (got ${typeof key})`);
1510
1576
  }
1511
- if (options.rejectDuplicateMapKeys === true) {
1512
- if (useMaps && m.has(key) || !useMaps && key in obj) {
1577
+ if (rejectDuplicateMapKeys) {
1578
+ if (useMaps && m.has(key) || !useMaps && Object.hasOwn(obj, key)) {
1513
1579
  throw new Error(`${decodeErrPrefix} found repeat map key "${key}"`);
1514
1580
  }
1515
1581
  }
@@ -1530,19 +1596,19 @@ function tokensToObject(tokeniser, options) {
1530
1596
  return DONE;
1531
1597
  }
1532
1598
  const token = tokeniser.next();
1533
- if (token.type === Type.break) {
1599
+ if (Type.equals(token.type, Type.break)) {
1534
1600
  return BREAK;
1535
1601
  }
1536
1602
  if (token.type.terminal) {
1537
1603
  return token.value;
1538
1604
  }
1539
- if (token.type === Type.array) {
1605
+ if (Type.equals(token.type, Type.array)) {
1540
1606
  return tokenToArray(token, tokeniser, options);
1541
1607
  }
1542
- if (token.type === Type.map) {
1608
+ if (Type.equals(token.type, Type.map)) {
1543
1609
  return tokenToMap(token, tokeniser, options);
1544
1610
  }
1545
- if (token.type === Type.tag) {
1611
+ if (Type.equals(token.type, Type.tag)) {
1546
1612
  if (options.tags && typeof options.tags[token.value] === "function") {
1547
1613
  const tagged = tokensToObject(tokeniser, options);
1548
1614
  return options.tags[token.value](tagged);
@@ -1556,7 +1622,8 @@ function decodeFirst(data, options) {
1556
1622
  throw new Error(`${decodeErrPrefix} data to decode must be a Uint8Array`);
1557
1623
  }
1558
1624
  options = Object.assign({}, defaultDecodeOptions, options);
1559
- const tokeniser = options.tokenizer || new Tokeniser(data, options);
1625
+ const u8aData = asU8A(data);
1626
+ const tokeniser = options.tokenizer || new Tokeniser(u8aData, options);
1560
1627
  const decoded = tokensToObject(tokeniser, options);
1561
1628
  if (decoded === DONE) {
1562
1629
  throw new Error(`${decodeErrPrefix} did not find any content to decode`);
@@ -1574,51 +1641,41 @@ function decode$1(data, options) {
1574
1641
  return decoded;
1575
1642
  }
1576
1643
  const CID_CBOR_TAG = 42;
1577
- function cidEncoder(cid) {
1578
- const bytes = new Uint8Array(cid.bytes.byteLength + 1);
1579
- bytes.set(cid.bytes, 1);
1580
- return [new Token(Type.tag, CID_CBOR_TAG), new Token(Type.bytes, bytes)];
1581
- }
1582
- function objectEncoder(obj, _typ, _options) {
1583
- const cid = lexData.ifCid(obj);
1584
- if (cid) return cidEncoder(cid);
1585
- return null;
1586
- }
1587
- function undefinedEncoder() {
1588
- throw new Error("`undefined` is not allowed by the AT Data Model");
1589
- }
1590
- function numberEncoder(num) {
1591
- if (Number.isInteger(num) && Number.isSafeInteger(num)) return null;
1592
- throw new Error("Non-integer numbers are not allowed by the AT Data Model");
1593
- }
1594
- function mapEncoder(map) {
1595
- for (const key of map.keys()) {
1596
- if (typeof key !== "string") {
1644
+ const encodeOptions = Object.freeze({
1645
+ float64: true,
1646
+ ignoreUndefinedProperties: true,
1647
+ typeEncoders: Object.freeze({
1648
+ Map: (map) => {
1649
+ for (const key of map.keys()) {
1650
+ if (typeof key !== "string") {
1651
+ throw new Error(
1652
+ 'Only string keys are allowed in CBOR "map" by the AT Data Model'
1653
+ );
1654
+ }
1655
+ }
1656
+ return null;
1657
+ },
1658
+ Object: (obj) => {
1659
+ const cid = lexData.ifCid(obj);
1660
+ if (cid) {
1661
+ const bytes = new Uint8Array(cid.bytes.byteLength + 1);
1662
+ bytes.set(cid.bytes, 1);
1663
+ return [new Token(Type.tag, CID_CBOR_TAG), new Token(Type.bytes, bytes)];
1664
+ }
1665
+ return null;
1666
+ },
1667
+ undefined: () => {
1668
+ throw new Error("`undefined` is not supported by the AT Data Model");
1669
+ },
1670
+ number: (num) => {
1671
+ if (Number.isSafeInteger(num)) return null;
1597
1672
  throw new Error(
1598
- 'Only string keys are allowed in CBOR "map" by the AT Data Model'
1673
+ `Non-integer numbers (${num}) are not supported by the AT Data Model`
1599
1674
  );
1600
1675
  }
1601
- }
1602
- return null;
1603
- }
1604
- const encodeOptions = {
1605
- float64: true,
1606
- typeEncoders: {
1607
- Map: mapEncoder,
1608
- Object: objectEncoder,
1609
- undefined: undefinedEncoder,
1610
- number: numberEncoder
1611
- }
1612
- };
1613
- function cidDecoder(bytes) {
1614
- if (bytes[0] !== 0) {
1615
- throw new Error("Invalid CID for CBOR tag 42; expected leading 0x00");
1616
- }
1617
- return lexData.decodeCid(bytes.subarray(1));
1618
- }
1619
- const tagDecoders = [];
1620
- tagDecoders[CID_CBOR_TAG] = cidDecoder;
1621
- const decodeOptions = {
1676
+ })
1677
+ });
1678
+ const decodeOptions = /* @__PURE__ */ Object.freeze({
1622
1679
  allowIndefinite: false,
1623
1680
  coerceUndefinedToNull: true,
1624
1681
  allowNaN: false,
@@ -1627,8 +1684,18 @@ const decodeOptions = {
1627
1684
  strict: true,
1628
1685
  useMaps: false,
1629
1686
  rejectDuplicateMapKeys: true,
1630
- tags: tagDecoders
1631
- };
1687
+ tags: /* @__PURE__ */ Object.freeze(
1688
+ /* @__PURE__ */ Object.assign([], {
1689
+ [CID_CBOR_TAG]: (bytes) => {
1690
+ if (bytes[0] !== 0) {
1691
+ throw new Error("Invalid CID for CBOR tag 42; expected leading 0x00");
1692
+ }
1693
+ const cibBytes = bytes.subarray(1);
1694
+ return lexData.decodeCid(cibBytes);
1695
+ }
1696
+ })
1697
+ )
1698
+ });
1632
1699
  function encode(data) {
1633
1700
  return encode$1(data, encodeOptions);
1634
1701
  }
@@ -1651,4 +1718,6 @@ exports.cborEncode = encode;
1651
1718
  exports.cidForLex = cidForLex;
1652
1719
  exports.decode = decode;
1653
1720
  exports.decodeAll = decodeAll;
1721
+ exports.decodeOptions = decodeOptions;
1654
1722
  exports.encode = encode;
1723
+ exports.encodeOptions = encodeOptions;