@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.
- package/CHANGELOG.md +64 -0
- package/LICENSE +674 -0
- package/README.md +345 -0
- package/dist/chunk-2FUTHZQQ.cjs +755 -0
- package/dist/chunk-2FUTHZQQ.cjs.map +1 -0
- package/dist/chunk-2HBCILJS.cjs +2034 -0
- package/dist/chunk-2HBCILJS.cjs.map +1 -0
- package/dist/chunk-7CFYWHS6.js +742 -0
- package/dist/chunk-7CFYWHS6.js.map +1 -0
- package/dist/chunk-PD72MVTX.cjs +160 -0
- package/dist/chunk-PD72MVTX.cjs.map +1 -0
- package/dist/chunk-ZDZ2B5PE.js +149 -0
- package/dist/chunk-ZDZ2B5PE.js.map +1 -0
- package/dist/chunk-ZRPJUEIZ.js +2020 -0
- package/dist/chunk-ZRPJUEIZ.js.map +1 -0
- package/dist/encoder/index.cjs +57 -0
- package/dist/encoder/index.cjs.map +1 -0
- package/dist/encoder/index.d.cts +72 -0
- package/dist/encoder/index.d.ts +72 -0
- package/dist/encoder/index.js +4 -0
- package/dist/encoder/index.js.map +1 -0
- package/dist/index.cjs +606 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +494 -0
- package/dist/index.d.ts +494 -0
- package/dist/index.js +523 -0
- package/dist/index.js.map +1 -0
- package/dist/metafile-cjs.json +1 -0
- package/dist/metafile-esm.json +1 -0
- package/dist/parser/index.cjs +85 -0
- package/dist/parser/index.cjs.map +1 -0
- package/dist/parser/index.d.cts +72 -0
- package/dist/parser/index.d.ts +72 -0
- package/dist/parser/index.js +4 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/types-DvNlfbKB.d.cts +301 -0
- package/dist/types-DvNlfbKB.d.ts +301 -0
- package/dist/useCborSimpleEncoder-ButVU988.d.cts +268 -0
- package/dist/useCborSimpleEncoder-TVxzNJ_9.d.ts +268 -0
- package/dist/useCborTag-B_iaShG6.d.ts +142 -0
- package/dist/useCborTag-BfTIV8HM.d.cts +142 -0
- package/package.json +102 -0
- package/src/__tests__/public-api.test.ts +326 -0
- package/src/encoder/__tests__/cbor-collection-encoder.test.ts +331 -0
- package/src/encoder/__tests__/cbor-integer-encoder.test.ts +283 -0
- package/src/encoder/__tests__/cbor-simple-encoder.test.ts +224 -0
- package/src/encoder/__tests__/cbor-string-encoder.test.ts +345 -0
- package/src/encoder/__tests__/cbor-tag-encoder.test.ts +565 -0
- package/src/encoder/composables/#useCborTagEncoder.ts# +158 -0
- package/src/encoder/composables/useCborCollectionEncoder.ts +424 -0
- package/src/encoder/composables/useCborEncoder.ts +203 -0
- package/src/encoder/composables/useCborIntegerEncoder.ts +188 -0
- package/src/encoder/composables/useCborSimpleEncoder.ts +266 -0
- package/src/encoder/composables/useCborStringEncoder.ts +266 -0
- package/src/encoder/composables/useCborTagEncoder.ts +158 -0
- package/src/encoder/index.ts +35 -0
- package/src/encoder/types.ts +88 -0
- package/src/encoder/utils.ts +80 -0
- package/src/index.ts +434 -0
- package/src/parser/__tests__/ast-tree-structure.test.ts +311 -0
- package/src/parser/__tests__/cbor-collection-errors.test.ts +296 -0
- package/src/parser/__tests__/cbor-collection.test.ts +369 -0
- package/src/parser/__tests__/cbor-deterministic-encoding.test.ts +432 -0
- package/src/parser/__tests__/cbor-diagnostic.test.ts +333 -0
- package/src/parser/__tests__/cbor-duplicate-keys.test.ts +235 -0
- package/src/parser/__tests__/cbor-float-errors.test.ts +222 -0
- package/src/parser/__tests__/cbor-float.test.ts +502 -0
- package/src/parser/__tests__/cbor-integer-errors.test.ts +139 -0
- package/src/parser/__tests__/cbor-integer.test.ts +200 -0
- package/src/parser/__tests__/cbor-map-duplicate-keys.test.ts +403 -0
- package/src/parser/__tests__/cbor-parser-errors.test.ts +126 -0
- package/src/parser/__tests__/cbor-security-dos-protection.test.ts +503 -0
- package/src/parser/__tests__/cbor-sequences.test.ts +150 -0
- package/src/parser/__tests__/cbor-source-map.test.ts +321 -0
- package/src/parser/__tests__/cbor-standard-tags.test.ts +340 -0
- package/src/parser/__tests__/cbor-string-errors.test.ts +227 -0
- package/src/parser/__tests__/cbor-string.test.ts +224 -0
- package/src/parser/__tests__/cbor-tag-advanced.test.ts +500 -0
- package/src/parser/__tests__/cbor-tag-errors.test.ts +447 -0
- package/src/parser/__tests__/cbor-tag-source-map.test.ts +360 -0
- package/src/parser/__tests__/cbor-tag.test.ts +684 -0
- package/src/parser/__tests__/extreme-edge-cases.test.ts +146 -0
- package/src/parser/__tests__/pathBuilder.test.ts +256 -0
- package/src/parser/__tests__/rfc-test-vectors.test.ts +607 -0
- package/src/parser/__tests__/security-limits.test.ts +248 -0
- package/src/parser/__tests__/utils-errors.test.ts +127 -0
- package/src/parser/composables/useCborCollection.ts +509 -0
- package/src/parser/composables/useCborDiagnostic.ts +381 -0
- package/src/parser/composables/useCborFloat.ts +256 -0
- package/src/parser/composables/useCborInteger.ts +114 -0
- package/src/parser/composables/useCborParser.ts +951 -0
- package/src/parser/composables/useCborString.ts +330 -0
- package/src/parser/composables/useCborStringTypes.ts +129 -0
- package/src/parser/composables/useCborTag.ts +739 -0
- package/src/parser/index.ts +56 -0
- package/src/parser/types.ts +371 -0
- package/src/parser/utils/pathBuilder.ts +259 -0
- package/src/parser/utils.ts +398 -0
- package/src/utils/__tests__/logger.test.ts +186 -0
- 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
|
+
})
|