@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
package/package.json ADDED
@@ -0,0 +1,80 @@
1
+ {
2
+ "name": "@bcts/dcbor",
3
+ "version": "1.0.0-alpha.10",
4
+ "type": "module",
5
+ "description": "Blockchain Commons Deterministic CBOR (dCBOR) for TypeScript",
6
+ "license": "BSD-2-Clause-Patent",
7
+ "author": "Leonardo Custodio <leonardo@custodio.me>",
8
+ "homepage": "https://bcts.dev",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/leonardocustodio/bcts",
12
+ "directory": "packages/dcbor"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/leonardocustodio/bcts/issues"
16
+ },
17
+ "main": "dist/index.cjs",
18
+ "module": "dist/index.mjs",
19
+ "types": "dist/index.d.mts",
20
+ "browser": "dist/index.iife.js",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.mts",
24
+ "import": "./dist/index.mjs",
25
+ "require": "./dist/index.cjs",
26
+ "default": "./dist/index.mjs"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "src",
32
+ "README.md"
33
+ ],
34
+ "scripts": {
35
+ "build": "tsdown",
36
+ "dev": "tsdown --watch",
37
+ "test": "vitest run",
38
+ "test:watch": "vitest",
39
+ "test:cli": "vitest run tests/cli.test.ts",
40
+ "test:examples": "npm run build && node scripts/test-examples.js",
41
+ "lint": "eslint 'src/**/*.ts' 'tests/**/*.ts'",
42
+ "lint:fix": "eslint 'src/**/*.ts' 'tests/**/*.ts' --fix",
43
+ "typecheck": "tsc --noEmit",
44
+ "clean": "rm -rf dist",
45
+ "docs": "typedoc",
46
+ "prepublishOnly": "npm run clean && npm run build && npm test"
47
+ },
48
+ "keywords": [
49
+ "cbor",
50
+ "dcbor",
51
+ "deterministic",
52
+ "blockchain-commons",
53
+ "encoding",
54
+ "serialization",
55
+ "codec",
56
+ "binary"
57
+ ],
58
+ "engines": {
59
+ "node": ">=18.0.0"
60
+ },
61
+ "devDependencies": {
62
+ "@bcts/eslint": "^0.1.0",
63
+ "@bcts/tsconfig": "^0.1.0",
64
+ "@eslint/js": "^9.39.2",
65
+ "@types/collections": "^5.1.5",
66
+ "@types/node": "^25.0.3",
67
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
68
+ "@typescript-eslint/parser": "^8.50.1",
69
+ "eslint": "^9.39.2",
70
+ "ts-node": "^10.9.2",
71
+ "tsdown": "^0.18.3",
72
+ "typedoc": "^0.28.15",
73
+ "typescript": "^5.9.3",
74
+ "vitest": "^4.0.16"
75
+ },
76
+ "dependencies": {
77
+ "byte-data": "^19.0.1",
78
+ "collections": "^5.1.13"
79
+ }
80
+ }
@@ -0,0 +1,87 @@
1
+ {
2
+ "startTime": 1764550116519,
3
+ "sessionId": "session-1764550116519",
4
+ "lastActivity": 1764550116519,
5
+ "sessionDuration": 0,
6
+ "totalTasks": 1,
7
+ "successfulTasks": 1,
8
+ "failedTasks": 0,
9
+ "totalAgents": 0,
10
+ "activeAgents": 0,
11
+ "neuralEvents": 0,
12
+ "memoryMode": {
13
+ "reasoningbankOperations": 0,
14
+ "basicOperations": 0,
15
+ "autoModeSelections": 0,
16
+ "modeOverrides": 0,
17
+ "currentMode": "auto"
18
+ },
19
+ "operations": {
20
+ "store": {
21
+ "count": 0,
22
+ "totalDuration": 0,
23
+ "errors": 0
24
+ },
25
+ "retrieve": {
26
+ "count": 0,
27
+ "totalDuration": 0,
28
+ "errors": 0
29
+ },
30
+ "query": {
31
+ "count": 0,
32
+ "totalDuration": 0,
33
+ "errors": 0
34
+ },
35
+ "list": {
36
+ "count": 0,
37
+ "totalDuration": 0,
38
+ "errors": 0
39
+ },
40
+ "delete": {
41
+ "count": 0,
42
+ "totalDuration": 0,
43
+ "errors": 0
44
+ },
45
+ "search": {
46
+ "count": 0,
47
+ "totalDuration": 0,
48
+ "errors": 0
49
+ },
50
+ "init": {
51
+ "count": 0,
52
+ "totalDuration": 0,
53
+ "errors": 0
54
+ }
55
+ },
56
+ "performance": {
57
+ "avgOperationDuration": 0,
58
+ "minOperationDuration": null,
59
+ "maxOperationDuration": null,
60
+ "slowOperations": 0,
61
+ "fastOperations": 0,
62
+ "totalOperationTime": 0
63
+ },
64
+ "storage": {
65
+ "totalEntries": 0,
66
+ "reasoningbankEntries": 0,
67
+ "basicEntries": 0,
68
+ "databaseSize": 0,
69
+ "lastBackup": null,
70
+ "growthRate": 0
71
+ },
72
+ "errors": {
73
+ "total": 0,
74
+ "byType": {},
75
+ "byOperation": {},
76
+ "recent": []
77
+ },
78
+ "reasoningbank": {
79
+ "semanticSearches": 0,
80
+ "sqlFallbacks": 0,
81
+ "embeddingGenerated": 0,
82
+ "consolidations": 0,
83
+ "avgQueryTime": 0,
84
+ "cacheHits": 0,
85
+ "cacheMisses": 0
86
+ }
87
+ }
@@ -0,0 +1,10 @@
1
+ [
2
+ {
3
+ "id": "cmd-hooks-1764550116550",
4
+ "type": "hooks",
5
+ "success": true,
6
+ "duration": 3.348541999999995,
7
+ "timestamp": 1764550116553,
8
+ "metadata": {}
9
+ }
10
+ ]
@@ -0,0 +1,300 @@
1
+ /**
2
+ * Byte string utilities for dCBOR.
3
+ *
4
+ * Represents a CBOR byte string (major type 2).
5
+ *
6
+ * `ByteString` is a wrapper around a byte array, optimized for use in CBOR
7
+ * encoding and decoding operations. It provides a richer API for working with
8
+ * byte data in the context of CBOR compared to using raw `Uint8Array` values.
9
+ *
10
+ * In dCBOR, byte strings follow the general deterministic encoding rules:
11
+ * - They must use definite-length encoding
12
+ * - Their length must be encoded in the shortest possible form
13
+ *
14
+ * @module byte-string
15
+ */
16
+
17
+ import { type Cbor, MajorType, cbor as toCbor } from "./cbor";
18
+ import { CborError } from "./error";
19
+
20
+ /**
21
+ * Represents a CBOR byte string (major type 2).
22
+ *
23
+ * Use Cases:
24
+ * - Binary data such as images, audio, or other non-text content
25
+ * - Cryptographic values like hashes, signatures, and public keys
26
+ * - Embedded CBOR (wrapped with tag 24)
27
+ * - Other serialized data formats embedded in CBOR
28
+ *
29
+ * @example
30
+ * ```typescript
31
+ * // Creating a byte string from various sources
32
+ * const bytes1 = new ByteString(new Uint8Array([1, 2, 3, 4]));
33
+ * const bytes2 = ByteString.from([5, 6, 7, 8]);
34
+ * const bytes3 = ByteString.from(new Uint8Array([9, 10, 11, 12]));
35
+ *
36
+ * // Converting to and from CBOR
37
+ * const cborValue = bytes1.toCbor();
38
+ *
39
+ * // ByteString provides Uint8Array-like operations
40
+ * const bytes = new ByteString(new Uint8Array([1, 2]));
41
+ * bytes.extend(new Uint8Array([3, 4]));
42
+ * assert(bytes.len() === 4);
43
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4]));
44
+ * ```
45
+ */
46
+ export class ByteString {
47
+ #data: Uint8Array;
48
+
49
+ /**
50
+ * Creates a new `ByteString` from a Uint8Array or array of bytes.
51
+ *
52
+ * @param data - The byte data
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * // From a Uint8Array
57
+ * const bytes1 = new ByteString(new Uint8Array([1, 2, 3, 4]));
58
+ *
59
+ * // From a number array
60
+ * const bytes2 = new ByteString(new Uint8Array([5, 6, 7, 8]));
61
+ * ```
62
+ */
63
+ constructor(data: Uint8Array | number[]) {
64
+ if (Array.isArray(data)) {
65
+ this.#data = new Uint8Array(data);
66
+ } else {
67
+ this.#data = new Uint8Array(data);
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Creates a new `ByteString` from various input types.
73
+ *
74
+ * @param data - Uint8Array, number array, or string
75
+ * @returns New ByteString instance
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const bytes1 = ByteString.from([1, 2, 3, 4]);
80
+ * const bytes2 = ByteString.from(new Uint8Array([5, 6, 7, 8]));
81
+ * const bytes3 = ByteString.from("hello");
82
+ * ```
83
+ */
84
+ static from(data: Uint8Array | number[] | string): ByteString {
85
+ if (typeof data === "string") {
86
+ return new ByteString(new TextEncoder().encode(data));
87
+ }
88
+ return new ByteString(data);
89
+ }
90
+
91
+ /**
92
+ * Returns a reference to the underlying byte data.
93
+ *
94
+ * @returns The raw bytes
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3, 4]));
99
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4]));
100
+ *
101
+ * // You can use standard slice operations on the result
102
+ * assert.deepEqual(bytes.data().slice(1, 3), new Uint8Array([2, 3]));
103
+ * ```
104
+ */
105
+ data(): Uint8Array {
106
+ return this.#data;
107
+ }
108
+
109
+ /**
110
+ * Returns the length of the byte string in bytes.
111
+ *
112
+ * @returns Number of bytes
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * const empty = new ByteString(new Uint8Array([]));
117
+ * assert(empty.len() === 0);
118
+ *
119
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3, 4]));
120
+ * assert(bytes.len() === 4);
121
+ * ```
122
+ */
123
+ len(): number {
124
+ return this.#data.length;
125
+ }
126
+
127
+ /**
128
+ * Returns `true` if the byte string contains no bytes.
129
+ *
130
+ * @returns true if empty
131
+ *
132
+ * @example
133
+ * ```typescript
134
+ * const empty = new ByteString(new Uint8Array([]));
135
+ * assert(empty.isEmpty());
136
+ *
137
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3, 4]));
138
+ * assert(!bytes.isEmpty());
139
+ * ```
140
+ */
141
+ isEmpty(): boolean {
142
+ return this.#data.length === 0;
143
+ }
144
+
145
+ /**
146
+ * Extends the byte string with additional bytes.
147
+ *
148
+ * @param other - Bytes to append
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const bytes = new ByteString(new Uint8Array([1, 2]));
153
+ * bytes.extend(new Uint8Array([3, 4]));
154
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4]));
155
+ *
156
+ * // You can extend with different types
157
+ * bytes.extend([5, 6]);
158
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4, 5, 6]));
159
+ * ```
160
+ */
161
+ extend(other: Uint8Array | number[]): void {
162
+ const otherArray = Array.isArray(other) ? new Uint8Array(other) : other;
163
+ const newData = new Uint8Array(this.#data.length + otherArray.length);
164
+ newData.set(this.#data, 0);
165
+ newData.set(otherArray, this.#data.length);
166
+ this.#data = newData;
167
+ }
168
+
169
+ /**
170
+ * Creates a new Uint8Array containing a copy of the byte string's data.
171
+ *
172
+ * @returns Copy of the data
173
+ *
174
+ * @example
175
+ * ```typescript
176
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3, 4]));
177
+ * const arr = bytes.toUint8Array();
178
+ * assert.deepEqual(arr, new Uint8Array([1, 2, 3, 4]));
179
+ *
180
+ * // The returned array is a clone, so you can modify it independently
181
+ * const arr2 = bytes.toUint8Array();
182
+ * arr2[0] = 99;
183
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4])); // original unchanged
184
+ * ```
185
+ */
186
+ toUint8Array(): Uint8Array {
187
+ return new Uint8Array(this.#data);
188
+ }
189
+
190
+ /**
191
+ * Returns an iterator over the bytes in the byte string.
192
+ *
193
+ * @returns Iterator yielding each byte
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3]));
198
+ * const iter = bytes.iter();
199
+ *
200
+ * assert(iter.next().value === 1);
201
+ * assert(iter.next().value === 2);
202
+ * assert(iter.next().value === 3);
203
+ * assert(iter.next().done);
204
+ *
205
+ * // You can also use for loops
206
+ * let sum = 0;
207
+ * for (const byte of bytes) {
208
+ * sum += byte;
209
+ * }
210
+ * assert(sum === 6);
211
+ * ```
212
+ */
213
+ iter(): Iterator<number> {
214
+ return this.#data.values();
215
+ }
216
+
217
+ /**
218
+ * Makes ByteString iterable.
219
+ */
220
+ [Symbol.iterator](): Iterator<number> {
221
+ return this.iter();
222
+ }
223
+
224
+ /**
225
+ * Converts the ByteString to a CBOR value.
226
+ *
227
+ * @returns CBOR byte string
228
+ *
229
+ * @example
230
+ * ```typescript
231
+ * const bytes = new ByteString(new Uint8Array([1, 2, 3, 4]));
232
+ * const cborValue = bytes.toCbor();
233
+ * ```
234
+ */
235
+ toCbor(): Cbor {
236
+ return toCbor(this.#data);
237
+ }
238
+
239
+ /**
240
+ * Attempts to convert a CBOR value into a ByteString.
241
+ *
242
+ * @param cbor - CBOR value
243
+ * @returns ByteString if successful
244
+ * @throws Error if the CBOR value is not a byte string
245
+ *
246
+ * @example
247
+ * ```typescript
248
+ * const cborValue = toCbor(new Uint8Array([1, 2, 3, 4]));
249
+ * const bytes = ByteString.fromCbor(cborValue);
250
+ * assert.deepEqual(bytes.data(), new Uint8Array([1, 2, 3, 4]));
251
+ *
252
+ * // Converting from a different CBOR type throws
253
+ * const cborInt = toCbor(42);
254
+ * try {
255
+ * ByteString.fromCbor(cborInt); // throws
256
+ * } catch(e) {
257
+ * // Error: Wrong type
258
+ * }
259
+ * ```
260
+ */
261
+ static fromCbor(cbor: Cbor): ByteString {
262
+ if (cbor.type !== MajorType.ByteString) {
263
+ throw new CborError({ type: "WrongType" });
264
+ }
265
+ return new ByteString(cbor.value);
266
+ }
267
+
268
+ /**
269
+ * Get element at index.
270
+ *
271
+ * @param index - Index to access
272
+ * @returns Byte at index or undefined
273
+ */
274
+ at(index: number): number | undefined {
275
+ return this.#data[index];
276
+ }
277
+
278
+ /**
279
+ * Equality comparison.
280
+ *
281
+ * @param other - ByteString to compare with
282
+ * @returns true if equal
283
+ */
284
+ equals(other: ByteString): boolean {
285
+ if (this.#data.length !== other.#data.length) return false;
286
+ for (let i = 0; i < this.#data.length; i++) {
287
+ if (this.#data[i] !== other.#data[i]) return false;
288
+ }
289
+ return true;
290
+ }
291
+
292
+ /**
293
+ * Clone this ByteString.
294
+ *
295
+ * @returns New ByteString with copied data
296
+ */
297
+ clone(): ByteString {
298
+ return new ByteString(this.toUint8Array());
299
+ }
300
+ }
@@ -0,0 +1,170 @@
1
+ /**
2
+ * CBOR Encoding and Decoding Interfaces.
3
+ *
4
+ * These interfaces provide functionality for converting between TypeScript types and
5
+ * CBOR data. They form the foundation of the dCBOR serialization
6
+ * infrastructure.
7
+ *
8
+ * The main interfaces are:
9
+ *
10
+ * - `CborEncodable`: For types that can be encoded to CBOR
11
+ * - `CborDecodable`: For types that can be decoded from CBOR
12
+ * - `CborCodable`: For types that can do both (a combination of the above)
13
+ *
14
+ * These interfaces allow for ergonomic conversions using TypeScript's type system and
15
+ * enable seamless integration with dCBOR's deterministic encoding rules.
16
+ *
17
+ * @module cbor-codable
18
+ */
19
+
20
+ import type { Cbor } from "./cbor";
21
+
22
+ /**
23
+ * Interface for types that can be encoded to CBOR.
24
+ *
25
+ * This interface provides convenient methods for converting
26
+ * instances into CBOR objects and binary data.
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * // Custom type that can convert to CBOR
31
+ * class Person implements CborEncodable {
32
+ * constructor (public name: string, public age: number) {}
33
+ *
34
+ * toCbor(): Cbor {
35
+ * const map = new CborMap();
36
+ * map.set(cbor('name'), cbor(this.name));
37
+ * map.set(cbor('age'), cbor(this.age));
38
+ * return cbor(map);
39
+ * }
40
+ *
41
+ * toCborData(): Uint8Array {
42
+ * return cborData(this.toCbor());
43
+ * }
44
+ * }
45
+ *
46
+ * // Use the interface
47
+ * const person = new Person('Alice', 30);
48
+ *
49
+ * // Convert to CBOR
50
+ * const cborValue = person.toCbor();
51
+ *
52
+ * // Convert directly to binary CBOR data
53
+ * const data = person.toCborData();
54
+ * ```
55
+ */
56
+ export interface CborEncodable {
57
+ /**
58
+ * Converts this value to a CBOR object.
59
+ *
60
+ * @returns CBOR representation
61
+ */
62
+ toCbor(): Cbor;
63
+
64
+ /**
65
+ * Converts this value directly to binary CBOR data.
66
+ *
67
+ * This is a shorthand for `cborData(this.toCbor())`.
68
+ *
69
+ * @returns Binary CBOR data
70
+ */
71
+ toCborData(): Uint8Array;
72
+ }
73
+
74
+ /**
75
+ * Interface for types that can be decoded from CBOR.
76
+ *
77
+ * This interface serves as a marker to indicate that a type
78
+ * supports being created from CBOR data.
79
+ *
80
+ * @typeParam T - The type being decoded
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Custom type that can be decoded from CBOR
85
+ * class Person implements CborDecodable<Person> {
86
+ * constructor(public name: string = '', public age: number = 0) {}
87
+ *
88
+ * static fromCbor(cbor: Cbor): Person {
89
+ * if (cbor.type !== MajorType.Map) {
90
+ * throw new Error('Expected a CBOR map');
91
+ * }
92
+ * const map = cbor.value as CborMap;
93
+ * const name = extractCbor(map.get(cbor('name'))!) as string;
94
+ * const age = extractCbor(map.get(cbor('age'))!) as number;
95
+ * return new Person(name, age);
96
+ * }
97
+ *
98
+ * tryFromCbor(cbor: Cbor): Person {
99
+ * return Person.fromCbor(cbor);
100
+ * }
101
+ * }
102
+ *
103
+ * // Parse from CBOR
104
+ * const cborMap = ...; // some CBOR map
105
+ * const person = Person.fromCbor(cborMap);
106
+ * ```
107
+ */
108
+ export interface CborDecodable<T> {
109
+ /**
110
+ * Try to create an instance from a CBOR value.
111
+ *
112
+ * @param cbor - CBOR value to decode
113
+ * @returns Decoded instance
114
+ * @throws Error if decoding fails
115
+ */
116
+ tryFromCbor(cbor: Cbor): T;
117
+ }
118
+
119
+ /**
120
+ * Interface for types that can be both encoded to and decoded from CBOR.
121
+ *
122
+ * This interface is a convenience marker for types that implement both
123
+ * `CborEncodable` and `CborDecodable`. It serves to indicate full CBOR
124
+ * serialization support.
125
+ *
126
+ * @typeParam T - The type being encoded/decoded
127
+ *
128
+ * @example
129
+ * ```typescript
130
+ * // Custom type that implements both conversion directions
131
+ * class Person implements CborCodable<Person> {
132
+ * constructor(public name: string = '', public age: number = 0) {}
133
+ *
134
+ * // Implement encoding to CBOR
135
+ * toCbor(): Cbor {
136
+ * const map = new CborMap();
137
+ * map.set(cbor('name'), cbor(this.name));
138
+ * map.set(cbor('age'), cbor(this.age));
139
+ * return cbor(map);
140
+ * }
141
+ *
142
+ * toCborData(): Uint8Array {
143
+ * return cborData(this.toCbor());
144
+ * }
145
+ *
146
+ * // Implement decoding from CBOR
147
+ * static fromCbor(cbor: Cbor): Person {
148
+ * if (cbor.type !== MajorType.Map) {
149
+ * throw new Error('Expected a CBOR map');
150
+ * }
151
+ * const map = cbor.value as CborMap;
152
+ * const name = extractCbor(map.get(cbor('name'))!) as string;
153
+ * const age = extractCbor(map.get(cbor('age'))!) as number;
154
+ * return new Person(name, age);
155
+ * }
156
+ *
157
+ * tryFromCbor(cbor: Cbor): Person {
158
+ * return Person.fromCbor(cbor);
159
+ * }
160
+ * }
161
+ *
162
+ * // Person now implements CborCodable
163
+ * const person = new Person('Alice', 30);
164
+ * const cborValue = person.toCbor(); // Using CborEncodable
165
+ *
166
+ * // Create a round-trip copy
167
+ * const personCopy = Person.fromCbor(cborValue); // Using CborDecodable
168
+ * ```
169
+ */
170
+ export interface CborCodable<T> extends CborEncodable, CborDecodable<T> {}