@bcts/dcbor 1.0.0-alpha.5
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
package/src/cbor.ts
ADDED
|
@@ -0,0 +1,869 @@
|
|
|
1
|
+
import { CborMap } from "./map";
|
|
2
|
+
import type { Simple } from "./simple";
|
|
3
|
+
import { simpleCborData, isFloat as isSimpleFloat } from "./simple";
|
|
4
|
+
import { hasFractionalPart } from "./float";
|
|
5
|
+
import { encodeVarInt } from "./varint";
|
|
6
|
+
import { concatBytes } from "./stdlib";
|
|
7
|
+
import { bytesToHex, hexOpt } from "./dump";
|
|
8
|
+
import { hexToBytes } from "./dump";
|
|
9
|
+
import type { Tag } from "./tag";
|
|
10
|
+
import type { ByteString } from "./byte-string";
|
|
11
|
+
import type { CborDate } from "./date";
|
|
12
|
+
import { diagnosticOpt } from "./diag";
|
|
13
|
+
import { decodeCbor } from "./decode";
|
|
14
|
+
import type { TagsStore } from "./tags-store";
|
|
15
|
+
import { getGlobalTagsStore } from "./tags-store";
|
|
16
|
+
import type { Visitor } from "./walk";
|
|
17
|
+
import { walk } from "./walk";
|
|
18
|
+
import { CborError } from "./error";
|
|
19
|
+
|
|
20
|
+
export type { Simple };
|
|
21
|
+
|
|
22
|
+
export const MajorType = {
|
|
23
|
+
Unsigned: 0,
|
|
24
|
+
Negative: 1,
|
|
25
|
+
ByteString: 2,
|
|
26
|
+
Text: 3,
|
|
27
|
+
Array: 4,
|
|
28
|
+
Map: 5,
|
|
29
|
+
Tagged: 6,
|
|
30
|
+
Simple: 7,
|
|
31
|
+
} as const;
|
|
32
|
+
|
|
33
|
+
// eslint-disable-next-line no-redeclare -- Intentionally using same name for value and type
|
|
34
|
+
export type MajorType = (typeof MajorType)[keyof typeof MajorType];
|
|
35
|
+
|
|
36
|
+
// Helper to get MajorType name from value (replaces enum reverse mapping)
|
|
37
|
+
const MajorTypeNames: Record<MajorType, string> = {
|
|
38
|
+
[MajorType.Unsigned]: "Unsigned",
|
|
39
|
+
[MajorType.Negative]: "Negative",
|
|
40
|
+
[MajorType.ByteString]: "ByteString",
|
|
41
|
+
[MajorType.Text]: "Text",
|
|
42
|
+
[MajorType.Array]: "Array",
|
|
43
|
+
[MajorType.Map]: "Map",
|
|
44
|
+
[MajorType.Tagged]: "Tagged",
|
|
45
|
+
[MajorType.Simple]: "Simple",
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getMajorTypeName = (type: MajorType): string => MajorTypeNames[type];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Numeric type that can be encoded in CBOR.
|
|
52
|
+
*
|
|
53
|
+
* Supports both standard JavaScript numbers and BigInt for large integers.
|
|
54
|
+
* Numbers are automatically encoded as either unsigned or negative integers
|
|
55
|
+
* depending on their value, following dCBOR canonical encoding rules.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const smallNum: CborNumber = 42;
|
|
60
|
+
* const largeNum: CborNumber = 9007199254740992n;
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export type CborNumber = number | bigint;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Type for values that can be converted to CBOR.
|
|
67
|
+
*
|
|
68
|
+
* This is a comprehensive union type representing all values that can be encoded
|
|
69
|
+
* as CBOR using the `cbor()` function. It includes:
|
|
70
|
+
* - Already-encoded CBOR values (`Cbor`)
|
|
71
|
+
* - Primitive types: numbers, bigints, strings, booleans, null, undefined
|
|
72
|
+
* - Binary data: `Uint8Array`, `ByteString`
|
|
73
|
+
* - Dates: `CborDate`
|
|
74
|
+
* - Collections: `CborMap`, arrays, JavaScript `Map`, JavaScript `Set`
|
|
75
|
+
* - Objects: Plain objects are converted to CBOR maps
|
|
76
|
+
*
|
|
77
|
+
* Matches Rust's `From<T>` trait implementations for CBOR.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```typescript
|
|
81
|
+
* cbor(42); // number
|
|
82
|
+
* cbor("hello"); // string
|
|
83
|
+
* cbor([1, 2, 3]); // array
|
|
84
|
+
* cbor(new Map([["key", "value"]])); // Map
|
|
85
|
+
* cbor({ name: "Alice", age: 30 }); // plain object -> CborMap
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export type CborInput =
|
|
89
|
+
| Cbor
|
|
90
|
+
| CborNumber
|
|
91
|
+
| string
|
|
92
|
+
| boolean
|
|
93
|
+
| null
|
|
94
|
+
| undefined
|
|
95
|
+
| Uint8Array
|
|
96
|
+
| ByteString
|
|
97
|
+
| CborDate
|
|
98
|
+
| CborMap
|
|
99
|
+
| CborInput[]
|
|
100
|
+
| Map<unknown, unknown>
|
|
101
|
+
| Set<unknown>
|
|
102
|
+
| Record<string, unknown>;
|
|
103
|
+
|
|
104
|
+
export const isCborNumber = (value: unknown): value is CborNumber => {
|
|
105
|
+
return typeof value === "number" || typeof value === "bigint";
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
export const isCbor = (value: unknown): value is Cbor => {
|
|
109
|
+
return value !== null && typeof value === "object" && "isCbor" in value && value.isCbor === true;
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
export interface CborUnsignedType {
|
|
113
|
+
readonly isCbor: true;
|
|
114
|
+
readonly type: typeof MajorType.Unsigned;
|
|
115
|
+
readonly value: CborNumber;
|
|
116
|
+
}
|
|
117
|
+
export interface CborNegativeType {
|
|
118
|
+
readonly isCbor: true;
|
|
119
|
+
readonly type: typeof MajorType.Negative;
|
|
120
|
+
readonly value: CborNumber;
|
|
121
|
+
}
|
|
122
|
+
export interface CborByteStringType {
|
|
123
|
+
readonly isCbor: true;
|
|
124
|
+
readonly type: typeof MajorType.ByteString;
|
|
125
|
+
readonly value: Uint8Array;
|
|
126
|
+
}
|
|
127
|
+
export interface CborTextType {
|
|
128
|
+
readonly isCbor: true;
|
|
129
|
+
readonly type: typeof MajorType.Text;
|
|
130
|
+
readonly value: string;
|
|
131
|
+
}
|
|
132
|
+
export interface CborArrayType {
|
|
133
|
+
readonly isCbor: true;
|
|
134
|
+
readonly type: typeof MajorType.Array;
|
|
135
|
+
readonly value: readonly Cbor[];
|
|
136
|
+
}
|
|
137
|
+
export interface CborMapType {
|
|
138
|
+
readonly isCbor: true;
|
|
139
|
+
readonly type: typeof MajorType.Map;
|
|
140
|
+
readonly value: CborMap;
|
|
141
|
+
}
|
|
142
|
+
export interface CborTaggedType {
|
|
143
|
+
readonly isCbor: true;
|
|
144
|
+
readonly type: typeof MajorType.Tagged;
|
|
145
|
+
readonly tag: CborNumber;
|
|
146
|
+
readonly value: Cbor;
|
|
147
|
+
}
|
|
148
|
+
export interface CborSimpleType {
|
|
149
|
+
readonly isCbor: true;
|
|
150
|
+
readonly type: typeof MajorType.Simple;
|
|
151
|
+
readonly value: Simple;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Instance methods interface
|
|
155
|
+
export interface CborMethods {
|
|
156
|
+
// Universal encoding/formatting
|
|
157
|
+
toData(): Uint8Array;
|
|
158
|
+
toHex(): string;
|
|
159
|
+
toHexAnnotated(tagsStore?: TagsStore): string;
|
|
160
|
+
toString(): string;
|
|
161
|
+
toDebugString(): string;
|
|
162
|
+
toDiagnostic(): string;
|
|
163
|
+
toDiagnosticAnnotated(): string;
|
|
164
|
+
|
|
165
|
+
// Type checking
|
|
166
|
+
isByteString(): boolean;
|
|
167
|
+
isText(): boolean;
|
|
168
|
+
isArray(): boolean;
|
|
169
|
+
isMap(): boolean;
|
|
170
|
+
isTagged(): boolean;
|
|
171
|
+
isSimple(): boolean;
|
|
172
|
+
isBool(): boolean;
|
|
173
|
+
isTrue(): boolean;
|
|
174
|
+
isFalse(): boolean;
|
|
175
|
+
isNull(): boolean;
|
|
176
|
+
isNumber(): boolean;
|
|
177
|
+
isInteger(): boolean;
|
|
178
|
+
isUnsigned(): boolean;
|
|
179
|
+
isNegative(): boolean;
|
|
180
|
+
isNaN(): boolean;
|
|
181
|
+
isFloat(): boolean;
|
|
182
|
+
|
|
183
|
+
// Safe conversion (returns undefined on mismatch)
|
|
184
|
+
asByteString(): Uint8Array | undefined;
|
|
185
|
+
asText(): string | undefined;
|
|
186
|
+
asArray(): readonly Cbor[] | undefined;
|
|
187
|
+
asMap(): CborMap | undefined;
|
|
188
|
+
asTagged(): [Tag, Cbor] | undefined;
|
|
189
|
+
asBool(): boolean | undefined;
|
|
190
|
+
asInteger(): (number | bigint) | undefined;
|
|
191
|
+
asNumber(): (number | bigint) | undefined;
|
|
192
|
+
asSimpleValue(): Simple | undefined;
|
|
193
|
+
|
|
194
|
+
// Throwing conversion (throws on mismatch)
|
|
195
|
+
/**
|
|
196
|
+
* Convert to byte string, throwing if type doesn't match.
|
|
197
|
+
* @throws {TypeError} If value is not a byte string type
|
|
198
|
+
*/
|
|
199
|
+
toByteString(): Uint8Array;
|
|
200
|
+
/**
|
|
201
|
+
* Convert to text string, throwing if type doesn't match.
|
|
202
|
+
* @throws {TypeError} If value is not a text string type
|
|
203
|
+
*/
|
|
204
|
+
toText(): string;
|
|
205
|
+
/**
|
|
206
|
+
* Convert to array, throwing if type doesn't match.
|
|
207
|
+
* @throws {TypeError} If value is not an array type
|
|
208
|
+
*/
|
|
209
|
+
toArray(): readonly Cbor[];
|
|
210
|
+
/**
|
|
211
|
+
* Convert to map, throwing if type doesn't match.
|
|
212
|
+
* @throws {TypeError} If value is not a map type
|
|
213
|
+
*/
|
|
214
|
+
toMap(): CborMap;
|
|
215
|
+
/**
|
|
216
|
+
* Convert to tagged value, throwing if type doesn't match.
|
|
217
|
+
* @throws {TypeError} If value is not a tagged type
|
|
218
|
+
*/
|
|
219
|
+
toTagged(): [Tag, Cbor];
|
|
220
|
+
/**
|
|
221
|
+
* Convert to boolean, throwing if type doesn't match.
|
|
222
|
+
* @throws {TypeError} If value is not a boolean (True/False) type
|
|
223
|
+
*/
|
|
224
|
+
toBool(): boolean;
|
|
225
|
+
/**
|
|
226
|
+
* Convert to integer, throwing if type doesn't match.
|
|
227
|
+
* @throws {TypeError} If value is not an integer (Unsigned or Negative) type
|
|
228
|
+
*/
|
|
229
|
+
toInteger(): number | bigint;
|
|
230
|
+
/**
|
|
231
|
+
* Convert to number, throwing if type doesn't match.
|
|
232
|
+
* @throws {TypeError} If value is not a numeric (Unsigned, Negative, or Float) type
|
|
233
|
+
*/
|
|
234
|
+
toNumber(): number | bigint;
|
|
235
|
+
/**
|
|
236
|
+
* Convert to simple value, throwing if type doesn't match.
|
|
237
|
+
* @throws {TypeError} If value is not a simple type
|
|
238
|
+
*/
|
|
239
|
+
toSimpleValue(): Simple;
|
|
240
|
+
/**
|
|
241
|
+
* Expect specific tag and return content, throwing if tag doesn't match.
|
|
242
|
+
* @param tag - Expected tag value
|
|
243
|
+
* @throws {CborError} With type 'WrongType' if value is not tagged, or 'Custom' if tag doesn't match
|
|
244
|
+
*/
|
|
245
|
+
expectTag(tag: CborNumber | Tag): Cbor;
|
|
246
|
+
|
|
247
|
+
// Advanced operations
|
|
248
|
+
/**
|
|
249
|
+
* Walk the CBOR structure with a visitor function.
|
|
250
|
+
* @param initialState - Initial state for the visitor
|
|
251
|
+
* @param visitor - Visitor function called for each element
|
|
252
|
+
*/
|
|
253
|
+
walk<State>(initialState: State, visitor: Visitor<State>): State;
|
|
254
|
+
/**
|
|
255
|
+
* Validate that value has one of the expected tags.
|
|
256
|
+
* @param expectedTags - Array of expected tag values
|
|
257
|
+
* @throws {CborError} With type 'WrongType' if value is not tagged, or 'Custom' if tag doesn't match any expected value
|
|
258
|
+
*/
|
|
259
|
+
validateTag(expectedTags: Tag[]): Tag;
|
|
260
|
+
/**
|
|
261
|
+
* Remove one level of tagging, returning the inner content.
|
|
262
|
+
*/
|
|
263
|
+
untagged(): Cbor;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
export type Cbor = (
|
|
267
|
+
| CborUnsignedType
|
|
268
|
+
| CborNegativeType
|
|
269
|
+
| CborByteStringType
|
|
270
|
+
| CborTextType
|
|
271
|
+
| CborArrayType
|
|
272
|
+
| CborMapType
|
|
273
|
+
| CborTaggedType
|
|
274
|
+
| CborSimpleType
|
|
275
|
+
) &
|
|
276
|
+
CborMethods;
|
|
277
|
+
|
|
278
|
+
// ============================================================================
|
|
279
|
+
// Encoding Functions (matches Rust CBOR conversion logic)
|
|
280
|
+
// ============================================================================
|
|
281
|
+
|
|
282
|
+
export interface ToCbor {
|
|
283
|
+
toCbor(): Cbor;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export interface TaggedCborEncodable {
|
|
287
|
+
taggedCbor(): Cbor;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Type guard to check if value has taggedCbor method.
|
|
292
|
+
*/
|
|
293
|
+
const hasTaggedCbor = (value: unknown): value is TaggedCborEncodable => {
|
|
294
|
+
return (
|
|
295
|
+
typeof value === "object" &&
|
|
296
|
+
value !== null &&
|
|
297
|
+
"taggedCbor" in value &&
|
|
298
|
+
typeof (value as TaggedCborEncodable).taggedCbor === "function"
|
|
299
|
+
);
|
|
300
|
+
};
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Type guard to check if value has toCbor method.
|
|
304
|
+
*/
|
|
305
|
+
const hasToCbor = (value: unknown): value is ToCbor => {
|
|
306
|
+
return (
|
|
307
|
+
typeof value === "object" &&
|
|
308
|
+
value !== null &&
|
|
309
|
+
"toCbor" in value &&
|
|
310
|
+
typeof (value as ToCbor).toCbor === "function"
|
|
311
|
+
);
|
|
312
|
+
};
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Convert any value to a CBOR representation.
|
|
316
|
+
* Matches Rust's `From` trait implementations for CBOR.
|
|
317
|
+
*/
|
|
318
|
+
export const cbor = (value: CborInput): Cbor => {
|
|
319
|
+
// If already CBOR and has methods, return as-is
|
|
320
|
+
if (isCbor(value) && "toData" in value) {
|
|
321
|
+
return value;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// If CBOR but no methods, attach them
|
|
325
|
+
if (isCbor(value)) {
|
|
326
|
+
return attachMethods(value as Omit<Cbor, keyof CborMethods>) as Cbor;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
let result: Omit<Cbor, keyof CborMethods>;
|
|
330
|
+
|
|
331
|
+
if (isCborNumber(value)) {
|
|
332
|
+
if (typeof value === "number" && Number.isNaN(value)) {
|
|
333
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "Float", value: NaN } };
|
|
334
|
+
} else if (typeof value === "number" && hasFractionalPart(value)) {
|
|
335
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "Float", value: value } };
|
|
336
|
+
} else if (value == Infinity) {
|
|
337
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "Float", value: Infinity } };
|
|
338
|
+
} else if (value == -Infinity) {
|
|
339
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "Float", value: -Infinity } };
|
|
340
|
+
} else if (value < 0) {
|
|
341
|
+
// Store the magnitude to encode, matching Rust's representation
|
|
342
|
+
// For a negative value n, CBOR encodes it as -1-n, so we store -n-1
|
|
343
|
+
if (typeof value === "bigint") {
|
|
344
|
+
result = { isCbor: true, type: MajorType.Negative, value: -value - 1n };
|
|
345
|
+
} else {
|
|
346
|
+
result = { isCbor: true, type: MajorType.Negative, value: -value - 1 };
|
|
347
|
+
}
|
|
348
|
+
} else {
|
|
349
|
+
result = { isCbor: true, type: MajorType.Unsigned, value: value };
|
|
350
|
+
}
|
|
351
|
+
} else if (typeof value === "string") {
|
|
352
|
+
// dCBOR requires all text strings to be in Unicode Normalization Form C (NFC)
|
|
353
|
+
// This ensures deterministic encoding regardless of how the string was composed
|
|
354
|
+
const normalized = value.normalize("NFC");
|
|
355
|
+
result = { isCbor: true, type: MajorType.Text, value: normalized };
|
|
356
|
+
} else if (value === null || value === undefined) {
|
|
357
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "Null" } };
|
|
358
|
+
} else if (value === true) {
|
|
359
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "True" } };
|
|
360
|
+
} else if (value === false) {
|
|
361
|
+
result = { isCbor: true, type: MajorType.Simple, value: { type: "False" } };
|
|
362
|
+
} else if (Array.isArray(value)) {
|
|
363
|
+
result = { isCbor: true, type: MajorType.Array, value: value.map(cbor) };
|
|
364
|
+
} else if (value instanceof Uint8Array) {
|
|
365
|
+
result = { isCbor: true, type: MajorType.ByteString, value: value };
|
|
366
|
+
} else if (value instanceof CborMap) {
|
|
367
|
+
result = { isCbor: true, type: MajorType.Map, value: value };
|
|
368
|
+
} else if (value instanceof Map) {
|
|
369
|
+
result = { isCbor: true, type: MajorType.Map, value: new CborMap(value) };
|
|
370
|
+
} else if (value instanceof Set) {
|
|
371
|
+
result = {
|
|
372
|
+
isCbor: true,
|
|
373
|
+
type: MajorType.Array,
|
|
374
|
+
value: Array.from(value).map((v) => cbor(v as CborInput)),
|
|
375
|
+
};
|
|
376
|
+
} else if (hasTaggedCbor(value)) {
|
|
377
|
+
return value.taggedCbor();
|
|
378
|
+
} else if (hasToCbor(value)) {
|
|
379
|
+
return value.toCbor();
|
|
380
|
+
} else if (typeof value === "object" && value !== null && "tag" in value && "value" in value) {
|
|
381
|
+
// Handle plain tagged value format: { tag: number, value: unknown }
|
|
382
|
+
const keys = Object.keys(value);
|
|
383
|
+
const objValue = value as { tag: unknown; value: unknown; [key: string]: unknown };
|
|
384
|
+
if (keys.length === 2 && keys.includes("tag") && keys.includes("value")) {
|
|
385
|
+
return taggedCbor(objValue.tag, objValue.value as CborInput);
|
|
386
|
+
}
|
|
387
|
+
// Not a tagged value, fall through to map handling
|
|
388
|
+
const map = new CborMap();
|
|
389
|
+
for (const [key, val] of Object.entries(value)) {
|
|
390
|
+
map.set(cbor(key as CborInput), cbor(val as CborInput));
|
|
391
|
+
}
|
|
392
|
+
result = { isCbor: true, type: MajorType.Map, value: map };
|
|
393
|
+
} else if (typeof value === "object" && value !== null) {
|
|
394
|
+
// Handle plain objects by converting to CborMap
|
|
395
|
+
const map = new CborMap();
|
|
396
|
+
for (const [key, val] of Object.entries(value)) {
|
|
397
|
+
map.set(cbor(key as CborInput), cbor(val as CborInput));
|
|
398
|
+
}
|
|
399
|
+
result = { isCbor: true, type: MajorType.Map, value: map };
|
|
400
|
+
} else {
|
|
401
|
+
throw new CborError({ type: "Custom", message: "Unsupported type for CBOR encoding" });
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
return attachMethods(result) as Cbor;
|
|
405
|
+
};
|
|
406
|
+
|
|
407
|
+
export const cborHex = (value: CborInput): string => {
|
|
408
|
+
return bytesToHex(cborData(value));
|
|
409
|
+
};
|
|
410
|
+
|
|
411
|
+
/**
|
|
412
|
+
* Encode a CBOR value to binary data.
|
|
413
|
+
* Matches Rust's `CBOR::to_cbor_data()` method.
|
|
414
|
+
*/
|
|
415
|
+
export const cborData = (value: CborInput): Uint8Array => {
|
|
416
|
+
const c = cbor(value);
|
|
417
|
+
switch (c.type) {
|
|
418
|
+
case MajorType.Unsigned: {
|
|
419
|
+
return encodeVarInt(c.value, MajorType.Unsigned);
|
|
420
|
+
}
|
|
421
|
+
case MajorType.Negative: {
|
|
422
|
+
// Value is already stored as the magnitude to encode (matching Rust)
|
|
423
|
+
return encodeVarInt(c.value, MajorType.Negative);
|
|
424
|
+
}
|
|
425
|
+
case MajorType.ByteString: {
|
|
426
|
+
if (c.value instanceof Uint8Array) {
|
|
427
|
+
const lengthBytes = encodeVarInt(c.value.length, MajorType.ByteString);
|
|
428
|
+
return new Uint8Array([...lengthBytes, ...c.value]);
|
|
429
|
+
}
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
case MajorType.Text: {
|
|
433
|
+
if (typeof c.value === "string") {
|
|
434
|
+
const utf8Bytes = new TextEncoder().encode(c.value);
|
|
435
|
+
const lengthBytes = encodeVarInt(utf8Bytes.length, MajorType.Text);
|
|
436
|
+
return new Uint8Array([...lengthBytes, ...utf8Bytes]);
|
|
437
|
+
}
|
|
438
|
+
break;
|
|
439
|
+
}
|
|
440
|
+
case MajorType.Tagged: {
|
|
441
|
+
if (typeof c.tag === "bigint" || typeof c.tag === "number") {
|
|
442
|
+
const tagBytes = encodeVarInt(c.tag, MajorType.Tagged);
|
|
443
|
+
const valueBytes = cborData(c.value);
|
|
444
|
+
return new Uint8Array([...tagBytes, ...valueBytes]);
|
|
445
|
+
}
|
|
446
|
+
break;
|
|
447
|
+
}
|
|
448
|
+
case MajorType.Simple: {
|
|
449
|
+
// Use the simpleCborData function from simple.ts
|
|
450
|
+
return simpleCborData(c.value);
|
|
451
|
+
}
|
|
452
|
+
case MajorType.Array: {
|
|
453
|
+
const arrayBytes = c.value.map(cborData);
|
|
454
|
+
const flatArrayBytes = concatBytes(arrayBytes);
|
|
455
|
+
const lengthBytes = encodeVarInt(c.value.length, MajorType.Array);
|
|
456
|
+
return new Uint8Array([...lengthBytes, ...flatArrayBytes]);
|
|
457
|
+
}
|
|
458
|
+
case MajorType.Map: {
|
|
459
|
+
const entries = c.value.entriesArray;
|
|
460
|
+
const arrayBytes = entries.map(({ key, value }) =>
|
|
461
|
+
concatBytes([cborData(key), cborData(value)]),
|
|
462
|
+
);
|
|
463
|
+
const flatArrayBytes = concatBytes(arrayBytes);
|
|
464
|
+
const lengthBytes = encodeVarInt(entries.length, MajorType.Map);
|
|
465
|
+
return new Uint8Array([...lengthBytes, ...flatArrayBytes]);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
throw new CborError({ type: "WrongType" });
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
export const encodeCbor = (value: CborInput): Uint8Array => {
|
|
472
|
+
return cborData(cbor(value));
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
export const taggedCbor = (tag: unknown, value: CborInput): Cbor => {
|
|
476
|
+
// Validate and convert tag to CborNumber
|
|
477
|
+
const tagNumber: CborNumber =
|
|
478
|
+
typeof tag === "number" || typeof tag === "bigint" ? tag : Number(tag);
|
|
479
|
+
return attachMethods({
|
|
480
|
+
isCbor: true,
|
|
481
|
+
type: MajorType.Tagged,
|
|
482
|
+
tag: tagNumber,
|
|
483
|
+
value: cbor(value),
|
|
484
|
+
});
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
// ============================================================================
|
|
488
|
+
// Static Factory Functions
|
|
489
|
+
// (Keep only essential creation functions)
|
|
490
|
+
// ============================================================================
|
|
491
|
+
|
|
492
|
+
export const toByteString = (data: Uint8Array): Cbor => {
|
|
493
|
+
return cbor(data);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
export const toByteStringFromHex = (hex: string): Cbor => {
|
|
497
|
+
return toByteString(hexToBytes(hex));
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
export const toTaggedValue = (tag: CborNumber | Tag, item: CborInput): Cbor => {
|
|
501
|
+
const tagValue = typeof tag === "object" && "value" in tag ? tag.value : tag;
|
|
502
|
+
return attachMethods({
|
|
503
|
+
isCbor: true,
|
|
504
|
+
type: MajorType.Tagged,
|
|
505
|
+
tag: tagValue,
|
|
506
|
+
value: cbor(item),
|
|
507
|
+
});
|
|
508
|
+
};
|
|
509
|
+
|
|
510
|
+
export const cborFalse = (): Cbor => {
|
|
511
|
+
return attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "False" } });
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
export const cborTrue = (): Cbor => {
|
|
515
|
+
return attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "True" } });
|
|
516
|
+
};
|
|
517
|
+
|
|
518
|
+
export const cborNull = (): Cbor => {
|
|
519
|
+
return attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "Null" } });
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
export const cborNaN = (): Cbor => {
|
|
523
|
+
return attachMethods({
|
|
524
|
+
isCbor: true,
|
|
525
|
+
type: MajorType.Simple,
|
|
526
|
+
value: { type: "Float", value: NaN },
|
|
527
|
+
});
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// ============================================================================
|
|
531
|
+
// Method Attachment System
|
|
532
|
+
// ============================================================================
|
|
533
|
+
|
|
534
|
+
/**
|
|
535
|
+
* Attaches instance methods to a CBOR value.
|
|
536
|
+
* This enables method chaining like cbor.toHex() instead of Cbor.toHex(cbor).
|
|
537
|
+
* @internal
|
|
538
|
+
*/
|
|
539
|
+
export const attachMethods = <T extends Omit<Cbor, keyof CborMethods>>(obj: T): T & CborMethods => {
|
|
540
|
+
return Object.assign(obj, {
|
|
541
|
+
// Universal encoding/formatting
|
|
542
|
+
toData(this: Cbor): Uint8Array {
|
|
543
|
+
return cborData(this);
|
|
544
|
+
},
|
|
545
|
+
toHex(this: Cbor): string {
|
|
546
|
+
return bytesToHex(cborData(this));
|
|
547
|
+
},
|
|
548
|
+
toHexAnnotated(this: Cbor, tagsStore?: TagsStore): string {
|
|
549
|
+
tagsStore = tagsStore ?? getGlobalTagsStore();
|
|
550
|
+
return hexOpt(this, { annotate: true, tagsStore });
|
|
551
|
+
},
|
|
552
|
+
toString(this: Cbor): string {
|
|
553
|
+
return diagnosticOpt(this, { flat: true });
|
|
554
|
+
},
|
|
555
|
+
toDebugString(this: Cbor): string {
|
|
556
|
+
return diagnosticOpt(this, { flat: false });
|
|
557
|
+
},
|
|
558
|
+
toDiagnostic(this: Cbor): string {
|
|
559
|
+
return diagnosticOpt(this, { flat: false });
|
|
560
|
+
},
|
|
561
|
+
toDiagnosticAnnotated(this: Cbor): string {
|
|
562
|
+
return diagnosticOpt(this, { annotate: true });
|
|
563
|
+
},
|
|
564
|
+
|
|
565
|
+
// Type checking
|
|
566
|
+
isByteString(this: Cbor): boolean {
|
|
567
|
+
return this.type === MajorType.ByteString;
|
|
568
|
+
},
|
|
569
|
+
isText(this: Cbor): boolean {
|
|
570
|
+
return this.type === MajorType.Text;
|
|
571
|
+
},
|
|
572
|
+
isArray(this: Cbor): boolean {
|
|
573
|
+
return this.type === MajorType.Array;
|
|
574
|
+
},
|
|
575
|
+
isMap(this: Cbor): boolean {
|
|
576
|
+
return this.type === MajorType.Map;
|
|
577
|
+
},
|
|
578
|
+
isTagged(this: Cbor): boolean {
|
|
579
|
+
return this.type === MajorType.Tagged;
|
|
580
|
+
},
|
|
581
|
+
isSimple(this: Cbor): boolean {
|
|
582
|
+
return this.type === MajorType.Simple;
|
|
583
|
+
},
|
|
584
|
+
isBool(this: Cbor): boolean {
|
|
585
|
+
return (
|
|
586
|
+
this.type === MajorType.Simple &&
|
|
587
|
+
(this.value.type === "True" || this.value.type === "False")
|
|
588
|
+
);
|
|
589
|
+
},
|
|
590
|
+
isTrue(this: Cbor): boolean {
|
|
591
|
+
return this.type === MajorType.Simple && this.value.type === "True";
|
|
592
|
+
},
|
|
593
|
+
isFalse(this: Cbor): boolean {
|
|
594
|
+
return this.type === MajorType.Simple && this.value.type === "False";
|
|
595
|
+
},
|
|
596
|
+
isNull(this: Cbor): boolean {
|
|
597
|
+
return this.type === MajorType.Simple && this.value.type === "Null";
|
|
598
|
+
},
|
|
599
|
+
isNumber(this: Cbor): boolean {
|
|
600
|
+
if (this.type === MajorType.Unsigned || this.type === MajorType.Negative) {
|
|
601
|
+
return true;
|
|
602
|
+
}
|
|
603
|
+
if (this.type === MajorType.Simple) {
|
|
604
|
+
return isSimpleFloat(this.value);
|
|
605
|
+
}
|
|
606
|
+
return false;
|
|
607
|
+
},
|
|
608
|
+
isInteger(this: Cbor): boolean {
|
|
609
|
+
return this.type === MajorType.Unsigned || this.type === MajorType.Negative;
|
|
610
|
+
},
|
|
611
|
+
isUnsigned(this: Cbor): boolean {
|
|
612
|
+
return this.type === MajorType.Unsigned;
|
|
613
|
+
},
|
|
614
|
+
isNegative(this: Cbor): boolean {
|
|
615
|
+
return this.type === MajorType.Negative;
|
|
616
|
+
},
|
|
617
|
+
isNaN(this: Cbor): boolean {
|
|
618
|
+
return (
|
|
619
|
+
this.type === MajorType.Simple &&
|
|
620
|
+
this.value.type === "Float" &&
|
|
621
|
+
Number.isNaN(this.value.value)
|
|
622
|
+
);
|
|
623
|
+
},
|
|
624
|
+
isFloat(this: Cbor): boolean {
|
|
625
|
+
return this.type === MajorType.Simple && isSimpleFloat(this.value);
|
|
626
|
+
},
|
|
627
|
+
|
|
628
|
+
// Safe conversion (returns undefined on mismatch)
|
|
629
|
+
asByteString(this: Cbor): Uint8Array | undefined {
|
|
630
|
+
return this.type === MajorType.ByteString ? this.value : undefined;
|
|
631
|
+
},
|
|
632
|
+
asText(this: Cbor): string | undefined {
|
|
633
|
+
return this.type === MajorType.Text ? this.value : undefined;
|
|
634
|
+
},
|
|
635
|
+
asArray(this: Cbor): readonly Cbor[] | undefined {
|
|
636
|
+
return this.type === MajorType.Array ? this.value : undefined;
|
|
637
|
+
},
|
|
638
|
+
asMap(this: Cbor): CborMap | undefined {
|
|
639
|
+
return this.type === MajorType.Map ? this.value : undefined;
|
|
640
|
+
},
|
|
641
|
+
asTagged(this: Cbor): [Tag, Cbor] | undefined {
|
|
642
|
+
if (this.type !== MajorType.Tagged) {
|
|
643
|
+
return undefined;
|
|
644
|
+
}
|
|
645
|
+
const tag: Tag = { value: this.tag, name: `tag-${this.tag}` };
|
|
646
|
+
return [tag, this.value];
|
|
647
|
+
},
|
|
648
|
+
asBool(this: Cbor): boolean | undefined {
|
|
649
|
+
if (this.type !== MajorType.Simple) return undefined;
|
|
650
|
+
if (this.value.type === "True") return true;
|
|
651
|
+
if (this.value.type === "False") return false;
|
|
652
|
+
return undefined;
|
|
653
|
+
},
|
|
654
|
+
asInteger(this: Cbor): (number | bigint) | undefined {
|
|
655
|
+
if (this.type === MajorType.Unsigned) {
|
|
656
|
+
return this.value;
|
|
657
|
+
} else if (this.type === MajorType.Negative) {
|
|
658
|
+
if (typeof this.value === "bigint") {
|
|
659
|
+
return -this.value - 1n;
|
|
660
|
+
} else {
|
|
661
|
+
return -this.value - 1;
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return undefined;
|
|
665
|
+
},
|
|
666
|
+
asNumber(this: Cbor): (number | bigint) | undefined {
|
|
667
|
+
if (this.type === MajorType.Unsigned) {
|
|
668
|
+
return this.value;
|
|
669
|
+
} else if (this.type === MajorType.Negative) {
|
|
670
|
+
if (typeof this.value === "bigint") {
|
|
671
|
+
return -this.value - 1n;
|
|
672
|
+
} else {
|
|
673
|
+
return -this.value - 1;
|
|
674
|
+
}
|
|
675
|
+
} else if (this.type === MajorType.Simple && isSimpleFloat(this.value)) {
|
|
676
|
+
return this.value.value;
|
|
677
|
+
}
|
|
678
|
+
return undefined;
|
|
679
|
+
},
|
|
680
|
+
asSimpleValue(this: Cbor): Simple | undefined {
|
|
681
|
+
return this.type === MajorType.Simple ? this.value : undefined;
|
|
682
|
+
},
|
|
683
|
+
|
|
684
|
+
// Throwing conversion (throws on mismatch)
|
|
685
|
+
toByteString(this: Cbor): Uint8Array {
|
|
686
|
+
if (this.type !== MajorType.ByteString) {
|
|
687
|
+
throw new TypeError(
|
|
688
|
+
`Cannot convert CBOR to ByteString: expected ByteString type, got ${getMajorTypeName(this.type)}`,
|
|
689
|
+
);
|
|
690
|
+
}
|
|
691
|
+
return this.value;
|
|
692
|
+
},
|
|
693
|
+
toText(this: Cbor): string {
|
|
694
|
+
if (this.type !== MajorType.Text) {
|
|
695
|
+
throw new TypeError(
|
|
696
|
+
`Cannot convert CBOR to Text: expected Text type, got ${getMajorTypeName(this.type)}`,
|
|
697
|
+
);
|
|
698
|
+
}
|
|
699
|
+
return this.value;
|
|
700
|
+
},
|
|
701
|
+
toArray(this: Cbor): readonly Cbor[] {
|
|
702
|
+
if (this.type !== MajorType.Array) {
|
|
703
|
+
throw new TypeError(
|
|
704
|
+
`Cannot convert CBOR to Array: expected Array type, got ${getMajorTypeName(this.type)}`,
|
|
705
|
+
);
|
|
706
|
+
}
|
|
707
|
+
return this.value;
|
|
708
|
+
},
|
|
709
|
+
toMap(this: Cbor): CborMap {
|
|
710
|
+
if (this.type !== MajorType.Map) {
|
|
711
|
+
throw new TypeError(
|
|
712
|
+
`Cannot convert CBOR to Map: expected Map type, got ${getMajorTypeName(this.type)}`,
|
|
713
|
+
);
|
|
714
|
+
}
|
|
715
|
+
return this.value;
|
|
716
|
+
},
|
|
717
|
+
toTagged(this: Cbor): [Tag, Cbor] {
|
|
718
|
+
if (this.type !== MajorType.Tagged) {
|
|
719
|
+
throw new TypeError(
|
|
720
|
+
`Cannot convert CBOR to Tagged: expected Tagged type, got ${getMajorTypeName(this.type)}`,
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
const tag: Tag = { value: this.tag, name: `tag-${this.tag}` };
|
|
724
|
+
return [tag, this.value];
|
|
725
|
+
},
|
|
726
|
+
toBool(this: Cbor): boolean {
|
|
727
|
+
const result = this.asBool();
|
|
728
|
+
if (result === undefined) {
|
|
729
|
+
throw new TypeError(
|
|
730
|
+
`Cannot convert CBOR to boolean: expected Simple(True/False) type, got ${getMajorTypeName(this.type)}`,
|
|
731
|
+
);
|
|
732
|
+
}
|
|
733
|
+
return result;
|
|
734
|
+
},
|
|
735
|
+
toInteger(this: Cbor): number | bigint {
|
|
736
|
+
const result = this.asInteger();
|
|
737
|
+
if (result === undefined) {
|
|
738
|
+
throw new TypeError(
|
|
739
|
+
`Cannot convert CBOR to integer: expected Unsigned or Negative type, got ${getMajorTypeName(this.type)}`,
|
|
740
|
+
);
|
|
741
|
+
}
|
|
742
|
+
return result;
|
|
743
|
+
},
|
|
744
|
+
toNumber(this: Cbor): number | bigint {
|
|
745
|
+
const result = this.asNumber();
|
|
746
|
+
if (result === undefined) {
|
|
747
|
+
throw new TypeError(
|
|
748
|
+
`Cannot convert CBOR to number: expected Unsigned, Negative, or Float type, got ${getMajorTypeName(this.type)}`,
|
|
749
|
+
);
|
|
750
|
+
}
|
|
751
|
+
return result;
|
|
752
|
+
},
|
|
753
|
+
toSimpleValue(this: Cbor): Simple {
|
|
754
|
+
if (this.type !== MajorType.Simple) {
|
|
755
|
+
throw new TypeError(
|
|
756
|
+
`Cannot convert CBOR to Simple: expected Simple type, got ${getMajorTypeName(this.type)}`,
|
|
757
|
+
);
|
|
758
|
+
}
|
|
759
|
+
return this.value;
|
|
760
|
+
},
|
|
761
|
+
expectTag(this: Cbor, expectedTag: CborNumber | Tag): Cbor {
|
|
762
|
+
if (this.type !== MajorType.Tagged) {
|
|
763
|
+
throw new CborError({ type: "WrongType" });
|
|
764
|
+
}
|
|
765
|
+
const expectedValue =
|
|
766
|
+
typeof expectedTag === "object" && "value" in expectedTag ? expectedTag.value : expectedTag;
|
|
767
|
+
if (this.tag !== expectedValue) {
|
|
768
|
+
throw new CborError({
|
|
769
|
+
type: "Custom",
|
|
770
|
+
message: `Wrong tag: expected ${expectedValue}, got ${this.tag}`,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
return this.value;
|
|
774
|
+
},
|
|
775
|
+
|
|
776
|
+
// Advanced operations
|
|
777
|
+
walk<State>(this: Cbor, initialState: State, visitor: Visitor<State>): State {
|
|
778
|
+
return walk(this, initialState, visitor);
|
|
779
|
+
},
|
|
780
|
+
validateTag(this: Cbor, expectedTags: Tag[]): Tag {
|
|
781
|
+
if (this.type !== MajorType.Tagged) {
|
|
782
|
+
throw new CborError({ type: "WrongType" });
|
|
783
|
+
}
|
|
784
|
+
const expectedValues = expectedTags.map((t) => t.value);
|
|
785
|
+
const tagValue = this.tag;
|
|
786
|
+
const matchingTag = expectedTags.find((t) => t.value === tagValue);
|
|
787
|
+
if (matchingTag === undefined) {
|
|
788
|
+
const expectedStr = expectedValues.join(" or ");
|
|
789
|
+
throw new CborError({
|
|
790
|
+
type: "Custom",
|
|
791
|
+
message: `Wrong tag: expected ${expectedStr}, got ${tagValue}`,
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
return matchingTag;
|
|
795
|
+
},
|
|
796
|
+
untagged(this: Cbor): Cbor {
|
|
797
|
+
if (this.type !== MajorType.Tagged) {
|
|
798
|
+
throw new CborError({ type: "WrongType" });
|
|
799
|
+
}
|
|
800
|
+
return this.value;
|
|
801
|
+
},
|
|
802
|
+
});
|
|
803
|
+
};
|
|
804
|
+
|
|
805
|
+
// ============================================================================
|
|
806
|
+
// Cbor Namespace - Static Constants and Factory Methods
|
|
807
|
+
// ============================================================================
|
|
808
|
+
|
|
809
|
+
/**
|
|
810
|
+
* CBOR constants and helper methods.
|
|
811
|
+
*
|
|
812
|
+
* Provides constants for common simple values (False, True, Null) and static methods
|
|
813
|
+
* matching the Rust CBOR API for encoding/decoding.
|
|
814
|
+
*/
|
|
815
|
+
// eslint-disable-next-line no-redeclare
|
|
816
|
+
export const Cbor = {
|
|
817
|
+
// Static CBOR simple values (matching Rust naming) - with methods attached
|
|
818
|
+
False: attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "False" } }),
|
|
819
|
+
True: attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "True" } }),
|
|
820
|
+
Null: attachMethods({ isCbor: true, type: MajorType.Simple, value: { type: "Null" } }),
|
|
821
|
+
NaN: attachMethods({
|
|
822
|
+
isCbor: true,
|
|
823
|
+
type: MajorType.Simple,
|
|
824
|
+
value: { type: "Float", value: NaN },
|
|
825
|
+
}),
|
|
826
|
+
|
|
827
|
+
// ============================================================================
|
|
828
|
+
// Static Factory/Decoding Methods (matches Rust CBOR static methods)
|
|
829
|
+
// ============================================================================
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Creates a CBOR value from any JavaScript value.
|
|
833
|
+
*
|
|
834
|
+
* Matches Rust's `CBOR::from()` behavior for various types.
|
|
835
|
+
*
|
|
836
|
+
* @param value - Any JavaScript value (number, string, boolean, null, array, object, etc.)
|
|
837
|
+
* @returns A CBOR symbolic representation with instance methods
|
|
838
|
+
*/
|
|
839
|
+
from(value: CborInput): Cbor {
|
|
840
|
+
return cbor(value);
|
|
841
|
+
},
|
|
842
|
+
|
|
843
|
+
/**
|
|
844
|
+
* Decodes binary data into CBOR symbolic representation.
|
|
845
|
+
*
|
|
846
|
+
* Matches Rust's `CBOR::try_from_data()` method.
|
|
847
|
+
*
|
|
848
|
+
* @param data - The binary data to decode
|
|
849
|
+
* @returns A CBOR value with instance methods
|
|
850
|
+
* @throws Error if the data is not valid CBOR or violates dCBOR encoding rules
|
|
851
|
+
*/
|
|
852
|
+
tryFromData(data: Uint8Array): Cbor {
|
|
853
|
+
return decodeCbor(data);
|
|
854
|
+
},
|
|
855
|
+
|
|
856
|
+
/**
|
|
857
|
+
* Decodes a hexadecimal string into CBOR symbolic representation.
|
|
858
|
+
*
|
|
859
|
+
* Matches Rust's `CBOR::try_from_hex()` method.
|
|
860
|
+
*
|
|
861
|
+
* @param hex - A string containing hexadecimal characters
|
|
862
|
+
* @returns A CBOR value with instance methods
|
|
863
|
+
* @throws Error if the hex string is invalid or the resulting data is not valid dCBOR
|
|
864
|
+
*/
|
|
865
|
+
tryFromHex(hex: string): Cbor {
|
|
866
|
+
const data = hexToBytes(hex);
|
|
867
|
+
return this.tryFromData(data);
|
|
868
|
+
},
|
|
869
|
+
};
|