@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,447 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CBOR Tag 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 { useCborTag } from '../composables/useCborTag'
|
|
8
|
+
|
|
9
|
+
describe('useCborTag - Error Handling', () => {
|
|
10
|
+
describe('parseItem - Unexpected End of Buffer', () => {
|
|
11
|
+
it('should throw error when buffer ends before tagged value', () => {
|
|
12
|
+
const { parseTag } = useCborTag()
|
|
13
|
+
|
|
14
|
+
// Tag 0 with no value following
|
|
15
|
+
expect(() => parseTag('c0')).toThrow('Unexpected end of buffer after tag 0')
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
it('should throw error when nested structure is incomplete', () => {
|
|
19
|
+
const { parseTag } = useCborTag()
|
|
20
|
+
|
|
21
|
+
// Tag with array that's incomplete
|
|
22
|
+
// c1 (tag 1) + 82 (array of 2) + 01 (element 1) - missing element 2
|
|
23
|
+
expect(() => parseTag('c18201')).toThrow('Unexpected end of buffer at offset')
|
|
24
|
+
})
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
describe('parseItem - Unknown Major Type', () => {
|
|
28
|
+
it('should never have unknown major type (defensive check)', () => {
|
|
29
|
+
const { parseTag } = useCborTag()
|
|
30
|
+
|
|
31
|
+
// All major types 0-7 should be handled correctly in tagged values
|
|
32
|
+
// MT 0-7 are all valid, so this defensive code path is hard to trigger
|
|
33
|
+
// without mocking, but the code exists for safety
|
|
34
|
+
|
|
35
|
+
// Test that all major types work correctly when tagged
|
|
36
|
+
expect(() => parseTag('c000')).not.toThrow() // Tag(0)
|
|
37
|
+
expect(() => parseTag('c020')).not.toThrow() // Tag(-1)
|
|
38
|
+
expect(() => parseTag('c040')).not.toThrow() // Tag(h'')
|
|
39
|
+
expect(() => parseTag('c060')).not.toThrow() // Tag("")
|
|
40
|
+
expect(() => parseTag('c080')).not.toThrow() // Tag([])
|
|
41
|
+
expect(() => parseTag('c0a0')).not.toThrow() // Tag({})
|
|
42
|
+
expect(() => parseTag('c0c000')).not.toThrow() // Tag(Tag(0))
|
|
43
|
+
expect(() => parseTag('c0f4')).not.toThrow() // Tag(false)
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
describe('parseItem - Simple Values in Tags', () => {
|
|
48
|
+
it('should parse tag with boolean values', () => {
|
|
49
|
+
const { parseTag } = useCborTag()
|
|
50
|
+
|
|
51
|
+
// Tag with false
|
|
52
|
+
const result1 = parseTag('c0f4')
|
|
53
|
+
expect(result1.value).toEqual({ tag: 0, value: false })
|
|
54
|
+
|
|
55
|
+
// Tag with true
|
|
56
|
+
const result2 = parseTag('c0f5')
|
|
57
|
+
expect(result2.value).toEqual({ tag: 0, value: true })
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should parse tag with null', () => {
|
|
61
|
+
const { parseTag } = useCborTag()
|
|
62
|
+
|
|
63
|
+
// Tag with null
|
|
64
|
+
const result = parseTag('c0f6')
|
|
65
|
+
expect(result.value).toEqual({ tag: 0, value: null })
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('should parse tag with undefined', () => {
|
|
69
|
+
const { parseTag } = useCborTag()
|
|
70
|
+
|
|
71
|
+
// Tag with undefined
|
|
72
|
+
const result = parseTag('c0f7')
|
|
73
|
+
expect(result.value).toEqual({ tag: 0, value: undefined })
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('should parse tag with unassigned simple values', () => {
|
|
77
|
+
const { parseTag } = useCborTag()
|
|
78
|
+
|
|
79
|
+
// Tag with simple(16)
|
|
80
|
+
const result = parseTag('c0f0')
|
|
81
|
+
expect(result.value).toEqual({ tag: 0, value: { simpleValue: 16 } })
|
|
82
|
+
})
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
describe('parseArrayInternal - Wrong Major Type', () => {
|
|
86
|
+
it('should throw error when expecting array but gets integer', () => {
|
|
87
|
+
const { parseTag } = useCborTag()
|
|
88
|
+
|
|
89
|
+
// This is hard to trigger directly, but we can test by ensuring
|
|
90
|
+
// arrays in tagged values work correctly
|
|
91
|
+
// Tag 0 with array should work
|
|
92
|
+
expect(() => parseTag('c080')).not.toThrow()
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
describe('parseArrayInternal - All Length Encodings', () => {
|
|
97
|
+
it('should parse tag with 1-byte array length (AI 24)', () => {
|
|
98
|
+
const { parseTag } = useCborTag()
|
|
99
|
+
|
|
100
|
+
// Tag 0 with array of 24 elements (AI 24)
|
|
101
|
+
// c0 (tag 0) + 9818 (array, 24 elements, 1-byte length) + 24x 00
|
|
102
|
+
const result = parseTag('c09818' + '00'.repeat(24))
|
|
103
|
+
expect(result.value.value).toHaveLength(24)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
it('should parse tag with 2-byte array length (AI 25)', () => {
|
|
107
|
+
const { parseTag } = useCborTag()
|
|
108
|
+
|
|
109
|
+
// Tag 0 with array of 256 elements (AI 25)
|
|
110
|
+
// c0 (tag 0) + 990100 (array, 256 elements, 2-byte length) + 256x 00
|
|
111
|
+
const result = parseTag('c0990100' + '00'.repeat(256))
|
|
112
|
+
expect(result.value.value).toHaveLength(256)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
it('should parse tag with 4-byte array length (AI 26)', () => {
|
|
116
|
+
const { parseTag } = useCborTag()
|
|
117
|
+
|
|
118
|
+
// Tag 0 with array of 1000 elements (AI 26)
|
|
119
|
+
// c0 (tag 0) + 9a000003e8 (array, 1000 elements, 4-byte length) + 1000x 00
|
|
120
|
+
const result = parseTag('c09a000003e8' + '00'.repeat(1000))
|
|
121
|
+
expect(result.value.value).toHaveLength(1000)
|
|
122
|
+
})
|
|
123
|
+
|
|
124
|
+
it('should parse tag with 8-byte array length (AI 27)', () => {
|
|
125
|
+
const { parseTag } = useCborTag()
|
|
126
|
+
|
|
127
|
+
// Tag 0 with array of 100 elements (AI 27, 8-byte length)
|
|
128
|
+
// c0 (tag 0) + 9b0000000000000064 (array, 100 elements, 8-byte length) + 100x 00
|
|
129
|
+
const result = parseTag('c09b0000000000000064' + '00'.repeat(100))
|
|
130
|
+
expect(result.value.value).toHaveLength(100)
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
it('should throw error for reserved AI 28 in array', () => {
|
|
134
|
+
const { parseTag } = useCborTag()
|
|
135
|
+
|
|
136
|
+
// Tag 0 with array using reserved AI 28
|
|
137
|
+
// c0 (tag 0) + 9c (array, AI 28 - reserved)
|
|
138
|
+
expect(() => parseTag('c09c')).toThrow('Invalid additional info for array: 28')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('should throw error for reserved AI 29 in array', () => {
|
|
142
|
+
const { parseTag } = useCborTag()
|
|
143
|
+
|
|
144
|
+
// Tag 0 with array using reserved AI 29
|
|
145
|
+
expect(() => parseTag('c09d')).toThrow('Invalid additional info for array: 29')
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
it('should throw error for reserved AI 30 in array', () => {
|
|
149
|
+
const { parseTag } = useCborTag()
|
|
150
|
+
|
|
151
|
+
// Tag 0 with array using reserved AI 30
|
|
152
|
+
expect(() => parseTag('c09e')).toThrow('Invalid additional info for array: 30')
|
|
153
|
+
})
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
describe('parseArrayInternal - Indefinite Length', () => {
|
|
157
|
+
it('should parse tag with indefinite-length array', () => {
|
|
158
|
+
const { parseTag } = useCborTag()
|
|
159
|
+
|
|
160
|
+
// Tag 0 with indefinite array [_ 1, 2, 3]
|
|
161
|
+
// c0 (tag 0) + 9f (indefinite array) + 01 02 03 + ff (break)
|
|
162
|
+
const result = parseTag('c09f010203ff')
|
|
163
|
+
expect(Array.isArray(result.value.value)).toBe(true)
|
|
164
|
+
const arr = result.value.value as any[]
|
|
165
|
+
expect(arr[0]).toBe(1)
|
|
166
|
+
expect(arr[1]).toBe(2)
|
|
167
|
+
expect(arr[2]).toBe(3)
|
|
168
|
+
})
|
|
169
|
+
|
|
170
|
+
it('should parse tag with empty indefinite array', () => {
|
|
171
|
+
const { parseTag } = useCborTag()
|
|
172
|
+
|
|
173
|
+
// Tag 0 with empty indefinite array
|
|
174
|
+
// c0 (tag 0) + 9f (indefinite array) + ff (break)
|
|
175
|
+
const result = parseTag('c09fff')
|
|
176
|
+
expect(Array.isArray(result.value.value)).toBe(true)
|
|
177
|
+
expect(result.value.value).toHaveLength(0)
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
it('should parse nested indefinite arrays in tag', () => {
|
|
181
|
+
const { parseTag } = useCborTag()
|
|
182
|
+
|
|
183
|
+
// Tag 0 with nested indefinite arrays
|
|
184
|
+
// c0 (tag 0) + 9f (indefinite) + 9f 01 ff (nested [_ 1]) + ff (break)
|
|
185
|
+
const result = parseTag('c09f9f01ffff')
|
|
186
|
+
expect(Array.isArray(result.value.value)).toBe(true)
|
|
187
|
+
const arr = result.value.value as any[]
|
|
188
|
+
expect(arr).toHaveLength(1)
|
|
189
|
+
expect(Array.isArray(arr[0])).toBe(true)
|
|
190
|
+
expect(arr[0][0]).toBe(1)
|
|
191
|
+
})
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
describe('parseMapInternal - Wrong Major Type', () => {
|
|
195
|
+
it('should parse tag with map correctly', () => {
|
|
196
|
+
const { parseTag } = useCborTag()
|
|
197
|
+
|
|
198
|
+
// Tag 0 with map
|
|
199
|
+
expect(() => parseTag('c0a0')).not.toThrow()
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
describe('parseMapInternal - All Length Encodings', () => {
|
|
204
|
+
it('should parse tag with 1-byte map length (AI 24)', () => {
|
|
205
|
+
const { parseTag } = useCborTag()
|
|
206
|
+
|
|
207
|
+
// Tag 0 with map of 24 entries (AI 24)
|
|
208
|
+
// c0 (tag 0) + b818 (map, 24 entries, 1-byte length) + 24x unique key-value pairs
|
|
209
|
+
// Use keys 0-23 which are safe (direct encoding, no reserved values)
|
|
210
|
+
const entries = Array.from({ length: 24 }, (_, i) => {
|
|
211
|
+
// Use keys 0-23, values 0-23 (but different from key)
|
|
212
|
+
const key = i.toString(16).padStart(2, '0')
|
|
213
|
+
const value = ((i + 1) % 24).toString(16).padStart(2, '0')
|
|
214
|
+
return key + value
|
|
215
|
+
}).join('')
|
|
216
|
+
const result = parseTag('c0b818' + entries)
|
|
217
|
+
// Should have 24 entries (keys 0-23 are unique)
|
|
218
|
+
expect(result.value.value.size).toBe(24)
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
it('should parse tag with 2-byte map length (AI 25)', () => {
|
|
222
|
+
const { parseTag } = useCborTag()
|
|
223
|
+
|
|
224
|
+
// Tag 0 with map of 100 entries (AI 25)
|
|
225
|
+
// c0 (tag 0) + b90064 (map, 100 entries, 2-byte length) + 100x unique key-value pairs
|
|
226
|
+
// Use 1-byte length encoding for keys to avoid reserved AI values
|
|
227
|
+
const entries = Array.from({ length: 100 }, (_, i) => {
|
|
228
|
+
// Use AI 24 encoding: 1818 for value 24, 1819 for 25, etc.
|
|
229
|
+
const keyHex = '18' + (24 + i).toString(16).padStart(2, '0')
|
|
230
|
+
const valueHex = '18' + (124 + i).toString(16).padStart(2, '0')
|
|
231
|
+
return keyHex + valueHex
|
|
232
|
+
}).join('')
|
|
233
|
+
const result = parseTag('c0b90064' + entries)
|
|
234
|
+
expect(result.value.value.size).toBe(100)
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
it('should parse tag with 4-byte map length (AI 26)', () => {
|
|
238
|
+
const { parseTag } = useCborTag()
|
|
239
|
+
|
|
240
|
+
// Tag 0 with map of 50 entries (AI 26, 4-byte length)
|
|
241
|
+
// c0 (tag 0) + ba00000032 (map, 50 entries, 4-byte length) + 50x unique key-value pairs
|
|
242
|
+
const entries = Array.from({ length: 50 }, (_, i) => {
|
|
243
|
+
const keyHex = '18' + (30 + i).toString(16).padStart(2, '0')
|
|
244
|
+
const valueHex = '18' + (80 + i).toString(16).padStart(2, '0')
|
|
245
|
+
return keyHex + valueHex
|
|
246
|
+
}).join('')
|
|
247
|
+
const result = parseTag('c0ba00000032' + entries)
|
|
248
|
+
expect(result.value.value.size).toBe(50)
|
|
249
|
+
})
|
|
250
|
+
|
|
251
|
+
it('should parse tag with 8-byte map length (AI 27)', () => {
|
|
252
|
+
const { parseTag } = useCborTag()
|
|
253
|
+
|
|
254
|
+
// Tag 0 with map of 30 entries (AI 27, 8-byte length)
|
|
255
|
+
// c0 (tag 0) + bb000000000000001e (map, 30 entries, 8-byte length) + 30x unique key-value pairs
|
|
256
|
+
const entries = Array.from({ length: 30 }, (_, i) => {
|
|
257
|
+
const keyHex = '18' + (40 + i).toString(16).padStart(2, '0')
|
|
258
|
+
const valueHex = '18' + (70 + i).toString(16).padStart(2, '0')
|
|
259
|
+
return keyHex + valueHex
|
|
260
|
+
}).join('')
|
|
261
|
+
const result = parseTag('c0bb000000000000001e' + entries)
|
|
262
|
+
expect(result.value.value.size).toBe(30)
|
|
263
|
+
})
|
|
264
|
+
|
|
265
|
+
it('should throw error for reserved AI 28 in map', () => {
|
|
266
|
+
const { parseTag } = useCborTag()
|
|
267
|
+
|
|
268
|
+
// Tag 0 with map using reserved AI 28
|
|
269
|
+
// c0 (tag 0) + bc (map, AI 28 - reserved)
|
|
270
|
+
expect(() => parseTag('c0bc')).toThrow('Invalid additional info for map: 28')
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
it('should throw error for reserved AI 29 in map', () => {
|
|
274
|
+
const { parseTag } = useCborTag()
|
|
275
|
+
|
|
276
|
+
// Tag 0 with map using reserved AI 29
|
|
277
|
+
expect(() => parseTag('c0bd')).toThrow('Invalid additional info for map: 29')
|
|
278
|
+
})
|
|
279
|
+
|
|
280
|
+
it('should throw error for reserved AI 30 in map', () => {
|
|
281
|
+
const { parseTag } = useCborTag()
|
|
282
|
+
|
|
283
|
+
// Tag 0 with map using reserved AI 30
|
|
284
|
+
expect(() => parseTag('c0be')).toThrow('Invalid additional info for map: 30')
|
|
285
|
+
})
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
describe('parseMapInternal - Indefinite Length', () => {
|
|
289
|
+
it('should parse tag with indefinite-length map', () => {
|
|
290
|
+
const { parseTag } = useCborTag()
|
|
291
|
+
|
|
292
|
+
// Tag 0 with indefinite map {_ 1: 2, 3: 4}
|
|
293
|
+
// c0 (tag 0) + bf (indefinite map) + 01 02 03 04 + ff (break)
|
|
294
|
+
const result = parseTag('c0bf01020304ff')
|
|
295
|
+
expect(result.value.value).toEqual(new Map([[1, 2], [3, 4]]))
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
it('should parse tag with empty indefinite map', () => {
|
|
299
|
+
const { parseTag } = useCborTag()
|
|
300
|
+
|
|
301
|
+
// Tag 0 with empty indefinite map
|
|
302
|
+
// c0 (tag 0) + bf (indefinite map) + ff (break)
|
|
303
|
+
const result = parseTag('c0bfff')
|
|
304
|
+
expect(result.value.value).toEqual(new Map())
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
it('should parse nested indefinite maps in tag', () => {
|
|
308
|
+
const { parseTag } = useCborTag()
|
|
309
|
+
|
|
310
|
+
// Tag 0 with nested indefinite map
|
|
311
|
+
// c0 (tag 0) + bf (indefinite) + 01 (key) + bf 02 03 ff (nested map) + ff (break)
|
|
312
|
+
const result = parseTag('c0bf01bf0203ffff')
|
|
313
|
+
expect(result.value.value).toEqual(new Map([[1, new Map([[2, 3]])]]))
|
|
314
|
+
})
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
describe('parseTagNumber - Large Tag Numbers', () => {
|
|
318
|
+
it('should parse tag with 1-byte number (AI 24)', () => {
|
|
319
|
+
const { parseTag } = useCborTag()
|
|
320
|
+
|
|
321
|
+
// Tag 255 (largest 1-byte tag)
|
|
322
|
+
// d8ff (tag 255) + 00 (value)
|
|
323
|
+
const result = parseTag('d8ff00')
|
|
324
|
+
expect(result.value.tag).toBe(255)
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
it('should parse tag with 2-byte number (AI 25)', () => {
|
|
328
|
+
const { parseTag } = useCborTag()
|
|
329
|
+
|
|
330
|
+
// Tag 256 (smallest 2-byte tag)
|
|
331
|
+
// d90100 (tag 256) + 00 (value)
|
|
332
|
+
const result = parseTag('d9010000')
|
|
333
|
+
expect(result.value.tag).toBe(256)
|
|
334
|
+
})
|
|
335
|
+
|
|
336
|
+
it('should parse tag with 4-byte number (AI 26)', () => {
|
|
337
|
+
const { parseTag } = useCborTag()
|
|
338
|
+
|
|
339
|
+
// Tag 70000 (requires 4 bytes)
|
|
340
|
+
// da00011170 (tag 70000) + 00 (value)
|
|
341
|
+
const result = parseTag('da0001117000')
|
|
342
|
+
expect(result.value.tag).toBe(70000)
|
|
343
|
+
})
|
|
344
|
+
|
|
345
|
+
it('should parse tag with 8-byte number (AI 27)', () => {
|
|
346
|
+
const { parseTag } = useCborTag()
|
|
347
|
+
|
|
348
|
+
// Tag with 8-byte number (within safe integer range)
|
|
349
|
+
// db0000000000000064 (tag 100, 8-byte encoding) + 00 (value)
|
|
350
|
+
const result = parseTag('db000000000000006400')
|
|
351
|
+
expect(result.value.tag).toBe(100)
|
|
352
|
+
})
|
|
353
|
+
|
|
354
|
+
it('should throw error for tag number exceeding MAX_SAFE_INTEGER', () => {
|
|
355
|
+
const { parseTag } = useCborTag()
|
|
356
|
+
|
|
357
|
+
// Tag number larger than MAX_SAFE_INTEGER (2^53 - 1)
|
|
358
|
+
// db0020000000000000 (tag 2^53) + 00 (value)
|
|
359
|
+
expect(() => parseTag('db002000000000000000')).toThrow('Tag number')
|
|
360
|
+
expect(() => parseTag('db002000000000000000')).toThrow('exceeds maximum safe integer')
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('should throw error for reserved AI 28', () => {
|
|
364
|
+
const { parseTag } = useCborTag()
|
|
365
|
+
|
|
366
|
+
// MT 6, AI 28 - reserved
|
|
367
|
+
expect(() => parseTag('dc')).toThrow('Reserved additional info 28 for major type 6')
|
|
368
|
+
})
|
|
369
|
+
|
|
370
|
+
it('should throw error for reserved AI 29', () => {
|
|
371
|
+
const { parseTag } = useCborTag()
|
|
372
|
+
|
|
373
|
+
// MT 6, AI 29 - reserved
|
|
374
|
+
expect(() => parseTag('dd')).toThrow('Reserved additional info 29 for major type 6')
|
|
375
|
+
})
|
|
376
|
+
|
|
377
|
+
it('should throw error for reserved AI 30', () => {
|
|
378
|
+
const { parseTag } = useCborTag()
|
|
379
|
+
|
|
380
|
+
// MT 6, AI 30 - reserved
|
|
381
|
+
expect(() => parseTag('de')).toThrow('Reserved additional info 30 for major type 6')
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
it('should throw error for AI 31 (break marker invalid for tags)', () => {
|
|
385
|
+
const { parseTag } = useCborTag()
|
|
386
|
+
|
|
387
|
+
// MT 6, AI 31 - invalid for tags (break marker)
|
|
388
|
+
expect(() => parseTag('df')).toThrow('Invalid additional info 31 for tags')
|
|
389
|
+
})
|
|
390
|
+
})
|
|
391
|
+
|
|
392
|
+
describe('Nested Tags', () => {
|
|
393
|
+
it('should parse doubly-nested tags', () => {
|
|
394
|
+
const { parseTag } = useCborTag()
|
|
395
|
+
|
|
396
|
+
// Tag 0 containing Tag 1 containing 100
|
|
397
|
+
// c0 (tag 0) + c1 (tag 1) + 1864 (100)
|
|
398
|
+
const result = parseTag('c0c11864')
|
|
399
|
+
expect(result.value).toEqual({
|
|
400
|
+
tag: 0,
|
|
401
|
+
value: { tag: 1, value: 100 }
|
|
402
|
+
})
|
|
403
|
+
})
|
|
404
|
+
|
|
405
|
+
it('should parse triply-nested tags', () => {
|
|
406
|
+
const { parseTag } = useCborTag()
|
|
407
|
+
|
|
408
|
+
// Tag 0 containing Tag 1 containing Tag 2 containing 0
|
|
409
|
+
// c0 (tag 0) + c1 (tag 1) + c2 (tag 2) + 00 (0)
|
|
410
|
+
const result = parseTag('c0c1c200')
|
|
411
|
+
expect(result.value).toEqual({
|
|
412
|
+
tag: 0,
|
|
413
|
+
value: { tag: 1, value: { tag: 2, value: 0 } }
|
|
414
|
+
})
|
|
415
|
+
})
|
|
416
|
+
})
|
|
417
|
+
|
|
418
|
+
describe('parse() alias', () => {
|
|
419
|
+
it('should work identically to parseTag', () => {
|
|
420
|
+
const { parse, parseTag } = useCborTag()
|
|
421
|
+
|
|
422
|
+
const hexString = 'c11a514b67b0' // Tag 1 with epoch timestamp
|
|
423
|
+
|
|
424
|
+
const parseResult = parse(hexString)
|
|
425
|
+
const parseTagResult = parseTag(hexString)
|
|
426
|
+
|
|
427
|
+
expect(parseResult.value).toEqual(parseTagResult.value)
|
|
428
|
+
expect(parseResult.bytesRead).toBe(parseTagResult.bytesRead)
|
|
429
|
+
})
|
|
430
|
+
})
|
|
431
|
+
|
|
432
|
+
describe('Wrong Major Type for Tag', () => {
|
|
433
|
+
it('should throw error when major type is not 6', () => {
|
|
434
|
+
const { parseTag } = useCborTag()
|
|
435
|
+
|
|
436
|
+
// MT 0 (integer) is not a tag
|
|
437
|
+
expect(() => parseTag('00')).toThrow('Expected major type 6 (tag), got 0')
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
it('should throw error for MT 7 (simple value)', () => {
|
|
441
|
+
const { parseTag } = useCborTag()
|
|
442
|
+
|
|
443
|
+
// MT 7 (simple value) is not a tag
|
|
444
|
+
expect(() => parseTag('f4')).toThrow('Expected major type 6 (tag), got 7')
|
|
445
|
+
})
|
|
446
|
+
})
|
|
447
|
+
})
|