@marcuspuchalla/nachos 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/LICENSE +674 -0
  3. package/README.md +345 -0
  4. package/dist/chunk-2FUTHZQQ.cjs +755 -0
  5. package/dist/chunk-2FUTHZQQ.cjs.map +1 -0
  6. package/dist/chunk-2HBCILJS.cjs +2034 -0
  7. package/dist/chunk-2HBCILJS.cjs.map +1 -0
  8. package/dist/chunk-7CFYWHS6.js +742 -0
  9. package/dist/chunk-7CFYWHS6.js.map +1 -0
  10. package/dist/chunk-PD72MVTX.cjs +160 -0
  11. package/dist/chunk-PD72MVTX.cjs.map +1 -0
  12. package/dist/chunk-ZDZ2B5PE.js +149 -0
  13. package/dist/chunk-ZDZ2B5PE.js.map +1 -0
  14. package/dist/chunk-ZRPJUEIZ.js +2020 -0
  15. package/dist/chunk-ZRPJUEIZ.js.map +1 -0
  16. package/dist/encoder/index.cjs +57 -0
  17. package/dist/encoder/index.cjs.map +1 -0
  18. package/dist/encoder/index.d.cts +72 -0
  19. package/dist/encoder/index.d.ts +72 -0
  20. package/dist/encoder/index.js +4 -0
  21. package/dist/encoder/index.js.map +1 -0
  22. package/dist/index.cjs +606 -0
  23. package/dist/index.cjs.map +1 -0
  24. package/dist/index.d.cts +494 -0
  25. package/dist/index.d.ts +494 -0
  26. package/dist/index.js +523 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/metafile-cjs.json +1 -0
  29. package/dist/metafile-esm.json +1 -0
  30. package/dist/parser/index.cjs +85 -0
  31. package/dist/parser/index.cjs.map +1 -0
  32. package/dist/parser/index.d.cts +72 -0
  33. package/dist/parser/index.d.ts +72 -0
  34. package/dist/parser/index.js +4 -0
  35. package/dist/parser/index.js.map +1 -0
  36. package/dist/types-DvNlfbKB.d.cts +301 -0
  37. package/dist/types-DvNlfbKB.d.ts +301 -0
  38. package/dist/useCborSimpleEncoder-ButVU988.d.cts +268 -0
  39. package/dist/useCborSimpleEncoder-TVxzNJ_9.d.ts +268 -0
  40. package/dist/useCborTag-B_iaShG6.d.ts +142 -0
  41. package/dist/useCborTag-BfTIV8HM.d.cts +142 -0
  42. package/package.json +102 -0
  43. package/src/__tests__/public-api.test.ts +326 -0
  44. package/src/encoder/__tests__/cbor-collection-encoder.test.ts +331 -0
  45. package/src/encoder/__tests__/cbor-integer-encoder.test.ts +283 -0
  46. package/src/encoder/__tests__/cbor-simple-encoder.test.ts +224 -0
  47. package/src/encoder/__tests__/cbor-string-encoder.test.ts +345 -0
  48. package/src/encoder/__tests__/cbor-tag-encoder.test.ts +565 -0
  49. package/src/encoder/composables/#useCborTagEncoder.ts# +158 -0
  50. package/src/encoder/composables/useCborCollectionEncoder.ts +424 -0
  51. package/src/encoder/composables/useCborEncoder.ts +203 -0
  52. package/src/encoder/composables/useCborIntegerEncoder.ts +188 -0
  53. package/src/encoder/composables/useCborSimpleEncoder.ts +266 -0
  54. package/src/encoder/composables/useCborStringEncoder.ts +266 -0
  55. package/src/encoder/composables/useCborTagEncoder.ts +158 -0
  56. package/src/encoder/index.ts +35 -0
  57. package/src/encoder/types.ts +88 -0
  58. package/src/encoder/utils.ts +80 -0
  59. package/src/index.ts +434 -0
  60. package/src/parser/__tests__/ast-tree-structure.test.ts +311 -0
  61. package/src/parser/__tests__/cbor-collection-errors.test.ts +296 -0
  62. package/src/parser/__tests__/cbor-collection.test.ts +369 -0
  63. package/src/parser/__tests__/cbor-deterministic-encoding.test.ts +432 -0
  64. package/src/parser/__tests__/cbor-diagnostic.test.ts +333 -0
  65. package/src/parser/__tests__/cbor-duplicate-keys.test.ts +235 -0
  66. package/src/parser/__tests__/cbor-float-errors.test.ts +222 -0
  67. package/src/parser/__tests__/cbor-float.test.ts +502 -0
  68. package/src/parser/__tests__/cbor-integer-errors.test.ts +139 -0
  69. package/src/parser/__tests__/cbor-integer.test.ts +200 -0
  70. package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +403 -0
  71. package/src/parser/__tests__/cbor-parser-errors.test.ts +126 -0
  72. package/src/parser/__tests__/cbor-security-dos-protection.test.ts +503 -0
  73. package/src/parser/__tests__/cbor-sequences.test.ts +150 -0
  74. package/src/parser/__tests__/cbor-source-map.test.ts +321 -0
  75. package/src/parser/__tests__/cbor-standard-tags.test.ts +340 -0
  76. package/src/parser/__tests__/cbor-string-errors.test.ts +227 -0
  77. package/src/parser/__tests__/cbor-string.test.ts +224 -0
  78. package/src/parser/__tests__/cbor-tag-advanced.test.ts +500 -0
  79. package/src/parser/__tests__/cbor-tag-errors.test.ts +447 -0
  80. package/src/parser/__tests__/cbor-tag-source-map.test.ts +360 -0
  81. package/src/parser/__tests__/cbor-tag.test.ts +684 -0
  82. package/src/parser/__tests__/extreme-edge-cases.test.ts +146 -0
  83. package/src/parser/__tests__/pathBuilder.test.ts +256 -0
  84. package/src/parser/__tests__/rfc-test-vectors.test.ts +607 -0
  85. package/src/parser/__tests__/security-limits.test.ts +248 -0
  86. package/src/parser/__tests__/utils-errors.test.ts +127 -0
  87. package/src/parser/composables/useCborCollection.ts +509 -0
  88. package/src/parser/composables/useCborDiagnostic.ts +381 -0
  89. package/src/parser/composables/useCborFloat.ts +256 -0
  90. package/src/parser/composables/useCborInteger.ts +114 -0
  91. package/src/parser/composables/useCborParser.ts +951 -0
  92. package/src/parser/composables/useCborString.ts +330 -0
  93. package/src/parser/composables/useCborStringTypes.ts +129 -0
  94. package/src/parser/composables/useCborTag.ts +739 -0
  95. package/src/parser/index.ts +56 -0
  96. package/src/parser/types.ts +371 -0
  97. package/src/parser/utils/pathBuilder.ts +259 -0
  98. package/src/parser/utils.ts +398 -0
  99. package/src/utils/__tests__/logger.test.ts +186 -0
  100. package/src/utils/logger.ts +96 -0
@@ -0,0 +1,502 @@
1
+ /**
2
+ * CBOR Float and Simple Values Parser Tests
3
+ * Major Type 7 (Simple Values and Floats)
4
+ * Following RFC 8949 specification
5
+ */
6
+
7
+ import { describe, it, expect } from 'vitest'
8
+ import { useCborFloat } from '../composables/useCborFloat'
9
+
10
+ describe('useCborFloat', () => {
11
+ describe('Simple Values', () => {
12
+ describe('Boolean Values', () => {
13
+ it('should parse false (0xf4)', () => {
14
+ const { parseSimple } = useCborFloat()
15
+
16
+ // RFC 8949: false = 0xf4
17
+ const result = parseSimple('f4')
18
+ expect(result.value).toBe(false)
19
+ expect(result.bytesRead).toBe(1)
20
+ })
21
+
22
+ it('should parse true (0xf5)', () => {
23
+ const { parseSimple } = useCborFloat()
24
+
25
+ // RFC 8949: true = 0xf5
26
+ const result = parseSimple('f5')
27
+ expect(result.value).toBe(true)
28
+ expect(result.bytesRead).toBe(1)
29
+ })
30
+ })
31
+
32
+ describe('Null and Undefined', () => {
33
+ it('should parse null (0xf6)', () => {
34
+ const { parseSimple } = useCborFloat()
35
+
36
+ // RFC 8949: null = 0xf6
37
+ const result = parseSimple('f6')
38
+ expect(result.value).toBe(null)
39
+ expect(result.bytesRead).toBe(1)
40
+ })
41
+
42
+ it('should parse undefined (0xf7)', () => {
43
+ const { parseSimple } = useCborFloat()
44
+
45
+ // RFC 8949: undefined = 0xf7
46
+ const result = parseSimple('f7')
47
+ expect(result.value).toBe(undefined)
48
+ expect(result.bytesRead).toBe(1)
49
+ })
50
+ })
51
+
52
+ describe('Unassigned Simple Values', () => {
53
+ it('should handle simple value 0 (0xe0)', () => {
54
+ const { parseSimple } = useCborFloat()
55
+
56
+ // Simple value 0 = 0xe0
57
+ const result = parseSimple('e0')
58
+ expect(result.value).toEqual({ simpleValue: 0 })
59
+ expect(result.bytesRead).toBe(1)
60
+ })
61
+
62
+ it('should handle simple value 19 (0xf3)', () => {
63
+ const { parseSimple } = useCborFloat()
64
+
65
+ // Simple value 19 = 0xf3
66
+ const result = parseSimple('f3')
67
+ expect(result.value).toEqual({ simpleValue: 19 })
68
+ expect(result.bytesRead).toBe(1)
69
+ })
70
+
71
+ it('should handle 1-byte simple value 32 (0xf8 0x20)', () => {
72
+ const { parseSimple } = useCborFloat()
73
+
74
+ // Simple value 32 = 0xf8 0x20
75
+ const result = parseSimple('f820')
76
+ expect(result.value).toEqual({ simpleValue: 32 })
77
+ expect(result.bytesRead).toBe(2)
78
+ })
79
+
80
+ it('should handle 1-byte simple value 255 (0xf8 0xff)', () => {
81
+ const { parseSimple } = useCborFloat()
82
+
83
+ // Simple value 255 = 0xf8 0xff
84
+ const result = parseSimple('f8ff')
85
+ expect(result.value).toEqual({ simpleValue: 255 })
86
+ expect(result.bytesRead).toBe(2)
87
+ })
88
+ })
89
+ })
90
+
91
+ describe('Float16 (IEEE 754 binary16)', () => {
92
+ it('should parse 0.0 (0xf9 0x0000)', () => {
93
+ const { parseFloat } = useCborFloat()
94
+
95
+ // Float16: 0.0 = 0xf9 0x00 0x00
96
+ const result = parseFloat('f90000')
97
+ expect(result.value).toBe(0.0)
98
+ expect(result.bytesRead).toBe(3)
99
+ })
100
+
101
+ it('should parse -0.0 (0xf9 0x8000)', () => {
102
+ const { parseFloat } = useCborFloat()
103
+
104
+ // Float16: -0.0 = 0xf9 0x80 0x00
105
+ const result = parseFloat('f98000')
106
+ expect(result.value).toBe(-0.0)
107
+ expect(Object.is(result.value, -0.0)).toBe(true)
108
+ expect(result.bytesRead).toBe(3)
109
+ })
110
+
111
+ it('should parse 1.0 (0xf9 0x3c00)', () => {
112
+ const { parseFloat } = useCborFloat()
113
+
114
+ // Float16: 1.0 = 0xf9 0x3c 0x00
115
+ const result = parseFloat('f93c00')
116
+ expect(result.value).toBe(1.0)
117
+ expect(result.bytesRead).toBe(3)
118
+ })
119
+
120
+ it('should parse -1.0 (0xf9 0xbc00)', () => {
121
+ const { parseFloat } = useCborFloat()
122
+
123
+ // Float16: -1.0 = 0xf9 0xbc 0x00
124
+ const result = parseFloat('f9bc00')
125
+ expect(result.value).toBe(-1.0)
126
+ expect(result.bytesRead).toBe(3)
127
+ })
128
+
129
+ it('should parse 1.5 (0xf9 0x3e00)', () => {
130
+ const { parseFloat } = useCborFloat()
131
+
132
+ // Float16: 1.5 = 0xf9 0x3e 0x00
133
+ const result = parseFloat('f93e00')
134
+ expect(result.value).toBe(1.5)
135
+ expect(result.bytesRead).toBe(3)
136
+ })
137
+
138
+ it('should parse 65504.0 (max normal) (0xf9 0x7bff)', () => {
139
+ const { parseFloat } = useCborFloat()
140
+
141
+ // Float16: 65504.0 (max) = 0xf9 0x7b 0xff
142
+ const result = parseFloat('f97bff')
143
+ expect(result.value).toBe(65504.0)
144
+ expect(result.bytesRead).toBe(3)
145
+ })
146
+
147
+ it('should parse Infinity (0xf9 0x7c00)', () => {
148
+ const { parseFloat } = useCborFloat()
149
+
150
+ // Float16: +Infinity = 0xf9 0x7c 0x00
151
+ const result = parseFloat('f97c00')
152
+ expect(result.value).toBe(Infinity)
153
+ expect(result.bytesRead).toBe(3)
154
+ })
155
+
156
+ it('should parse -Infinity (0xf9 0xfc00)', () => {
157
+ const { parseFloat } = useCborFloat()
158
+
159
+ // Float16: -Infinity = 0xf9 0xfc 0x00
160
+ const result = parseFloat('f9fc00')
161
+ expect(result.value).toBe(-Infinity)
162
+ expect(result.bytesRead).toBe(3)
163
+ })
164
+
165
+ it('should parse NaN (0xf9 0x7e00)', () => {
166
+ const { parseFloat } = useCborFloat()
167
+
168
+ // Float16: NaN = 0xf9 0x7e 0x00
169
+ const result = parseFloat('f97e00')
170
+ expect(Number.isNaN(result.value)).toBe(true)
171
+ expect(result.bytesRead).toBe(3)
172
+ })
173
+
174
+ it('should parse smallest positive subnormal (0xf9 0x0001)', () => {
175
+ const { parseFloat } = useCborFloat()
176
+
177
+ // Float16: smallest positive subnormal = 0xf9 0x00 0x01
178
+ // Formula: 2^-14 * (1/1024) = 2^-24 ≈ 5.960464477539063e-8
179
+ const result = parseFloat('f90001')
180
+ expect(result.value).toBeCloseTo(5.960464477539063e-8, 15)
181
+ expect(result.bytesRead).toBe(3)
182
+ })
183
+ })
184
+
185
+ describe('Float32 (IEEE 754 single precision)', () => {
186
+ it('should parse 0.0 (0xfa 0x00000000)', () => {
187
+ const { parseFloat } = useCborFloat()
188
+
189
+ // Float32: 0.0 = 0xfa 0x00 0x00 0x00 0x00
190
+ const result = parseFloat('fa00000000')
191
+ expect(result.value).toBe(0.0)
192
+ expect(result.bytesRead).toBe(5)
193
+ })
194
+
195
+ it('should parse 1.0 (0xfa 0x3f800000)', () => {
196
+ const { parseFloat } = useCborFloat()
197
+
198
+ // Float32: 1.0 = 0xfa 0x3f 0x80 0x00 0x00
199
+ const result = parseFloat('fa3f800000')
200
+ expect(result.value).toBe(1.0)
201
+ expect(result.bytesRead).toBe(5)
202
+ })
203
+
204
+ it('should parse -1.0 (0xfa 0xbf800000)', () => {
205
+ const { parseFloat } = useCborFloat()
206
+
207
+ // Float32: -1.0 = 0xfa 0xbf 0x80 0x00 0x00
208
+ const result = parseFloat('fabf800000')
209
+ expect(result.value).toBe(-1.0)
210
+ expect(result.bytesRead).toBe(5)
211
+ })
212
+
213
+ it('should parse 3.4028234663852886e+38 (max) (0xfa 0x7f7fffff)', () => {
214
+ const { parseFloat } = useCborFloat()
215
+
216
+ // Float32: max value = 0xfa 0x7f 0x7f 0xff 0xff
217
+ const result = parseFloat('fa7f7fffff')
218
+ expect(result.value).toBeCloseTo(3.4028234663852886e+38, -30)
219
+ expect(result.bytesRead).toBe(5)
220
+ })
221
+
222
+ it('should parse Infinity (0xfa 0x7f800000)', () => {
223
+ const { parseFloat } = useCborFloat()
224
+
225
+ // Float32: +Infinity = 0xfa 0x7f 0x80 0x00 0x00
226
+ const result = parseFloat('fa7f800000')
227
+ expect(result.value).toBe(Infinity)
228
+ expect(result.bytesRead).toBe(5)
229
+ })
230
+
231
+ it('should parse -Infinity (0xfa 0xff800000)', () => {
232
+ const { parseFloat } = useCborFloat()
233
+
234
+ // Float32: -Infinity = 0xfa 0xff 0x80 0x00 0x00
235
+ const result = parseFloat('faff800000')
236
+ expect(result.value).toBe(-Infinity)
237
+ expect(result.bytesRead).toBe(5)
238
+ })
239
+
240
+ it('should parse NaN (0xfa 0x7fc00000)', () => {
241
+ const { parseFloat } = useCborFloat()
242
+
243
+ // Float32: NaN = 0xfa 0x7fc00000
244
+ const result = parseFloat('fa7fc00000')
245
+ expect(Number.isNaN(result.value)).toBe(true)
246
+ expect(result.bytesRead).toBe(5)
247
+ })
248
+
249
+ it('should parse 100000.0', () => {
250
+ const { parseFloat } = useCborFloat()
251
+
252
+ // Float32: 100000.0 = 0xfa 0x47 0xc3 0x50 0x00
253
+ const result = parseFloat('fa47c35000')
254
+ expect(result.value).toBe(100000.0)
255
+ expect(result.bytesRead).toBe(5)
256
+ })
257
+ })
258
+
259
+ describe('Float64 (IEEE 754 double precision)', () => {
260
+ it('should parse 0.0 (0xfb 0x0000000000000000)', () => {
261
+ const { parseFloat } = useCborFloat()
262
+
263
+ // Float64: 0.0 = 0xfb + 8 bytes of zero
264
+ const result = parseFloat('fb0000000000000000')
265
+ expect(result.value).toBe(0.0)
266
+ expect(result.bytesRead).toBe(9)
267
+ })
268
+
269
+ it('should parse 1.0 (0xfb 0x3ff0000000000000)', () => {
270
+ const { parseFloat } = useCborFloat()
271
+
272
+ // Float64: 1.0 = 0xfb 0x3ff0000000000000
273
+ const result = parseFloat('fb3ff0000000000000')
274
+ expect(result.value).toBe(1.0)
275
+ expect(result.bytesRead).toBe(9)
276
+ })
277
+
278
+ it('should parse -1.0 (0xfb 0xbff0000000000000)', () => {
279
+ const { parseFloat } = useCborFloat()
280
+
281
+ // Float64: -1.0 = 0xfb 0xbff0000000000000
282
+ const result = parseFloat('fbbff0000000000000')
283
+ expect(result.value).toBe(-1.0)
284
+ expect(result.bytesRead).toBe(9)
285
+ })
286
+
287
+ it('should parse 1.1 (0xfb 0x3ff199999999999a)', () => {
288
+ const { parseFloat } = useCborFloat()
289
+
290
+ // Float64: 1.1 = 0xfb 0x3ff199999999999a
291
+ const result = parseFloat('fb3ff199999999999a')
292
+ expect(result.value).toBe(1.1)
293
+ expect(result.bytesRead).toBe(9)
294
+ })
295
+
296
+ it('should parse -4.1 (0xfb 0xc010666666666666)', () => {
297
+ const { parseFloat } = useCborFloat()
298
+
299
+ // Float64: -4.1 = 0xfb 0xc010666666666666
300
+ const result = parseFloat('fbc010666666666666')
301
+ expect(result.value).toBe(-4.1)
302
+ expect(result.bytesRead).toBe(9)
303
+ })
304
+
305
+ it('should parse 1.0e+300 (0xfb 0x7e37e43c8800759c)', () => {
306
+ const { parseFloat } = useCborFloat()
307
+
308
+ // Float64: 1.0e+300 = 0xfb 0x7e37e43c8800759c
309
+ const result = parseFloat('fb7e37e43c8800759c')
310
+ expect(result.value).toBe(1.0e+300)
311
+ expect(result.bytesRead).toBe(9)
312
+ })
313
+
314
+ it('should parse Infinity (0xfb 0x7ff0000000000000)', () => {
315
+ const { parseFloat } = useCborFloat()
316
+
317
+ // Float64: +Infinity = 0xfb 0x7ff0000000000000
318
+ const result = parseFloat('fb7ff0000000000000')
319
+ expect(result.value).toBe(Infinity)
320
+ expect(result.bytesRead).toBe(9)
321
+ })
322
+
323
+ it('should parse -Infinity (0xfb 0xfff0000000000000)', () => {
324
+ const { parseFloat } = useCborFloat()
325
+
326
+ // Float64: -Infinity = 0xfb 0xfff0000000000000
327
+ const result = parseFloat('fbfff0000000000000')
328
+ expect(result.value).toBe(-Infinity)
329
+ expect(result.bytesRead).toBe(9)
330
+ })
331
+
332
+ it('should parse NaN (0xfb 0x7ff8000000000000)', () => {
333
+ const { parseFloat } = useCborFloat()
334
+
335
+ // Float64: NaN = 0xfb 0x7ff8000000000000
336
+ const result = parseFloat('fb7ff8000000000000')
337
+ expect(Number.isNaN(result.value)).toBe(true)
338
+ expect(result.bytesRead).toBe(9)
339
+ })
340
+ })
341
+
342
+ describe('Auto-detect parse function', () => {
343
+ it('should auto-detect and parse false', () => {
344
+ const { parse } = useCborFloat()
345
+
346
+ const result = parse('f4')
347
+ expect(result.value).toBe(false)
348
+ expect(result.bytesRead).toBe(1)
349
+ })
350
+
351
+ it('should auto-detect and parse true', () => {
352
+ const { parse } = useCborFloat()
353
+
354
+ const result = parse('f5')
355
+ expect(result.value).toBe(true)
356
+ expect(result.bytesRead).toBe(1)
357
+ })
358
+
359
+ it('should auto-detect and parse null', () => {
360
+ const { parse } = useCborFloat()
361
+
362
+ const result = parse('f6')
363
+ expect(result.value).toBe(null)
364
+ expect(result.bytesRead).toBe(1)
365
+ })
366
+
367
+ it('should auto-detect and parse undefined', () => {
368
+ const { parse } = useCborFloat()
369
+
370
+ const result = parse('f7')
371
+ expect(result.value).toBe(undefined)
372
+ expect(result.bytesRead).toBe(1)
373
+ })
374
+
375
+ it('should auto-detect and parse Float16', () => {
376
+ const { parse } = useCborFloat()
377
+
378
+ const result = parse('f93c00')
379
+ expect(result.value).toBe(1.0)
380
+ expect(result.bytesRead).toBe(3)
381
+ })
382
+
383
+ it('should auto-detect and parse Float32', () => {
384
+ const { parse } = useCborFloat()
385
+
386
+ const result = parse('fa3f800000')
387
+ expect(result.value).toBe(1.0)
388
+ expect(result.bytesRead).toBe(5)
389
+ })
390
+
391
+ it('should auto-detect and parse Float64', () => {
392
+ const { parse } = useCborFloat()
393
+
394
+ const result = parse('fb3ff0000000000000')
395
+ expect(result.value).toBe(1.0)
396
+ expect(result.bytesRead).toBe(9)
397
+ })
398
+
399
+ it('should auto-detect and parse unassigned simple value', () => {
400
+ const { parse } = useCborFloat()
401
+
402
+ const result = parse('e0')
403
+ expect(result.value).toEqual({ simpleValue: 0 })
404
+ expect(result.bytesRead).toBe(1)
405
+ })
406
+ })
407
+
408
+ describe('Error Handling', () => {
409
+ it('should throw error for invalid major type', () => {
410
+ const { parse } = useCborFloat()
411
+
412
+ // 0x00 = integer 0, not MT 7
413
+ expect(() => parse('00')).toThrow('Expected major type 7')
414
+ })
415
+
416
+ it('should throw error for reserved additional info values', () => {
417
+ const { parse } = useCborFloat()
418
+
419
+ // 0xfc = MT 7, AI 28 (reserved)
420
+ expect(() => parse('fc')).toThrow()
421
+ })
422
+
423
+ it('should throw error for truncated Float16', () => {
424
+ const { parseFloat } = useCborFloat()
425
+
426
+ // 0xf9 = Float16 indicator, but no data
427
+ expect(() => parseFloat('f9')).toThrow()
428
+ })
429
+
430
+ it('should throw error for truncated Float32', () => {
431
+ const { parseFloat } = useCborFloat()
432
+
433
+ // 0xfa = Float32 indicator, incomplete data
434
+ expect(() => parseFloat('fa3f8000')).toThrow()
435
+ })
436
+
437
+ it('should throw error for truncated Float64', () => {
438
+ const { parseFloat } = useCborFloat()
439
+
440
+ // 0xfb = Float64 indicator, incomplete data
441
+ expect(() => parseFloat('fb3ff00000')).toThrow()
442
+ })
443
+ })
444
+
445
+ describe('RFC 8949 Appendix A Examples', () => {
446
+ it('should parse RFC example: false', () => {
447
+ const { parse } = useCborFloat()
448
+
449
+ const result = parse('f4')
450
+ expect(result.value).toBe(false)
451
+ })
452
+
453
+ it('should parse RFC example: true', () => {
454
+ const { parse } = useCborFloat()
455
+
456
+ const result = parse('f5')
457
+ expect(result.value).toBe(true)
458
+ })
459
+
460
+ it('should parse RFC example: null', () => {
461
+ const { parse } = useCborFloat()
462
+
463
+ const result = parse('f6')
464
+ expect(result.value).toBe(null)
465
+ })
466
+
467
+ it('should parse RFC example: undefined', () => {
468
+ const { parse } = useCborFloat()
469
+
470
+ const result = parse('f7')
471
+ expect(result.value).toBe(undefined)
472
+ })
473
+
474
+ it('should parse RFC example: Float16 0.0', () => {
475
+ const { parse } = useCborFloat()
476
+
477
+ const result = parse('f90000')
478
+ expect(result.value).toBe(0.0)
479
+ })
480
+
481
+ it('should parse RFC example: Float32 100000.0', () => {
482
+ const { parse } = useCborFloat()
483
+
484
+ const result = parse('fa47c35000')
485
+ expect(result.value).toBe(100000.0)
486
+ })
487
+
488
+ it('should parse RFC example: Float64 1.1', () => {
489
+ const { parse } = useCborFloat()
490
+
491
+ const result = parse('fb3ff199999999999a')
492
+ expect(result.value).toBe(1.1)
493
+ })
494
+
495
+ it('should parse RFC example: Float64 1.0e+300', () => {
496
+ const { parse } = useCborFloat()
497
+
498
+ const result = parse('fb7e37e43c8800759c')
499
+ expect(result.value).toBe(1.0e+300)
500
+ })
501
+ })
502
+ })
@@ -0,0 +1,139 @@
1
+ /**
2
+ * CBOR Integer Parser Error Handling Tests
3
+ * Tests all error cases and edge cases for 100% code coverage
4
+ */
5
+
6
+ import { describe, it, expect } from 'vitest'
7
+ import { useCborInteger } from '../composables/useCborInteger'
8
+
9
+ describe('useCborInteger - Error Handling', () => {
10
+ describe('Invalid Additional Info', () => {
11
+ it('should throw error for reserved additional info 28', () => {
12
+ const { parseInteger } = useCborInteger()
13
+ // MT 0, AI 28 (0x1c) - reserved
14
+ expect(() => parseInteger('1c')).toThrow('Invalid additional info: 28')
15
+ })
16
+
17
+ it('should throw error for reserved additional info 29', () => {
18
+ const { parseInteger } = useCborInteger()
19
+ // MT 0, AI 29 (0x1d) - reserved
20
+ expect(() => parseInteger('1d')).toThrow('Invalid additional info: 29')
21
+ })
22
+
23
+ it('should throw error for reserved additional info 30', () => {
24
+ const { parseInteger } = useCborInteger()
25
+ // MT 0, AI 30 (0x1e) - reserved
26
+ expect(() => parseInteger('1e')).toThrow('Invalid additional info: 30')
27
+ })
28
+
29
+ it('should throw error for break marker 31', () => {
30
+ const { parseInteger } = useCborInteger()
31
+ // MT 0, AI 31 (0x1f) - break marker, invalid for integers
32
+ expect(() => parseInteger('1f')).toThrow('Invalid additional info: 31')
33
+ })
34
+ })
35
+
36
+ describe('Wrong Major Type', () => {
37
+ it('should throw error when major type is 2 (byte string)', () => {
38
+ const { parseInteger } = useCborInteger()
39
+ // MT 2 (byte string) should not be parsed as integer
40
+ expect(() => parseInteger('40')).toThrow('Expected major type 0 or 1, got 2')
41
+ })
42
+
43
+ it('should throw error when major type is 3 (text string)', () => {
44
+ const { parseInteger } = useCborInteger()
45
+ // MT 3 (text string) should not be parsed as integer
46
+ expect(() => parseInteger('60')).toThrow('Expected major type 0 or 1, got 3')
47
+ })
48
+
49
+ it('should throw error when major type is 4 (array)', () => {
50
+ const { parseInteger } = useCborInteger()
51
+ // MT 4 (array) should not be parsed as integer
52
+ expect(() => parseInteger('80')).toThrow('Expected major type 0 or 1, got 4')
53
+ })
54
+
55
+ it('should throw error when major type is 7 (simple/float)', () => {
56
+ const { parseInteger } = useCborInteger()
57
+ // MT 7 (simple value) should not be parsed as integer
58
+ expect(() => parseInteger('f4')).toThrow('Expected major type 0 or 1, got 7')
59
+ })
60
+ })
61
+
62
+ describe('BigInt Conversion Edge Cases', () => {
63
+ it('should convert large negative BigInt to Number when it fits in safe range', () => {
64
+ const { parseInteger } = useCborInteger()
65
+
66
+ // This tests line 80-81: negative BigInt that fits in safe integer
67
+ // The smallest safe negative integer is -9007199254740991 (-(2^53 - 1))
68
+ // We need a CBOR value that produces this
69
+
70
+ // For MT 1, value = -1 - N
71
+ // We want -9007199254740991, so N = 9007199254740990
72
+ // 9007199254740990 = 0x001FFFFFFFFFFFFF - 1 = 0x001FFFFFFFFFFFFE
73
+
74
+ // This requires 8-byte encoding (AI = 27)
75
+ // Hex: 3b (MT 1, AI 27) + 001FFFFFFFFFFFFE
76
+ const result = parseInteger('3b001ffffffffffffe')
77
+
78
+ expect(typeof result.value).toBe('number')
79
+ expect(result.value).toBe(-9007199254740991) // -(2^53 - 1)
80
+ })
81
+
82
+ it('should keep as BigInt when negative value is outside safe range', () => {
83
+ const { parseInteger } = useCborInteger()
84
+
85
+ // Value below Number.MIN_SAFE_INTEGER should remain BigInt
86
+ // For MT 1, value = -1 - N
87
+ // We want something below -9007199254740991
88
+
89
+ // Max uint64 produces -18446744073709551616
90
+ const result = parseInteger('3bffffffffffffffff')
91
+
92
+ expect(typeof result.value).toBe('bigint')
93
+ expect(result.value).toBe(-18446744073709551616n)
94
+ })
95
+
96
+ it('should convert to BigInt when negative number is outside safe range', () => {
97
+ const { parseInteger } = useCborInteger()
98
+
99
+ // This tests line 92: negative number conversion to BigInt
100
+ // We need a case where the raw value is a number, but result is BigInt
101
+ // This happens when rawValue fits in Number but result doesn't
102
+
103
+ // For MT 1 with AI 26 (4 bytes): max is 4294967295
104
+ // Result: -1 - 4294967295 = -4294967296 (still within safe integer range)
105
+ // We need AI 27 (8 bytes) for this edge case
106
+
107
+ // Let's use a value that creates a negative number outside safe range
108
+ // Raw value: 9007199254740992 (2^53, just beyond MAX_SAFE_INTEGER)
109
+ // Result: -1 - 9007199254740992 = -9007199254740993 (beyond MIN_SAFE_INTEGER)
110
+
111
+ const result = parseInteger('3b0020000000000000')
112
+
113
+ expect(typeof result.value).toBe('bigint')
114
+ expect(result.value).toBe(-9007199254740993n)
115
+ })
116
+ })
117
+
118
+ describe('All Additional Info Values Coverage', () => {
119
+ it('should parse all valid additional info values (0-27)', () => {
120
+ const { parseInteger } = useCborInteger()
121
+
122
+ // AI 0-23: direct encoding
123
+ expect(parseInteger('00').value).toBe(0)
124
+ expect(parseInteger('17').value).toBe(23)
125
+
126
+ // AI 24: 1 byte
127
+ expect(parseInteger('1818').value).toBe(24)
128
+
129
+ // AI 25: 2 bytes
130
+ expect(parseInteger('190100').value).toBe(256)
131
+
132
+ // AI 26: 4 bytes
133
+ expect(parseInteger('1a00010000').value).toBe(65536)
134
+
135
+ // AI 27: 8 bytes
136
+ expect(parseInteger('1b0000000100000000').value).toBe(4294967296)
137
+ })
138
+ })
139
+ })