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