@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.
- package/LICENSE +48 -0
- package/README.md +13 -0
- package/dist/index.cjs +9151 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3107 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +3107 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.iife.js +9155 -0
- package/dist/index.iife.js.map +1 -0
- package/dist/index.mjs +9027 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +80 -0
- package/src/.claude-flow/metrics/agent-metrics.json +1 -0
- package/src/.claude-flow/metrics/performance.json +87 -0
- package/src/.claude-flow/metrics/task-metrics.json +10 -0
- package/src/byte-string.ts +300 -0
- package/src/cbor-codable.ts +170 -0
- package/src/cbor-tagged-codable.ts +72 -0
- package/src/cbor-tagged-decodable.ts +184 -0
- package/src/cbor-tagged-encodable.ts +138 -0
- package/src/cbor-tagged.ts +104 -0
- package/src/cbor.ts +869 -0
- package/src/conveniences.ts +840 -0
- package/src/date.ts +553 -0
- package/src/decode.ts +276 -0
- package/src/diag.ts +462 -0
- package/src/dump.ts +277 -0
- package/src/error.ts +259 -0
- package/src/exact.ts +714 -0
- package/src/float.ts +279 -0
- package/src/global.d.ts +34 -0
- package/src/globals.d.ts +0 -0
- package/src/index.ts +180 -0
- package/src/map.ts +308 -0
- package/src/prelude.ts +70 -0
- package/src/set.ts +515 -0
- package/src/simple.ts +153 -0
- package/src/stdlib.ts +55 -0
- package/src/string-util.ts +55 -0
- package/src/tag.ts +53 -0
- package/src/tags-store.ts +294 -0
- package/src/tags.ts +231 -0
- package/src/varint.ts +124 -0
- 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";
|