@bcts/dcbor 1.0.0-alpha.10

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.
Files changed (45) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +13 -0
  3. package/dist/index.cjs +9151 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +3107 -0
  6. package/dist/index.d.cts.map +1 -0
  7. package/dist/index.d.mts +3107 -0
  8. package/dist/index.d.mts.map +1 -0
  9. package/dist/index.iife.js +9155 -0
  10. package/dist/index.iife.js.map +1 -0
  11. package/dist/index.mjs +9027 -0
  12. package/dist/index.mjs.map +1 -0
  13. package/package.json +80 -0
  14. package/src/.claude-flow/metrics/agent-metrics.json +1 -0
  15. package/src/.claude-flow/metrics/performance.json +87 -0
  16. package/src/.claude-flow/metrics/task-metrics.json +10 -0
  17. package/src/byte-string.ts +300 -0
  18. package/src/cbor-codable.ts +170 -0
  19. package/src/cbor-tagged-codable.ts +72 -0
  20. package/src/cbor-tagged-decodable.ts +184 -0
  21. package/src/cbor-tagged-encodable.ts +138 -0
  22. package/src/cbor-tagged.ts +104 -0
  23. package/src/cbor.ts +869 -0
  24. package/src/conveniences.ts +840 -0
  25. package/src/date.ts +553 -0
  26. package/src/decode.ts +276 -0
  27. package/src/diag.ts +462 -0
  28. package/src/dump.ts +277 -0
  29. package/src/error.ts +259 -0
  30. package/src/exact.ts +714 -0
  31. package/src/float.ts +279 -0
  32. package/src/global.d.ts +34 -0
  33. package/src/globals.d.ts +0 -0
  34. package/src/index.ts +180 -0
  35. package/src/map.ts +308 -0
  36. package/src/prelude.ts +70 -0
  37. package/src/set.ts +515 -0
  38. package/src/simple.ts +153 -0
  39. package/src/stdlib.ts +55 -0
  40. package/src/string-util.ts +55 -0
  41. package/src/tag.ts +53 -0
  42. package/src/tags-store.ts +294 -0
  43. package/src/tags.ts +231 -0
  44. package/src/varint.ts +124 -0
  45. package/src/walk.ts +516 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Tagged CBOR encoding and decoding support.
3
+ *
4
+ * This module provides the `CborTaggedCodable` interface, which serves as a
5
+ * convenience marker for types that can be both encoded to and decoded from
6
+ * tagged CBOR values.
7
+ *
8
+ * The interface is automatically implemented for any type that implements both
9
+ * `CborTaggedEncodable` and `CborTaggedDecodable`.
10
+ *
11
+ * @module cbor-tagged-codable
12
+ */
13
+
14
+ import type { CborTaggedEncodable } from "./cbor-tagged-encodable";
15
+ import type { CborTaggedDecodable } from "./cbor-tagged-decodable";
16
+
17
+ /**
18
+ * Interface for types that can be both encoded to and decoded from CBOR with a
19
+ * specific tag.
20
+ *
21
+ * This interface is automatically implemented for any type that implements both
22
+ * `CborTaggedEncodable` and `CborTaggedDecodable`. It serves as a convenience
23
+ * marker to indicate full-tagged CBOR serialization support.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Define a Date type
28
+ * class Date implements CborTaggedCodable<Date> {
29
+ * constructor(public timestamp: number) {}
30
+ *
31
+ * cborTags(): Tag[] {
32
+ * return [createTag(1, 'date')]; // Standard date tag
33
+ * }
34
+ *
35
+ * // Implement encoding to tagged CBOR
36
+ * untaggedCbor(): Cbor {
37
+ * return cbor(this.timestamp);
38
+ * }
39
+ *
40
+ * taggedCbor(): Cbor {
41
+ * const tags = this.cborTags();
42
+ * return {
43
+ * isCbor: true,
44
+ * type: MajorType.Tagged,
45
+ * tag: tags[0].value,
46
+ * value: this.untaggedCbor()
47
+ * };
48
+ * }
49
+ *
50
+ * // Implement decoding from tagged CBOR
51
+ * fromUntaggedCbor(cbor: Cbor): Date {
52
+ * const timestamp = cbor.value as number;
53
+ * return new Date(timestamp);
54
+ * }
55
+ *
56
+ * fromTaggedCbor(cbor: Cbor): Date {
57
+ * if (cbor.type !== MajorType.Tagged) {
58
+ * throw new Error('Wrong type');
59
+ * }
60
+ * return this.fromUntaggedCbor(cbor.value);
61
+ * }
62
+ * }
63
+ *
64
+ * // The CborTaggedCodable interface is automatically implemented
65
+ * // Create a date and demonstrate round-trip conversion
66
+ * const original = new Date(1609459200);
67
+ * const cborValue = original.taggedCbor();
68
+ * const roundtrip = new Date(0).fromTaggedCbor(cborValue);
69
+ * assert(original.timestamp === roundtrip.timestamp);
70
+ * ```
71
+ */
72
+ export interface CborTaggedCodable<T> extends CborTaggedEncodable, CborTaggedDecodable<T> {}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * Tagged CBOR decoding support.
3
+ *
4
+ * This module provides the `CborTaggedDecodable` interface, which enables types to
5
+ * be decoded from tagged CBOR values.
6
+ *
7
+ * Tagged CBOR values include semantic information about how to interpret the
8
+ * data. This interface allows TypeScript types to verify that incoming CBOR data has the
9
+ * expected tag(s) and to decode the data appropriately.
10
+ *
11
+ * @module cbor-tagged-decodable
12
+ */
13
+
14
+ import { type Cbor, MajorType } from "./cbor";
15
+ import type { CborTagged } from "./cbor-tagged";
16
+ import type { Tag } from "./tag";
17
+ import { CborError } from "./error";
18
+
19
+ /**
20
+ * Interface for types that can be decoded from CBOR with a specific tag.
21
+ *
22
+ * This interface extends `CborTagged` to provide methods for
23
+ * decoding tagged CBOR data into TypeScript types. It handles verification that
24
+ * the CBOR data has the expected tag(s) and provides utilities for both
25
+ * tagged and untagged decoding.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // Define a Date type
30
+ * class Date implements CborTaggedDecodable<Date> {
31
+ * constructor(public timestamp: number) {}
32
+ *
33
+ * cborTags(): Tag[] {
34
+ * return [createTag(1, 'date')]; // Standard date tag
35
+ * }
36
+ *
37
+ * fromUntaggedCbor(cbor: Cbor): Date {
38
+ * // Convert the untagged CBOR to a number
39
+ * if (cbor.type !== MajorType.Unsigned) {
40
+ * throw new Error('Wrong type');
41
+ * }
42
+ * const timestamp = typeof cbor.value === 'bigint' ? Number(cbor.value) : cbor.value;
43
+ * return new Date(timestamp);
44
+ * }
45
+ *
46
+ * fromTaggedCbor(cbor: Cbor): Date {
47
+ * if (cbor.type !== MajorType.Tagged) {
48
+ * throw new Error('Wrong type');
49
+ * }
50
+ *
51
+ * const tags = this.cborTags();
52
+ * const tagValues = tags.map(t => t.value);
53
+ * if (!tagValues.includes(cbor.tag as number)) {
54
+ * throw new Error(`Wrong tag: expected ${tagValues[0]}, got ${cbor.tag}`);
55
+ * }
56
+ *
57
+ * return this.fromUntaggedCbor(cbor.value);
58
+ * }
59
+ *
60
+ * static fromTaggedCborData(data: Uint8Array): Date {
61
+ * const cbor = decodeCbor(data);
62
+ * return new Date(0).fromTaggedCbor(cbor);
63
+ * }
64
+ *
65
+ * static fromUntaggedCborData(data: Uint8Array): Date {
66
+ * const cbor = decodeCbor(data);
67
+ * return new Date(0).fromUntaggedCbor(cbor);
68
+ * }
69
+ * }
70
+ *
71
+ * // Create tagged CBOR data
72
+ * const taggedCbor = {
73
+ * isCbor: true,
74
+ * type: MajorType.Tagged,
75
+ * tag: 1,
76
+ * value: cbor(1609459200)
77
+ * };
78
+ *
79
+ * // Decode using the interface
80
+ * const date = new Date(0).fromTaggedCbor(taggedCbor);
81
+ * assert(date.timestamp === 1609459200);
82
+ * ```
83
+ */
84
+ export interface CborTaggedDecodable<T> extends CborTagged {
85
+ /**
86
+ * Creates an instance of this type by decoding it from untagged CBOR.
87
+ *
88
+ * This method defines how to interpret the CBOR content (without
89
+ * considering the tag) and convert it to the implementing type.
90
+ *
91
+ * @param cbor - Untagged CBOR value
92
+ * @returns Decoded instance
93
+ * @throws Error if the CBOR value cannot be decoded
94
+ */
95
+ fromUntaggedCbor(cbor: Cbor): T;
96
+
97
+ /**
98
+ * Creates an instance of this type by decoding it from tagged CBOR.
99
+ *
100
+ * This method first verifies that the CBOR value has one of the expected
101
+ * tags (as defined by `cborTags()`), then delegates to
102
+ * `fromUntaggedCbor()` to decode the content.
103
+ *
104
+ * For backward compatibility, this method accepts any tag from the
105
+ * `cborTags()` array, not just the first one. This allows new
106
+ * versions of types to still accept data tagged with older/alternative
107
+ * tag values.
108
+ *
109
+ * In most cases, you don't need to override this method.
110
+ *
111
+ * @param cbor - Tagged CBOR value
112
+ * @returns Decoded instance
113
+ * @throws Error if the CBOR value has the wrong tag or cannot be decoded
114
+ */
115
+ fromTaggedCbor(cbor: Cbor): T;
116
+
117
+ /**
118
+ * Creates an instance of this type by decoding it from binary encoded
119
+ * tagged CBOR.
120
+ *
121
+ * This is a convenience method that first parses the binary data into a
122
+ * CBOR value, then uses `fromTaggedCbor()` to decode it.
123
+ *
124
+ * @param data - Binary CBOR data
125
+ * @returns Decoded instance
126
+ * @throws Error if the data cannot be parsed or decoded
127
+ */
128
+ fromTaggedCborData?(data: Uint8Array): T;
129
+
130
+ /**
131
+ * Creates an instance of this type by decoding it from binary encoded
132
+ * untagged CBOR.
133
+ *
134
+ * This is a convenience method that first parses the binary data into a
135
+ * CBOR value, then uses `fromUntaggedCbor()` to decode it.
136
+ *
137
+ * @param data - Binary CBOR data
138
+ * @returns Decoded instance
139
+ * @throws Error if the data cannot be parsed or decoded
140
+ */
141
+ fromUntaggedCborData?(data: Uint8Array): T;
142
+ }
143
+
144
+ /**
145
+ * Helper function to validate that a CBOR value has one of the expected tags.
146
+ *
147
+ * @param cbor - CBOR value to validate
148
+ * @param expectedTags - Array of valid tags
149
+ * @returns The matching tag
150
+ * @throws Error if the value is not tagged or has an unexpected tag
151
+ */
152
+ export const validateTag = (cbor: Cbor, expectedTags: Tag[]): Tag => {
153
+ if (cbor.type !== MajorType.Tagged) {
154
+ throw new CborError({ type: "WrongType" });
155
+ }
156
+
157
+ const expectedValues = expectedTags.map((t) => t.value);
158
+ const tagValue = cbor.tag;
159
+
160
+ const matchingTag = expectedTags.find((t) => t.value === tagValue);
161
+ if (matchingTag === undefined) {
162
+ const expectedStr = expectedValues.join(" or ");
163
+ throw new CborError({
164
+ type: "Custom",
165
+ message: `Wrong tag: expected ${expectedStr}, got ${tagValue}`,
166
+ });
167
+ }
168
+
169
+ return matchingTag;
170
+ };
171
+
172
+ /**
173
+ * Helper function to extract the content from a tagged CBOR value.
174
+ *
175
+ * @param cbor - Tagged CBOR value
176
+ * @returns The untagged content
177
+ * @throws Error if the value is not tagged
178
+ */
179
+ export const extractTaggedContent = (cbor: Cbor): Cbor => {
180
+ if (cbor.type !== MajorType.Tagged) {
181
+ throw new CborError({ type: "WrongType" });
182
+ }
183
+ return cbor.value;
184
+ };
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Tagged CBOR encoding support.
3
+ *
4
+ * This module provides the `CborTaggedEncodable` interface, which enables types to
5
+ * be encoded as tagged CBOR values.
6
+ *
7
+ * CBOR tags provide semantic information about the encoded data. For example,
8
+ * tag 1 is used for dates, indicating that the value should be interpreted
9
+ * as a timestamp. The dCBOR library ensures these tags are encoded
10
+ * deterministically.
11
+ *
12
+ * This interface enables seamless encoding of TypeScript types to properly tagged CBOR
13
+ * values.
14
+ *
15
+ * @module cbor-tagged-encodable
16
+ */
17
+
18
+ import { type Cbor, MajorType, attachMethods } from "./cbor";
19
+ import type { CborTagged } from "./cbor-tagged";
20
+ import { CborError } from "./error";
21
+
22
+ /**
23
+ * Interface for types that can be encoded to CBOR with a specific tag.
24
+ *
25
+ * This interface extends `CborTagged` to provide methods for encoding a value
26
+ * with its associated tag. Types that implement this interface define how they
27
+ * should be represented in CBOR format, both with and without their tag.
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Define a Date type
32
+ * class Date implements CborTaggedEncodable {
33
+ * constructor(private timestamp: number) {}
34
+ *
35
+ * cborTags(): Tag[] {
36
+ * return [createTag(1, 'date')]; // Standard date tag
37
+ * }
38
+ *
39
+ * untaggedCbor(): Cbor {
40
+ * // Date content is represented as a number
41
+ * return cbor(this.timestamp);
42
+ * }
43
+ *
44
+ * taggedCbor(): Cbor {
45
+ * const tags = this.cborTags();
46
+ * return {
47
+ * isCbor: true,
48
+ * type: MajorType.Tagged,
49
+ * tag: tags[0].value,
50
+ * value: this.untaggedCbor()
51
+ * };
52
+ * }
53
+ *
54
+ * taggedCborData(): Uint8Array {
55
+ * return cborData(this.taggedCbor());
56
+ * }
57
+ * }
58
+ *
59
+ * // Create a date and encode it
60
+ * const date = new Date(1609459200);
61
+ *
62
+ * // Get the untagged CBOR (just the timestamp)
63
+ * const untagged = date.untaggedCbor();
64
+ *
65
+ * // Get the tagged CBOR (with tag 1)
66
+ * const tagged = date.taggedCbor();
67
+ *
68
+ * // Get binary representation
69
+ * const data = date.taggedCborData();
70
+ * ```
71
+ */
72
+ export interface CborTaggedEncodable extends CborTagged {
73
+ /**
74
+ * Returns the untagged CBOR encoding of this instance.
75
+ *
76
+ * This method defines how the value itself (without its tag) should
77
+ * be represented in CBOR format.
78
+ *
79
+ * @returns Untagged CBOR representation
80
+ */
81
+ untaggedCbor(): Cbor;
82
+
83
+ /**
84
+ * Returns the tagged CBOR encoding of this instance.
85
+ *
86
+ * This method wraps the result of `untaggedCbor()` with the first tag
87
+ * from `cborTags()`, which is considered the "preferred" tag for the
88
+ * type.
89
+ *
90
+ * Even if a type supports multiple tags for backward-compatible decoding
91
+ * via `cborTags()`, only the first (preferred) tag is used for encoding.
92
+ * This ensures consistency in newly created data while maintaining the
93
+ * ability to read older formats.
94
+ *
95
+ * In most cases, you don't need to override this method.
96
+ *
97
+ * @returns Tagged CBOR representation
98
+ */
99
+ taggedCbor(): Cbor;
100
+
101
+ /**
102
+ * Returns the tagged value in CBOR binary representation.
103
+ *
104
+ * This is a convenience method that converts the result of `taggedCbor()`
105
+ * to binary format.
106
+ *
107
+ * @returns Binary CBOR representation
108
+ */
109
+ taggedCborData?(): Uint8Array;
110
+ }
111
+
112
+ /**
113
+ * Helper function to create tagged CBOR from an encodable object.
114
+ *
115
+ * Uses the first tag from cborTags().
116
+ *
117
+ * @param encodable - Object implementing CborTaggedEncodable
118
+ * @returns Tagged CBOR value
119
+ */
120
+ export const createTaggedCbor = (encodable: CborTaggedEncodable): Cbor => {
121
+ const tags = encodable.cborTags();
122
+ if (tags.length === 0) {
123
+ throw new CborError({ type: "Custom", message: "No tags defined for this type" });
124
+ }
125
+
126
+ const tag = tags[0];
127
+ if (tag === undefined) {
128
+ throw new CborError({ type: "Custom", message: "Tag is undefined" });
129
+ }
130
+ const untagged = encodable.untaggedCbor();
131
+
132
+ return attachMethods({
133
+ isCbor: true,
134
+ type: MajorType.Tagged,
135
+ tag: tag.value,
136
+ value: untagged,
137
+ });
138
+ };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Base trait for types that have associated CBOR tags.
3
+ *
4
+ * CBOR allows values to be "tagged" with semantic information using tag
5
+ * numbers. The dCBOR library provides a set of interfaces for working with tagged
6
+ * values in a type-safe manner.
7
+ *
8
+ * Tags in CBOR provide additional context about how a value should be
9
+ * interpreted. For example, tag 1 is used for dates, indicating the value is a
10
+ * timestamp.
11
+ *
12
+ * This interface system allows TypeScript types to define their associated CBOR tags
13
+ * and provide serialization/deserialization logic specifically for tagged
14
+ * values.
15
+ *
16
+ * @module cbor-tagged
17
+ */
18
+
19
+ import type { Tag } from "./tag";
20
+
21
+ /**
22
+ * Interface for types that have associated CBOR tags.
23
+ *
24
+ * In CBOR, tags provide semantic information about how to interpret data
25
+ * items. This interface defines which CBOR tag(s) are associated with a particular
26
+ * TypeScript type.
27
+ *
28
+ * Implementing this interface is a prerequisite for implementing
29
+ * `CborTaggedEncodable` and `CborTaggedDecodable`.
30
+ *
31
+ * ## Multiple Tags for Backward Compatibility
32
+ *
33
+ * The `cborTags()` method returns an array of tags, enabling support for
34
+ * backward compatibility with older tag versions:
35
+ *
36
+ * - **When encoding**: Only the first tag in the array is used for
37
+ * serialization
38
+ * - **When decoding**: Any of the tags in the array will be accepted
39
+ *
40
+ * This design solves several real-world problems:
41
+ *
42
+ * 1. **IANA Registration Simplification**: If you initially choose a tag in
43
+ * the Specification Required range (24-32767) and later want to move to the
44
+ * simpler First Come, First Served range (32768+), you can migrate while
45
+ * maintaining compatibility with existing data.
46
+ *
47
+ * 2. **Protocol Evolution**: As your protocol evolves, you can introduce new
48
+ * preferred tags while still supporting data encoded with older tags.
49
+ *
50
+ * 3. **Versioning**: Different tags can represent different versions of your
51
+ * data format while sharing the same TypeScript type for handling.
52
+ *
53
+ * @example
54
+ * ```typescript
55
+ * // Single tag
56
+ * class Date implements CborTagged {
57
+ * cborTags(): Tag[] {
58
+ * return [createTag(1, 'date')];
59
+ * }
60
+ * }
61
+ *
62
+ * // Multiple tags for backward compatibility
63
+ * class Seed implements CborTagged {
64
+ * cborTags(): Tag[] {
65
+ * return [
66
+ * createTag(40300, 'seed'), // Primary tag (used for encoding)
67
+ * createTag(300, 'seed-legacy'), // Legacy tag (accepted for decoding)
68
+ * ];
69
+ * }
70
+ * }
71
+ * ```
72
+ */
73
+ export interface CborTagged {
74
+ /**
75
+ * Returns the CBOR tags associated with this type.
76
+ *
77
+ * This method should return an array of tags in order of preference:
78
+ *
79
+ * - The first tag in the array is the "preferred" tag and will be used
80
+ * when encoding values of this type via
81
+ * `CborTaggedEncodable.taggedCbor()`.
82
+ *
83
+ * - All tags in the array are considered equivalent for decoding. When
84
+ * `CborTaggedDecodable.fromTaggedCbor()` is called, any tag in this
85
+ * array will be accepted as valid for this type.
86
+ *
87
+ * This design enables backward compatibility: you can introduce a new tag
88
+ * (placed first in the array) while still supporting older tags for
89
+ * decoding.
90
+ *
91
+ * For standard CBOR tags, you can use predefined tag constants from the
92
+ * `tags` module, or create custom tags with `createTag()`.
93
+ */
94
+ cborTags(): Tag[];
95
+ }
96
+
97
+ // Re-export interfaces and functions from separate modules for convenience
98
+ export { type CborTaggedEncodable, createTaggedCbor } from "./cbor-tagged-encodable";
99
+ export {
100
+ type CborTaggedDecodable,
101
+ validateTag,
102
+ extractTaggedContent,
103
+ } from "./cbor-tagged-decodable";
104
+ export { type CborTaggedCodable } from "./cbor-tagged-codable";