@bcts/dcbor 1.0.0-beta.2 → 1.0.0-beta.4

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.
@@ -4188,13 +4188,19 @@ var bctsDcbor = (function(exports) {
4188
4188
  name
4189
4189
  });
4190
4190
  /**
4191
+ * Compare two tag values for equality, normalizing `number` vs `bigint`.
4192
+ * A raw `===` would treat `100n` and `100` as unequal, so a large tag that
4193
+ * decoded to a `bigint` wouldn't match the same value written as a `number`.
4194
+ */
4195
+ const tagValuesEqual = (a, b) => {
4196
+ if (typeof a === "bigint" || typeof b === "bigint") return BigInt(a) === BigInt(b);
4197
+ return a === b;
4198
+ };
4199
+ /**
4191
4200
  * Compare two tags for equality. Mirrors Rust's `PartialEq for Tag`, which
4192
4201
  * compares by `value` only and ignores the optional `name`.
4193
4202
  */
4194
- const tagsEqual = (a, b) => {
4195
- if (typeof a.value === "bigint" || typeof b.value === "bigint") return BigInt(a.value) === BigInt(b.value);
4196
- return a.value === b.value;
4197
- };
4203
+ const tagsEqual = (a, b) => tagValuesEqual(a.value, b.value);
4198
4204
  /**
4199
4205
  * Get the string representation of a tag.
4200
4206
  * Internal function used for error messages.
@@ -4613,6 +4619,33 @@ var bctsDcbor = (function(exports) {
4613
4619
  const hasFract = (n) => {
4614
4620
  return n % 1 !== 0;
4615
4621
  };
4622
+ const U64_MAX_BIG = 18446744073709551615n;
4623
+ const I64_MAX_BIG = 9223372036854775807n;
4624
+ const I64_MIN_BIG = -9223372036854775808n;
4625
+ /**
4626
+ * Truncate a float to u64 with Rust's saturating `as u64` semantics: NaN and
4627
+ * negatives clamp to 0, values at or above 2^64 clamp to u64::MAX. This lets the
4628
+ * exact-float checks below mirror Rust's `(f as u64) == source` round-trip, where
4629
+ * u64::MAX rounds to 2^64 in float but saturates back to u64::MAX.
4630
+ */
4631
+ const saturateFloatToU64 = (f) => {
4632
+ if (Number.isNaN(f)) return 0n;
4633
+ const t = Math.trunc(f);
4634
+ if (t <= 0) return 0n;
4635
+ const big = BigInt(t);
4636
+ return big > U64_MAX_BIG ? U64_MAX_BIG : big;
4637
+ };
4638
+ /**
4639
+ * Truncate a float to i64 with Rust's saturating `as i64` semantics: NaN clamps
4640
+ * to 0, values clamp to i64::MAX or i64::MIN at the bounds.
4641
+ */
4642
+ const saturateFloatToI64 = (f) => {
4643
+ if (Number.isNaN(f)) return 0n;
4644
+ const big = BigInt(Math.trunc(f));
4645
+ if (big > I64_MAX_BIG) return I64_MAX_BIG;
4646
+ if (big < I64_MIN_BIG) return I64_MIN_BIG;
4647
+ return big;
4648
+ };
4616
4649
  /**
4617
4650
  * Exact conversions for i128 (JavaScript bigint).
4618
4651
  */
@@ -4776,6 +4809,55 @@ var bctsDcbor = (function(exports) {
4776
4809
  return source <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(source) : source;
4777
4810
  }
4778
4811
  };
4812
+ /**
4813
+ * Exact conversions for f64 (double precision float).
4814
+ */
4815
+ var ExactF64 = class {
4816
+ static exactFromF16(source) {
4817
+ if (Number.isNaN(source)) return NaN;
4818
+ return source;
4819
+ }
4820
+ static exactFromF32(source) {
4821
+ if (Number.isNaN(source)) return NaN;
4822
+ return source;
4823
+ }
4824
+ static exactFromF64(source) {
4825
+ if (Number.isNaN(source)) return NaN;
4826
+ return source;
4827
+ }
4828
+ static exactFromU64(source) {
4829
+ const srcBig = typeof source === "bigint" ? source : BigInt(source);
4830
+ const n = Number(srcBig);
4831
+ if (!Number.isFinite(n)) return void 0;
4832
+ return saturateFloatToU64(n) === srcBig ? n : void 0;
4833
+ }
4834
+ static exactFromI64(source) {
4835
+ const srcBig = typeof source === "bigint" ? source : BigInt(source);
4836
+ const n = Number(srcBig);
4837
+ if (!Number.isFinite(n)) return void 0;
4838
+ return saturateFloatToI64(n) === srcBig ? n : void 0;
4839
+ }
4840
+ static exactFromU128(source) {
4841
+ const n = Number(source);
4842
+ return BigInt(Math.trunc(n)) === source ? n : void 0;
4843
+ }
4844
+ static exactFromI128(source) {
4845
+ if (source < -9223372036854775808n || source > 9223372036854775807n) return;
4846
+ const absSource = source < 0n ? -source : source;
4847
+ if (absSource <= 4503599627370495n) return Number(source);
4848
+ const trailingZeros = countTrailingZeros(absSource);
4849
+ if (trailingZeros >= 53 && trailingZeros <= 63) return Number(source);
4850
+ }
4851
+ };
4852
+ const countTrailingZeros = (n) => {
4853
+ if (n === 0n) return 0;
4854
+ let count = 0;
4855
+ while ((n & 1n) === 0n) {
4856
+ count++;
4857
+ n = n >> 1n;
4858
+ }
4859
+ return count;
4860
+ };
4779
4861
  //#endregion
4780
4862
  //#region src/float.ts
4781
4863
  /**
@@ -4830,7 +4912,7 @@ var bctsDcbor = (function(exports) {
4830
4912
  * Convert number to 32-bit float binary (big-endian).
4831
4913
  */
4832
4914
  const numberToBinary32 = (n) => {
4833
- const data = new Uint8Array(4);
4915
+ const data = /* @__PURE__ */ new Uint8Array(4);
4834
4916
  import_byte_data.packTo(n, {
4835
4917
  bits: 32,
4836
4918
  fp: true,
@@ -4852,7 +4934,7 @@ var bctsDcbor = (function(exports) {
4852
4934
  * Convert number to 16-bit float binary (big-endian).
4853
4935
  */
4854
4936
  const numberToBinary16 = (n) => {
4855
- const data = new Uint8Array(2);
4937
+ const data = /* @__PURE__ */ new Uint8Array(2);
4856
4938
  import_byte_data.packTo(n, {
4857
4939
  bits: 16,
4858
4940
  fp: true,
@@ -4884,11 +4966,11 @@ var bctsDcbor = (function(exports) {
4884
4966
  const i128 = ExactI128.exactFromF64(n);
4885
4967
  if (i128 !== void 0) {
4886
4968
  const i = ExactU64.exactFromI128(-1n - i128);
4887
- if (i !== void 0) return encodeVarInt(typeof i === "bigint" ? Number(i) : i, MajorType.Negative);
4969
+ if (i !== void 0) return encodeVarInt(i, MajorType.Negative);
4888
4970
  }
4889
4971
  }
4890
4972
  const u = ExactU64.exactFromF64(n);
4891
- if (u !== void 0) return encodeVarInt(typeof u === "bigint" ? Number(u) : u, MajorType.Unsigned);
4973
+ if (u !== void 0) return encodeVarInt(u, MajorType.Unsigned);
4892
4974
  if (Number.isNaN(value)) return CBOR_NAN;
4893
4975
  const buffer = /* @__PURE__ */ new ArrayBuffer(8);
4894
4976
  new DataView(buffer).setFloat64(0, n, false);
@@ -4906,8 +4988,8 @@ var bctsDcbor = (function(exports) {
4906
4988
  const f = binary16ToNumber(numberToBinary16(n));
4907
4989
  if (f === n) return f16CborData(f);
4908
4990
  if (n < 0) {
4909
- const u = ExactU64.exactFromF32(-1 - n);
4910
- if (u !== void 0) return encodeVarInt(typeof u === "bigint" ? Number(u) : u, MajorType.Negative);
4991
+ const u = ExactU64.exactFromF32(Math.fround(-1 - n));
4992
+ if (u !== void 0) return encodeVarInt(u, MajorType.Negative);
4911
4993
  }
4912
4994
  const u = ExactU32.exactFromF32(n);
4913
4995
  if (u !== void 0) return encodeVarInt(u, MajorType.Unsigned);
@@ -4925,7 +5007,7 @@ var bctsDcbor = (function(exports) {
4925
5007
  const n = value;
4926
5008
  if (n < 0) {
4927
5009
  const u = ExactU64.exactFromF64(-1 - n);
4928
- if (u !== void 0) return encodeVarInt(typeof u === "bigint" ? Number(u) : u, MajorType.Negative);
5010
+ if (u !== void 0) return encodeVarInt(u, MajorType.Negative);
4929
5011
  }
4930
5012
  const u = ExactU16.exactFromF64(n);
4931
5013
  if (u !== void 0) return encodeVarInt(u, MajorType.Unsigned);
@@ -4933,6 +5015,31 @@ var bctsDcbor = (function(exports) {
4933
5015
  const bytes = numberToBinary16(value);
4934
5016
  return new Uint8Array([249, ...bytes]);
4935
5017
  };
5018
+ /**
5019
+ * Render a float to its diagnostic string, matching Rust's `Simple` Display.
5020
+ *
5021
+ * Finite non-zero values with magnitude in [1e-4, 1e16) print in decimal with
5022
+ * at least one fractional digit (whole values get a trailing `.0`); everything
5023
+ * else prints in exponential form. Zero prints as `0.0`/`-0.0`.
5024
+ *
5025
+ * JS already produces the same shortest round-tripping digits; we only fix up
5026
+ * the notation threshold, the `e+` → `e` exponent, and the `.0` suffix.
5027
+ *
5028
+ * @param value - The float value
5029
+ * @returns Rust-`Display`-compatible string
5030
+ */
5031
+ const floatDisplayString = (value) => {
5032
+ if (Number.isNaN(value)) return "NaN";
5033
+ if (!Number.isFinite(value)) return value > 0 ? "Infinity" : "-Infinity";
5034
+ if (value === 0) return Object.is(value, -0) ? "-0.0" : "0.0";
5035
+ const abs = Math.abs(value);
5036
+ if (abs >= 1e-4 && abs < 0x2386f26fc10000) {
5037
+ let str = String(value);
5038
+ if (!str.includes(".")) str = `${str}.0`;
5039
+ return str;
5040
+ }
5041
+ return value.toExponential().replace("e+", "e");
5042
+ };
4936
5043
  //#endregion
4937
5044
  //#region src/varint.ts
4938
5045
  /**
@@ -5197,6 +5304,34 @@ var bctsDcbor = (function(exports) {
5197
5304
  globalTagsStore ??= new TagsStore();
5198
5305
  return globalTagsStore;
5199
5306
  };
5307
+ /**
5308
+ * Execute a function with access to the global tags store.
5309
+ *
5310
+ * @template T - Return type of the action function
5311
+ * @param action - Function to execute with the tags store
5312
+ * @returns Result of the action function
5313
+ *
5314
+ * @example
5315
+ * ```typescript
5316
+ * const tagName = withTags(store => store.nameForValue(1));
5317
+ * console.log(tagName); // 'date'
5318
+ * ```
5319
+ */
5320
+ const withTags = (action) => {
5321
+ return action(getGlobalTagsStore());
5322
+ };
5323
+ /**
5324
+ * Execute a function with mutable access to the global tags store.
5325
+ *
5326
+ * This is an alias for withTags() for consistency with Rust API.
5327
+ *
5328
+ * @template T - Return type of the action function
5329
+ * @param action - Function to execute with the tags store
5330
+ * @returns Result of the action function
5331
+ */
5332
+ const withTagsMut = (action) => {
5333
+ return action(getGlobalTagsStore());
5334
+ };
5200
5335
  //#endregion
5201
5336
  //#region src/dump.ts
5202
5337
  /**
@@ -5400,7 +5535,7 @@ var bctsDcbor = (function(exports) {
5400
5535
  if (simple.type === "True") note = "true";
5401
5536
  else if (simple.type === "False") note = "false";
5402
5537
  else if (simple.type === "Null") note = "null";
5403
- else if (simple.type === "Float") note = `${simple.value}`;
5538
+ else if (simple.type === "Float") note = floatDisplayString(simple.value);
5404
5539
  else note = "simple";
5405
5540
  items.push(new DumpItem(level, [data], note));
5406
5541
  break;
@@ -5627,7 +5762,7 @@ var bctsDcbor = (function(exports) {
5627
5762
  if (summarizer !== void 0) {
5628
5763
  const result = summarizer(content, opts.flat ?? false);
5629
5764
  if (result.ok) return item(result.value);
5630
- return item(`<error: ${result.error.type === "Custom" ? result.error.message : result.error.type === "WrongTag" ? `expected CBOR tag ${result.error.expected.value}, but got ${result.error.actual.value}` : result.error.type}>`);
5765
+ return item(`<error: ${errorToString(result.error)}>`);
5631
5766
  }
5632
5767
  }
5633
5768
  let comment;
@@ -5650,7 +5785,7 @@ var bctsDcbor = (function(exports) {
5650
5785
  return `h'${bytesToHex(value)}'`;
5651
5786
  }
5652
5787
  function formatText(value) {
5653
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t")}"`;
5788
+ return `"${value.replace(/"/g, "\\\"")}"`;
5654
5789
  }
5655
5790
  function formatSimple(value) {
5656
5791
  switch (value.type) {
@@ -5661,20 +5796,11 @@ var bctsDcbor = (function(exports) {
5661
5796
  }
5662
5797
  }
5663
5798
  /**
5664
- * Format a finite CBOR float to match Rust `Simple::format!("{:?}", v)`.
5665
- *
5666
- * - `1.0` → `"1.0"` (Rust Debug). JS `String(1.0)` gives `"1"` so we append `.0`.
5667
- * - `1.5` → `"1.5"`.
5668
- * - `1e100` → `"1e100"` (Rust uses no `+` sign in the exponent). JS uses `1e+100`.
5669
- * - Specials (NaN / ±Infinity) produce the exact Rust strings.
5799
+ * Format a CBOR float for diagnostic output. Shared with the hex-dump
5800
+ * annotation path; see {@link floatDisplayString}.
5670
5801
  */
5671
5802
  function formatFloat(value) {
5672
- if (Number.isNaN(value)) return "NaN";
5673
- if (!Number.isFinite(value)) return value > 0 ? "Infinity" : "-Infinity";
5674
- let str = String(value);
5675
- str = str.replace(/e\+/, "e");
5676
- if (!str.includes(".") && !str.includes("e")) str = `${str}.0`;
5677
- return str;
5803
+ return floatDisplayString(value);
5678
5804
  }
5679
5805
  function resolveTagsStore(tags) {
5680
5806
  if (tags === "none") return void 0;
@@ -5764,7 +5890,7 @@ var bctsDcbor = (function(exports) {
5764
5890
  return data.getUint8(index);
5765
5891
  }
5766
5892
  function from(data, index) {
5767
- return new DataView(data.buffer, data.byteOffset + index);
5893
+ return new DataView(data.buffer, data.byteOffset + index, data.byteLength - index);
5768
5894
  }
5769
5895
  function range(data, start, end) {
5770
5896
  return new DataView(data.buffer, data.byteOffset + start, end - start);
@@ -5868,7 +5994,15 @@ var bctsDcbor = (function(exports) {
5868
5994
  const textLen = value;
5869
5995
  if (typeof textLen === "bigint") throw new CborError({ type: "OutOfRange" });
5870
5996
  const textBuf = parseBytes(from(data, varIntLen), textLen);
5871
- const text = new TextDecoder().decode(textBuf);
5997
+ let text;
5998
+ try {
5999
+ text = new TextDecoder("utf-8", { fatal: true }).decode(textBuf);
6000
+ } catch (e) {
6001
+ throw new CborError({
6002
+ type: "InvalidUtf8",
6003
+ message: e instanceof Error ? e.message : String(e)
6004
+ });
6005
+ }
5872
6006
  if (text.normalize("NFC") !== text) throw new CborError({ type: "NonCanonicalString" });
5873
6007
  return {
5874
6008
  cbor: attachMethods({
@@ -6247,9 +6381,12 @@ var bctsDcbor = (function(exports) {
6247
6381
  * @returns Float or undefined
6248
6382
  */
6249
6383
  const asFloat = (cbor) => {
6250
- if (cbor.type !== MajorType.Simple) return;
6251
- const simple = cbor.value;
6252
- if (isFloat$1(simple)) return simple.value;
6384
+ if (cbor.type === MajorType.Unsigned) return ExactF64.exactFromU64(cbor.value);
6385
+ if (cbor.type === MajorType.Negative) {
6386
+ const f = ExactF64.exactFromU64(cbor.value);
6387
+ return f === void 0 ? void 0 : -1 - f;
6388
+ }
6389
+ if (cbor.type === MajorType.Simple) return isFloat$1(cbor.value) ? cbor.value.value : void 0;
6253
6390
  };
6254
6391
  /**
6255
6392
  * Extract any numeric value (integer or float).
@@ -6370,9 +6507,13 @@ var bctsDcbor = (function(exports) {
6370
6507
  * @throws {CborError} With type 'WrongType' if cbor is not a float
6371
6508
  */
6372
6509
  const expectFloat = (cbor) => {
6373
- const value = asFloat(cbor);
6374
- if (value === void 0) throw new CborError({ type: "WrongType" });
6375
- return value;
6510
+ if (cbor.type === MajorType.Unsigned || cbor.type === MajorType.Negative) {
6511
+ const value = asFloat(cbor);
6512
+ if (value === void 0) throw new CborError({ type: "OutOfRange" });
6513
+ return value;
6514
+ }
6515
+ if (cbor.type === MajorType.Simple && isFloat$1(cbor.value)) return cbor.value.value;
6516
+ throw new CborError({ type: "WrongType" });
6376
6517
  };
6377
6518
  /**
6378
6519
  * Extract any numeric value, throwing if type doesn't match.
@@ -6510,7 +6651,7 @@ var bctsDcbor = (function(exports) {
6510
6651
  */
6511
6652
  const hasTag = (cbor, tag) => {
6512
6653
  if (cbor.type !== MajorType.Tagged) return false;
6513
- return cbor.tag === tag;
6654
+ return tagValuesEqual(cbor.tag, tag);
6514
6655
  };
6515
6656
  /**
6516
6657
  * Extract content if has specific tag.
@@ -6520,7 +6661,7 @@ var bctsDcbor = (function(exports) {
6520
6661
  * @returns Tagged content or undefined
6521
6662
  */
6522
6663
  const getTaggedContent = (cbor, tag) => {
6523
- if (cbor.type === MajorType.Tagged && cbor.tag === tag) return cbor.value;
6664
+ if (cbor.type === MajorType.Tagged && tagValuesEqual(cbor.tag, tag)) return cbor.value;
6524
6665
  };
6525
6666
  /**
6526
6667
  * Extract content if has specific tag, throwing if not.
@@ -6535,7 +6676,7 @@ var bctsDcbor = (function(exports) {
6535
6676
  */
6536
6677
  const expectTaggedContent = (cbor, tag) => {
6537
6678
  if (cbor.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
6538
- if (cbor.tag !== tag) throw new CborError({
6679
+ if (!tagValuesEqual(cbor.tag, tag)) throw new CborError({
6539
6680
  type: "WrongTag",
6540
6681
  expected: { value: tag },
6541
6682
  actual: { value: cbor.tag }
@@ -6775,15 +6916,13 @@ var bctsDcbor = (function(exports) {
6775
6916
  * Matches Rust's Map::insert_next().
6776
6917
  */
6777
6918
  setNext(key, value) {
6778
- const lastEntry = this._dict.max();
6779
- if (lastEntry === void 0) {
6780
- this.set(key, value);
6781
- return;
6782
- }
6783
6919
  const keyCbor = cbor(key);
6784
6920
  const newKey = cborData(keyCbor);
6785
6921
  if (this._dict.has(newKey)) throw new CborError({ type: "DuplicateMapKey" });
6786
- if (lexicographicallyCompareBytes(newKey, this._makeKey(lastEntry.key)) <= 0) throw new CborError({ type: "MisorderedMapKey" });
6922
+ const greatest = this._dict.store.max();
6923
+ if (greatest !== void 0) {
6924
+ if (lexicographicallyCompareBytes(newKey, greatest.key) <= 0) throw new CborError({ type: "MisorderedMapKey" });
6925
+ }
6787
6926
  this._dict.set(newKey, {
6788
6927
  key: keyCbor,
6789
6928
  value: cbor(value)
@@ -7137,15 +7276,27 @@ var bctsDcbor = (function(exports) {
7137
7276
  value: -Infinity
7138
7277
  }
7139
7278
  };
7140
- else if (typeof value === "number" && !Number.isSafeInteger(value)) result = {
7141
- isCbor: true,
7142
- type: MajorType.Simple,
7143
- value: {
7144
- type: "Float",
7145
- value
7146
- }
7147
- };
7148
- else if (typeof value === "bigint" && (value > 18446744073709551615n || value < -18446744073709551616n)) throw new CborError({ type: "OutOfRange" });
7279
+ else if (typeof value === "number" && !Number.isSafeInteger(value)) {
7280
+ const big = BigInt(value);
7281
+ if (big >= 0n && big <= 18446744073709551615n) result = {
7282
+ isCbor: true,
7283
+ type: MajorType.Unsigned,
7284
+ value: big
7285
+ };
7286
+ else if (big < 0n && big >= -18446744073709551616n) result = {
7287
+ isCbor: true,
7288
+ type: MajorType.Negative,
7289
+ value: -big - 1n
7290
+ };
7291
+ else result = {
7292
+ isCbor: true,
7293
+ type: MajorType.Simple,
7294
+ value: {
7295
+ type: "Float",
7296
+ value
7297
+ }
7298
+ };
7299
+ } else if (typeof value === "bigint" && (value > 18446744073709551615n || value < -18446744073709551616n)) throw new CborError({ type: "OutOfRange" });
7149
7300
  else if (value < 0) if (typeof value === "bigint") result = {
7150
7301
  isCbor: true,
7151
7302
  type: MajorType.Negative,
@@ -7496,7 +7647,7 @@ var bctsDcbor = (function(exports) {
7496
7647
  expectTag(expectedTag) {
7497
7648
  if (this.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
7498
7649
  const expected = typeof expectedTag === "object" && "value" in expectedTag ? expectedTag : { value: expectedTag };
7499
- if (this.tag !== expected.value) throw new CborError({
7650
+ if (!tagValuesEqual(this.tag, expected.value)) throw new CborError({
7500
7651
  type: "WrongTag",
7501
7652
  expected,
7502
7653
  actual: { value: this.tag }
@@ -7509,7 +7660,7 @@ var bctsDcbor = (function(exports) {
7509
7660
  validateTag(expectedTags) {
7510
7661
  if (this.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
7511
7662
  const tagValue = this.tag;
7512
- const matchingTag = expectedTags.find((t) => t.value === tagValue);
7663
+ const matchingTag = expectedTags.find((t) => tagValuesEqual(t.value, tagValue));
7513
7664
  if (matchingTag === void 0) throw new CborError({
7514
7665
  type: "WrongTag",
7515
7666
  expected: expectedTags[0],
@@ -7591,809 +7742,1267 @@ var bctsDcbor = (function(exports) {
7591
7742
  }
7592
7743
  };
7593
7744
  //#endregion
7594
- //#region src/cbor-tagged-encodable.ts
7595
- /**
7596
- * Copyright © 2023-2026 Blockchain Commons, LLC
7597
- * Copyright © 2025-2026 Parity Technologies
7598
- *
7599
- *
7600
- * Tagged CBOR encoding support.
7601
- *
7602
- * This module provides the `CborTaggedEncodable` interface, which enables types to
7603
- * be encoded as tagged CBOR values.
7604
- *
7605
- * CBOR tags provide semantic information about the encoded data. For example,
7606
- * tag 1 is used for dates, indicating that the value should be interpreted
7607
- * as a timestamp. The dCBOR library ensures these tags are encoded
7608
- * deterministically.
7609
- *
7610
- * This interface enables seamless encoding of TypeScript types to properly tagged CBOR
7611
- * values.
7612
- *
7613
- * @module cbor-tagged-encodable
7614
- */
7615
- /**
7616
- * Helper function to create tagged CBOR from an encodable object.
7617
- *
7618
- * Uses the first tag from cborTags().
7619
- *
7620
- * @param encodable - Object implementing CborTaggedEncodable
7621
- * @returns Tagged CBOR value
7622
- */
7623
- const createTaggedCbor = (encodable) => {
7624
- const tags = encodable.cborTags();
7625
- if (tags.length === 0) throw new CborError({
7626
- type: "Custom",
7627
- message: "No tags defined for this type"
7628
- });
7629
- const tag = tags[0];
7630
- if (tag === void 0) throw new CborError({
7631
- type: "Custom",
7632
- message: "Tag is undefined"
7633
- });
7634
- const untagged = encodable.untaggedCbor();
7635
- return attachMethods({
7636
- isCbor: true,
7637
- type: MajorType.Tagged,
7638
- tag: tag.value,
7639
- value: untagged
7640
- });
7641
- };
7642
- /**
7643
- * Default `taggedCborData()` implementation — `taggedCbor().toData()`.
7644
- *
7645
- * Mirrors Rust's default `tagged_cbor_data()` impl on
7646
- * `CBORTaggedEncodable`. TypeScript interfaces don't carry method bodies,
7647
- * so this helper plays the role of the Rust trait default; concrete types
7648
- * call it from their own `taggedCborData()` if they don't need to override.
7649
- */
7650
- const taggedCborData = (encodable) => encodable.taggedCbor().toData();
7651
- //#endregion
7652
- //#region src/cbor-tagged-decodable.ts
7653
- /**
7654
- * Copyright © 2023-2026 Blockchain Commons, LLC
7655
- * Copyright © 2025-2026 Parity Technologies
7656
- *
7657
- *
7658
- * Tagged CBOR decoding support.
7659
- *
7660
- * This module provides the `CborTaggedDecodable` interface, which enables types to
7661
- * be decoded from tagged CBOR values.
7662
- *
7663
- * Tagged CBOR values include semantic information about how to interpret the
7664
- * data. This interface allows TypeScript types to verify that incoming CBOR data has the
7665
- * expected tag(s) and to decode the data appropriately.
7666
- *
7667
- * @module cbor-tagged-decodable
7668
- */
7669
- /**
7670
- * Helper function to validate that a CBOR value has one of the expected tags.
7671
- *
7672
- * @param cbor - CBOR value to validate
7673
- * @param expectedTags - Array of valid tags
7674
- * @returns The matching tag
7675
- * @throws Error if the value is not tagged or has an unexpected tag
7676
- */
7677
- const validateTag = (cbor, expectedTags) => {
7678
- if (cbor.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
7679
- const tagValue = cbor.tag;
7680
- const matchingTag = expectedTags.find((t) => t.value === tagValue);
7681
- if (matchingTag === void 0) throw new CborError({
7682
- type: "WrongTag",
7683
- expected: expectedTags[0],
7684
- actual: { value: tagValue }
7685
- });
7686
- return matchingTag;
7687
- };
7688
- /**
7689
- * Helper function to extract the content from a tagged CBOR value.
7690
- *
7691
- * @param cbor - Tagged CBOR value
7692
- * @returns The untagged content
7693
- * @throws Error if the value is not tagged
7694
- */
7695
- const extractTaggedContent = (cbor) => {
7696
- if (cbor.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
7697
- return cbor.value;
7698
- };
7699
- /**
7700
- * Default `fromTaggedCborData()` implementation — `decodeCbor(data)` then
7701
- * delegate to the decodable's `fromTaggedCbor()`.
7702
- *
7703
- * Mirrors Rust's default `from_tagged_cbor_data` impl on
7704
- * `CBORTaggedDecodable`.
7705
- */
7706
- function fromTaggedCborData(decodable, data) {
7707
- return decodable.fromTaggedCbor(decodeCbor(data));
7708
- }
7709
- /**
7710
- * Default `fromUntaggedCborData()` implementation — `decodeCbor(data)`
7711
- * then delegate to the decodable's `fromUntaggedCbor()`.
7712
- *
7713
- * Mirrors Rust's default `from_untagged_cbor_data` impl on
7714
- * `CBORTaggedDecodable`.
7715
- */
7716
- function fromUntaggedCborData(decodable, data) {
7717
- return decodable.fromUntaggedCbor(decodeCbor(data));
7718
- }
7719
- //#endregion
7720
- //#region src/date.ts
7745
+ //#region src/set.ts
7721
7746
  /**
7722
7747
  * Copyright © 2023-2026 Blockchain Commons, LLC
7723
7748
  * Copyright © 2025-2026 Parity Technologies
7724
7749
  *
7725
7750
  *
7726
- * Date/time support for CBOR with tag(1) encoding.
7727
- *
7728
- * A CBOR-friendly representation of a date and time.
7729
- *
7730
- * The `CborDate` type provides a wrapper around JavaScript's native `Date` that
7731
- * supports encoding and decoding to/from CBOR with tag 1, following the CBOR
7732
- * date/time standard specified in RFC 8949.
7751
+ * Set data structure for CBOR.
7733
7752
  *
7734
- * When encoded to CBOR, dates are represented as tag 1 followed by a numeric
7735
- * value representing the number of seconds since (or before) the Unix epoch
7736
- * (1970-01-01T00:00:00Z). The numeric value can be a positive or negative
7737
- * integer, or a floating-point value for dates with fractional seconds.
7753
+ * A Set encodes to a plain (untagged) array of unique elements in canonical
7754
+ * ascending CBOR-byte order. There's no tag-258 here: this matches Rust
7755
+ * dcbor's `From<Set> for CBOR`, which emits an untagged array.
7738
7756
  *
7739
- * @module date
7757
+ * @module set
7740
7758
  */
7741
7759
  /**
7742
- * A CBOR-friendly representation of a date and time.
7743
- *
7744
- * The `CborDate` type provides a wrapper around JavaScript's native `Date` that
7745
- * supports encoding and decoding to/from CBOR with tag 1, following the CBOR
7746
- * date/time standard specified in RFC 8949.
7747
- *
7748
- * When encoded to CBOR, dates are represented as tag 1 followed by a numeric
7749
- * value representing the number of seconds since (or before) the Unix epoch
7750
- * (1970-01-01T00:00:00Z). The numeric value can be a positive or negative
7751
- * integer, or a floating-point value for dates with fractional seconds.
7752
- *
7753
- * # Features
7760
+ * CBOR Set type, encoded as a plain (untagged) array.
7754
7761
  *
7755
- * - Supports UTC dates with optional fractional seconds
7756
- * - Provides convenient constructors for common date creation patterns
7757
- * - Implements the `CborTagged`, `CborTaggedEncodable`, and
7758
- * `CborTaggedDecodable` interfaces
7759
- * - Supports arithmetic operations with durations and between dates
7762
+ * Internally uses a CborMap to ensure unique elements with deterministic ordering.
7763
+ * Elements are ordered by their CBOR encoding (lexicographic byte order).
7760
7764
  *
7761
7765
  * @example
7762
7766
  * ```typescript
7763
- * import { CborDate } from './date';
7764
- *
7765
- * // Create a date from a timestamp (seconds since Unix epoch)
7766
- * const date = CborDate.fromTimestamp(1675854714.0);
7767
+ * // Create set
7768
+ * const set = CborSet.fromArray([1, 2, 3]);
7769
+ * const set2 = CborSet.fromSet(new Set([1, 2, 3]));
7767
7770
  *
7768
- * // Create a date from year, month, day
7769
- * const date2 = CborDate.fromYmd(2023, 2, 8);
7771
+ * // Add elements
7772
+ * set.insert(4);
7773
+ * set.insert(2); // Duplicate, no effect
7770
7774
  *
7771
- * // Convert to CBOR
7772
- * const cborValue = date.taggedCbor();
7775
+ * // Check membership
7776
+ * console.log(set.contains(2)); // true
7777
+ * console.log(set.contains(99)); // false
7773
7778
  *
7774
- * // Decode from CBOR
7775
- * const decoded = CborDate.fromTaggedCbor(cborValue);
7779
+ * // Encode to CBOR (untagged array)
7780
+ * const c = set.toCbor();
7776
7781
  * ```
7777
7782
  */
7778
- var CborDate = class CborDate {
7779
- /**
7780
- * Canonical timestamp in seconds since the Unix epoch as a JS `number`
7781
- * (`f64`). dCBOR encodes Date (tag 1) as a numeric value in seconds, so
7782
- * keeping `_seconds` as the source of truth avoids the millisecond-only
7783
- * round-trip precision loss that going through a JS `Date` instance
7784
- * introduced in earlier versions of this port.
7785
- *
7786
- * f64 still bounds the achievable precision (~16 decimal digits, so
7787
- * roughly microseconds for current epoch values); Rust's
7788
- * `chrono::DateTime<Utc>` retains nanoseconds in memory but encodes
7789
- * to the same f64 over the wire, so the *encode/decode round-trip* is
7790
- * byte-identical.
7791
- */
7792
- _seconds;
7783
+ var CborSet = class CborSet {
7784
+ _map;
7785
+ constructor() {
7786
+ this._map = new CborMap();
7787
+ }
7793
7788
  /**
7794
- * Creates a new `CborDate` from the given JavaScript `Date`.
7795
- *
7796
- * This method creates a new `CborDate` instance by wrapping a
7797
- * JavaScript `Date`.
7789
+ * Create CborSet from array.
7798
7790
  *
7799
- * @param dateTime - A `Date` instance to wrap
7791
+ * Duplicates are automatically removed.
7800
7792
  *
7801
- * @returns A new `CborDate` instance
7793
+ * @param items - Array of items to add to the set
7794
+ * @returns New CborSet instance
7802
7795
  *
7803
7796
  * @example
7804
7797
  * ```typescript
7805
- * const datetime = new Date();
7806
- * const date = CborDate.fromDatetime(datetime);
7798
+ * const set = CborSet.fromArray([1, 2, 3, 2, 1]);
7799
+ * console.log(set.size); // 3
7807
7800
  * ```
7808
7801
  */
7809
- static fromDatetime(dateTime) {
7810
- const instance = new CborDate();
7811
- instance._seconds = dateTime.getTime() / 1e3;
7812
- return instance;
7802
+ static fromArray(items) {
7803
+ const set = new CborSet();
7804
+ for (const item of items) set.insert(item);
7805
+ return set;
7813
7806
  }
7814
7807
  /**
7815
- * Creates a new `CborDate` from year, month, and day components.
7816
- *
7817
- * This method creates a new `CborDate` with the time set to 00:00:00 UTC.
7818
- *
7819
- * @param year - The year component (e.g., 2023)
7820
- * @param month - The month component (1-12)
7821
- * @param day - The day component (1-31)
7808
+ * Create CborSet from JavaScript Set.
7822
7809
  *
7823
- * @returns A new `CborDate` instance
7810
+ * @param items - JavaScript Set of items
7811
+ * @returns New CborSet instance
7824
7812
  *
7825
7813
  * @example
7826
7814
  * ```typescript
7827
- * // Create February 8, 2023
7828
- * const date = CborDate.fromYmd(2023, 2, 8);
7815
+ * const jsSet = new Set([1, 2, 3]);
7816
+ * const cborSet = CborSet.fromSet(jsSet);
7829
7817
  * ```
7818
+ */
7819
+ static fromSet(items) {
7820
+ return CborSet.fromArray(Array.from(items));
7821
+ }
7822
+ /**
7823
+ * Create CborSet from iterable.
7830
7824
  *
7831
- * @throws Error if the provided components do not form a valid date.
7825
+ * @param items - Iterable of items
7826
+ * @returns New CborSet instance
7832
7827
  */
7833
- static fromYmd(year, month, day) {
7834
- const dt = new Date(Date.UTC(year, month - 1, day, 0, 0, 0, 0));
7835
- return CborDate.fromDatetime(dt);
7828
+ static fromIterable(items) {
7829
+ return CborSet.fromArray(Array.from(items));
7836
7830
  }
7837
7831
  /**
7838
- * Creates a new `CborDate` from year, month, day, hour, minute, and second
7839
- * components.
7832
+ * Insert an element into the set.
7840
7833
  *
7841
- * @param year - The year component (e.g., 2023)
7842
- * @param month - The month component (1-12)
7843
- * @param day - The day component (1-31)
7844
- * @param hour - The hour component (0-23)
7845
- * @param minute - The minute component (0-59)
7846
- * @param second - The second component (0-59)
7834
+ * If the element already exists, has no effect.
7847
7835
  *
7848
- * @returns A new `CborDate` instance
7836
+ * @param value - Value to insert
7849
7837
  *
7850
7838
  * @example
7851
7839
  * ```typescript
7852
- * // Create February 8, 2023, 15:30:45 UTC
7853
- * const date = CborDate.fromYmdHms(2023, 2, 8, 15, 30, 45);
7840
+ * const set = new CborSet();
7841
+ * set.insert(1);
7842
+ * set.insert(2);
7843
+ * set.insert(1); // No effect, already exists
7854
7844
  * ```
7855
- *
7856
- * @throws Error if the provided components do not form a valid date and time.
7857
7845
  */
7858
- static fromYmdHms(year, month, day, hour, minute, second) {
7859
- const dt = new Date(Date.UTC(year, month - 1, day, hour, minute, second, 0));
7860
- return CborDate.fromDatetime(dt);
7846
+ insert(value) {
7847
+ const cborValue = encodeCborValue(value);
7848
+ this._map.set(cborValue, cborValue);
7861
7849
  }
7862
7850
  /**
7863
- * Creates a new `CborDate` from seconds since (or before) the Unix epoch.
7851
+ * Insert an element that must sort strictly after every element inserted so
7852
+ * far (canonical CBOR-byte order). The decoder uses this to reject
7853
+ * misordered or duplicate elements.
7864
7854
  *
7865
- * This method creates a new `CborDate` representing the specified number of
7866
- * seconds since the Unix epoch (1970-01-01T00:00:00Z). Negative values
7867
- * represent times before the epoch.
7855
+ * Mirrors Rust `Set::insert_next` (`pub(crate)`); exposed here because
7856
+ * TypeScript has no crate-private visibility.
7868
7857
  *
7869
- * @param secondsSinceUnixEpoch - Seconds from the Unix epoch (positive or
7870
- * negative), which can include a fractional part for sub-second
7871
- * precision
7858
+ * @throws CborError of type `MisorderedMap` if `value` would not preserve
7859
+ * strict ascending CBOR-byte order, or `DuplicateMapKey` for an exact
7860
+ * repeat.
7861
+ */
7862
+ insertNext(value) {
7863
+ const cborValue = encodeCborValue(value);
7864
+ this._map.setNext(cborValue, cborValue);
7865
+ }
7866
+ /**
7867
+ * Check if set contains an element.
7872
7868
  *
7873
- * @returns A new `CborDate` instance
7869
+ * @param value - Value to check
7870
+ * @returns true if element is in the set
7874
7871
  *
7875
7872
  * @example
7876
7873
  * ```typescript
7877
- * // Create a date from a timestamp
7878
- * const date = CborDate.fromTimestamp(1675854714.0);
7879
- *
7880
- * // Create a date one second before the Unix epoch
7881
- * const beforeEpoch = CborDate.fromTimestamp(-1.0);
7882
- *
7883
- * // Create a date with fractional seconds
7884
- * const withFraction = CborDate.fromTimestamp(1675854714.5);
7874
+ * const set = CborSet.fromArray([1, 2, 3]);
7875
+ * console.log(set.contains(2)); // true
7876
+ * console.log(set.contains(99)); // false
7885
7877
  * ```
7886
7878
  */
7887
- static fromTimestamp(secondsSinceUnixEpoch) {
7888
- const instance = new CborDate();
7889
- instance._seconds = secondsSinceUnixEpoch;
7890
- return instance;
7879
+ contains(value) {
7880
+ const cborValue = encodeCborValue(value);
7881
+ return this._map.has(cborValue);
7891
7882
  }
7892
7883
  /**
7893
- * Creates a new `CborDate` from a string containing an ISO-8601 (RFC-3339)
7894
- * date (with or without time).
7895
- *
7896
- * This method parses a string representation of a date or date-time in
7897
- * ISO-8601/RFC-3339 format and creates a new `CborDate` instance. It
7898
- * supports both full date-time strings (e.g., "2023-02-08T15:30:45Z")
7899
- * and date-only strings (e.g., "2023-02-08").
7900
- *
7901
- * @param value - A string containing a date or date-time in ISO-8601/RFC-3339
7902
- * format
7903
- *
7904
- * @returns A new `CborDate` instance if parsing succeeds
7884
+ * Remove an element from the set.
7905
7885
  *
7906
- * @throws Error if the string cannot be parsed as a valid date or date-time
7886
+ * @param value - Value to remove
7887
+ * @returns true if element was removed, false if not found
7907
7888
  *
7908
7889
  * @example
7909
7890
  * ```typescript
7910
- * // Parse a date-time string
7911
- * const date = CborDate.fromString("2023-02-08T15:30:45Z");
7912
- *
7913
- * // Parse a date-only string (time will be set to 00:00:00)
7914
- * const date2 = CborDate.fromString("2023-02-08");
7891
+ * const set = CborSet.fromArray([1, 2, 3]);
7892
+ * set.delete(2); // Returns true
7893
+ * set.delete(99); // Returns false
7915
7894
  * ```
7916
7895
  */
7917
- static fromString(value) {
7918
- const dt = new Date(value);
7919
- if (isNaN(dt.getTime())) throw new CborError({
7920
- type: "InvalidDate",
7921
- message: "Invalid date string"
7922
- });
7923
- return CborDate.fromDatetime(dt);
7896
+ delete(value) {
7897
+ const cborValue = encodeCborValue(value);
7898
+ return this._map.delete(cborValue);
7924
7899
  }
7925
7900
  /**
7926
- * Creates a new `CborDate` containing the current date and time.
7927
- *
7928
- * @returns A new `CborDate` instance representing the current UTC date and time
7901
+ * Remove all elements from the set.
7902
+ */
7903
+ clear() {
7904
+ this._map.clear();
7905
+ }
7906
+ /**
7907
+ * Get the number of elements in the set.
7929
7908
  *
7930
- * @example
7931
- * ```typescript
7932
- * const now = CborDate.now();
7933
- * ```
7909
+ * @returns Number of elements
7934
7910
  */
7935
- static now() {
7936
- return CborDate.fromDatetime(/* @__PURE__ */ new Date());
7911
+ get size() {
7912
+ return this._map.size;
7937
7913
  }
7938
7914
  /**
7939
- * Creates a new `CborDate` containing the current date and time plus the given
7940
- * duration.
7915
+ * Check if the set is empty.
7941
7916
  *
7942
- * @param durationMs - The duration in milliseconds to add to the current time
7917
+ * @returns true if set has no elements
7918
+ */
7919
+ isEmpty() {
7920
+ return this._map.size === 0;
7921
+ }
7922
+ /**
7923
+ * Create a new set containing elements in this set or the other set.
7943
7924
  *
7944
- * @returns A new `CborDate` instance representing the current UTC date and time plus
7945
- * the duration
7925
+ * @param other - Other set
7926
+ * @returns New set with union of elements
7946
7927
  *
7947
7928
  * @example
7948
7929
  * ```typescript
7949
- * // Get a date 1 hour from now
7950
- * const oneHourLater = CborDate.withDurationFromNow(3600 * 1000);
7930
+ * const set1 = CborSet.fromArray([1, 2, 3]);
7931
+ * const set2 = CborSet.fromArray([3, 4, 5]);
7932
+ * const union = set1.union(set2);
7933
+ * // union contains [1, 2, 3, 4, 5]
7951
7934
  * ```
7952
7935
  */
7953
- static withDurationFromNow(durationMs) {
7954
- const future = new Date((/* @__PURE__ */ new Date()).getTime() + durationMs);
7955
- return CborDate.fromDatetime(future);
7936
+ union(other) {
7937
+ const result = new CborSet();
7938
+ for (const value of this) result.insert(extractCbor(value));
7939
+ for (const value of other) result.insert(extractCbor(value));
7940
+ return result;
7956
7941
  }
7957
7942
  /**
7958
- * Returns the underlying JavaScript `Date` object.
7959
- *
7960
- * This method provides access to the wrapped JavaScript `Date`
7961
- * instance.
7943
+ * Create a new set containing elements in both this set and the other set.
7962
7944
  *
7963
- * @returns The wrapped `Date` instance
7945
+ * @param other - Other set
7946
+ * @returns New set with intersection of elements
7964
7947
  *
7965
7948
  * @example
7966
7949
  * ```typescript
7967
- * const date = CborDate.now();
7968
- * const datetime = date.datetime();
7969
- * const year = datetime.getFullYear();
7950
+ * const set1 = CborSet.fromArray([1, 2, 3]);
7951
+ * const set2 = CborSet.fromArray([2, 3, 4]);
7952
+ * const intersection = set1.intersection(set2);
7953
+ * // intersection contains [2, 3]
7970
7954
  * ```
7971
7955
  */
7972
- datetime() {
7973
- return /* @__PURE__ */ new Date(this._seconds * 1e3);
7956
+ intersection(other) {
7957
+ const result = new CborSet();
7958
+ for (const value of this) {
7959
+ const extracted = extractCbor(value);
7960
+ if (other.contains(extracted)) result.insert(extracted);
7961
+ }
7962
+ return result;
7974
7963
  }
7975
7964
  /**
7976
- * Returns the `CborDate` as the number of seconds since the Unix epoch.
7977
- *
7978
- * This method converts the date to a floating-point number representing
7979
- * the number of seconds since the Unix epoch (1970-01-01T00:00:00Z).
7980
- * Negative values represent times before the epoch. The fractional
7981
- * part represents sub-second precision.
7965
+ * Create a new set containing elements in this set but not in the other set.
7982
7966
  *
7983
- * @returns Seconds since the Unix epoch as a `number`
7967
+ * @param other - Other set
7968
+ * @returns New set with difference of elements
7984
7969
  *
7985
7970
  * @example
7986
7971
  * ```typescript
7987
- * const date = CborDate.fromYmd(2023, 2, 8);
7988
- * const timestamp = date.timestamp();
7972
+ * const set1 = CborSet.fromArray([1, 2, 3]);
7973
+ * const set2 = CborSet.fromArray([2, 3, 4]);
7974
+ * const diff = set1.difference(set2);
7975
+ * // diff contains [1]
7989
7976
  * ```
7990
7977
  */
7991
- timestamp() {
7992
- return this._seconds;
7978
+ difference(other) {
7979
+ const result = new CborSet();
7980
+ for (const value of this) {
7981
+ const extracted = extractCbor(value);
7982
+ if (!other.contains(extracted)) result.insert(extracted);
7983
+ }
7984
+ return result;
7993
7985
  }
7994
7986
  /**
7995
- * Add seconds to this date.
7987
+ * Check if this set is a subset of another set.
7996
7988
  *
7997
- * @param seconds - Seconds to add (can be fractional)
7998
- * @returns New CborDate instance
7989
+ * @param other - Other set
7990
+ * @returns true if all elements of this set are in the other set
7991
+ */
7992
+ isSubsetOf(other) {
7993
+ for (const value of this) if (!other.contains(extractCbor(value))) return false;
7994
+ return true;
7995
+ }
7996
+ /**
7997
+ * Check if this set is a superset of another set.
7999
7998
  *
8000
- * @example
8001
- * ```typescript
8002
- * const date = CborDate.fromYmd(2022, 3, 21);
8003
- * const tomorrow = date.add(24 * 60 * 60);
8004
- * ```
7999
+ * @param other - Other set
8000
+ * @returns true if all elements of the other set are in this set
8005
8001
  */
8006
- add(seconds) {
8007
- return CborDate.fromTimestamp(this.timestamp() + seconds);
8002
+ isSupersetOf(other) {
8003
+ return other.isSubsetOf(this);
8008
8004
  }
8009
8005
  /**
8010
- * Subtract seconds from this date.
8006
+ * Iterate over elements in the set.
8011
8007
  *
8012
- * @param seconds - Seconds to subtract (can be fractional)
8013
- * @returns New CborDate instance
8008
+ * Elements are returned in deterministic order (by CBOR encoding).
8014
8009
  *
8015
8010
  * @example
8016
8011
  * ```typescript
8017
- * const date = CborDate.fromYmd(2022, 3, 21);
8018
- * const yesterday = date.subtract(24 * 60 * 60);
8012
+ * const set = CborSet.fromArray([3, 1, 2]);
8013
+ * for (const value of set) {
8014
+ * console.log(extractCbor(value));
8015
+ * }
8019
8016
  * ```
8020
8017
  */
8021
- subtract(seconds) {
8022
- return CborDate.fromTimestamp(this.timestamp() - seconds);
8018
+ *[Symbol.iterator]() {
8019
+ for (const [_, value] of this._map) yield value;
8023
8020
  }
8024
8021
  /**
8025
- * Get the difference in seconds between this date and another.
8022
+ * Get all values as an array.
8026
8023
  *
8027
- * @param other - Other CborDate to compare with
8028
- * @returns Difference in seconds (this - other)
8024
+ * @returns Array of CBOR values in deterministic order
8029
8025
  *
8030
8026
  * @example
8031
8027
  * ```typescript
8032
- * const date1 = CborDate.fromYmd(2022, 3, 22);
8033
- * const date2 = CborDate.fromYmd(2022, 3, 21);
8034
- * const diff = date1.difference(date2);
8035
- * // Returns 86400 (one day in seconds)
8028
+ * const set = CborSet.fromArray([3, 1, 2]);
8029
+ * const values = set.values();
8030
+ * // Values in deterministic order
8036
8031
  * ```
8037
8032
  */
8038
- difference(other) {
8039
- return this.timestamp() - other.timestamp();
8033
+ values() {
8034
+ return Array.from(this);
8040
8035
  }
8041
8036
  /**
8042
- * Implementation of the `CborTagged` interface for `CborDate`.
8037
+ * Execute a function for each element.
8043
8038
  *
8044
- * This implementation specifies that `CborDate` values are tagged with CBOR tag 1,
8045
- * which is the standard CBOR tag for date/time values represented as seconds
8046
- * since the Unix epoch per RFC 8949.
8039
+ * @param callback - Function to call for each element
8047
8040
  *
8048
- * @returns A vector containing tag 1
8041
+ * @example
8042
+ * ```typescript
8043
+ * set.forEach(value => {
8044
+ * console.log(extractCbor(value));
8045
+ * });
8046
+ * ```
8049
8047
  */
8050
- cborTags() {
8051
- return [createTag(1, "date")];
8048
+ forEach(callback) {
8049
+ for (const value of this) callback(value);
8052
8050
  }
8053
8051
  /**
8054
- * Implementation of the `CborTaggedEncodable` interface for `CborDate`.
8052
+ * Encode the set as an (untagged) CBOR array of its elements, in canonical
8053
+ * ascending CBOR-byte order. Matches Rust `From<Set> for CBOR`.
8055
8054
  *
8056
- * Converts this `CborDate` to an untagged CBOR value.
8057
- *
8058
- * The date is converted to a numeric value representing the number of
8059
- * seconds since the Unix epoch. This value may be an integer or a
8060
- * floating-point number, depending on whether the date has fractional
8061
- * seconds.
8062
- *
8063
- * @returns A CBOR value representing the timestamp
8055
+ * @returns CBOR array
8064
8056
  */
8065
8057
  untaggedCbor() {
8066
- return cbor(this.timestamp());
8067
- }
8068
- /**
8069
- * Converts this `CborDate` to a tagged CBOR value with tag 1.
8070
- *
8071
- * @returns Tagged CBOR value
8072
- */
8073
- taggedCbor() {
8074
- return createTaggedCbor(this);
8058
+ return cbor(this.values());
8075
8059
  }
8076
8060
  /**
8077
- * Implementation of the `CborTaggedDecodable` interface for `CborDate`.
8078
- *
8079
- * Creates a `CborDate` from an untagged CBOR value.
8080
- *
8081
- * The CBOR value must be a numeric value (integer or floating-point)
8082
- * representing the number of seconds since the Unix epoch.
8083
- *
8084
- * @param cbor - The untagged CBOR value
8061
+ * Decode a CborSet from a CBOR array into this instance.
8085
8062
  *
8086
- * @returns This CborDate instance (mutated)
8063
+ * Mirrors Rust `Set::try_from_vec`, calling `insert_next` per item, so the
8064
+ * array must already be in strict ascending CBOR-byte order with no
8065
+ * duplicates (else `MisorderedMapKey`/`DuplicateMapKey`).
8087
8066
  *
8088
- * @throws Error if the CBOR value is not a valid timestamp
8067
+ * @param c - CBOR array value
8068
+ * @returns this
8069
+ * @throws CborError of type `WrongType` if `c` is not an array.
8089
8070
  */
8090
- fromUntaggedCbor(cbor) {
8091
- let timestamp;
8092
- switch (cbor.type) {
8093
- case MajorType.Unsigned:
8094
- timestamp = typeof cbor.value === "number" ? cbor.value : Number(cbor.value);
8095
- break;
8096
- case MajorType.Negative:
8097
- if (typeof cbor.value === "bigint") timestamp = Number(-cbor.value - 1n);
8098
- else timestamp = -cbor.value - 1;
8099
- break;
8100
- case MajorType.Simple:
8101
- if (cbor.value.type === "Float") timestamp = cbor.value.value;
8102
- else throw new CborError({ type: "WrongType" });
8103
- break;
8104
- default: throw new CborError({ type: "WrongType" });
8105
- }
8106
- this._seconds = timestamp;
8071
+ fromUntaggedCbor(c) {
8072
+ if (c.type !== MajorType.Array) throw new CborError({ type: "WrongType" });
8073
+ this.clear();
8074
+ for (const value of c.value) this.insertNext(extractCbor(value));
8107
8075
  return this;
8108
8076
  }
8109
8077
  /**
8110
- * Creates a `CborDate` from a tagged CBOR value with tag 1.
8111
- *
8112
- * @param cbor - Tagged CBOR value
8078
+ * Decode a CborSet from a CBOR array.
8113
8079
  *
8114
- * @returns This CborDate instance (mutated)
8115
- *
8116
- * @throws Error if the CBOR value has the wrong tag or cannot be decoded
8080
+ * @param c - CBOR array value
8081
+ * @returns Decoded CborSet instance
8117
8082
  */
8118
- fromTaggedCbor(cbor) {
8119
- validateTag(cbor, this.cborTags());
8120
- const content = extractTaggedContent(cbor);
8121
- return this.fromUntaggedCbor(content);
8083
+ static fromCbor(c) {
8084
+ return new CborSet().fromUntaggedCbor(c);
8122
8085
  }
8123
8086
  /**
8124
- * Static method to create a CborDate from tagged CBOR.
8087
+ * Convert to CBOR array (untagged).
8125
8088
  *
8126
- * @param cbor - Tagged CBOR value
8127
- * @returns New CborDate instance
8089
+ * @returns CBOR array
8128
8090
  */
8129
- static fromTaggedCbor(cbor) {
8130
- return new CborDate().fromTaggedCbor(cbor);
8091
+ toCbor() {
8092
+ return this.untaggedCbor();
8131
8093
  }
8132
8094
  /**
8133
- * Static method to create a CborDate from untagged CBOR.
8095
+ * Convert to encoded CBOR bytes.
8134
8096
  *
8135
- * @param cbor - Untagged CBOR value
8136
- * @returns New CborDate instance
8097
+ * @returns Encoded CBOR bytes
8137
8098
  */
8138
- static fromUntaggedCbor(cbor) {
8139
- return new CborDate().fromUntaggedCbor(cbor);
8099
+ toBytes() {
8100
+ return cborData(this.untaggedCbor());
8140
8101
  }
8141
8102
  /**
8142
- * Implementation of the `toString` method for `CborDate`.
8143
- *
8144
- * This implementation provides a string representation of a `CborDate` in ISO-8601
8145
- * format. For dates with time exactly at midnight (00:00:00), only the date
8146
- * part is shown. For other times, a full date-time string is shown.
8103
+ * Convert to JavaScript Set.
8147
8104
  *
8148
- * @returns String representation in ISO-8601 format
8105
+ * @returns JavaScript Set with extracted values
8149
8106
  *
8150
8107
  * @example
8151
8108
  * ```typescript
8152
- * // A date at midnight will display as just the date
8153
- * const date = CborDate.fromYmd(2023, 2, 8);
8154
- * // Returns "2023-02-08"
8155
- * console.log(date.toString());
8156
- *
8157
- * // A date with time will display as date and time
8158
- * const date2 = CborDate.fromYmdHms(2023, 2, 8, 15, 30, 45);
8159
- * // Returns "2023-02-08T15:30:45.000Z"
8160
- * console.log(date2.toString());
8109
+ * const cborSet = CborSet.fromArray([1, 2, 3]);
8110
+ * const jsSet = cborSet.toSet();
8111
+ * console.log(jsSet.has(1)); // true
8161
8112
  * ```
8162
8113
  */
8163
- toString() {
8164
- const dt = /* @__PURE__ */ new Date(this._seconds * 1e3);
8165
- if (!(dt.getUTCHours() !== 0 || dt.getUTCMinutes() !== 0 || dt.getUTCSeconds() !== 0)) {
8166
- const datePart = dt.toISOString().split("T")[0];
8167
- if (datePart === void 0) throw new CborError({
8168
- type: "Custom",
8169
- message: "Invalid ISO string format"
8170
- });
8171
- return datePart;
8172
- } else return dt.toISOString().replace(/\.\d{3}Z$/, "Z");
8114
+ toSet() {
8115
+ const result = /* @__PURE__ */ new Set();
8116
+ for (const value of this) result.add(extractCbor(value));
8117
+ return result;
8173
8118
  }
8174
8119
  /**
8175
- * Compare two dates for equality.
8120
+ * Convert to JavaScript Array.
8176
8121
  *
8177
- * @param other - Other CborDate to compare
8178
- * @returns true if dates represent the same moment in time
8122
+ * @returns Array with extracted values
8179
8123
  */
8180
- equals(other) {
8181
- return this._seconds === other._seconds;
8124
+ toArray() {
8125
+ return Array.from(this.toSet());
8182
8126
  }
8183
8127
  /**
8184
- * Compare two dates.
8128
+ * Get diagnostic notation for the set.
8185
8129
  *
8186
- * @param other - Other CborDate to compare
8187
- * @returns -1 if this < other, 0 if equal, 1 if this > other
8130
+ * @returns String representation
8131
+ *
8132
+ * @example
8133
+ * ```typescript
8134
+ * const set = CborSet.fromArray([1, 2, 3]);
8135
+ * console.log(set.diagnostic); // "[1, 2, 3]"
8136
+ * ```
8188
8137
  */
8189
- compare(other) {
8190
- if (this._seconds < other._seconds) return -1;
8191
- if (this._seconds > other._seconds) return 1;
8192
- return 0;
8138
+ get diagnostic() {
8139
+ return `[${this.values().map((v) => {
8140
+ const extracted = extractCbor(v);
8141
+ if (typeof extracted === "string") return `"${extracted}"`;
8142
+ return String(extracted);
8143
+ }).join(", ")}]`;
8193
8144
  }
8194
8145
  /**
8195
- * Convert to JSON (returns ISO 8601 string).
8146
+ * Convert to string (same as diagnostic).
8196
8147
  *
8197
- * @returns ISO 8601 string
8148
+ * @returns String representation
8198
8149
  */
8199
- toJSON() {
8200
- return this.toString();
8150
+ toString() {
8151
+ return this.diagnostic;
8201
8152
  }
8202
- constructor() {
8203
- this._seconds = Date.now() / 1e3;
8153
+ /**
8154
+ * Convert to JSON (returns array of values).
8155
+ *
8156
+ * @returns Array for JSON serialization
8157
+ */
8158
+ toJSON() {
8159
+ return this.toArray();
8204
8160
  }
8205
8161
  };
8162
+ /**
8163
+ * Convert a value to CBOR for use in set operations.
8164
+ *
8165
+ * @internal
8166
+ */
8167
+ function encodeCborValue(value) {
8168
+ if (typeof value === "object" && value !== null && "isCbor" in value && value.isCbor === true) return value;
8169
+ return cbor(value);
8170
+ }
8206
8171
  //#endregion
8207
- //#region src/bignum.ts
8172
+ //#region src/cbor-tagged-encodable.ts
8208
8173
  /**
8209
8174
  * Copyright © 2023-2026 Blockchain Commons, LLC
8210
8175
  * Copyright © 2025-2026 Parity Technologies
8211
8176
  *
8212
8177
  *
8213
- * CBOR bignum (tags 2 and 3) support.
8178
+ * Tagged CBOR encoding support.
8214
8179
  *
8215
- * This module provides conversion between CBOR and JavaScript BigInt types,
8216
- * implementing RFC 8949 §3.4.3 (Bignums) with dCBOR/CDE canonical encoding rules.
8180
+ * This module provides the `CborTaggedEncodable` interface, which enables types to
8181
+ * be encoded as tagged CBOR values.
8217
8182
  *
8218
- * Encoding:
8219
- * - `biguintToCbor` always encodes as tag 2 (positive bignum) with a byte
8220
- * string content.
8221
- * - `bigintToCbor` encodes as tag 2 for non-negative values or tag 3
8222
- * (negative bignum) for negative values.
8223
- * - No numeric reduction is performed: values are always encoded as bignums,
8224
- * even if they would fit in normal CBOR integers.
8183
+ * CBOR tags provide semantic information about the encoded data. For example,
8184
+ * tag 1 is used for dates, indicating that the value should be interpreted
8185
+ * as a timestamp. The dCBOR library ensures these tags are encoded
8186
+ * deterministically.
8225
8187
  *
8226
- * Decoding:
8227
- * - Accepts CBOR integers (major types 0 and 1) and converts them to bigints.
8228
- * - Accepts tag 2 (positive bignum) and tag 3 (negative bignum) with byte
8229
- * string content.
8230
- * - Enforces shortest-form canonical representation for bignum magnitudes.
8231
- * - Rejects floating-point values.
8188
+ * This interface enables seamless encoding of TypeScript types to properly tagged CBOR
8189
+ * values.
8232
8190
  *
8233
- * @module bignum
8191
+ * @module cbor-tagged-encodable
8234
8192
  */
8235
- const TAG_2_POSITIVE_BIGNUM = 2;
8236
- const TAG_3_NEGATIVE_BIGNUM = 3;
8237
8193
  /**
8238
- * Validates that a bignum magnitude byte string is in shortest canonical form.
8239
- *
8240
- * Matches Rust's `validate_bignum_magnitude()`.
8194
+ * Helper function to create tagged CBOR from an encodable object.
8241
8195
  *
8242
- * Rules:
8243
- * - For positive bignums (tag 2): empty byte string represents zero;
8244
- * non-empty must not have leading zero bytes.
8245
- * - For negative bignums (tag 3): byte string must not be empty
8246
- * (magnitude zero is encoded as `0x00`); must not have leading zero bytes
8247
- * except when the magnitude is zero (single `0x00`).
8196
+ * Uses the first tag from cborTags().
8248
8197
  *
8249
- * @param bytes - The magnitude byte string to validate
8250
- * @param isNegative - Whether this is for a negative bignum (tag 3)
8251
- * @throws CborError with type NonCanonicalNumeric on validation failure
8198
+ * @param encodable - Object implementing CborTaggedEncodable
8199
+ * @returns Tagged CBOR value
8252
8200
  */
8253
- function validateBignumMagnitude(bytes, isNegative) {
8254
- if (isNegative) {
8255
- if (bytes.length === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8256
- if (bytes.length > 1 && bytes[0] === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8257
- } else if (bytes.length > 0 && bytes[0] === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8258
- }
8201
+ const createTaggedCbor = (encodable) => {
8202
+ const tags = encodable.cborTags();
8203
+ if (tags.length === 0) throw new CborError({
8204
+ type: "Custom",
8205
+ message: "No tags defined for this type"
8206
+ });
8207
+ const tag = tags[0];
8208
+ if (tag === void 0) throw new CborError({
8209
+ type: "Custom",
8210
+ message: "Tag is undefined"
8211
+ });
8212
+ const untagged = encodable.untaggedCbor();
8213
+ return attachMethods({
8214
+ isCbor: true,
8215
+ type: MajorType.Tagged,
8216
+ tag: tag.value,
8217
+ value: untagged
8218
+ });
8219
+ };
8259
8220
  /**
8260
- * Strips leading zero bytes from a byte array, returning the minimal
8261
- * representation.
8262
- *
8263
- * Matches Rust's `strip_leading_zeros()`.
8221
+ * Default `taggedCborData()` implementation `taggedCbor().toData()`.
8264
8222
  *
8265
- * @param bytes - The byte array to strip
8266
- * @returns A subarray with leading zeros removed
8223
+ * Mirrors Rust's default `tagged_cbor_data()` impl on
8224
+ * `CBORTaggedEncodable`. TypeScript interfaces don't carry method bodies,
8225
+ * so this helper plays the role of the Rust trait default; concrete types
8226
+ * call it from their own `taggedCborData()` if they don't need to override.
8267
8227
  */
8268
- function stripLeadingZeros(bytes) {
8269
- let start = 0;
8270
- while (start < bytes.length && bytes[start] === 0) start++;
8271
- return bytes.subarray(start);
8272
- }
8228
+ const taggedCborData = (encodable) => encodable.taggedCbor().toData();
8229
+ //#endregion
8230
+ //#region src/cbor-tagged-decodable.ts
8273
8231
  /**
8274
- * Convert a non-negative bigint to a big-endian byte array.
8232
+ * Copyright © 2023-2026 Blockchain Commons, LLC
8233
+ * Copyright © 2025-2026 Parity Technologies
8275
8234
  *
8276
- * Zero returns an empty Uint8Array.
8277
8235
  *
8278
- * @param value - A non-negative bigint value
8279
- * @returns Big-endian byte representation
8280
- */
8281
- function bigintToBytes(value) {
8282
- if (value === 0n) return new Uint8Array(0);
8283
- const hex = value.toString(16);
8284
- const padded = hex.length % 2 !== 0 ? `0${hex}` : hex;
8285
- const bytes = new Uint8Array(padded.length / 2);
8286
- for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(padded.substring(i * 2, i * 2 + 2), 16);
8287
- return bytes;
8288
- }
8289
- /**
8290
- * Convert a big-endian byte array to a bigint.
8236
+ * Tagged CBOR decoding support.
8291
8237
  *
8292
- * Empty array returns 0n.
8238
+ * This module provides the `CborTaggedDecodable` interface, which enables types to
8239
+ * be decoded from tagged CBOR values.
8293
8240
  *
8294
- * @param bytes - Big-endian byte representation
8295
- * @returns The bigint value
8241
+ * Tagged CBOR values include semantic information about how to interpret the
8242
+ * data. This interface allows TypeScript types to verify that incoming CBOR data has the
8243
+ * expected tag(s) and to decode the data appropriately.
8244
+ *
8245
+ * @module cbor-tagged-decodable
8296
8246
  */
8297
- function bytesToBigint(bytes) {
8298
- if (bytes.length === 0) return 0n;
8299
- let result = 0n;
8300
- for (const byte of bytes) result = result << 8n | BigInt(byte);
8301
- return result;
8302
- }
8303
8247
  /**
8304
- * Encode a non-negative bigint as a CBOR tag 2 (positive bignum).
8248
+ * Helper function to validate that a CBOR value has one of the expected tags.
8305
8249
  *
8306
- * Matches Rust's `From<BigUint> for CBOR`.
8250
+ * @param cbor - CBOR value to validate
8251
+ * @param expectedTags - Array of valid tags
8252
+ * @returns The matching tag
8253
+ * @throws Error if the value is not tagged or has an unexpected tag
8254
+ */
8255
+ const validateTag = (cbor, expectedTags) => {
8256
+ if (cbor.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
8257
+ const tagValue = cbor.tag;
8258
+ const matchingTag = expectedTags.find((t) => tagValuesEqual(t.value, tagValue));
8259
+ if (matchingTag === void 0) throw new CborError({
8260
+ type: "WrongTag",
8261
+ expected: expectedTags[0],
8262
+ actual: { value: tagValue }
8263
+ });
8264
+ return matchingTag;
8265
+ };
8266
+ /**
8267
+ * Helper function to extract the content from a tagged CBOR value.
8307
8268
  *
8308
- * The value is always encoded as a bignum regardless of size.
8309
- * Zero is encoded as tag 2 with an empty byte string.
8269
+ * @param cbor - Tagged CBOR value
8270
+ * @returns The untagged content
8271
+ * @throws Error if the value is not tagged
8272
+ */
8273
+ const extractTaggedContent = (cbor) => {
8274
+ if (cbor.type !== MajorType.Tagged) throw new CborError({ type: "WrongType" });
8275
+ return cbor.value;
8276
+ };
8277
+ /**
8278
+ * Default `fromTaggedCborData()` implementation — `decodeCbor(data)` then
8279
+ * delegate to the decodable's `fromTaggedCbor()`.
8310
8280
  *
8311
- * @param value - A non-negative bigint (must be >= 0n)
8312
- * @returns CBOR tagged value
8313
- * @throws CborError with type OutOfRange if value is negative
8281
+ * Mirrors Rust's default `from_tagged_cbor_data` impl on
8282
+ * `CBORTaggedDecodable`.
8314
8283
  */
8315
- function biguintToCbor(value) {
8316
- if (value < 0n) throw new CborError({ type: "OutOfRange" });
8317
- return toTaggedValue(TAG_2_POSITIVE_BIGNUM, stripLeadingZeros(bigintToBytes(value)));
8284
+ function fromTaggedCborData(decodable, data) {
8285
+ return decodable.fromTaggedCbor(decodeCbor(data));
8318
8286
  }
8319
8287
  /**
8320
- * Encode a bigint as a CBOR tag 2 or tag 3 bignum.
8321
- *
8322
- * Matches Rust's `From<BigInt> for CBOR`.
8323
- *
8324
- * - Non-negative values use tag 2 (positive bignum).
8325
- * - Negative values use tag 3 (negative bignum), where the encoded
8326
- * magnitude is `|value| - 1` per RFC 8949.
8288
+ * Default `fromUntaggedCborData()` implementation `decodeCbor(data)`
8289
+ * then delegate to the decodable's `fromUntaggedCbor()`.
8327
8290
  *
8328
- * @param value - Any bigint value
8329
- * @returns CBOR tagged value
8291
+ * Mirrors Rust's default `from_untagged_cbor_data` impl on
8292
+ * `CBORTaggedDecodable`.
8330
8293
  */
8331
- function bigintToCbor(value) {
8332
- if (value >= 0n) return biguintToCbor(value);
8333
- const stripped = stripLeadingZeros(bigintToBytes(-value - 1n));
8334
- return toTaggedValue(TAG_3_NEGATIVE_BIGNUM, stripped.length === 0 ? new Uint8Array([0]) : stripped);
8294
+ function fromUntaggedCborData(decodable, data) {
8295
+ return decodable.fromUntaggedCbor(decodeCbor(data));
8335
8296
  }
8297
+ //#endregion
8298
+ //#region src/date.ts
8336
8299
  /**
8337
- * Decode a BigUint from an untagged CBOR byte string.
8300
+ * Copyright © 2023-2026 Blockchain Commons, LLC
8301
+ * Copyright © 2025-2026 Parity Technologies
8338
8302
  *
8339
- * Matches Rust's `biguint_from_untagged_cbor()`.
8340
8303
  *
8341
- * This function is intended for use in tag summarizers where the tag has
8342
- * already been stripped. It expects a CBOR byte string representing the
8343
- * big-endian magnitude of a positive bignum (tag 2 content).
8304
+ * Date/time support for CBOR with tag(1) encoding.
8344
8305
  *
8345
- * Enforces canonical encoding: no leading zero bytes (except empty for zero).
8306
+ * A CBOR-friendly representation of a date and time.
8346
8307
  *
8347
- * @param cbor - A CBOR value that should be a byte string
8348
- * @returns Non-negative bigint
8349
- * @throws CborError with type WrongType if not a byte string
8350
- * @throws CborError with type NonCanonicalNumeric if encoding is non-canonical
8351
- */
8352
- function biguintFromUntaggedCbor(cbor) {
8353
- if (cbor.type !== MajorType.ByteString) throw new CborError({ type: "WrongType" });
8354
- const bytes = cbor.value;
8355
- validateBignumMagnitude(bytes, false);
8356
- return bytesToBigint(bytes);
8357
- }
8358
- /**
8359
- * Decode a BigInt from an untagged CBOR byte string for a negative bignum.
8308
+ * The `CborDate` type provides a wrapper around JavaScript's native `Date` that
8309
+ * supports encoding and decoding to/from CBOR with tag 1, following the CBOR
8310
+ * date/time standard specified in RFC 8949.
8360
8311
  *
8361
- * Matches Rust's `bigint_from_negative_untagged_cbor()`.
8312
+ * When encoded to CBOR, dates are represented as tag 1 followed by a numeric
8313
+ * value representing the number of seconds since (or before) the Unix epoch
8314
+ * (1970-01-01T00:00:00Z). The numeric value can be a positive or negative
8315
+ * integer, or a floating-point value for dates with fractional seconds.
8362
8316
  *
8363
- * This function is intended for use in tag summarizers where the tag has
8364
- * already been stripped. It expects a CBOR byte string representing `n` where
8365
- * the actual value is `-1 - n` (tag 3 content per RFC 8949).
8317
+ * @module date
8318
+ */
8319
+ /**
8320
+ * Normalize a timestamp (seconds since the Unix epoch) to whole seconds plus a
8321
+ * non-negative, sub-second nanosecond part, matching Rust's
8322
+ * `Date::from_timestamp` so dates round-trip byte-identically with the reference.
8366
8323
  *
8367
- * Enforces canonical encoding: no leading zero bytes (except single `0x00`
8368
- * for -1).
8324
+ * The nanosecond part is computed like Rust's `as u32` cast: truncated toward
8325
+ * zero and clamped to [0, u32::MAX]. So a negative fraction floors the value
8326
+ * (`-1.5` becomes `-1.0`) and sub-nanosecond precision is dropped
8327
+ * (`1.0000000005` becomes `1.0`).
8369
8328
  *
8370
- * @param cbor - A CBOR value that should be a byte string
8371
- * @returns Negative bigint
8372
- * @throws CborError with type WrongType if not a byte string
8373
- * @throws CborError with type NonCanonicalNumeric if encoding is non-canonical
8329
+ * @internal
8374
8330
  */
8375
- function bigintFromNegativeUntaggedCbor(cbor) {
8376
- if (cbor.type !== MajorType.ByteString) throw new CborError({ type: "WrongType" });
8377
- const bytes = cbor.value;
8378
- validateBignumMagnitude(bytes, true);
8379
- return -(bytesToBigint(bytes) + 1n);
8331
+ function normalizeTimestampSeconds(seconds) {
8332
+ if (!Number.isFinite(seconds)) throw new CborError({
8333
+ type: "InvalidDate",
8334
+ message: "non-finite timestamp"
8335
+ });
8336
+ const whole = Math.trunc(seconds);
8337
+ let nsecs = Math.trunc((seconds - whole) * 1e9);
8338
+ if (nsecs < 0) nsecs = 0;
8339
+ else if (nsecs > 4294967295) nsecs = 4294967295;
8340
+ return whole + nsecs / 1e9;
8380
8341
  }
8381
8342
  /**
8382
- * Convert CBOR to a non-negative bigint.
8343
+ * A CBOR-friendly representation of a date and time.
8383
8344
  *
8384
- * Matches Rust's `TryFrom<CBOR> for BigUint`.
8345
+ * The `CborDate` type provides a wrapper around JavaScript's native `Date` that
8346
+ * supports encoding and decoding to/from CBOR with tag 1, following the CBOR
8347
+ * date/time standard specified in RFC 8949.
8385
8348
  *
8386
- * Accepts:
8387
- * - Major type 0 (unsigned integer)
8388
- * - Tag 2 (positive bignum) with canonical byte string
8349
+ * When encoded to CBOR, dates are represented as tag 1 followed by a numeric
8350
+ * value representing the number of seconds since (or before) the Unix epoch
8351
+ * (1970-01-01T00:00:00Z). The numeric value can be a positive or negative
8352
+ * integer, or a floating-point value for dates with fractional seconds.
8389
8353
  *
8390
- * Rejects:
8391
- * - Major type 1 (negative integer) -> OutOfRange
8392
- * - Tag 3 (negative bignum) -> OutOfRange
8393
- * - Floating-point values -> WrongType
8394
- * - Non-canonical bignum encodings -> NonCanonicalNumeric
8354
+ * # Features
8395
8355
  *
8396
- * @param cbor - The CBOR value to convert
8356
+ * - Supports UTC dates with optional fractional seconds
8357
+ * - Provides convenient constructors for common date creation patterns
8358
+ * - Implements the `CborTagged`, `CborTaggedEncodable`, and
8359
+ * `CborTaggedDecodable` interfaces
8360
+ * - Supports arithmetic operations with durations and between dates
8361
+ *
8362
+ * @example
8363
+ * ```typescript
8364
+ * import { CborDate } from './date';
8365
+ *
8366
+ * // Create a date from a timestamp (seconds since Unix epoch)
8367
+ * const date = CborDate.fromTimestamp(1675854714.0);
8368
+ *
8369
+ * // Create a date from year, month, day
8370
+ * const date2 = CborDate.fromYmd(2023, 2, 8);
8371
+ *
8372
+ * // Convert to CBOR
8373
+ * const cborValue = date.taggedCbor();
8374
+ *
8375
+ * // Decode from CBOR
8376
+ * const decoded = CborDate.fromTaggedCbor(cborValue);
8377
+ * ```
8378
+ */
8379
+ var CborDate = class CborDate {
8380
+ /**
8381
+ * Canonical timestamp in seconds since the Unix epoch as a JS `number`
8382
+ * (`f64`). dCBOR encodes Date (tag 1) as a numeric value in seconds, so
8383
+ * keeping `_seconds` as the source of truth avoids the millisecond-only
8384
+ * round-trip precision loss that going through a JS `Date` instance
8385
+ * introduced in earlier versions of this port.
8386
+ *
8387
+ * f64 still bounds the achievable precision (~16 decimal digits, so
8388
+ * roughly microseconds for current epoch values); Rust's
8389
+ * `chrono::DateTime<Utc>` retains nanoseconds in memory but encodes
8390
+ * to the same f64 over the wire, so the *encode/decode round-trip* is
8391
+ * byte-identical.
8392
+ */
8393
+ _seconds;
8394
+ /**
8395
+ * Creates a new `CborDate` from the given JavaScript `Date`.
8396
+ *
8397
+ * This method creates a new `CborDate` instance by wrapping a
8398
+ * JavaScript `Date`.
8399
+ *
8400
+ * @param dateTime - A `Date` instance to wrap
8401
+ *
8402
+ * @returns A new `CborDate` instance
8403
+ *
8404
+ * @example
8405
+ * ```typescript
8406
+ * const datetime = new Date();
8407
+ * const date = CborDate.fromDatetime(datetime);
8408
+ * ```
8409
+ */
8410
+ static fromDatetime(dateTime) {
8411
+ const instance = new CborDate();
8412
+ instance._seconds = dateTime.getTime() / 1e3;
8413
+ return instance;
8414
+ }
8415
+ /**
8416
+ * Creates a new `CborDate` from year, month, and day components.
8417
+ *
8418
+ * This method creates a new `CborDate` with the time set to 00:00:00 UTC.
8419
+ *
8420
+ * @param year - The year component (e.g., 2023)
8421
+ * @param month - The month component (1-12)
8422
+ * @param day - The day component (1-31)
8423
+ *
8424
+ * @returns A new `CborDate` instance
8425
+ *
8426
+ * @example
8427
+ * ```typescript
8428
+ * // Create February 8, 2023
8429
+ * const date = CborDate.fromYmd(2023, 2, 8);
8430
+ * ```
8431
+ *
8432
+ * @throws Error if the provided components do not form a valid date.
8433
+ */
8434
+ static fromYmd(year, month, day) {
8435
+ const dt = new Date(Date.UTC(year, month - 1, day, 0, 0, 0, 0));
8436
+ return CborDate.fromDatetime(dt);
8437
+ }
8438
+ /**
8439
+ * Creates a new `CborDate` from year, month, day, hour, minute, and second
8440
+ * components.
8441
+ *
8442
+ * @param year - The year component (e.g., 2023)
8443
+ * @param month - The month component (1-12)
8444
+ * @param day - The day component (1-31)
8445
+ * @param hour - The hour component (0-23)
8446
+ * @param minute - The minute component (0-59)
8447
+ * @param second - The second component (0-59)
8448
+ *
8449
+ * @returns A new `CborDate` instance
8450
+ *
8451
+ * @example
8452
+ * ```typescript
8453
+ * // Create February 8, 2023, 15:30:45 UTC
8454
+ * const date = CborDate.fromYmdHms(2023, 2, 8, 15, 30, 45);
8455
+ * ```
8456
+ *
8457
+ * @throws Error if the provided components do not form a valid date and time.
8458
+ */
8459
+ static fromYmdHms(year, month, day, hour, minute, second) {
8460
+ const dt = new Date(Date.UTC(year, month - 1, day, hour, minute, second, 0));
8461
+ return CborDate.fromDatetime(dt);
8462
+ }
8463
+ /**
8464
+ * Creates a new `CborDate` from seconds since (or before) the Unix epoch.
8465
+ *
8466
+ * This method creates a new `CborDate` representing the specified number of
8467
+ * seconds since the Unix epoch (1970-01-01T00:00:00Z). Negative values
8468
+ * represent times before the epoch.
8469
+ *
8470
+ * @param secondsSinceUnixEpoch - Seconds from the Unix epoch (positive or
8471
+ * negative), which can include a fractional part for sub-second
8472
+ * precision
8473
+ *
8474
+ * @returns A new `CborDate` instance
8475
+ *
8476
+ * @example
8477
+ * ```typescript
8478
+ * // Create a date from a timestamp
8479
+ * const date = CborDate.fromTimestamp(1675854714.0);
8480
+ *
8481
+ * // Create a date one second before the Unix epoch
8482
+ * const beforeEpoch = CborDate.fromTimestamp(-1.0);
8483
+ *
8484
+ * // Create a date with fractional seconds
8485
+ * const withFraction = CborDate.fromTimestamp(1675854714.5);
8486
+ * ```
8487
+ */
8488
+ static fromTimestamp(secondsSinceUnixEpoch) {
8489
+ const instance = new CborDate();
8490
+ instance._seconds = normalizeTimestampSeconds(secondsSinceUnixEpoch);
8491
+ return instance;
8492
+ }
8493
+ /**
8494
+ * Creates a new `CborDate` from a string containing an ISO-8601 (RFC-3339)
8495
+ * date (with or without time).
8496
+ *
8497
+ * This method parses a string representation of a date or date-time in
8498
+ * ISO-8601/RFC-3339 format and creates a new `CborDate` instance. It
8499
+ * supports both full date-time strings (e.g., "2023-02-08T15:30:45Z")
8500
+ * and date-only strings (e.g., "2023-02-08").
8501
+ *
8502
+ * @param value - A string containing a date or date-time in ISO-8601/RFC-3339
8503
+ * format
8504
+ *
8505
+ * @returns A new `CborDate` instance if parsing succeeds
8506
+ *
8507
+ * @throws Error if the string cannot be parsed as a valid date or date-time
8508
+ *
8509
+ * @example
8510
+ * ```typescript
8511
+ * // Parse a date-time string
8512
+ * const date = CborDate.fromString("2023-02-08T15:30:45Z");
8513
+ *
8514
+ * // Parse a date-only string (time will be set to 00:00:00)
8515
+ * const date2 = CborDate.fromString("2023-02-08");
8516
+ * ```
8517
+ */
8518
+ static fromString(value) {
8519
+ const invalidDate = new CborError({
8520
+ type: "InvalidDate",
8521
+ message: "Invalid date string"
8522
+ });
8523
+ const rfc3339 = /^\d{4}-\d{2}-\d{2}[Tt]\d{2}:\d{2}:\d{2}(\.\d+)?([Zz]|[+-]\d{2}:\d{2})$/;
8524
+ const dateOnly = /^\d{4}-\d{2}-\d{2}$/;
8525
+ let parsed;
8526
+ if (rfc3339.test(value)) parsed = new Date(value);
8527
+ else if (dateOnly.test(value)) parsed = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
8528
+ else throw invalidDate;
8529
+ const [y, m, d] = value.slice(0, 10).split("-").map(Number);
8530
+ const probe = new Date(Date.UTC(y, m - 1, d));
8531
+ if (!(probe.getUTCFullYear() === y && probe.getUTCMonth() === m - 1 && probe.getUTCDate() === d) || isNaN(parsed.getTime())) throw invalidDate;
8532
+ return CborDate.fromDatetime(parsed);
8533
+ }
8534
+ /**
8535
+ * Creates a new `CborDate` containing the current date and time.
8536
+ *
8537
+ * @returns A new `CborDate` instance representing the current UTC date and time
8538
+ *
8539
+ * @example
8540
+ * ```typescript
8541
+ * const now = CborDate.now();
8542
+ * ```
8543
+ */
8544
+ static now() {
8545
+ return CborDate.fromDatetime(/* @__PURE__ */ new Date());
8546
+ }
8547
+ /**
8548
+ * Creates a new `CborDate` containing the current date and time plus the given
8549
+ * duration.
8550
+ *
8551
+ * @param durationMs - The duration in milliseconds to add to the current time
8552
+ *
8553
+ * @returns A new `CborDate` instance representing the current UTC date and time plus
8554
+ * the duration
8555
+ *
8556
+ * @example
8557
+ * ```typescript
8558
+ * // Get a date 1 hour from now
8559
+ * const oneHourLater = CborDate.withDurationFromNow(3600 * 1000);
8560
+ * ```
8561
+ */
8562
+ static withDurationFromNow(durationMs) {
8563
+ const future = new Date((/* @__PURE__ */ new Date()).getTime() + durationMs);
8564
+ return CborDate.fromDatetime(future);
8565
+ }
8566
+ /**
8567
+ * Returns the underlying JavaScript `Date` object.
8568
+ *
8569
+ * This method provides access to the wrapped JavaScript `Date`
8570
+ * instance.
8571
+ *
8572
+ * @returns The wrapped `Date` instance
8573
+ *
8574
+ * @example
8575
+ * ```typescript
8576
+ * const date = CborDate.now();
8577
+ * const datetime = date.datetime();
8578
+ * const year = datetime.getFullYear();
8579
+ * ```
8580
+ */
8581
+ datetime() {
8582
+ return /* @__PURE__ */ new Date(this._seconds * 1e3);
8583
+ }
8584
+ /**
8585
+ * Returns the `CborDate` as the number of seconds since the Unix epoch.
8586
+ *
8587
+ * This method converts the date to a floating-point number representing
8588
+ * the number of seconds since the Unix epoch (1970-01-01T00:00:00Z).
8589
+ * Negative values represent times before the epoch. The fractional
8590
+ * part represents sub-second precision.
8591
+ *
8592
+ * @returns Seconds since the Unix epoch as a `number`
8593
+ *
8594
+ * @example
8595
+ * ```typescript
8596
+ * const date = CborDate.fromYmd(2023, 2, 8);
8597
+ * const timestamp = date.timestamp();
8598
+ * ```
8599
+ */
8600
+ timestamp() {
8601
+ return this._seconds;
8602
+ }
8603
+ /**
8604
+ * Add seconds to this date.
8605
+ *
8606
+ * @param seconds - Seconds to add (can be fractional)
8607
+ * @returns New CborDate instance
8608
+ *
8609
+ * @example
8610
+ * ```typescript
8611
+ * const date = CborDate.fromYmd(2022, 3, 21);
8612
+ * const tomorrow = date.add(24 * 60 * 60);
8613
+ * ```
8614
+ */
8615
+ add(seconds) {
8616
+ return CborDate.fromTimestamp(this.timestamp() + seconds);
8617
+ }
8618
+ /**
8619
+ * Subtract seconds from this date.
8620
+ *
8621
+ * @param seconds - Seconds to subtract (can be fractional)
8622
+ * @returns New CborDate instance
8623
+ *
8624
+ * @example
8625
+ * ```typescript
8626
+ * const date = CborDate.fromYmd(2022, 3, 21);
8627
+ * const yesterday = date.subtract(24 * 60 * 60);
8628
+ * ```
8629
+ */
8630
+ subtract(seconds) {
8631
+ return CborDate.fromTimestamp(this.timestamp() - seconds);
8632
+ }
8633
+ /**
8634
+ * Get the difference in seconds between this date and another.
8635
+ *
8636
+ * @param other - Other CborDate to compare with
8637
+ * @returns Difference in seconds (this - other)
8638
+ *
8639
+ * @example
8640
+ * ```typescript
8641
+ * const date1 = CborDate.fromYmd(2022, 3, 22);
8642
+ * const date2 = CborDate.fromYmd(2022, 3, 21);
8643
+ * const diff = date1.difference(date2);
8644
+ * // Returns 86400 (one day in seconds)
8645
+ * ```
8646
+ */
8647
+ difference(other) {
8648
+ return this.timestamp() - other.timestamp();
8649
+ }
8650
+ /**
8651
+ * Implementation of the `CborTagged` interface for `CborDate`.
8652
+ *
8653
+ * This implementation specifies that `CborDate` values are tagged with CBOR tag 1,
8654
+ * which is the standard CBOR tag for date/time values represented as seconds
8655
+ * since the Unix epoch per RFC 8949.
8656
+ *
8657
+ * @returns A vector containing tag 1
8658
+ */
8659
+ cborTags() {
8660
+ return [createTag(1, "date")];
8661
+ }
8662
+ /**
8663
+ * Implementation of the `CborTaggedEncodable` interface for `CborDate`.
8664
+ *
8665
+ * Converts this `CborDate` to an untagged CBOR value.
8666
+ *
8667
+ * The date is converted to a numeric value representing the number of
8668
+ * seconds since the Unix epoch. This value may be an integer or a
8669
+ * floating-point number, depending on whether the date has fractional
8670
+ * seconds.
8671
+ *
8672
+ * @returns A CBOR value representing the timestamp
8673
+ */
8674
+ untaggedCbor() {
8675
+ return cbor(this.timestamp());
8676
+ }
8677
+ /**
8678
+ * Converts this `CborDate` to a tagged CBOR value with tag 1.
8679
+ *
8680
+ * @returns Tagged CBOR value
8681
+ */
8682
+ taggedCbor() {
8683
+ return createTaggedCbor(this);
8684
+ }
8685
+ /**
8686
+ * Implementation of the `CborTaggedDecodable` interface for `CborDate`.
8687
+ *
8688
+ * Creates a `CborDate` from an untagged CBOR value.
8689
+ *
8690
+ * The CBOR value must be a numeric value (integer or floating-point)
8691
+ * representing the number of seconds since the Unix epoch.
8692
+ *
8693
+ * @param cbor - The untagged CBOR value
8694
+ *
8695
+ * @returns This CborDate instance (mutated)
8696
+ *
8697
+ * @throws Error if the CBOR value is not a valid timestamp
8698
+ */
8699
+ fromUntaggedCbor(cbor) {
8700
+ let timestamp;
8701
+ switch (cbor.type) {
8702
+ case MajorType.Unsigned:
8703
+ timestamp = typeof cbor.value === "number" ? cbor.value : Number(cbor.value);
8704
+ break;
8705
+ case MajorType.Negative:
8706
+ if (typeof cbor.value === "bigint") timestamp = Number(-cbor.value - 1n);
8707
+ else timestamp = -cbor.value - 1;
8708
+ break;
8709
+ case MajorType.Simple:
8710
+ if (cbor.value.type === "Float") timestamp = cbor.value.value;
8711
+ else throw new CborError({ type: "WrongType" });
8712
+ break;
8713
+ default: throw new CborError({ type: "WrongType" });
8714
+ }
8715
+ this._seconds = normalizeTimestampSeconds(timestamp);
8716
+ return this;
8717
+ }
8718
+ /**
8719
+ * Creates a `CborDate` from a tagged CBOR value with tag 1.
8720
+ *
8721
+ * @param cbor - Tagged CBOR value
8722
+ *
8723
+ * @returns This CborDate instance (mutated)
8724
+ *
8725
+ * @throws Error if the CBOR value has the wrong tag or cannot be decoded
8726
+ */
8727
+ fromTaggedCbor(cbor) {
8728
+ validateTag(cbor, this.cborTags());
8729
+ const content = extractTaggedContent(cbor);
8730
+ return this.fromUntaggedCbor(content);
8731
+ }
8732
+ /**
8733
+ * Static method to create a CborDate from tagged CBOR.
8734
+ *
8735
+ * @param cbor - Tagged CBOR value
8736
+ * @returns New CborDate instance
8737
+ */
8738
+ static fromTaggedCbor(cbor) {
8739
+ return new CborDate().fromTaggedCbor(cbor);
8740
+ }
8741
+ /**
8742
+ * Static method to create a CborDate from untagged CBOR.
8743
+ *
8744
+ * @param cbor - Untagged CBOR value
8745
+ * @returns New CborDate instance
8746
+ */
8747
+ static fromUntaggedCbor(cbor) {
8748
+ return new CborDate().fromUntaggedCbor(cbor);
8749
+ }
8750
+ /**
8751
+ * Implementation of the `toString` method for `CborDate`.
8752
+ *
8753
+ * This implementation provides a string representation of a `CborDate` in ISO-8601
8754
+ * format. For dates with time exactly at midnight (00:00:00), only the date
8755
+ * part is shown. For other times, a full date-time string is shown.
8756
+ *
8757
+ * @returns String representation in ISO-8601 format
8758
+ *
8759
+ * @example
8760
+ * ```typescript
8761
+ * // A date at midnight will display as just the date
8762
+ * const date = CborDate.fromYmd(2023, 2, 8);
8763
+ * // Returns "2023-02-08"
8764
+ * console.log(date.toString());
8765
+ *
8766
+ * // A date with time will display as date and time
8767
+ * const date2 = CborDate.fromYmdHms(2023, 2, 8, 15, 30, 45);
8768
+ * // Returns "2023-02-08T15:30:45.000Z"
8769
+ * console.log(date2.toString());
8770
+ * ```
8771
+ */
8772
+ toString() {
8773
+ const dt = /* @__PURE__ */ new Date(this._seconds * 1e3);
8774
+ if (!(dt.getUTCHours() !== 0 || dt.getUTCMinutes() !== 0 || dt.getUTCSeconds() !== 0)) {
8775
+ const datePart = dt.toISOString().split("T")[0];
8776
+ if (datePart === void 0) throw new CborError({
8777
+ type: "Custom",
8778
+ message: "Invalid ISO string format"
8779
+ });
8780
+ return datePart;
8781
+ } else return dt.toISOString().replace(/\.\d{3}Z$/, "Z");
8782
+ }
8783
+ /**
8784
+ * Compare two dates for equality.
8785
+ *
8786
+ * @param other - Other CborDate to compare
8787
+ * @returns true if dates represent the same moment in time
8788
+ */
8789
+ equals(other) {
8790
+ return this._seconds === other._seconds;
8791
+ }
8792
+ /**
8793
+ * Compare two dates.
8794
+ *
8795
+ * @param other - Other CborDate to compare
8796
+ * @returns -1 if this < other, 0 if equal, 1 if this > other
8797
+ */
8798
+ compare(other) {
8799
+ if (this._seconds < other._seconds) return -1;
8800
+ if (this._seconds > other._seconds) return 1;
8801
+ return 0;
8802
+ }
8803
+ /**
8804
+ * Convert to JSON (returns ISO 8601 string).
8805
+ *
8806
+ * @returns ISO 8601 string
8807
+ */
8808
+ toJSON() {
8809
+ return this.toString();
8810
+ }
8811
+ constructor() {
8812
+ this._seconds = Date.now() / 1e3;
8813
+ }
8814
+ };
8815
+ //#endregion
8816
+ //#region src/bignum.ts
8817
+ /**
8818
+ * Copyright © 2023-2026 Blockchain Commons, LLC
8819
+ * Copyright © 2025-2026 Parity Technologies
8820
+ *
8821
+ *
8822
+ * CBOR bignum (tags 2 and 3) support.
8823
+ *
8824
+ * This module provides conversion between CBOR and JavaScript BigInt types,
8825
+ * implementing RFC 8949 §3.4.3 (Bignums) with dCBOR/CDE canonical encoding rules.
8826
+ *
8827
+ * Encoding:
8828
+ * - `biguintToCbor` always encodes as tag 2 (positive bignum) with a byte
8829
+ * string content.
8830
+ * - `bigintToCbor` encodes as tag 2 for non-negative values or tag 3
8831
+ * (negative bignum) for negative values.
8832
+ * - No numeric reduction is performed: values are always encoded as bignums,
8833
+ * even if they would fit in normal CBOR integers.
8834
+ *
8835
+ * Decoding:
8836
+ * - Accepts CBOR integers (major types 0 and 1) and converts them to bigints.
8837
+ * - Accepts tag 2 (positive bignum) and tag 3 (negative bignum) with byte
8838
+ * string content.
8839
+ * - Enforces shortest-form canonical representation for bignum magnitudes.
8840
+ * - Rejects floating-point values.
8841
+ *
8842
+ * @module bignum
8843
+ */
8844
+ const TAG_2_POSITIVE_BIGNUM = 2;
8845
+ const TAG_3_NEGATIVE_BIGNUM = 3;
8846
+ /**
8847
+ * Validates that a bignum magnitude byte string is in shortest canonical form.
8848
+ *
8849
+ * Matches Rust's `validate_bignum_magnitude()`.
8850
+ *
8851
+ * Rules:
8852
+ * - For positive bignums (tag 2): empty byte string represents zero;
8853
+ * non-empty must not have leading zero bytes.
8854
+ * - For negative bignums (tag 3): byte string must not be empty
8855
+ * (magnitude zero is encoded as `0x00`); must not have leading zero bytes
8856
+ * except when the magnitude is zero (single `0x00`).
8857
+ *
8858
+ * @param bytes - The magnitude byte string to validate
8859
+ * @param isNegative - Whether this is for a negative bignum (tag 3)
8860
+ * @throws CborError with type NonCanonicalNumeric on validation failure
8861
+ */
8862
+ function validateBignumMagnitude(bytes, isNegative) {
8863
+ if (isNegative) {
8864
+ if (bytes.length === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8865
+ if (bytes.length > 1 && bytes[0] === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8866
+ } else if (bytes.length > 0 && bytes[0] === 0) throw new CborError({ type: "NonCanonicalNumeric" });
8867
+ }
8868
+ /**
8869
+ * Strips leading zero bytes from a byte array, returning the minimal
8870
+ * representation.
8871
+ *
8872
+ * Matches Rust's `strip_leading_zeros()`.
8873
+ *
8874
+ * @param bytes - The byte array to strip
8875
+ * @returns A subarray with leading zeros removed
8876
+ */
8877
+ function stripLeadingZeros(bytes) {
8878
+ let start = 0;
8879
+ while (start < bytes.length && bytes[start] === 0) start++;
8880
+ return bytes.subarray(start);
8881
+ }
8882
+ /**
8883
+ * Convert a non-negative bigint to a big-endian byte array.
8884
+ *
8885
+ * Zero returns an empty Uint8Array.
8886
+ *
8887
+ * @param value - A non-negative bigint value
8888
+ * @returns Big-endian byte representation
8889
+ */
8890
+ function bigintToBytes(value) {
8891
+ if (value === 0n) return /* @__PURE__ */ new Uint8Array(0);
8892
+ const hex = value.toString(16);
8893
+ const padded = hex.length % 2 !== 0 ? `0${hex}` : hex;
8894
+ const bytes = new Uint8Array(padded.length / 2);
8895
+ for (let i = 0; i < bytes.length; i++) bytes[i] = parseInt(padded.substring(i * 2, i * 2 + 2), 16);
8896
+ return bytes;
8897
+ }
8898
+ /**
8899
+ * Convert a big-endian byte array to a bigint.
8900
+ *
8901
+ * Empty array returns 0n.
8902
+ *
8903
+ * @param bytes - Big-endian byte representation
8904
+ * @returns The bigint value
8905
+ */
8906
+ function bytesToBigint(bytes) {
8907
+ if (bytes.length === 0) return 0n;
8908
+ let result = 0n;
8909
+ for (const byte of bytes) result = result << 8n | BigInt(byte);
8910
+ return result;
8911
+ }
8912
+ /**
8913
+ * Encode a non-negative bigint as a CBOR tag 2 (positive bignum).
8914
+ *
8915
+ * Matches Rust's `From<BigUint> for CBOR`.
8916
+ *
8917
+ * The value is always encoded as a bignum regardless of size.
8918
+ * Zero is encoded as tag 2 with an empty byte string.
8919
+ *
8920
+ * @param value - A non-negative bigint (must be >= 0n)
8921
+ * @returns CBOR tagged value
8922
+ * @throws CborError with type OutOfRange if value is negative
8923
+ */
8924
+ function biguintToCbor(value) {
8925
+ if (value < 0n) throw new CborError({ type: "OutOfRange" });
8926
+ return toTaggedValue(TAG_2_POSITIVE_BIGNUM, stripLeadingZeros(bigintToBytes(value)));
8927
+ }
8928
+ /**
8929
+ * Encode a bigint as a CBOR tag 2 or tag 3 bignum.
8930
+ *
8931
+ * Matches Rust's `From<BigInt> for CBOR`.
8932
+ *
8933
+ * - Non-negative values use tag 2 (positive bignum).
8934
+ * - Negative values use tag 3 (negative bignum), where the encoded
8935
+ * magnitude is `|value| - 1` per RFC 8949.
8936
+ *
8937
+ * @param value - Any bigint value
8938
+ * @returns CBOR tagged value
8939
+ */
8940
+ function bigintToCbor(value) {
8941
+ if (value >= 0n) return biguintToCbor(value);
8942
+ const stripped = stripLeadingZeros(bigintToBytes(-value - 1n));
8943
+ return toTaggedValue(TAG_3_NEGATIVE_BIGNUM, stripped.length === 0 ? new Uint8Array([0]) : stripped);
8944
+ }
8945
+ /**
8946
+ * Decode a BigUint from an untagged CBOR byte string.
8947
+ *
8948
+ * Matches Rust's `biguint_from_untagged_cbor()`.
8949
+ *
8950
+ * This function is intended for use in tag summarizers where the tag has
8951
+ * already been stripped. It expects a CBOR byte string representing the
8952
+ * big-endian magnitude of a positive bignum (tag 2 content).
8953
+ *
8954
+ * Enforces canonical encoding: no leading zero bytes (except empty for zero).
8955
+ *
8956
+ * @param cbor - A CBOR value that should be a byte string
8957
+ * @returns Non-negative bigint
8958
+ * @throws CborError with type WrongType if not a byte string
8959
+ * @throws CborError with type NonCanonicalNumeric if encoding is non-canonical
8960
+ */
8961
+ function biguintFromUntaggedCbor(cbor) {
8962
+ if (cbor.type !== MajorType.ByteString) throw new CborError({ type: "WrongType" });
8963
+ const bytes = cbor.value;
8964
+ validateBignumMagnitude(bytes, false);
8965
+ return bytesToBigint(bytes);
8966
+ }
8967
+ /**
8968
+ * Decode a BigInt from an untagged CBOR byte string for a negative bignum.
8969
+ *
8970
+ * Matches Rust's `bigint_from_negative_untagged_cbor()`.
8971
+ *
8972
+ * This function is intended for use in tag summarizers where the tag has
8973
+ * already been stripped. It expects a CBOR byte string representing `n` where
8974
+ * the actual value is `-1 - n` (tag 3 content per RFC 8949).
8975
+ *
8976
+ * Enforces canonical encoding: no leading zero bytes (except single `0x00`
8977
+ * for -1).
8978
+ *
8979
+ * @param cbor - A CBOR value that should be a byte string
8980
+ * @returns Negative bigint
8981
+ * @throws CborError with type WrongType if not a byte string
8982
+ * @throws CborError with type NonCanonicalNumeric if encoding is non-canonical
8983
+ */
8984
+ function bigintFromNegativeUntaggedCbor(cbor) {
8985
+ if (cbor.type !== MajorType.ByteString) throw new CborError({ type: "WrongType" });
8986
+ const bytes = cbor.value;
8987
+ validateBignumMagnitude(bytes, true);
8988
+ return -(bytesToBigint(bytes) + 1n);
8989
+ }
8990
+ /**
8991
+ * Convert CBOR to a non-negative bigint.
8992
+ *
8993
+ * Matches Rust's `TryFrom<CBOR> for BigUint`.
8994
+ *
8995
+ * Accepts:
8996
+ * - Major type 0 (unsigned integer)
8997
+ * - Tag 2 (positive bignum) with canonical byte string
8998
+ *
8999
+ * Rejects:
9000
+ * - Major type 1 (negative integer) -> OutOfRange
9001
+ * - Tag 3 (negative bignum) -> OutOfRange
9002
+ * - Floating-point values -> WrongType
9003
+ * - Non-canonical bignum encodings -> NonCanonicalNumeric
9004
+ *
9005
+ * @param cbor - The CBOR value to convert
8397
9006
  * @returns Non-negative bigint
8398
9007
  * @throws CborError
8399
9008
  */
@@ -8572,553 +9181,132 @@ var bctsDcbor = (function(exports) {
8572
9181
  /**
8573
9182
  * Tag 37: Binary UUID
8574
9183
  */
8575
- const TAG_UUID = 37;
8576
- /**
8577
- * Tag 256: string reference (namespace)
8578
- */
8579
- const TAG_STRING_REF_NAMESPACE = 256;
8580
- /**
8581
- * Tag 257: binary UUID reference
8582
- */
8583
- const TAG_BINARY_UUID = 257;
8584
- /**
8585
- * Tag 258: Set of values (array with no duplicates)
8586
- */
8587
- const TAG_SET = 258;
8588
- /**
8589
- * Tag 55799: Self-describe CBOR (magic number 0xd9d9f7)
8590
- */
8591
- const TAG_SELF_DESCRIBE_CBOR = 55799;
8592
- const TAG_DATE = 1;
8593
- const TAG_NAME_DATE = "date";
8594
- /**
8595
- * Register standard tags in a specific tags store.
8596
- * Matches Rust's register_tags_in() function.
8597
- *
8598
- * @param tagsStore - The tags store to register tags into
8599
- */
8600
- const registerTagsIn = (tagsStore) => {
8601
- const tags = [createTag(1, TAG_NAME_DATE)];
8602
- tagsStore.insertAll(tags);
8603
- tagsStore.setSummarizer(1, (untaggedCbor, _flat) => {
8604
- try {
8605
- return {
8606
- ok: true,
8607
- value: CborDate.fromUntaggedCbor(untaggedCbor).toString()
8608
- };
8609
- } catch (e) {
8610
- return {
8611
- ok: false,
8612
- error: {
8613
- type: "Custom",
8614
- message: e instanceof Error ? e.message : String(e)
8615
- }
8616
- };
8617
- }
8618
- });
8619
- const biguintTag = createTag(2, TAG_NAME_POSITIVE_BIGNUM);
8620
- const bigintTag = createTag(3, TAG_NAME_NEGATIVE_BIGNUM);
8621
- tagsStore.insertAll([biguintTag, bigintTag]);
8622
- tagsStore.setSummarizer(2, (untaggedCbor, _flat) => {
8623
- try {
8624
- return {
8625
- ok: true,
8626
- value: `bignum(${biguintFromUntaggedCbor(untaggedCbor)})`
8627
- };
8628
- } catch (e) {
8629
- return {
8630
- ok: false,
8631
- error: {
8632
- type: "Custom",
8633
- message: e instanceof Error ? e.message : String(e)
8634
- }
8635
- };
8636
- }
8637
- });
8638
- tagsStore.setSummarizer(3, (untaggedCbor, _flat) => {
8639
- try {
8640
- return {
8641
- ok: true,
8642
- value: `bignum(${bigintFromNegativeUntaggedCbor(untaggedCbor)})`
8643
- };
8644
- } catch (e) {
8645
- return {
8646
- ok: false,
8647
- error: {
8648
- type: "Custom",
8649
- message: e instanceof Error ? e.message : String(e)
8650
- }
8651
- };
8652
- }
8653
- });
8654
- };
8655
- /**
8656
- * Register standard tags in the global tags store.
8657
- * Matches Rust's register_tags() function.
8658
- *
8659
- * This function is idempotent - calling it multiple times is safe.
8660
- */
8661
- const registerTags = () => {
8662
- registerTagsIn(getGlobalTagsStore());
8663
- };
8664
- /**
8665
- * Converts an array of tag values to their corresponding Tag objects.
8666
- * Matches Rust's tags_for_values() function.
8667
- *
8668
- * This function looks up each tag value in the global tag registry and returns
8669
- * an array of complete Tag objects. For any tag values that aren't
8670
- * registered in the global registry, it creates a basic Tag with just the
8671
- * value (no name).
8672
- *
8673
- * @param values - Array of numeric tag values to convert
8674
- * @returns Array of Tag objects corresponding to the input values
8675
- *
8676
- * @example
8677
- * ```typescript
8678
- * // Register some tags first
8679
- * registerTags();
8680
- *
8681
- * // Convert tag values to Tag objects
8682
- * const tags = tagsForValues([1, 42, 999]);
8683
- *
8684
- * // The first tag (value 1) should be registered as "date"
8685
- * console.log(tags[0].value); // 1
8686
- * console.log(tags[0].name); // "date"
8687
- *
8688
- * // Unregistered tags will have a value but no name
8689
- * console.log(tags[1].value); // 42
8690
- * console.log(tags[2].value); // 999
8691
- * ```
8692
- */
8693
- const tagsForValues = (values) => {
8694
- const globalStore = getGlobalTagsStore();
8695
- return values.map((value) => {
8696
- const tag = globalStore.tagForValue(value);
8697
- if (tag !== void 0) return tag;
8698
- return createTag(value);
8699
- });
8700
- };
8701
- //#endregion
8702
- //#region src/set.ts
9184
+ const TAG_UUID = 37;
8703
9185
  /**
8704
- * Copyright © 2023-2026 Blockchain Commons, LLC
8705
- * Copyright © 2025-2026 Parity Technologies
8706
- *
8707
- *
8708
- * Set data structure for CBOR with tag(258) encoding.
8709
- *
8710
- * A Set is encoded as an array with no duplicate elements,
8711
- * tagged with tag(258) to indicate set semantics.
8712
- *
8713
- * @module set
9186
+ * Tag 256: string reference (namespace)
8714
9187
  */
9188
+ const TAG_STRING_REF_NAMESPACE = 256;
8715
9189
  /**
8716
- * CBOR Set type with tag(258) encoding.
8717
- *
8718
- * Internally uses a CborMap to ensure unique elements with deterministic ordering.
8719
- * Elements are ordered by their CBOR encoding (lexicographic byte order).
8720
- *
8721
- * @example
8722
- * ```typescript
8723
- * // Create set
8724
- * const set = CborSet.fromArray([1, 2, 3]);
8725
- * const set2 = CborSet.fromSet(new Set([1, 2, 3]));
8726
- *
8727
- * // Add elements
8728
- * set.insert(4);
8729
- * set.insert(2); // Duplicate, no effect
8730
- *
8731
- * // Check membership
8732
- * console.log(set.contains(2)); // true
8733
- * console.log(set.contains(99)); // false
9190
+ * Tag 257: binary UUID reference
9191
+ */
9192
+ const TAG_BINARY_UUID = 257;
9193
+ /**
9194
+ * Tag 258: Set of values (array with no duplicates)
9195
+ */
9196
+ const TAG_SET = 258;
9197
+ /**
9198
+ * Tag 55799: Self-describe CBOR (magic number 0xd9d9f7)
9199
+ */
9200
+ const TAG_SELF_DESCRIBE_CBOR = 55799;
9201
+ const TAG_DATE = 1;
9202
+ const TAG_NAME_DATE = "date";
9203
+ /**
9204
+ * Register standard tags in a specific tags store.
9205
+ * Matches Rust's register_tags_in() function.
8734
9206
  *
8735
- * // Encode to CBOR
8736
- * const tagged = set.taggedCbor();
8737
- * ```
9207
+ * @param tagsStore - The tags store to register tags into
8738
9208
  */
8739
- var CborSet = class CborSet {
8740
- _map;
8741
- constructor() {
8742
- this._map = new CborMap();
8743
- }
8744
- /**
8745
- * Create CborSet from array.
8746
- *
8747
- * Duplicates are automatically removed.
8748
- *
8749
- * @param items - Array of items to add to the set
8750
- * @returns New CborSet instance
8751
- *
8752
- * @example
8753
- * ```typescript
8754
- * const set = CborSet.fromArray([1, 2, 3, 2, 1]);
8755
- * console.log(set.size); // 3
8756
- * ```
8757
- */
8758
- static fromArray(items) {
8759
- const set = new CborSet();
8760
- for (const item of items) set.insert(item);
8761
- return set;
8762
- }
8763
- /**
8764
- * Create CborSet from JavaScript Set.
8765
- *
8766
- * @param items - JavaScript Set of items
8767
- * @returns New CborSet instance
8768
- *
8769
- * @example
8770
- * ```typescript
8771
- * const jsSet = new Set([1, 2, 3]);
8772
- * const cborSet = CborSet.fromSet(jsSet);
8773
- * ```
8774
- */
8775
- static fromSet(items) {
8776
- return CborSet.fromArray(Array.from(items));
8777
- }
8778
- /**
8779
- * Create CborSet from iterable.
8780
- *
8781
- * @param items - Iterable of items
8782
- * @returns New CborSet instance
8783
- */
8784
- static fromIterable(items) {
8785
- return CborSet.fromArray(Array.from(items));
8786
- }
8787
- /**
8788
- * Insert an element into the set.
8789
- *
8790
- * If the element already exists, has no effect.
8791
- *
8792
- * @param value - Value to insert
8793
- *
8794
- * @example
8795
- * ```typescript
8796
- * const set = new CborSet();
8797
- * set.insert(1);
8798
- * set.insert(2);
8799
- * set.insert(1); // No effect, already exists
8800
- * ```
8801
- */
8802
- insert(value) {
8803
- const cborValue = encodeCborValue(value);
8804
- this._map.set(cborValue, cborValue);
8805
- }
8806
- /**
8807
- * Insert an element into the set, requiring it to be strictly greater
8808
- * (in canonical CBOR-encoded byte order) than every previously-inserted
8809
- * element. Used by the decoder to reject misordered or duplicate
8810
- * elements in tag-258 set encodings.
8811
- *
8812
- * Mirrors Rust `Set::insert_next` (`pub(crate)`); exposed here because
8813
- * TypeScript doesn't have a crate-private visibility level.
8814
- *
8815
- * @throws CborError of type `MisorderedMap` if `value` would not preserve
8816
- * strict ascending CBOR-byte order, or `DuplicateMapKey` for an exact
8817
- * repeat.
8818
- */
8819
- insertNext(value) {
8820
- const cborValue = encodeCborValue(value);
8821
- this._map.setNext(cborValue, cborValue);
8822
- }
8823
- /**
8824
- * Check if set contains an element.
8825
- *
8826
- * @param value - Value to check
8827
- * @returns true if element is in the set
8828
- *
8829
- * @example
8830
- * ```typescript
8831
- * const set = CborSet.fromArray([1, 2, 3]);
8832
- * console.log(set.contains(2)); // true
8833
- * console.log(set.contains(99)); // false
8834
- * ```
8835
- */
8836
- contains(value) {
8837
- const cborValue = encodeCborValue(value);
8838
- return this._map.has(cborValue);
8839
- }
8840
- /**
8841
- * Remove an element from the set.
8842
- *
8843
- * @param value - Value to remove
8844
- * @returns true if element was removed, false if not found
8845
- *
8846
- * @example
8847
- * ```typescript
8848
- * const set = CborSet.fromArray([1, 2, 3]);
8849
- * set.delete(2); // Returns true
8850
- * set.delete(99); // Returns false
8851
- * ```
8852
- */
8853
- delete(value) {
8854
- const cborValue = encodeCborValue(value);
8855
- return this._map.delete(cborValue);
8856
- }
8857
- /**
8858
- * Remove all elements from the set.
8859
- */
8860
- clear() {
8861
- this._map.clear();
8862
- }
8863
- /**
8864
- * Get the number of elements in the set.
8865
- *
8866
- * @returns Number of elements
8867
- */
8868
- get size() {
8869
- return this._map.size;
8870
- }
8871
- /**
8872
- * Check if the set is empty.
8873
- *
8874
- * @returns true if set has no elements
8875
- */
8876
- isEmpty() {
8877
- return this._map.size === 0;
8878
- }
8879
- /**
8880
- * Create a new set containing elements in this set or the other set.
8881
- *
8882
- * @param other - Other set
8883
- * @returns New set with union of elements
8884
- *
8885
- * @example
8886
- * ```typescript
8887
- * const set1 = CborSet.fromArray([1, 2, 3]);
8888
- * const set2 = CborSet.fromArray([3, 4, 5]);
8889
- * const union = set1.union(set2);
8890
- * // union contains [1, 2, 3, 4, 5]
8891
- * ```
8892
- */
8893
- union(other) {
8894
- const result = new CborSet();
8895
- for (const value of this) result.insert(extractCbor(value));
8896
- for (const value of other) result.insert(extractCbor(value));
8897
- return result;
8898
- }
8899
- /**
8900
- * Create a new set containing elements in both this set and the other set.
8901
- *
8902
- * @param other - Other set
8903
- * @returns New set with intersection of elements
8904
- *
8905
- * @example
8906
- * ```typescript
8907
- * const set1 = CborSet.fromArray([1, 2, 3]);
8908
- * const set2 = CborSet.fromArray([2, 3, 4]);
8909
- * const intersection = set1.intersection(set2);
8910
- * // intersection contains [2, 3]
8911
- * ```
8912
- */
8913
- intersection(other) {
8914
- const result = new CborSet();
8915
- for (const value of this) {
8916
- const extracted = extractCbor(value);
8917
- if (other.contains(extracted)) result.insert(extracted);
9209
+ const registerTagsIn = (tagsStore) => {
9210
+ const tags = [createTag(1, TAG_NAME_DATE)];
9211
+ tagsStore.insertAll(tags);
9212
+ tagsStore.setSummarizer(1, (untaggedCbor, _flat) => {
9213
+ try {
9214
+ return {
9215
+ ok: true,
9216
+ value: CborDate.fromUntaggedCbor(untaggedCbor).toString()
9217
+ };
9218
+ } catch (e) {
9219
+ return {
9220
+ ok: false,
9221
+ error: {
9222
+ type: "Custom",
9223
+ message: e instanceof Error ? e.message : String(e)
9224
+ }
9225
+ };
9226
+ }
9227
+ });
9228
+ const biguintTag = createTag(2, TAG_NAME_POSITIVE_BIGNUM);
9229
+ const bigintTag = createTag(3, TAG_NAME_NEGATIVE_BIGNUM);
9230
+ tagsStore.insertAll([biguintTag, bigintTag]);
9231
+ tagsStore.setSummarizer(2, (untaggedCbor, _flat) => {
9232
+ try {
9233
+ return {
9234
+ ok: true,
9235
+ value: `bignum(${biguintFromUntaggedCbor(untaggedCbor)})`
9236
+ };
9237
+ } catch (e) {
9238
+ return {
9239
+ ok: false,
9240
+ error: {
9241
+ type: "Custom",
9242
+ message: e instanceof Error ? e.message : String(e)
9243
+ }
9244
+ };
8918
9245
  }
8919
- return result;
8920
- }
8921
- /**
8922
- * Create a new set containing elements in this set but not in the other set.
8923
- *
8924
- * @param other - Other set
8925
- * @returns New set with difference of elements
8926
- *
8927
- * @example
8928
- * ```typescript
8929
- * const set1 = CborSet.fromArray([1, 2, 3]);
8930
- * const set2 = CborSet.fromArray([2, 3, 4]);
8931
- * const diff = set1.difference(set2);
8932
- * // diff contains [1]
8933
- * ```
8934
- */
8935
- difference(other) {
8936
- const result = new CborSet();
8937
- for (const value of this) {
8938
- const extracted = extractCbor(value);
8939
- if (!other.contains(extracted)) result.insert(extracted);
9246
+ });
9247
+ tagsStore.setSummarizer(3, (untaggedCbor, _flat) => {
9248
+ try {
9249
+ return {
9250
+ ok: true,
9251
+ value: `bignum(${bigintFromNegativeUntaggedCbor(untaggedCbor)})`
9252
+ };
9253
+ } catch (e) {
9254
+ return {
9255
+ ok: false,
9256
+ error: {
9257
+ type: "Custom",
9258
+ message: e instanceof Error ? e.message : String(e)
9259
+ }
9260
+ };
8940
9261
  }
8941
- return result;
8942
- }
8943
- /**
8944
- * Check if this set is a subset of another set.
8945
- *
8946
- * @param other - Other set
8947
- * @returns true if all elements of this set are in the other set
8948
- */
8949
- isSubsetOf(other) {
8950
- for (const value of this) if (!other.contains(extractCbor(value))) return false;
8951
- return true;
8952
- }
8953
- /**
8954
- * Check if this set is a superset of another set.
8955
- *
8956
- * @param other - Other set
8957
- * @returns true if all elements of the other set are in this set
8958
- */
8959
- isSupersetOf(other) {
8960
- return other.isSubsetOf(this);
8961
- }
8962
- /**
8963
- * Iterate over elements in the set.
8964
- *
8965
- * Elements are returned in deterministic order (by CBOR encoding).
8966
- *
8967
- * @example
8968
- * ```typescript
8969
- * const set = CborSet.fromArray([3, 1, 2]);
8970
- * for (const value of set) {
8971
- * console.log(extractCbor(value));
8972
- * }
8973
- * ```
8974
- */
8975
- *[Symbol.iterator]() {
8976
- for (const [_, value] of this._map) yield value;
8977
- }
8978
- /**
8979
- * Get all values as an array.
8980
- *
8981
- * @returns Array of CBOR values in deterministic order
8982
- *
8983
- * @example
8984
- * ```typescript
8985
- * const set = CborSet.fromArray([3, 1, 2]);
8986
- * const values = set.values();
8987
- * // Values in deterministic order
8988
- * ```
8989
- */
8990
- values() {
8991
- return Array.from(this);
8992
- }
8993
- /**
8994
- * Execute a function for each element.
8995
- *
8996
- * @param callback - Function to call for each element
8997
- *
8998
- * @example
8999
- * ```typescript
9000
- * set.forEach(value => {
9001
- * console.log(extractCbor(value));
9002
- * });
9003
- * ```
9004
- */
9005
- forEach(callback) {
9006
- for (const value of this) callback(value);
9007
- }
9008
- cborTags() {
9009
- return [createTag(258, "set")];
9010
- }
9011
- untaggedCbor() {
9012
- return cbor(this.values());
9013
- }
9014
- taggedCbor() {
9015
- return createTaggedCbor(this);
9016
- }
9017
- fromUntaggedCbor(c) {
9018
- if (c.type !== MajorType.Array) throw new CborError({ type: "WrongType" });
9019
- this.clear();
9020
- for (const value of c.value) this.insertNext(extractCbor(value));
9021
- return this;
9022
- }
9023
- fromTaggedCbor(c) {
9024
- validateTag(c, this.cborTags());
9025
- const content = extractTaggedContent(c);
9026
- return this.fromUntaggedCbor(content);
9027
- }
9028
- /**
9029
- * Decode a CborSet from tagged CBOR (static method).
9030
- *
9031
- * @param cbor - Tagged CBOR value with tag(258)
9032
- * @returns Decoded CborSet instance
9033
- */
9034
- static fromTaggedCborStatic(cbor) {
9035
- return new CborSet().fromTaggedCbor(cbor);
9036
- }
9037
- /**
9038
- * Convert to CBOR array (untagged).
9039
- *
9040
- * @returns CBOR array
9041
- */
9042
- toCbor() {
9043
- return this.untaggedCbor();
9044
- }
9045
- /**
9046
- * Convert to CBOR bytes (tagged).
9047
- *
9048
- * @returns Encoded CBOR bytes
9049
- */
9050
- toBytes() {
9051
- return cborData(this.taggedCbor());
9052
- }
9053
- /**
9054
- * Convert to JavaScript Set.
9055
- *
9056
- * @returns JavaScript Set with extracted values
9057
- *
9058
- * @example
9059
- * ```typescript
9060
- * const cborSet = CborSet.fromArray([1, 2, 3]);
9061
- * const jsSet = cborSet.toSet();
9062
- * console.log(jsSet.has(1)); // true
9063
- * ```
9064
- */
9065
- toSet() {
9066
- const result = /* @__PURE__ */ new Set();
9067
- for (const value of this) result.add(extractCbor(value));
9068
- return result;
9069
- }
9070
- /**
9071
- * Convert to JavaScript Array.
9072
- *
9073
- * @returns Array with extracted values
9074
- */
9075
- toArray() {
9076
- return Array.from(this.toSet());
9077
- }
9078
- /**
9079
- * Get diagnostic notation for the set.
9080
- *
9081
- * @returns String representation
9082
- *
9083
- * @example
9084
- * ```typescript
9085
- * const set = CborSet.fromArray([1, 2, 3]);
9086
- * console.log(set.diagnostic); // "[1, 2, 3]"
9087
- * ```
9088
- */
9089
- get diagnostic() {
9090
- return `[${this.values().map((v) => {
9091
- const extracted = extractCbor(v);
9092
- if (typeof extracted === "string") return `"${extracted}"`;
9093
- return String(extracted);
9094
- }).join(", ")}]`;
9095
- }
9096
- /**
9097
- * Convert to string (same as diagnostic).
9098
- *
9099
- * @returns String representation
9100
- */
9101
- toString() {
9102
- return this.diagnostic;
9103
- }
9104
- /**
9105
- * Convert to JSON (returns array of values).
9106
- *
9107
- * @returns Array for JSON serialization
9108
- */
9109
- toJSON() {
9110
- return this.toArray();
9111
- }
9262
+ });
9112
9263
  };
9113
9264
  /**
9114
- * Convert a value to CBOR for use in set operations.
9265
+ * Register standard tags in the global tags store.
9266
+ * Matches Rust's register_tags() function.
9115
9267
  *
9116
- * @internal
9268
+ * This function is idempotent - calling it multiple times is safe.
9117
9269
  */
9118
- function encodeCborValue(value) {
9119
- if (typeof value === "object" && value !== null && "isCbor" in value && value.isCbor === true) return value;
9120
- return cbor(value);
9121
- }
9270
+ const registerTags = () => {
9271
+ registerTagsIn(getGlobalTagsStore());
9272
+ };
9273
+ /**
9274
+ * Converts an array of tag values to their corresponding Tag objects.
9275
+ * Matches Rust's tags_for_values() function.
9276
+ *
9277
+ * This function looks up each tag value in the global tag registry and returns
9278
+ * an array of complete Tag objects. For any tag values that aren't
9279
+ * registered in the global registry, it creates a basic Tag with just the
9280
+ * value (no name).
9281
+ *
9282
+ * @param values - Array of numeric tag values to convert
9283
+ * @returns Array of Tag objects corresponding to the input values
9284
+ *
9285
+ * @example
9286
+ * ```typescript
9287
+ * // Register some tags first
9288
+ * registerTags();
9289
+ *
9290
+ * // Convert tag values to Tag objects
9291
+ * const tags = tagsForValues([1, 42, 999]);
9292
+ *
9293
+ * // The first tag (value 1) should be registered as "date"
9294
+ * console.log(tags[0].value); // 1
9295
+ * console.log(tags[0].name); // "date"
9296
+ *
9297
+ * // Unregistered tags will have a value but no name
9298
+ * console.log(tags[1].value); // 42
9299
+ * console.log(tags[2].value); // 999
9300
+ * ```
9301
+ */
9302
+ const tagsForValues = (values) => {
9303
+ const globalStore = getGlobalTagsStore();
9304
+ return values.map((value) => {
9305
+ const tag = globalStore.tagForValue(value);
9306
+ if (tag !== void 0) return tag;
9307
+ return createTag(value);
9308
+ });
9309
+ };
9122
9310
  //#endregion
9123
9311
  //#region src/sortable.ts
9124
9312
  /**
@@ -9533,6 +9721,7 @@ var bctsDcbor = (function(exports) {
9533
9721
  exports.summary = summary;
9534
9722
  exports.tagContent = tagContent;
9535
9723
  exports.tagValue = tagValue;
9724
+ exports.tagValuesEqual = tagValuesEqual;
9536
9725
  exports.tagWithStaticName = tagWithStaticName;
9537
9726
  exports.tagWithValue = tagWithValue;
9538
9727
  exports.taggedCborData = taggedCborData;
@@ -9547,6 +9736,8 @@ var bctsDcbor = (function(exports) {
9547
9736
  exports.tryIntoText = expectText;
9548
9737
  exports.validateTag = validateTag;
9549
9738
  exports.walk = walk;
9739
+ exports.withTags = withTags;
9740
+ exports.withTagsMut = withTagsMut;
9550
9741
  return exports;
9551
9742
  })({});
9552
9743