ox 0.9.13 → 0.9.15
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/CHANGELOG.md +12 -0
- package/Cbor/package.json +6 -0
- package/_cjs/core/AbiConstructor.js +1 -1
- package/_cjs/core/AbiConstructor.js.map +1 -1
- package/_cjs/core/AbiError.js +1 -1
- package/_cjs/core/AbiError.js.map +1 -1
- package/_cjs/core/AbiFunction.js +1 -1
- package/_cjs/core/AbiFunction.js.map +1 -1
- package/_cjs/core/Cbor.js +690 -0
- package/_cjs/core/Cbor.js.map +1 -0
- package/_cjs/core/Errors.js +38 -4
- package/_cjs/core/Errors.js.map +1 -1
- package/_cjs/index.js +3 -2
- package/_cjs/index.js.map +1 -1
- package/_cjs/version.js +1 -1
- package/_esm/core/AbiConstructor.js +1 -1
- package/_esm/core/AbiConstructor.js.map +1 -1
- package/_esm/core/AbiError.js +1 -1
- package/_esm/core/AbiError.js.map +1 -1
- package/_esm/core/AbiFunction.js +1 -1
- package/_esm/core/AbiFunction.js.map +1 -1
- package/_esm/core/Cbor.js +771 -0
- package/_esm/core/Cbor.js.map +1 -0
- package/_esm/core/Errors.js +38 -4
- package/_esm/core/Errors.js.map +1 -1
- package/_esm/index.js +32 -0
- package/_esm/index.js.map +1 -1
- package/_esm/version.js +1 -1
- package/_types/core/Cbor.d.ts +187 -0
- package/_types/core/Cbor.d.ts.map +1 -0
- package/_types/core/Errors.d.ts +22 -0
- package/_types/core/Errors.d.ts.map +1 -1
- package/_types/core/WebAuthnP256.d.ts +1 -0
- package/_types/core/WebAuthnP256.d.ts.map +1 -1
- package/_types/index.d.ts +32 -0
- package/_types/index.d.ts.map +1 -1
- package/_types/version.d.ts +1 -1
- package/core/AbiConstructor.ts +1 -1
- package/core/AbiError.ts +1 -1
- package/core/AbiFunction.ts +1 -1
- package/core/Cbor.ts +912 -0
- package/core/Errors.ts +43 -4
- package/core/WebAuthnP256.ts +28 -0
- package/index.ts +33 -0
- package/package.json +6 -1
- package/version.ts +1 -1
|
@@ -0,0 +1,771 @@
|
|
|
1
|
+
import * as Bytes from './Bytes.js';
|
|
2
|
+
import * as Errors from './Errors.js';
|
|
3
|
+
import * as Hex from './Hex.js';
|
|
4
|
+
import * as Cursor from './internal/cursor.js';
|
|
5
|
+
/**
|
|
6
|
+
* Encodes a value into CBOR (Concise Binary Object Representation) format.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```ts twoslash
|
|
10
|
+
* import { Cbor } from 'ox'
|
|
11
|
+
*
|
|
12
|
+
* Cbor.encode([1, 2, 3])
|
|
13
|
+
* // @log: '0x83010203'
|
|
14
|
+
*
|
|
15
|
+
* Cbor.encode({ foo: 'bar', baz: [1, 2, 3] })
|
|
16
|
+
* // @log: '0xa263666f6f636261726362617a83010203'
|
|
17
|
+
*
|
|
18
|
+
* Cbor.encode('hello', { as: 'Bytes' })
|
|
19
|
+
* // @log: Uint8Array(6) [ 101, 104, 101, 108, 108, 111 ]
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param data - The value to encode.
|
|
23
|
+
* @param options - Encoding options.
|
|
24
|
+
* @returns The CBOR-encoded value.
|
|
25
|
+
*/
|
|
26
|
+
export function encode(data, options = {}) {
|
|
27
|
+
const { as = 'Hex' } = options;
|
|
28
|
+
const encodable = getEncodable(data);
|
|
29
|
+
const cursor = Cursor.create(new Uint8Array(encodable.length));
|
|
30
|
+
encodable.encode(cursor);
|
|
31
|
+
if (as === 'Hex')
|
|
32
|
+
return Hex.fromBytes(cursor.bytes);
|
|
33
|
+
return cursor.bytes;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Decodes CBOR (Concise Binary Object Representation) data into a JavaScript value.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts twoslash
|
|
40
|
+
* import { Cbor } from 'ox'
|
|
41
|
+
*
|
|
42
|
+
* Cbor.decode('0x83010203')
|
|
43
|
+
* // @log: [1, 2, 3]
|
|
44
|
+
*
|
|
45
|
+
* Cbor.decode('0xa263666f6f636261726362617a83010203')
|
|
46
|
+
* // @log: { foo: 'bar', baz: [1, 2, 3] }
|
|
47
|
+
*
|
|
48
|
+
* Cbor.decode(new Uint8Array([101, 104, 101, 108, 108, 111]))
|
|
49
|
+
* // @log: 'hello'
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @param data - The CBOR-encoded data to decode.
|
|
53
|
+
* @param options - Decoding options.
|
|
54
|
+
* @returns The decoded value.
|
|
55
|
+
*/
|
|
56
|
+
export function decode(data) {
|
|
57
|
+
const bytes = (() => {
|
|
58
|
+
if (typeof data === 'string') {
|
|
59
|
+
if (data.length > 3 && data.length % 2 !== 0)
|
|
60
|
+
throw new Hex.InvalidLengthError(data);
|
|
61
|
+
return Bytes.fromHex(data);
|
|
62
|
+
}
|
|
63
|
+
return data;
|
|
64
|
+
})();
|
|
65
|
+
const cursor = Cursor.create(bytes);
|
|
66
|
+
return decodeCursor(cursor);
|
|
67
|
+
}
|
|
68
|
+
export class InvalidMajorTypeError extends Errors.BaseError {
|
|
69
|
+
constructor({ majorType }) {
|
|
70
|
+
super(`Invalid CBOR major type: ${majorType}`);
|
|
71
|
+
Object.defineProperty(this, "name", {
|
|
72
|
+
enumerable: true,
|
|
73
|
+
configurable: true,
|
|
74
|
+
writable: true,
|
|
75
|
+
value: 'Cbor.InvalidMajorTypeError'
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export class InvalidAdditionalInfoError extends Errors.BaseError {
|
|
80
|
+
constructor({ additionalInfo }) {
|
|
81
|
+
super(`Invalid CBOR additional info: ${additionalInfo}`);
|
|
82
|
+
Object.defineProperty(this, "name", {
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true,
|
|
85
|
+
writable: true,
|
|
86
|
+
value: 'Cbor.InvalidAdditionalInfoError'
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
export class Unsupported64BitIntegerError extends Errors.BaseError {
|
|
91
|
+
constructor() {
|
|
92
|
+
super('64-bit integers are not supported in CBOR decoding.');
|
|
93
|
+
Object.defineProperty(this, "name", {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
configurable: true,
|
|
96
|
+
writable: true,
|
|
97
|
+
value: 'Cbor.Unsupported64BitIntegerError'
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
export class UnsupportedTagError extends Errors.BaseError {
|
|
102
|
+
constructor({ tag }) {
|
|
103
|
+
super(`CBOR tagged data (tag ${tag}) is not yet supported.`);
|
|
104
|
+
Object.defineProperty(this, "name", {
|
|
105
|
+
enumerable: true,
|
|
106
|
+
configurable: true,
|
|
107
|
+
writable: true,
|
|
108
|
+
value: 'Cbor.UnsupportedTagError'
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export class InvalidIndefiniteLengthChunkError extends Errors.BaseError {
|
|
113
|
+
constructor({ type }) {
|
|
114
|
+
super(`Invalid chunk type in indefinite-length ${type}`);
|
|
115
|
+
Object.defineProperty(this, "name", {
|
|
116
|
+
enumerable: true,
|
|
117
|
+
configurable: true,
|
|
118
|
+
writable: true,
|
|
119
|
+
value: 'Cbor.InvalidIndefiniteLengthChunkError'
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
export class InvalidSimpleValueError extends Errors.BaseError {
|
|
124
|
+
constructor({ value }) {
|
|
125
|
+
super(`Invalid CBOR simple value: ${value}`);
|
|
126
|
+
Object.defineProperty(this, "name", {
|
|
127
|
+
enumerable: true,
|
|
128
|
+
configurable: true,
|
|
129
|
+
writable: true,
|
|
130
|
+
value: 'Cbor.InvalidSimpleValueError'
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
export class UnsupportedBigIntError extends Errors.BaseError {
|
|
135
|
+
constructor() {
|
|
136
|
+
super('BigInt values are not supported in CBOR encoding.');
|
|
137
|
+
Object.defineProperty(this, "name", {
|
|
138
|
+
enumerable: true,
|
|
139
|
+
configurable: true,
|
|
140
|
+
writable: true,
|
|
141
|
+
value: 'Cbor.UnsupportedBigIntError'
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export class UnexpectedTokenError extends Errors.BaseError {
|
|
146
|
+
constructor({ token }) {
|
|
147
|
+
super(`Unexpected token: ${token}`);
|
|
148
|
+
Object.defineProperty(this, "name", {
|
|
149
|
+
enumerable: true,
|
|
150
|
+
configurable: true,
|
|
151
|
+
writable: true,
|
|
152
|
+
value: 'Cbor.UnexpectedTokenError'
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
export class NumberTooLargeError extends Errors.BaseError {
|
|
157
|
+
constructor({ number }) {
|
|
158
|
+
super(`Number exceeds maximum safe integer (${Number.MAX_SAFE_INTEGER}): ${number}`);
|
|
159
|
+
Object.defineProperty(this, "name", {
|
|
160
|
+
enumerable: true,
|
|
161
|
+
configurable: true,
|
|
162
|
+
writable: true,
|
|
163
|
+
value: 'Cbor.NumberTooLargeError'
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
export class StringTooLargeError extends Errors.BaseError {
|
|
168
|
+
constructor({ size }) {
|
|
169
|
+
super(`String length exceeds maximum (4294967295): ${size}`);
|
|
170
|
+
Object.defineProperty(this, "name", {
|
|
171
|
+
enumerable: true,
|
|
172
|
+
configurable: true,
|
|
173
|
+
writable: true,
|
|
174
|
+
value: 'Cbor.StringTooLargeError'
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
export class ArrayTooLargeError extends Errors.BaseError {
|
|
179
|
+
constructor({ size }) {
|
|
180
|
+
super(`Array length exceeds maximum (4294967295): ${size}`);
|
|
181
|
+
Object.defineProperty(this, "name", {
|
|
182
|
+
enumerable: true,
|
|
183
|
+
configurable: true,
|
|
184
|
+
writable: true,
|
|
185
|
+
value: 'Cbor.ArrayTooLargeError'
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
export class ObjectTooLargeError extends Errors.BaseError {
|
|
190
|
+
constructor({ size }) {
|
|
191
|
+
super(`Object size exceeds maximum (4294967295): ${size}`);
|
|
192
|
+
Object.defineProperty(this, "name", {
|
|
193
|
+
enumerable: true,
|
|
194
|
+
configurable: true,
|
|
195
|
+
writable: true,
|
|
196
|
+
value: 'Cbor.ObjectTooLargeError'
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
export class ByteStringTooLargeError extends Errors.BaseError {
|
|
201
|
+
constructor({ size }) {
|
|
202
|
+
super(`Byte string length exceeds maximum (4294967295): ${size}`);
|
|
203
|
+
Object.defineProperty(this, "name", {
|
|
204
|
+
enumerable: true,
|
|
205
|
+
configurable: true,
|
|
206
|
+
writable: true,
|
|
207
|
+
value: 'Cbor.ByteStringTooLargeError'
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/** @internal */
|
|
212
|
+
// biome-ignore lint/correctness/noUnusedVariables: _
|
|
213
|
+
function getEncodable(value) {
|
|
214
|
+
if (typeof value === 'undefined')
|
|
215
|
+
return { length: 1, encode: (cursor) => cursor.pushUint8(0xf7) };
|
|
216
|
+
if (value === null)
|
|
217
|
+
return { length: 1, encode: (cursor) => cursor.pushUint8(0xf6) };
|
|
218
|
+
if (typeof value === 'boolean')
|
|
219
|
+
return {
|
|
220
|
+
length: 1,
|
|
221
|
+
encode: (cursor) => cursor.pushUint8(value ? 0xf5 : 0xf4),
|
|
222
|
+
};
|
|
223
|
+
if (typeof value === 'number')
|
|
224
|
+
return getEncodable.number(value);
|
|
225
|
+
if (typeof value === 'bigint')
|
|
226
|
+
throw new UnsupportedBigIntError();
|
|
227
|
+
if (typeof value === 'string')
|
|
228
|
+
return getEncodable.string(value);
|
|
229
|
+
if (Array.isArray(value))
|
|
230
|
+
return getEncodable.array(value);
|
|
231
|
+
if (value instanceof Uint8Array)
|
|
232
|
+
return getEncodable.byteString(value);
|
|
233
|
+
if (value instanceof ArrayBuffer)
|
|
234
|
+
return getEncodable.byteString(new Uint8Array(value));
|
|
235
|
+
if (ArrayBuffer.isView(value))
|
|
236
|
+
return getEncodable.byteString(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
|
|
237
|
+
if (typeof value === 'object')
|
|
238
|
+
return getEncodable.object(value);
|
|
239
|
+
throw new UnexpectedTokenError({ token: String(value) });
|
|
240
|
+
}
|
|
241
|
+
/** @internal */
|
|
242
|
+
(function (getEncodable) {
|
|
243
|
+
/** @internal */
|
|
244
|
+
function number(value) {
|
|
245
|
+
// Handle non-safe integers (floats, NaN, Infinity)
|
|
246
|
+
if (!Number.isSafeInteger(value)) {
|
|
247
|
+
// Use Float32 if the value can be represented without precision loss
|
|
248
|
+
// This creates smaller encodings when possible (5 bytes vs 9 bytes)
|
|
249
|
+
const float32 = Math.fround(value);
|
|
250
|
+
if (Number.isNaN(value) || value === float32)
|
|
251
|
+
return {
|
|
252
|
+
length: 5, // 1 byte prefix + 4 bytes float32
|
|
253
|
+
encode(cursor) {
|
|
254
|
+
cursor.pushUint8(0xfa);
|
|
255
|
+
cursor.dataView.setFloat32(cursor.position, value, false);
|
|
256
|
+
cursor.position += 4;
|
|
257
|
+
},
|
|
258
|
+
};
|
|
259
|
+
return {
|
|
260
|
+
length: 9, // 1 byte prefix + 8 bytes float64
|
|
261
|
+
encode(cursor) {
|
|
262
|
+
cursor.pushUint8(0xfb);
|
|
263
|
+
cursor.dataView.setFloat64(cursor.position, value, false);
|
|
264
|
+
cursor.position += 8;
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
// Handle positive integers
|
|
269
|
+
if (value >= 0) {
|
|
270
|
+
if (value <= 0x17)
|
|
271
|
+
return { length: 1, encode: (cursor) => cursor.pushUint8(value) };
|
|
272
|
+
if (value <= 0xff)
|
|
273
|
+
return {
|
|
274
|
+
length: 2, // 1 byte prefix + 1 byte uint8
|
|
275
|
+
encode: (cursor) => {
|
|
276
|
+
cursor.pushUint8(0x18);
|
|
277
|
+
cursor.pushUint8(value);
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
if (value <= 0xffff)
|
|
281
|
+
return {
|
|
282
|
+
length: 3, // 1 byte prefix + 2 bytes uint16
|
|
283
|
+
encode: (cursor) => {
|
|
284
|
+
cursor.pushUint8(0x19);
|
|
285
|
+
cursor.pushUint16(value);
|
|
286
|
+
},
|
|
287
|
+
};
|
|
288
|
+
if (value <= 0xffffffff)
|
|
289
|
+
return {
|
|
290
|
+
length: 5, // 1 byte prefix + 4 bytes uint32
|
|
291
|
+
encode: (cursor) => {
|
|
292
|
+
cursor.pushUint8(0x1a);
|
|
293
|
+
cursor.pushUint32(value);
|
|
294
|
+
},
|
|
295
|
+
};
|
|
296
|
+
throw new NumberTooLargeError({ number: value.toString(10) });
|
|
297
|
+
}
|
|
298
|
+
// Handle negative integers
|
|
299
|
+
// CBOR encodes -n as (n-1)
|
|
300
|
+
const positiveNumber = -1 - value;
|
|
301
|
+
if (value >= -24)
|
|
302
|
+
return {
|
|
303
|
+
length: 1,
|
|
304
|
+
encode: (cursor) => cursor.pushUint8(0x20 + positiveNumber),
|
|
305
|
+
};
|
|
306
|
+
if (positiveNumber <= 0xff)
|
|
307
|
+
return {
|
|
308
|
+
length: 2, // 1 byte prefix + 1 byte uint8
|
|
309
|
+
encode: (cursor) => {
|
|
310
|
+
cursor.pushUint8(0x38);
|
|
311
|
+
cursor.pushUint8(positiveNumber);
|
|
312
|
+
},
|
|
313
|
+
};
|
|
314
|
+
if (positiveNumber <= 0xffff)
|
|
315
|
+
return {
|
|
316
|
+
length: 3, // 1 byte prefix + 2 bytes uint16
|
|
317
|
+
encode: (cursor) => {
|
|
318
|
+
cursor.pushUint8(0x39);
|
|
319
|
+
cursor.pushUint16(positiveNumber);
|
|
320
|
+
},
|
|
321
|
+
};
|
|
322
|
+
if (positiveNumber <= 0xffffffff)
|
|
323
|
+
return {
|
|
324
|
+
length: 5, // 1 byte prefix + 4 bytes uint32
|
|
325
|
+
encode: (cursor) => {
|
|
326
|
+
cursor.pushUint8(0x3a);
|
|
327
|
+
cursor.pushUint32(positiveNumber);
|
|
328
|
+
},
|
|
329
|
+
};
|
|
330
|
+
throw new NumberTooLargeError({ number: value.toString(10) });
|
|
331
|
+
}
|
|
332
|
+
getEncodable.number = number;
|
|
333
|
+
/** @internal */
|
|
334
|
+
function string(value) {
|
|
335
|
+
const encoded = Bytes.fromString(value);
|
|
336
|
+
const size = encoded.length;
|
|
337
|
+
if (size <= 0x17)
|
|
338
|
+
return {
|
|
339
|
+
length: 1 + size, // 1 byte prefix + size bytes
|
|
340
|
+
encode(cursor) {
|
|
341
|
+
cursor.pushUint8(0x60 + size);
|
|
342
|
+
if (size > 0)
|
|
343
|
+
cursor.pushBytes(encoded);
|
|
344
|
+
},
|
|
345
|
+
};
|
|
346
|
+
if (size <= 0xff)
|
|
347
|
+
return {
|
|
348
|
+
length: 2 + size, // 1 byte prefix + 1 byte uint8 + size bytes
|
|
349
|
+
encode(cursor) {
|
|
350
|
+
cursor.pushUint8(0x78);
|
|
351
|
+
cursor.pushUint8(size);
|
|
352
|
+
cursor.pushBytes(encoded);
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
if (size <= 0xffff)
|
|
356
|
+
return {
|
|
357
|
+
length: 3 + size, // 1 byte prefix + 2 bytes uint16 + size bytes
|
|
358
|
+
encode(cursor) {
|
|
359
|
+
cursor.pushUint8(0x79);
|
|
360
|
+
cursor.pushUint16(size);
|
|
361
|
+
cursor.pushBytes(encoded);
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
if (size <= 0xffffffff)
|
|
365
|
+
return {
|
|
366
|
+
length: 5 + size, // 1 byte prefix + 4 bytes uint32 + size bytes
|
|
367
|
+
encode(cursor) {
|
|
368
|
+
cursor.pushUint8(0x7a);
|
|
369
|
+
cursor.pushUint32(size);
|
|
370
|
+
cursor.pushBytes(encoded);
|
|
371
|
+
},
|
|
372
|
+
};
|
|
373
|
+
throw new StringTooLargeError({ size });
|
|
374
|
+
}
|
|
375
|
+
getEncodable.string = string;
|
|
376
|
+
/** @internal */
|
|
377
|
+
function array(value) {
|
|
378
|
+
const items = value.map((item) => getEncodable(item));
|
|
379
|
+
const bodyLength = items.reduce((acc, item) => acc + item.length, 0);
|
|
380
|
+
const size = value.length;
|
|
381
|
+
if (size <= 0x17)
|
|
382
|
+
return {
|
|
383
|
+
length: 1 + bodyLength, // 1 byte prefix + body length
|
|
384
|
+
encode(cursor) {
|
|
385
|
+
cursor.pushUint8(0x80 + size);
|
|
386
|
+
for (const item of items)
|
|
387
|
+
item.encode(cursor);
|
|
388
|
+
},
|
|
389
|
+
};
|
|
390
|
+
if (size <= 0xff)
|
|
391
|
+
return {
|
|
392
|
+
length: 2 + bodyLength, // 1 byte prefix + 1 byte uint8 + body length
|
|
393
|
+
encode(cursor) {
|
|
394
|
+
cursor.pushUint8(0x98);
|
|
395
|
+
cursor.pushUint8(size);
|
|
396
|
+
for (const item of items)
|
|
397
|
+
item.encode(cursor);
|
|
398
|
+
},
|
|
399
|
+
};
|
|
400
|
+
if (size <= 0xffff)
|
|
401
|
+
return {
|
|
402
|
+
length: 3 + bodyLength, // 1 byte prefix + 2 bytes uint16 + body length
|
|
403
|
+
encode(cursor) {
|
|
404
|
+
cursor.pushUint8(0x99);
|
|
405
|
+
cursor.pushUint16(size);
|
|
406
|
+
for (const item of items)
|
|
407
|
+
item.encode(cursor);
|
|
408
|
+
},
|
|
409
|
+
};
|
|
410
|
+
if (size <= 0xffffffff)
|
|
411
|
+
return {
|
|
412
|
+
length: 5 + bodyLength, // 1 byte prefix + 4 bytes uint32 + body length
|
|
413
|
+
encode(cursor) {
|
|
414
|
+
cursor.pushUint8(0x9a);
|
|
415
|
+
cursor.pushUint32(size);
|
|
416
|
+
for (const item of items)
|
|
417
|
+
item.encode(cursor);
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
throw new ArrayTooLargeError({ size });
|
|
421
|
+
}
|
|
422
|
+
getEncodable.array = array;
|
|
423
|
+
/** @internal */
|
|
424
|
+
function byteString(value) {
|
|
425
|
+
const size = value.byteLength;
|
|
426
|
+
if (size <= 0x17)
|
|
427
|
+
return {
|
|
428
|
+
length: 1 + size, // 1 byte prefix + size bytes
|
|
429
|
+
encode(cursor) {
|
|
430
|
+
cursor.pushUint8(0x40 + size);
|
|
431
|
+
cursor.pushBytes(value);
|
|
432
|
+
},
|
|
433
|
+
};
|
|
434
|
+
if (size <= 0xff)
|
|
435
|
+
return {
|
|
436
|
+
length: 2 + size, // 1 byte prefix + 1 byte uint8 + size bytes
|
|
437
|
+
encode(cursor) {
|
|
438
|
+
cursor.pushUint8(0x58);
|
|
439
|
+
cursor.pushUint8(size);
|
|
440
|
+
cursor.pushBytes(value);
|
|
441
|
+
},
|
|
442
|
+
};
|
|
443
|
+
if (size <= 0xffff)
|
|
444
|
+
return {
|
|
445
|
+
length: 3 + size, // 1 byte prefix + 2 bytes uint16 + size bytes
|
|
446
|
+
encode(cursor) {
|
|
447
|
+
cursor.pushUint8(0x59);
|
|
448
|
+
cursor.pushUint16(size);
|
|
449
|
+
cursor.pushBytes(value);
|
|
450
|
+
},
|
|
451
|
+
};
|
|
452
|
+
if (size <= 0xffffffff)
|
|
453
|
+
return {
|
|
454
|
+
length: 5 + size, // 1 byte prefix + 4 bytes uint32 + size bytes
|
|
455
|
+
encode(cursor) {
|
|
456
|
+
cursor.pushUint8(0x5a);
|
|
457
|
+
cursor.pushUint32(size);
|
|
458
|
+
cursor.pushBytes(value);
|
|
459
|
+
},
|
|
460
|
+
};
|
|
461
|
+
throw new ByteStringTooLargeError({ size });
|
|
462
|
+
}
|
|
463
|
+
getEncodable.byteString = byteString;
|
|
464
|
+
/** @internal */
|
|
465
|
+
function object(value) {
|
|
466
|
+
const keys = Object.keys(value);
|
|
467
|
+
const entries = keys.map((key) => ({
|
|
468
|
+
key: getEncodable(key),
|
|
469
|
+
value: getEncodable(value[key]),
|
|
470
|
+
}));
|
|
471
|
+
const bodyLength = entries.reduce((acc, entry) => acc + entry.key.length + entry.value.length, 0);
|
|
472
|
+
const size = keys.length;
|
|
473
|
+
if (size <= 0x17)
|
|
474
|
+
return {
|
|
475
|
+
length: 1 + bodyLength, // 1 byte prefix + body length
|
|
476
|
+
encode(cursor) {
|
|
477
|
+
cursor.pushUint8(0xa0 + size);
|
|
478
|
+
for (const entry of entries) {
|
|
479
|
+
entry.key.encode(cursor);
|
|
480
|
+
entry.value.encode(cursor);
|
|
481
|
+
}
|
|
482
|
+
},
|
|
483
|
+
};
|
|
484
|
+
if (size <= 0xff)
|
|
485
|
+
return {
|
|
486
|
+
length: 2 + bodyLength, // 1 byte prefix + 1 byte uint8 + body length
|
|
487
|
+
encode(cursor) {
|
|
488
|
+
cursor.pushUint8(0xb8);
|
|
489
|
+
cursor.pushUint8(size);
|
|
490
|
+
for (const entry of entries) {
|
|
491
|
+
entry.key.encode(cursor);
|
|
492
|
+
entry.value.encode(cursor);
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
};
|
|
496
|
+
if (size <= 0xffff)
|
|
497
|
+
return {
|
|
498
|
+
length: 3 + bodyLength, // 1 byte prefix + 2 bytes uint16 + body length
|
|
499
|
+
encode(cursor) {
|
|
500
|
+
cursor.pushUint8(0xb9);
|
|
501
|
+
cursor.pushUint16(size);
|
|
502
|
+
for (const entry of entries) {
|
|
503
|
+
entry.key.encode(cursor);
|
|
504
|
+
entry.value.encode(cursor);
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
};
|
|
508
|
+
if (size <= 0xffffffff)
|
|
509
|
+
return {
|
|
510
|
+
length: 5 + bodyLength, // 1 byte prefix + 4 bytes uint32 + body length
|
|
511
|
+
encode(cursor) {
|
|
512
|
+
cursor.pushUint8(0xba);
|
|
513
|
+
cursor.pushUint32(size);
|
|
514
|
+
for (const entry of entries) {
|
|
515
|
+
entry.key.encode(cursor);
|
|
516
|
+
entry.value.encode(cursor);
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
};
|
|
520
|
+
throw new ObjectTooLargeError({ size });
|
|
521
|
+
}
|
|
522
|
+
getEncodable.object = object;
|
|
523
|
+
})(getEncodable || (getEncodable = {}));
|
|
524
|
+
/** @internal */
|
|
525
|
+
// biome-ignore lint/correctness/noUnusedVariables: _
|
|
526
|
+
function decodeCursor(cursor) {
|
|
527
|
+
const initialByte = cursor.readUint8();
|
|
528
|
+
const majorType = initialByte >> 5;
|
|
529
|
+
const additionalInfo = initialByte & 0b00011111;
|
|
530
|
+
switch (majorType) {
|
|
531
|
+
// Major type 0: Unsigned integer
|
|
532
|
+
case 0:
|
|
533
|
+
return decodeCursor.readUnsignedInteger(cursor, additionalInfo);
|
|
534
|
+
// Major type 1: Negative integer
|
|
535
|
+
case 1:
|
|
536
|
+
return decodeCursor.readNegativeInteger(cursor, additionalInfo);
|
|
537
|
+
// Major type 2: Byte string
|
|
538
|
+
case 2:
|
|
539
|
+
return decodeCursor.readByteString(cursor, additionalInfo);
|
|
540
|
+
// Major type 3: Text string
|
|
541
|
+
case 3:
|
|
542
|
+
return decodeCursor.readTextString(cursor, additionalInfo);
|
|
543
|
+
// Major type 4: Array
|
|
544
|
+
case 4:
|
|
545
|
+
return decodeCursor.readArray(cursor, additionalInfo);
|
|
546
|
+
// Major type 5: Map
|
|
547
|
+
case 5:
|
|
548
|
+
return decodeCursor.readMap(cursor, additionalInfo);
|
|
549
|
+
// Major type 6: Tagged data (not yet supported)
|
|
550
|
+
case 6:
|
|
551
|
+
throw new UnsupportedTagError({ tag: additionalInfo });
|
|
552
|
+
// Major type 7: Simple values and floats
|
|
553
|
+
case 7:
|
|
554
|
+
return decodeCursor.readSimpleOrFloat(cursor, additionalInfo);
|
|
555
|
+
default:
|
|
556
|
+
throw new InvalidMajorTypeError({ majorType });
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
/** @internal */
|
|
560
|
+
(function (decodeCursor) {
|
|
561
|
+
/** @internal */
|
|
562
|
+
// biome-ignore lint/correctness/noUnusedVariables: _
|
|
563
|
+
function readLength(cursor, additionalInfo) {
|
|
564
|
+
if (additionalInfo < 24)
|
|
565
|
+
return additionalInfo;
|
|
566
|
+
if (additionalInfo === 24)
|
|
567
|
+
return cursor.readUint8();
|
|
568
|
+
if (additionalInfo === 25)
|
|
569
|
+
return cursor.readUint16();
|
|
570
|
+
if (additionalInfo === 26)
|
|
571
|
+
return cursor.readUint32();
|
|
572
|
+
if (additionalInfo === 27)
|
|
573
|
+
throw new Unsupported64BitIntegerError();
|
|
574
|
+
throw new InvalidAdditionalInfoError({ additionalInfo });
|
|
575
|
+
}
|
|
576
|
+
/** @internal */
|
|
577
|
+
function readUnsignedInteger(cursor, additionalInfo) {
|
|
578
|
+
return readLength(cursor, additionalInfo);
|
|
579
|
+
}
|
|
580
|
+
decodeCursor.readUnsignedInteger = readUnsignedInteger;
|
|
581
|
+
/** @internal */
|
|
582
|
+
function readNegativeInteger(cursor, additionalInfo) {
|
|
583
|
+
const value = readLength(cursor, additionalInfo);
|
|
584
|
+
return -1 - value;
|
|
585
|
+
}
|
|
586
|
+
decodeCursor.readNegativeInteger = readNegativeInteger;
|
|
587
|
+
/** @internal */
|
|
588
|
+
function readByteString(cursor, additionalInfo) {
|
|
589
|
+
// Indefinite-length byte string
|
|
590
|
+
if (additionalInfo === 31) {
|
|
591
|
+
const chunks = [];
|
|
592
|
+
let totalLength = 0;
|
|
593
|
+
while (true) {
|
|
594
|
+
const byte = cursor.inspectUint8();
|
|
595
|
+
if (byte === 0xff) {
|
|
596
|
+
cursor.readUint8(); // consume the break byte
|
|
597
|
+
break;
|
|
598
|
+
}
|
|
599
|
+
const chunk = decodeCursor(cursor);
|
|
600
|
+
if (!(chunk instanceof Uint8Array))
|
|
601
|
+
throw new InvalidIndefiniteLengthChunkError({ type: 'byte string' });
|
|
602
|
+
chunks.push(chunk);
|
|
603
|
+
totalLength += chunk.length;
|
|
604
|
+
}
|
|
605
|
+
// Concatenate chunks
|
|
606
|
+
const result = new Uint8Array(totalLength);
|
|
607
|
+
let offset = 0;
|
|
608
|
+
for (const chunk of chunks) {
|
|
609
|
+
result.set(chunk, offset);
|
|
610
|
+
offset += chunk.length;
|
|
611
|
+
}
|
|
612
|
+
return result;
|
|
613
|
+
}
|
|
614
|
+
const length = readLength(cursor, additionalInfo);
|
|
615
|
+
return cursor.readBytes(length);
|
|
616
|
+
}
|
|
617
|
+
decodeCursor.readByteString = readByteString;
|
|
618
|
+
/** @internal */
|
|
619
|
+
function readTextString(cursor, additionalInfo) {
|
|
620
|
+
// Indefinite-length text string
|
|
621
|
+
if (additionalInfo === 31) {
|
|
622
|
+
const chunks = [];
|
|
623
|
+
while (true) {
|
|
624
|
+
const byte = cursor.inspectUint8();
|
|
625
|
+
if (byte === 0xff) {
|
|
626
|
+
cursor.readUint8(); // consume the break byte
|
|
627
|
+
break;
|
|
628
|
+
}
|
|
629
|
+
const chunk = decodeCursor(cursor);
|
|
630
|
+
if (typeof chunk !== 'string')
|
|
631
|
+
throw new InvalidIndefiniteLengthChunkError({ type: 'text string' });
|
|
632
|
+
chunks.push(chunk);
|
|
633
|
+
}
|
|
634
|
+
return chunks.join('');
|
|
635
|
+
}
|
|
636
|
+
const length = readLength(cursor, additionalInfo);
|
|
637
|
+
const bytes = cursor.readBytes(length);
|
|
638
|
+
return Bytes.toString(bytes);
|
|
639
|
+
}
|
|
640
|
+
decodeCursor.readTextString = readTextString;
|
|
641
|
+
/** @internal */
|
|
642
|
+
function readArray(cursor, additionalInfo) {
|
|
643
|
+
// Indefinite-length array
|
|
644
|
+
if (additionalInfo === 31) {
|
|
645
|
+
const result = [];
|
|
646
|
+
while (true) {
|
|
647
|
+
const byte = cursor.inspectUint8();
|
|
648
|
+
if (byte === 0xff) {
|
|
649
|
+
cursor.readUint8(); // consume the break byte
|
|
650
|
+
break;
|
|
651
|
+
}
|
|
652
|
+
result.push(decodeCursor(cursor));
|
|
653
|
+
}
|
|
654
|
+
return result;
|
|
655
|
+
}
|
|
656
|
+
const length = readLength(cursor, additionalInfo);
|
|
657
|
+
const result = [];
|
|
658
|
+
for (let i = 0; i < length; i++) {
|
|
659
|
+
result.push(decodeCursor(cursor));
|
|
660
|
+
}
|
|
661
|
+
return result;
|
|
662
|
+
}
|
|
663
|
+
decodeCursor.readArray = readArray;
|
|
664
|
+
/** @internal */
|
|
665
|
+
function readMap(cursor, additionalInfo) {
|
|
666
|
+
// Indefinite-length map
|
|
667
|
+
if (additionalInfo === 31) {
|
|
668
|
+
const result = {};
|
|
669
|
+
while (true) {
|
|
670
|
+
const byte = cursor.inspectUint8();
|
|
671
|
+
if (byte === 0xff) {
|
|
672
|
+
cursor.readUint8(); // consume the break byte
|
|
673
|
+
break;
|
|
674
|
+
}
|
|
675
|
+
const key = decodeCursor(cursor);
|
|
676
|
+
// Support both string and number keys (for COSE_Key with integer keys)
|
|
677
|
+
const keyStr = typeof key === 'string'
|
|
678
|
+
? key
|
|
679
|
+
: typeof key === 'number'
|
|
680
|
+
? String(key)
|
|
681
|
+
: String(key);
|
|
682
|
+
const value = decodeCursor(cursor);
|
|
683
|
+
result[keyStr] = value;
|
|
684
|
+
}
|
|
685
|
+
return result;
|
|
686
|
+
}
|
|
687
|
+
const length = readLength(cursor, additionalInfo);
|
|
688
|
+
const result = {};
|
|
689
|
+
for (let i = 0; i < length; i++) {
|
|
690
|
+
const key = decodeCursor(cursor);
|
|
691
|
+
// Support both string and number keys (for COSE_Key with integer keys)
|
|
692
|
+
const keyStr = typeof key === 'string'
|
|
693
|
+
? key
|
|
694
|
+
: typeof key === 'number'
|
|
695
|
+
? String(key)
|
|
696
|
+
: String(key);
|
|
697
|
+
const value = decodeCursor(cursor);
|
|
698
|
+
result[keyStr] = value;
|
|
699
|
+
}
|
|
700
|
+
return result;
|
|
701
|
+
}
|
|
702
|
+
decodeCursor.readMap = readMap;
|
|
703
|
+
/** @internal */
|
|
704
|
+
function readSimpleOrFloat(cursor, additionalInfo) {
|
|
705
|
+
// Simple values
|
|
706
|
+
if (additionalInfo === 20)
|
|
707
|
+
return false;
|
|
708
|
+
if (additionalInfo === 21)
|
|
709
|
+
return true;
|
|
710
|
+
if (additionalInfo === 22)
|
|
711
|
+
return null;
|
|
712
|
+
if (additionalInfo === 23)
|
|
713
|
+
return undefined;
|
|
714
|
+
// Float16 (half-precision)
|
|
715
|
+
if (additionalInfo === 25) {
|
|
716
|
+
const bits = cursor.readUint16();
|
|
717
|
+
return getFloat16(bits);
|
|
718
|
+
}
|
|
719
|
+
// Float32
|
|
720
|
+
if (additionalInfo === 26) {
|
|
721
|
+
const value = cursor.dataView.getFloat32(cursor.position, false);
|
|
722
|
+
cursor.position += 4;
|
|
723
|
+
return value;
|
|
724
|
+
}
|
|
725
|
+
// Float64
|
|
726
|
+
if (additionalInfo === 27) {
|
|
727
|
+
const value = cursor.dataView.getFloat64(cursor.position, false);
|
|
728
|
+
cursor.position += 8;
|
|
729
|
+
return value;
|
|
730
|
+
}
|
|
731
|
+
// Simple value (additional byte)
|
|
732
|
+
if (additionalInfo === 24) {
|
|
733
|
+
const simpleValue = cursor.readUint8();
|
|
734
|
+
// Simple values 0-19 are assigned, 20-23 are in the initial byte
|
|
735
|
+
// 24-31 are reserved, 32-255 are unassigned
|
|
736
|
+
if (simpleValue < 32)
|
|
737
|
+
throw new InvalidSimpleValueError({ value: simpleValue });
|
|
738
|
+
// For now, treat unassigned simple values as undefined
|
|
739
|
+
return undefined;
|
|
740
|
+
}
|
|
741
|
+
throw new InvalidAdditionalInfoError({ additionalInfo });
|
|
742
|
+
}
|
|
743
|
+
decodeCursor.readSimpleOrFloat = readSimpleOrFloat;
|
|
744
|
+
/** @internal */
|
|
745
|
+
function getFloat16(bits) {
|
|
746
|
+
// IEEE 754 half-precision (16-bit) float decoding
|
|
747
|
+
// Format: 1 sign bit, 5 exponent bits, 10 fraction bits
|
|
748
|
+
const sign = (bits >> 15) & 0x1;
|
|
749
|
+
const exponent = (bits >> 10) & 0x1f;
|
|
750
|
+
const fraction = bits & 0x3ff;
|
|
751
|
+
// Handle special cases
|
|
752
|
+
if (exponent === 0) {
|
|
753
|
+
// Subnormal numbers or zero
|
|
754
|
+
if (fraction === 0)
|
|
755
|
+
return sign ? -0 : 0;
|
|
756
|
+
// Subnormal: (-1)^sign × 2^(-14) × (0 + fraction/1024)
|
|
757
|
+
const value = 2 ** -14 * (fraction / 1024);
|
|
758
|
+
return sign ? -value : value;
|
|
759
|
+
}
|
|
760
|
+
if (exponent === 0x1f) {
|
|
761
|
+
// Infinity or NaN
|
|
762
|
+
if (fraction === 0)
|
|
763
|
+
return sign ? -Infinity : Infinity;
|
|
764
|
+
return NaN;
|
|
765
|
+
}
|
|
766
|
+
// Normal numbers: (-1)^sign × 2^(exponent-15) × (1 + fraction/1024)
|
|
767
|
+
const value = 2 ** (exponent - 15) * (1 + fraction / 1024);
|
|
768
|
+
return sign ? -value : value;
|
|
769
|
+
}
|
|
770
|
+
})(decodeCursor || (decodeCursor = {}));
|
|
771
|
+
//# sourceMappingURL=Cbor.js.map
|