@marcuspuchalla/nachos 0.1.1 → 0.1.4
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 +55 -0
- package/dist/{chunk-ZRPJUEIZ.js → chunk-5IWW5H47.js} +546 -227
- package/dist/chunk-5IWW5H47.js.map +1 -0
- package/dist/{chunk-2HBCILJS.cjs → chunk-RVG2BY32.cjs} +545 -226
- package/dist/chunk-RVG2BY32.cjs.map +1 -0
- package/dist/{chunk-2FUTHZQQ.cjs → chunk-S4RXO6IB.cjs} +244 -166
- package/dist/chunk-S4RXO6IB.cjs.map +1 -0
- package/dist/{chunk-7CFYWHS6.js → chunk-UMAX5MX5.js} +244 -166
- package/dist/chunk-UMAX5MX5.js.map +1 -0
- package/dist/encoder/index.cjs +13 -13
- package/dist/encoder/index.d.cts +2 -2
- package/dist/encoder/index.d.ts +2 -2
- package/dist/encoder/index.js +1 -1
- package/dist/index.cjs +32 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +28 -19
- package/dist/index.d.ts +28 -19
- package/dist/index.js +16 -16
- package/dist/index.js.map +1 -1
- package/dist/metafile-cjs.json +1 -1
- package/dist/metafile-esm.json +1 -1
- package/dist/parser/index.cjs +14 -14
- package/dist/parser/index.d.cts +3 -1
- package/dist/parser/index.d.ts +3 -1
- package/dist/parser/index.js +1 -1
- package/dist/{useCborSimpleEncoder-TVxzNJ_9.d.ts → useCborSimpleEncoder-BoKEmjP9.d.ts} +0 -2
- package/dist/{useCborSimpleEncoder-ButVU988.d.cts → useCborSimpleEncoder-C_OHxoB8.d.cts} +0 -2
- package/dist/{useCborTag-B_iaShG6.d.ts → useCborTag-BD6Sqp7p.d.ts} +11 -6
- package/dist/{useCborTag-BfTIV8HM.d.cts → useCborTag-QpZR-Er2.d.cts} +11 -6
- package/package.json +1 -1
- package/src/__tests__/public-api.test.ts +153 -0
- package/src/__tests__/roundtrip.test.ts +701 -0
- package/src/encoder/__tests__/cbor-collection-encoder.test.ts +129 -5
- package/src/encoder/__tests__/cbor-encoder-errors.test.ts +847 -0
- package/src/encoder/__tests__/cbor-simple-encoder.test.ts +126 -0
- package/src/encoder/__tests__/cbor-string-encoder.test.ts +14 -0
- package/src/encoder/composables/useCborCollectionEncoder.ts +56 -23
- package/src/encoder/composables/useCborEncoder.ts +27 -1
- package/src/encoder/composables/useCborSimpleEncoder.ts +40 -8
- package/src/encoder/composables/useCborStringEncoder.ts +23 -10
- package/src/encoder/types.ts +0 -2
- package/src/index.ts +29 -20
- package/src/parser/__tests__/buffer-native-parsing.test.ts +338 -0
- package/src/parser/__tests__/cbor-float-errors.test.ts +41 -0
- package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +97 -7
- package/src/parser/__tests__/cbor-security-dos-protection.test.ts +166 -33
- package/src/parser/__tests__/cbor-standard-tags.test.ts +104 -7
- package/src/parser/__tests__/cbor-string-errors.test.ts +4 -4
- package/src/parser/__tests__/cbor-tag-errors.test.ts +1 -1
- package/src/parser/__tests__/cbor-tag-reparse-fix.test.ts +268 -0
- package/src/parser/composables/useCborCollection.ts +45 -42
- package/src/parser/composables/useCborFloat.ts +95 -9
- package/src/parser/composables/useCborInteger.ts +24 -10
- package/src/parser/composables/useCborParser.ts +387 -216
- package/src/parser/composables/useCborString.ts +22 -4
- package/src/parser/composables/useCborTag.ts +149 -53
- package/src/parser/utils.ts +11 -0
- package/dist/chunk-2FUTHZQQ.cjs.map +0 -1
- package/dist/chunk-2HBCILJS.cjs.map +0 -1
- package/dist/chunk-7CFYWHS6.js.map +0 -1
- package/dist/chunk-ZRPJUEIZ.js.map +0 -1
- package/src/encoder/composables/#useCborTagEncoder.ts# +0 -158
|
@@ -158,6 +158,9 @@ function useCborStringEncoder(globalOptions) {
|
|
|
158
158
|
const encodeByteString = (data, encodeOptions) => {
|
|
159
159
|
const isIndefinite = isCborByteString(data) && data[INDEFINITE_SYMBOL] === true;
|
|
160
160
|
if (encodeOptions?.indefinite || Array.isArray(data) || isIndefinite) {
|
|
161
|
+
if (options.allowIndefinite === false) {
|
|
162
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
163
|
+
}
|
|
161
164
|
if (options.canonical) {
|
|
162
165
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
163
166
|
}
|
|
@@ -168,17 +171,20 @@ function useCborStringEncoder(globalOptions) {
|
|
|
168
171
|
return encodeByteStringIndefinite(Array.isArray(bytes2) ? bytes2 : [bytes2]);
|
|
169
172
|
}
|
|
170
173
|
const bytes = isCborByteString(data) ? data.bytes : data;
|
|
174
|
+
if (bytes.length + 9 > options.maxOutputSize) {
|
|
175
|
+
throw new Error(`Encoded output exceeds maximum size`);
|
|
176
|
+
}
|
|
171
177
|
const header = encodeLengthHeader(2, bytes.length);
|
|
172
178
|
const result = concatenateUint8Arrays([header, bytes]);
|
|
173
|
-
if (result.length > options.maxOutputSize) {
|
|
174
|
-
throw new Error("Encoded output exceeds maximum size");
|
|
175
|
-
}
|
|
176
179
|
return {
|
|
177
180
|
bytes: result,
|
|
178
181
|
hex: bytesToHex(result)
|
|
179
182
|
};
|
|
180
183
|
};
|
|
181
184
|
const encodeByteStringIndefinite = (chunks) => {
|
|
185
|
+
if (options.allowIndefinite === false) {
|
|
186
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
187
|
+
}
|
|
182
188
|
if (options.canonical) {
|
|
183
189
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
184
190
|
}
|
|
@@ -198,6 +204,9 @@ function useCborStringEncoder(globalOptions) {
|
|
|
198
204
|
const encodeTextString = (text, encodeOptions) => {
|
|
199
205
|
const isIndefinite = isCborTextString(text) && text[INDEFINITE_SYMBOL] === true;
|
|
200
206
|
if (encodeOptions?.indefinite || isIndefinite) {
|
|
207
|
+
if (options.allowIndefinite === false) {
|
|
208
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
209
|
+
}
|
|
201
210
|
if (options.canonical) {
|
|
202
211
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
203
212
|
}
|
|
@@ -210,17 +219,20 @@ function useCborStringEncoder(globalOptions) {
|
|
|
210
219
|
const textStr = isCborTextString(text) ? text.text : text;
|
|
211
220
|
const encoder = new TextEncoder();
|
|
212
221
|
const utf8Bytes = encoder.encode(textStr);
|
|
222
|
+
if (utf8Bytes.length + 9 > options.maxOutputSize) {
|
|
223
|
+
throw new Error(`Encoded output exceeds maximum size`);
|
|
224
|
+
}
|
|
213
225
|
const header = encodeLengthHeader(3, utf8Bytes.length);
|
|
214
226
|
const result = concatenateUint8Arrays([header, utf8Bytes]);
|
|
215
|
-
if (result.length > options.maxOutputSize) {
|
|
216
|
-
throw new Error("Encoded output exceeds maximum size");
|
|
217
|
-
}
|
|
218
227
|
return {
|
|
219
228
|
bytes: result,
|
|
220
229
|
hex: bytesToHex(result)
|
|
221
230
|
};
|
|
222
231
|
};
|
|
223
232
|
const encodeTextStringIndefinite = (chunks) => {
|
|
233
|
+
if (options.allowIndefinite === false) {
|
|
234
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
235
|
+
}
|
|
224
236
|
if (options.canonical) {
|
|
225
237
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
226
238
|
}
|
|
@@ -247,11 +259,172 @@ function useCborStringEncoder(globalOptions) {
|
|
|
247
259
|
};
|
|
248
260
|
}
|
|
249
261
|
|
|
262
|
+
// src/encoder/composables/useCborSimpleEncoder.ts
|
|
263
|
+
function useCborSimpleEncoder(_globalOptions) {
|
|
264
|
+
const { encodeInteger } = useCborIntegerEncoder();
|
|
265
|
+
const encodeSimple = (value) => {
|
|
266
|
+
let byte;
|
|
267
|
+
if (value === false) {
|
|
268
|
+
byte = 244;
|
|
269
|
+
} else if (value === true) {
|
|
270
|
+
byte = 245;
|
|
271
|
+
} else if (value === null) {
|
|
272
|
+
byte = 246;
|
|
273
|
+
} else if (value === void 0) {
|
|
274
|
+
byte = 247;
|
|
275
|
+
} else {
|
|
276
|
+
throw new Error(`Unsupported simple value: ${value}`);
|
|
277
|
+
}
|
|
278
|
+
return {
|
|
279
|
+
bytes: new Uint8Array([byte]),
|
|
280
|
+
hex: bytesToHex(new Uint8Array([byte]))
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
const encodeFloat16Bytes = (value) => {
|
|
284
|
+
if (Object.is(value, -0)) return new Uint8Array([128, 0]);
|
|
285
|
+
if (value === 0) return new Uint8Array([0, 0]);
|
|
286
|
+
if (Number.isNaN(value)) return new Uint8Array([126, 0]);
|
|
287
|
+
if (value === Infinity) return new Uint8Array([124, 0]);
|
|
288
|
+
if (value === -Infinity) return new Uint8Array([252, 0]);
|
|
289
|
+
const sign = value < 0 ? 1 : 0;
|
|
290
|
+
const absValue = Math.abs(value);
|
|
291
|
+
const buffer = new ArrayBuffer(8);
|
|
292
|
+
const view = new DataView(buffer);
|
|
293
|
+
view.setFloat64(0, absValue, false);
|
|
294
|
+
const bits = view.getBigUint64(0, false);
|
|
295
|
+
const exp64 = Number(bits >> 52n & 0x7ffn) - 1023;
|
|
296
|
+
const mant64 = Number(bits & 0xfffffffffffffn);
|
|
297
|
+
const mant64n = BigInt(mant64);
|
|
298
|
+
let exp16;
|
|
299
|
+
let mant16;
|
|
300
|
+
if (exp64 < -24) {
|
|
301
|
+
exp16 = 0;
|
|
302
|
+
mant16 = 0;
|
|
303
|
+
} else if (exp64 < -14) {
|
|
304
|
+
exp16 = 0;
|
|
305
|
+
const shift = -14 - exp64;
|
|
306
|
+
const fullMant = 1n << 10n | mant64n >> 42n;
|
|
307
|
+
const lostFromExtract = mant64n & (1n << 42n) - 1n;
|
|
308
|
+
const shiftN = BigInt(shift);
|
|
309
|
+
const guardBit = Number(fullMant >> shiftN - 1n & 1n);
|
|
310
|
+
const stickyBitsBelow = shiftN > 1n ? fullMant & (1n << shiftN - 1n) - 1n : 0n;
|
|
311
|
+
const sticky = stickyBitsBelow !== 0n || lostFromExtract !== 0n ? 1 : 0;
|
|
312
|
+
const truncated = Number(fullMant >> shiftN);
|
|
313
|
+
const lsb = truncated & 1;
|
|
314
|
+
mant16 = truncated + (guardBit & (sticky | lsb));
|
|
315
|
+
} else if (exp64 > 15) {
|
|
316
|
+
exp16 = 31;
|
|
317
|
+
mant16 = 0;
|
|
318
|
+
} else {
|
|
319
|
+
exp16 = exp64 + 15;
|
|
320
|
+
const truncated = Number(mant64n >> 42n);
|
|
321
|
+
const guardBit = Number(mant64n >> 41n & 1n);
|
|
322
|
+
const stickyBits = (mant64n & (1n << 41n) - 1n) !== 0n ? 1 : 0;
|
|
323
|
+
const lsb = truncated & 1;
|
|
324
|
+
mant16 = truncated + (guardBit & (stickyBits | lsb));
|
|
325
|
+
if (mant16 > 1023) {
|
|
326
|
+
mant16 = 0;
|
|
327
|
+
exp16 += 1;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
const float16 = sign << 15 | exp16 << 10 | mant16;
|
|
331
|
+
return new Uint8Array([
|
|
332
|
+
float16 >> 8 & 255,
|
|
333
|
+
float16 & 255
|
|
334
|
+
]);
|
|
335
|
+
};
|
|
336
|
+
const encodeFloat32Bytes = (value) => {
|
|
337
|
+
const buffer = new ArrayBuffer(4);
|
|
338
|
+
const view = new DataView(buffer);
|
|
339
|
+
view.setFloat32(0, value, false);
|
|
340
|
+
return new Uint8Array(buffer);
|
|
341
|
+
};
|
|
342
|
+
const encodeFloat64Bytes = (value) => {
|
|
343
|
+
const buffer = new ArrayBuffer(8);
|
|
344
|
+
const view = new DataView(buffer);
|
|
345
|
+
view.setFloat64(0, value, false);
|
|
346
|
+
return new Uint8Array(buffer);
|
|
347
|
+
};
|
|
348
|
+
const canBeFloat16 = (value) => {
|
|
349
|
+
if (!Number.isFinite(value) || Object.is(value, 0) || Object.is(value, -0)) {
|
|
350
|
+
return true;
|
|
351
|
+
}
|
|
352
|
+
const absValue = Math.abs(value);
|
|
353
|
+
if (absValue < 6103515625e-14 || absValue > 65504) {
|
|
354
|
+
return false;
|
|
355
|
+
}
|
|
356
|
+
const bytes = encodeFloat16Bytes(value);
|
|
357
|
+
const view = new DataView(bytes.buffer);
|
|
358
|
+
const bits = view.getUint16(0, false);
|
|
359
|
+
const sign = bits >> 15 & 1;
|
|
360
|
+
const exp = bits >> 10 & 31;
|
|
361
|
+
const mant = bits & 1023;
|
|
362
|
+
let decoded;
|
|
363
|
+
if (exp === 0) {
|
|
364
|
+
decoded = (sign ? -1 : 1) * Math.pow(2, -14) * (mant / 1024);
|
|
365
|
+
} else if (exp === 31) {
|
|
366
|
+
decoded = mant === 0 ? sign ? -Infinity : Infinity : NaN;
|
|
367
|
+
} else {
|
|
368
|
+
decoded = (sign ? -1 : 1) * Math.pow(2, exp - 15) * (1 + mant / 1024);
|
|
369
|
+
}
|
|
370
|
+
return decoded === value;
|
|
371
|
+
};
|
|
372
|
+
const canBeFloat32 = (value) => {
|
|
373
|
+
if (!Number.isFinite(value) || Object.is(value, 0) || Object.is(value, -0)) {
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
const buffer = new ArrayBuffer(4);
|
|
377
|
+
const view = new DataView(buffer);
|
|
378
|
+
view.setFloat32(0, value, false);
|
|
379
|
+
const decoded = view.getFloat32(0, false);
|
|
380
|
+
return decoded === value;
|
|
381
|
+
};
|
|
382
|
+
const isInteger = (value) => {
|
|
383
|
+
return Number.isInteger(value) && Number.isSafeInteger(value);
|
|
384
|
+
};
|
|
385
|
+
const encodeFloat = (value, precision) => {
|
|
386
|
+
let bytes;
|
|
387
|
+
if (isInteger(value) && !precision) {
|
|
388
|
+
return encodeInteger(value);
|
|
389
|
+
}
|
|
390
|
+
if (precision === 16) {
|
|
391
|
+
const floatBytes = encodeFloat16Bytes(value);
|
|
392
|
+
bytes = new Uint8Array([249, ...floatBytes]);
|
|
393
|
+
} else if (precision === 32) {
|
|
394
|
+
const floatBytes = encodeFloat32Bytes(value);
|
|
395
|
+
bytes = new Uint8Array([250, ...floatBytes]);
|
|
396
|
+
} else if (precision === 64) {
|
|
397
|
+
const floatBytes = encodeFloat64Bytes(value);
|
|
398
|
+
bytes = new Uint8Array([251, ...floatBytes]);
|
|
399
|
+
} else {
|
|
400
|
+
if (canBeFloat16(value)) {
|
|
401
|
+
const floatBytes = encodeFloat16Bytes(value);
|
|
402
|
+
bytes = new Uint8Array([249, ...floatBytes]);
|
|
403
|
+
} else if (canBeFloat32(value)) {
|
|
404
|
+
const floatBytes = encodeFloat32Bytes(value);
|
|
405
|
+
bytes = new Uint8Array([250, ...floatBytes]);
|
|
406
|
+
} else {
|
|
407
|
+
const floatBytes = encodeFloat64Bytes(value);
|
|
408
|
+
bytes = new Uint8Array([251, ...floatBytes]);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return {
|
|
412
|
+
bytes,
|
|
413
|
+
hex: bytesToHex(bytes)
|
|
414
|
+
};
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
encodeSimple,
|
|
418
|
+
encodeFloat
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
250
422
|
// src/encoder/composables/useCborCollectionEncoder.ts
|
|
251
423
|
function useCborCollectionEncoder(globalOptions) {
|
|
252
424
|
const options = { ...DEFAULT_ENCODE_OPTIONS, ...globalOptions };
|
|
253
425
|
const { encodeInteger } = useCborIntegerEncoder();
|
|
254
426
|
const { encodeTextString, encodeByteString } = useCborStringEncoder(globalOptions);
|
|
427
|
+
const { encodeFloat } = useCborSimpleEncoder();
|
|
255
428
|
const { isCborByteString } = useCborByteString();
|
|
256
429
|
const { isCborTextString } = useCborTextString();
|
|
257
430
|
let mainEncode = null;
|
|
@@ -266,7 +439,15 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
266
439
|
return new Uint8Array([246]);
|
|
267
440
|
} else if (typeof value === "boolean") {
|
|
268
441
|
return new Uint8Array([value ? 245 : 244]);
|
|
269
|
-
} else if (typeof value === "number"
|
|
442
|
+
} else if (typeof value === "number") {
|
|
443
|
+
if (Object.is(value, -0)) {
|
|
444
|
+
return encodeFloat(value, 16).bytes;
|
|
445
|
+
}
|
|
446
|
+
if (Number.isInteger(value) && Number.isSafeInteger(value)) {
|
|
447
|
+
return encodeInteger(value).bytes;
|
|
448
|
+
}
|
|
449
|
+
return encodeFloat(value).bytes;
|
|
450
|
+
} else if (typeof value === "bigint") {
|
|
270
451
|
return encodeInteger(value).bytes;
|
|
271
452
|
} else if (typeof value === "string" || isCborTextString(value)) {
|
|
272
453
|
return encodeTextString(value).bytes;
|
|
@@ -276,6 +457,9 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
276
457
|
const isIndefinite = value[INDEFINITE_SYMBOL] === true;
|
|
277
458
|
const newCtx = { ...ctx, depth: ctx.depth + 1 };
|
|
278
459
|
if (isIndefinite) {
|
|
460
|
+
if (ctx.options.allowIndefinite === false) {
|
|
461
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
462
|
+
}
|
|
279
463
|
const parts = [new Uint8Array([159])];
|
|
280
464
|
for (const item of value) {
|
|
281
465
|
const encoded = encodeValue(item, newCtx);
|
|
@@ -295,6 +479,9 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
295
479
|
const isIndefinite = value[INDEFINITE_SYMBOL] === true;
|
|
296
480
|
const newCtx = { ...ctx, depth: ctx.depth + 1 };
|
|
297
481
|
if (isIndefinite) {
|
|
482
|
+
if (ctx.options.allowIndefinite === false) {
|
|
483
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
484
|
+
}
|
|
298
485
|
const entries = value instanceof Map ? Array.from(value.entries()) : Object.entries(value);
|
|
299
486
|
const parts = [new Uint8Array([191])];
|
|
300
487
|
for (const [key, val] of entries) {
|
|
@@ -340,10 +527,6 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
340
527
|
parts.push(encoded);
|
|
341
528
|
}
|
|
342
529
|
const result = concatenateUint8Arrays(parts);
|
|
343
|
-
ctx.bytesWritten += result.length;
|
|
344
|
-
if (ctx.bytesWritten > ctx.options.maxOutputSize) {
|
|
345
|
-
throw new Error("Encoded output exceeds maximum size");
|
|
346
|
-
}
|
|
347
530
|
return {
|
|
348
531
|
bytes: result,
|
|
349
532
|
hex: bytesToHex(result)
|
|
@@ -352,6 +535,9 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
352
535
|
const encodeArray = (array, encodeOptions) => {
|
|
353
536
|
const isIndefinite = array[INDEFINITE_SYMBOL] === true;
|
|
354
537
|
if (encodeOptions?.indefinite || isIndefinite) {
|
|
538
|
+
if (options.allowIndefinite === false) {
|
|
539
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
540
|
+
}
|
|
355
541
|
if (options.canonical) {
|
|
356
542
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
357
543
|
}
|
|
@@ -359,19 +545,20 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
359
545
|
}
|
|
360
546
|
const ctx = {
|
|
361
547
|
depth: 0,
|
|
362
|
-
bytesWritten: 0,
|
|
363
548
|
options
|
|
364
549
|
};
|
|
365
550
|
return encodeArrayInternal(array, ctx);
|
|
366
551
|
};
|
|
367
552
|
const encodeArrayIndefinite = (array) => {
|
|
553
|
+
if (options.allowIndefinite === false) {
|
|
554
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
555
|
+
}
|
|
368
556
|
if (options.canonical) {
|
|
369
557
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
370
558
|
}
|
|
371
559
|
const parts = [new Uint8Array([159])];
|
|
372
560
|
const ctx = {
|
|
373
561
|
depth: 0,
|
|
374
|
-
bytesWritten: 0,
|
|
375
562
|
options
|
|
376
563
|
};
|
|
377
564
|
for (const item of array) {
|
|
@@ -392,12 +579,27 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
392
579
|
} else {
|
|
393
580
|
entries = map instanceof Map ? Array.from(map.entries()) : Object.entries(map);
|
|
394
581
|
}
|
|
582
|
+
let preEncodedKeys = null;
|
|
395
583
|
if (ctx.options.canonical && !map[ALL_ENTRIES_SYMBOL]) {
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
});
|
|
584
|
+
const childCtx = { ...ctx, depth: ctx.depth + 1 };
|
|
585
|
+
const withEncodedKeys = entries.map((entry) => ({
|
|
586
|
+
encodedKey: encodeValue(entry[0], childCtx),
|
|
587
|
+
entry
|
|
588
|
+
}));
|
|
589
|
+
withEncodedKeys.sort((a, b) => compareBytes(a.encodedKey, b.encodedKey));
|
|
590
|
+
entries = withEncodedKeys.map((t) => t.entry);
|
|
591
|
+
preEncodedKeys = withEncodedKeys.map((t) => t.encodedKey);
|
|
592
|
+
}
|
|
593
|
+
if (ctx.options.rejectDuplicateKeys) {
|
|
594
|
+
const seen = /* @__PURE__ */ new Set();
|
|
595
|
+
const keysForDupCheck = preEncodedKeys ?? entries.map((e) => encodeValue(e[0], { ...ctx, depth: ctx.depth + 1 }));
|
|
596
|
+
for (const keyBytes of keysForDupCheck) {
|
|
597
|
+
const keyHex = bytesToHex(keyBytes);
|
|
598
|
+
if (seen.has(keyHex)) {
|
|
599
|
+
throw new Error("Duplicate map key detected");
|
|
600
|
+
}
|
|
601
|
+
seen.add(keyHex);
|
|
602
|
+
}
|
|
401
603
|
}
|
|
402
604
|
const header = encodeLengthHeader(5, entries.length);
|
|
403
605
|
const parts = [header];
|
|
@@ -408,10 +610,6 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
408
610
|
parts.push(encodedValue);
|
|
409
611
|
}
|
|
410
612
|
const result = concatenateUint8Arrays(parts);
|
|
411
|
-
ctx.bytesWritten += result.length;
|
|
412
|
-
if (ctx.bytesWritten > ctx.options.maxOutputSize) {
|
|
413
|
-
throw new Error("Encoded output exceeds maximum size");
|
|
414
|
-
}
|
|
415
613
|
return {
|
|
416
614
|
bytes: result,
|
|
417
615
|
hex: bytesToHex(result)
|
|
@@ -420,6 +618,9 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
420
618
|
const encodeMap = (map, encodeOptions) => {
|
|
421
619
|
const isIndefinite = map[INDEFINITE_SYMBOL] === true;
|
|
422
620
|
if (encodeOptions?.indefinite || isIndefinite) {
|
|
621
|
+
if (options.allowIndefinite === false) {
|
|
622
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
623
|
+
}
|
|
423
624
|
if (options.canonical) {
|
|
424
625
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
425
626
|
}
|
|
@@ -427,12 +628,14 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
427
628
|
}
|
|
428
629
|
const ctx = {
|
|
429
630
|
depth: 0,
|
|
430
|
-
bytesWritten: 0,
|
|
431
631
|
options
|
|
432
632
|
};
|
|
433
633
|
return encodeMapInternal(map, ctx);
|
|
434
634
|
};
|
|
435
635
|
const encodeMapIndefinite = (map) => {
|
|
636
|
+
if (options.allowIndefinite === false) {
|
|
637
|
+
throw new Error("Indefinite-length encoding is not allowed");
|
|
638
|
+
}
|
|
436
639
|
if (options.canonical) {
|
|
437
640
|
throw new Error("Indefinite-length encoding not allowed in canonical mode");
|
|
438
641
|
}
|
|
@@ -440,7 +643,6 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
440
643
|
const parts = [new Uint8Array([191])];
|
|
441
644
|
const ctx = {
|
|
442
645
|
depth: 0,
|
|
443
|
-
bytesWritten: 0,
|
|
444
646
|
options
|
|
445
647
|
};
|
|
446
648
|
for (const [key, value] of entries) {
|
|
@@ -465,145 +667,6 @@ function useCborCollectionEncoder(globalOptions) {
|
|
|
465
667
|
};
|
|
466
668
|
}
|
|
467
669
|
|
|
468
|
-
// src/encoder/composables/useCborSimpleEncoder.ts
|
|
469
|
-
function useCborSimpleEncoder(_globalOptions) {
|
|
470
|
-
const { encodeInteger } = useCborIntegerEncoder();
|
|
471
|
-
const encodeSimple = (value) => {
|
|
472
|
-
let byte;
|
|
473
|
-
if (value === false) {
|
|
474
|
-
byte = 244;
|
|
475
|
-
} else if (value === true) {
|
|
476
|
-
byte = 245;
|
|
477
|
-
} else if (value === null) {
|
|
478
|
-
byte = 246;
|
|
479
|
-
} else if (value === void 0) {
|
|
480
|
-
byte = 247;
|
|
481
|
-
} else {
|
|
482
|
-
throw new Error(`Unsupported simple value: ${value}`);
|
|
483
|
-
}
|
|
484
|
-
return {
|
|
485
|
-
bytes: new Uint8Array([byte]),
|
|
486
|
-
hex: bytesToHex(new Uint8Array([byte]))
|
|
487
|
-
};
|
|
488
|
-
};
|
|
489
|
-
const encodeFloat16Bytes = (value) => {
|
|
490
|
-
if (value === 0) return new Uint8Array([0, 0]);
|
|
491
|
-
if (value === -0) return new Uint8Array([128, 0]);
|
|
492
|
-
if (Number.isNaN(value)) return new Uint8Array([126, 0]);
|
|
493
|
-
if (value === Infinity) return new Uint8Array([124, 0]);
|
|
494
|
-
if (value === -Infinity) return new Uint8Array([252, 0]);
|
|
495
|
-
const sign = value < 0 ? 1 : 0;
|
|
496
|
-
const absValue = Math.abs(value);
|
|
497
|
-
const buffer = new ArrayBuffer(8);
|
|
498
|
-
const view = new DataView(buffer);
|
|
499
|
-
view.setFloat64(0, absValue, false);
|
|
500
|
-
const bits = view.getBigUint64(0, false);
|
|
501
|
-
const exp64 = Number(bits >> 52n & 0x7ffn) - 1023;
|
|
502
|
-
const mant64 = Number(bits & 0xfffffffffffffn);
|
|
503
|
-
let exp16;
|
|
504
|
-
let mant16;
|
|
505
|
-
if (exp64 < -14) {
|
|
506
|
-
exp16 = 0;
|
|
507
|
-
mant16 = 0;
|
|
508
|
-
} else if (exp64 > 15) {
|
|
509
|
-
exp16 = 31;
|
|
510
|
-
mant16 = 0;
|
|
511
|
-
} else {
|
|
512
|
-
exp16 = exp64 + 15;
|
|
513
|
-
mant16 = mant64 >> 42;
|
|
514
|
-
}
|
|
515
|
-
const float16 = sign << 15 | exp16 << 10 | mant16;
|
|
516
|
-
return new Uint8Array([
|
|
517
|
-
float16 >> 8 & 255,
|
|
518
|
-
float16 & 255
|
|
519
|
-
]);
|
|
520
|
-
};
|
|
521
|
-
const encodeFloat32Bytes = (value) => {
|
|
522
|
-
const buffer = new ArrayBuffer(4);
|
|
523
|
-
const view = new DataView(buffer);
|
|
524
|
-
view.setFloat32(0, value, false);
|
|
525
|
-
return new Uint8Array(buffer);
|
|
526
|
-
};
|
|
527
|
-
const encodeFloat64Bytes = (value) => {
|
|
528
|
-
const buffer = new ArrayBuffer(8);
|
|
529
|
-
const view = new DataView(buffer);
|
|
530
|
-
view.setFloat64(0, value, false);
|
|
531
|
-
return new Uint8Array(buffer);
|
|
532
|
-
};
|
|
533
|
-
const canBeFloat16 = (value) => {
|
|
534
|
-
if (!Number.isFinite(value) || value === 0 || value === -0) {
|
|
535
|
-
return true;
|
|
536
|
-
}
|
|
537
|
-
const absValue = Math.abs(value);
|
|
538
|
-
if (absValue < 6103515625e-14 || absValue > 65504) {
|
|
539
|
-
return false;
|
|
540
|
-
}
|
|
541
|
-
const bytes = encodeFloat16Bytes(value);
|
|
542
|
-
const view = new DataView(bytes.buffer);
|
|
543
|
-
const bits = view.getUint16(0, false);
|
|
544
|
-
const sign = bits >> 15 & 1;
|
|
545
|
-
const exp = bits >> 10 & 31;
|
|
546
|
-
const mant = bits & 1023;
|
|
547
|
-
let decoded;
|
|
548
|
-
if (exp === 0) {
|
|
549
|
-
decoded = (sign ? -1 : 1) * Math.pow(2, -14) * (mant / 1024);
|
|
550
|
-
} else if (exp === 31) {
|
|
551
|
-
decoded = mant === 0 ? sign ? -Infinity : Infinity : NaN;
|
|
552
|
-
} else {
|
|
553
|
-
decoded = (sign ? -1 : 1) * Math.pow(2, exp - 15) * (1 + mant / 1024);
|
|
554
|
-
}
|
|
555
|
-
return decoded === value;
|
|
556
|
-
};
|
|
557
|
-
const canBeFloat32 = (value) => {
|
|
558
|
-
if (!Number.isFinite(value) || value === 0 || value === -0) {
|
|
559
|
-
return true;
|
|
560
|
-
}
|
|
561
|
-
const buffer = new ArrayBuffer(4);
|
|
562
|
-
const view = new DataView(buffer);
|
|
563
|
-
view.setFloat32(0, value, false);
|
|
564
|
-
const decoded = view.getFloat32(0, false);
|
|
565
|
-
return decoded === value;
|
|
566
|
-
};
|
|
567
|
-
const isInteger = (value) => {
|
|
568
|
-
return Number.isInteger(value) && Number.isSafeInteger(value);
|
|
569
|
-
};
|
|
570
|
-
const encodeFloat = (value, precision) => {
|
|
571
|
-
let bytes;
|
|
572
|
-
if (isInteger(value) && !precision) {
|
|
573
|
-
return encodeInteger(value);
|
|
574
|
-
}
|
|
575
|
-
if (precision === 16) {
|
|
576
|
-
const floatBytes = encodeFloat16Bytes(value);
|
|
577
|
-
bytes = new Uint8Array([249, ...floatBytes]);
|
|
578
|
-
} else if (precision === 32) {
|
|
579
|
-
const floatBytes = encodeFloat32Bytes(value);
|
|
580
|
-
bytes = new Uint8Array([250, ...floatBytes]);
|
|
581
|
-
} else if (precision === 64) {
|
|
582
|
-
const floatBytes = encodeFloat64Bytes(value);
|
|
583
|
-
bytes = new Uint8Array([251, ...floatBytes]);
|
|
584
|
-
} else {
|
|
585
|
-
if (canBeFloat16(value)) {
|
|
586
|
-
const floatBytes = encodeFloat16Bytes(value);
|
|
587
|
-
bytes = new Uint8Array([249, ...floatBytes]);
|
|
588
|
-
} else if (canBeFloat32(value)) {
|
|
589
|
-
const floatBytes = encodeFloat32Bytes(value);
|
|
590
|
-
bytes = new Uint8Array([250, ...floatBytes]);
|
|
591
|
-
} else {
|
|
592
|
-
const floatBytes = encodeFloat64Bytes(value);
|
|
593
|
-
bytes = new Uint8Array([251, ...floatBytes]);
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
return {
|
|
597
|
-
bytes,
|
|
598
|
-
hex: bytesToHex(bytes)
|
|
599
|
-
};
|
|
600
|
-
};
|
|
601
|
-
return {
|
|
602
|
-
encodeSimple,
|
|
603
|
-
encodeFloat
|
|
604
|
-
};
|
|
605
|
-
}
|
|
606
|
-
|
|
607
670
|
// src/encoder/composables/useCborTagEncoder.ts
|
|
608
671
|
function useCborTagEncoder() {
|
|
609
672
|
const encodeTagNumber = (tagNumber) => {
|
|
@@ -657,6 +720,9 @@ function useCborTagEncoder() {
|
|
|
657
720
|
// src/encoder/composables/useCborEncoder.ts
|
|
658
721
|
function useCborEncoder(globalOptions) {
|
|
659
722
|
const options = { ...DEFAULT_ENCODE_OPTIONS, ...globalOptions };
|
|
723
|
+
if (options.canonical && options.allowIndefinite) {
|
|
724
|
+
options.allowIndefinite = false;
|
|
725
|
+
}
|
|
660
726
|
const { encodeInteger } = useCborIntegerEncoder();
|
|
661
727
|
const { encodeTextString, encodeByteString } = useCborStringEncoder(options);
|
|
662
728
|
const { encodeArray, encodeMap, setMainEncode } = useCborCollectionEncoder(options);
|
|
@@ -665,11 +731,23 @@ function useCborEncoder(globalOptions) {
|
|
|
665
731
|
const { isCborByteString } = useCborByteString();
|
|
666
732
|
const { isCborTextString } = useCborTextString();
|
|
667
733
|
const encode = (value) => {
|
|
734
|
+
const result = encodeValue(value);
|
|
735
|
+
if (options.maxOutputSize && result.bytes.length > options.maxOutputSize) {
|
|
736
|
+
throw new Error(
|
|
737
|
+
`Encoded output size ${result.bytes.length} bytes exceeds limit of ${options.maxOutputSize} bytes`
|
|
738
|
+
);
|
|
739
|
+
}
|
|
740
|
+
return result;
|
|
741
|
+
};
|
|
742
|
+
const encodeValue = (value) => {
|
|
668
743
|
if (value === null || value === void 0 || typeof value === "boolean") {
|
|
669
744
|
return encodeSimple(value);
|
|
670
745
|
}
|
|
671
746
|
if (typeof value === "number") {
|
|
672
|
-
if (
|
|
747
|
+
if (Object.is(value, -0)) {
|
|
748
|
+
return encodeFloat(value, 16);
|
|
749
|
+
}
|
|
750
|
+
if (Number.isSafeInteger(value)) {
|
|
673
751
|
return encodeInteger(value);
|
|
674
752
|
}
|
|
675
753
|
return encodeFloat(value);
|
|
@@ -738,5 +816,5 @@ function useCborEncoder(globalOptions) {
|
|
|
738
816
|
}
|
|
739
817
|
|
|
740
818
|
export { DEFAULT_ENCODE_OPTIONS, bytesToHex, compareBytes, concatenateUint8Arrays, useCborCollectionEncoder, useCborEncoder, useCborIntegerEncoder, useCborSimpleEncoder, useCborStringEncoder, useCborTagEncoder, writeBigUint, writeUint };
|
|
741
|
-
//# sourceMappingURL=chunk-
|
|
742
|
-
//# sourceMappingURL=chunk-
|
|
819
|
+
//# sourceMappingURL=chunk-UMAX5MX5.js.map
|
|
820
|
+
//# sourceMappingURL=chunk-UMAX5MX5.js.map
|