@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,360 @@
1
+ /**
2
+ * Tag Source Map Generation Test Suite
3
+ * Tests hierarchical source map generation for nested tagged values
4
+ */
5
+
6
+ import { describe, it, expect } from 'vitest'
7
+ import { useCborParser } from '../composables/useCborParser'
8
+
9
+ describe('Tag Source Map Generation', () => {
10
+ describe('Simple Tagged Values', () => {
11
+ it('should create source map entry for tag and value', () => {
12
+ const { parseWithSourceMap } = useCborParser()
13
+ // Tag 121 containing integer 42: d8 79 18 2a
14
+ const result = parseWithSourceMap('d879182a')
15
+
16
+ console.log('Source map entries:', result.sourceMap.length)
17
+ console.log(JSON.stringify(result.sourceMap, null, 2))
18
+
19
+ // Should have 2 entries: tag and integer value
20
+ expect(result.sourceMap).toHaveLength(2)
21
+
22
+ // Tag entry (entire structure)
23
+ expect(result.sourceMap[0]).toMatchObject({
24
+ path: '',
25
+ start: 0,
26
+ end: 2,
27
+ majorType: 6,
28
+ type: 'tag(121)'
29
+ })
30
+ expect(result.sourceMap[0].children).toEqual(['.value'])
31
+
32
+ // Value entry (the integer)
33
+ expect(result.sourceMap[1]).toMatchObject({
34
+ path: '.value',
35
+ start: 2,
36
+ end: 4,
37
+ majorType: 0,
38
+ type: 'Unsigned Integer',
39
+ parent: ''
40
+ })
41
+ })
42
+
43
+ it('should handle tag with string value', () => {
44
+ const { parseWithSourceMap } = useCborParser()
45
+ // Tag 0 (date/time) containing "2013-03-21T20:04:00Z"
46
+ const result = parseWithSourceMap('c074323031332d30332d32315432303a30343a30305a')
47
+
48
+ expect(result.sourceMap).toHaveLength(3)
49
+
50
+ expect(result.sourceMap[0]).toMatchObject({
51
+ path: '',
52
+ majorType: 6,
53
+ type: 'tag(0)'
54
+ })
55
+
56
+ // String header
57
+ expect(result.sourceMap[1]).toMatchObject({
58
+ path: '.value',
59
+ majorType: 3,
60
+ isHeader: true
61
+ })
62
+
63
+ // String content
64
+ expect(result.sourceMap[2]).toMatchObject({
65
+ path: '.value#content',
66
+ parent: '.value'
67
+ })
68
+ })
69
+
70
+ it('should handle tag with array value', () => {
71
+ const { parseWithSourceMap } = useCborParser()
72
+ // Tag 121 containing [1, 2, 3]
73
+ const result = parseWithSourceMap('d87983010203')
74
+
75
+ // Tag + array + 3 elements = 5 entries
76
+ expect(result.sourceMap.length).toBeGreaterThanOrEqual(2)
77
+
78
+ // Tag entry
79
+ const tagEntry = result.sourceMap.find(e => e.path === '')
80
+ expect(tagEntry).toBeDefined()
81
+ expect(tagEntry?.majorType).toBe(6)
82
+ expect(tagEntry?.children).toContain('.value')
83
+
84
+ // Array entry
85
+ const arrayEntry = result.sourceMap.find(e => e.path === '.value')
86
+ expect(arrayEntry).toBeDefined()
87
+ expect(arrayEntry?.majorType).toBe(4)
88
+ expect(arrayEntry?.parent).toBe('')
89
+ })
90
+ })
91
+
92
+ describe('Nested Tagged Values', () => {
93
+ it('should create source map for tag in tag', () => {
94
+ const { parseWithSourceMap } = useCborParser()
95
+ // Tag 121 containing Tag 121 containing empty array
96
+ // d8 79 81 d8 79 80
97
+ const result = parseWithSourceMap('d87981d87980')
98
+
99
+ expect(result.sourceMap.length).toBeGreaterThanOrEqual(4)
100
+
101
+ // Outer tag
102
+ const outerTag = result.sourceMap.find(e => e.path === '')
103
+ expect(outerTag).toBeDefined()
104
+ expect(outerTag?.majorType).toBe(6)
105
+ expect(outerTag?.type).toBe('tag(121)')
106
+ expect(outerTag?.children).toEqual(['.value'])
107
+
108
+ // Array inside outer tag
109
+ const array = result.sourceMap.find(e => e.path === '.value')
110
+ expect(array).toBeDefined()
111
+ expect(array?.majorType).toBe(4)
112
+ expect(array?.parent).toBe('')
113
+ expect(array?.children).toContain('.value[0]')
114
+
115
+ // Inner tag
116
+ const innerTag = result.sourceMap.find(e => e.path === '.value[0]')
117
+ expect(innerTag).toBeDefined()
118
+ expect(innerTag?.majorType).toBe(6)
119
+ expect(innerTag?.type).toBe('tag(121)')
120
+ expect(innerTag?.parent).toBe('.value')
121
+ expect(innerTag?.children).toEqual(['.value[0].value'])
122
+
123
+ // Empty array inside inner tag
124
+ const emptyArray = result.sourceMap.find(e => e.path === '.value[0].value')
125
+ expect(emptyArray).toBeDefined()
126
+ expect(emptyArray?.majorType).toBe(4)
127
+ expect(emptyArray?.parent).toBe('.value[0]')
128
+ })
129
+
130
+ it('should handle deeply nested tags (3 levels)', () => {
131
+ const { parseWithSourceMap } = useCborParser()
132
+ // Tag 121 -> [Tag 121 -> [Tag 121 -> []]]
133
+ const result = parseWithSourceMap('d87981d87981d87980')
134
+
135
+ // Should have entries for all levels
136
+ expect(result.sourceMap.find(e => e.path === '')).toBeDefined()
137
+ expect(result.sourceMap.find(e => e.path === '.value')).toBeDefined()
138
+ expect(result.sourceMap.find(e => e.path === '.value[0]')).toBeDefined()
139
+ expect(result.sourceMap.find(e => e.path === '.value[0].value')).toBeDefined()
140
+ expect(result.sourceMap.find(e => e.path === '.value[0].value[0]')).toBeDefined()
141
+ expect(result.sourceMap.find(e => e.path === '.value[0].value[0].value')).toBeDefined()
142
+ })
143
+ })
144
+
145
+ describe('Real-World Cardano Example', () => {
146
+ it('should create source map for tag in array in tag (user example)', () => {
147
+ const { parseWithSourceMap } = useCborParser()
148
+ // Real example: Tag 121 with array containing strings, integers, and nested tag
149
+ const hex = 'd8799f' + // Tag 121, indefinite array
150
+ '5773747265616d5f6d677870763171645f356b65376e6b6a' + // String
151
+ '581c2fc2a082557dc6a74dfc42d204a6d3ff1a241c103c0bbdd2f3525ce6' + // Byte string
152
+ '581cd8b6a54c95aac8970bcfbf625bb694336c43baa40aa1fc50952563f4' + // Byte string
153
+ '1a03473bc0' + // Integer
154
+ '1a064528dc' + // Integer
155
+ '1a064544e8' + // Integer
156
+ '1a06467a5c' + // Integer
157
+ '00' + // Integer 0
158
+ 'd87980' + // Tag 121 with empty array (nested tag)
159
+ 'ff' // Break
160
+
161
+ const result = parseWithSourceMap(hex)
162
+
163
+ // Find the nested tag entry at end of array
164
+ const nestedTagPath = '.value[8]'
165
+ const nestedTagEntry = result.sourceMap.find(e => e.path === nestedTagPath)
166
+
167
+ expect(nestedTagEntry).toBeDefined()
168
+ expect(nestedTagEntry?.majorType).toBe(6)
169
+ expect(nestedTagEntry?.type).toBe('tag(121)')
170
+ expect(nestedTagEntry?.parent).toBe('.value') // Parent is the array
171
+ expect(nestedTagEntry?.children).toContain('.value[8].value')
172
+
173
+ // Find the empty array inside the nested tag
174
+ const nestedArrayPath = '.value[8].value'
175
+ const nestedArrayEntry = result.sourceMap.find(e => e.path === nestedArrayPath)
176
+
177
+ expect(nestedArrayEntry).toBeDefined()
178
+ expect(nestedArrayEntry?.majorType).toBe(4)
179
+ expect(nestedArrayEntry?.type).toBe('array(0)')
180
+ expect(nestedArrayEntry?.parent).toBe(nestedTagPath)
181
+ })
182
+ })
183
+
184
+ describe('Plutus Constructor Tags', () => {
185
+ it('should create source maps for compact constructors (121-127)', () => {
186
+ const { parseWithSourceMap } = useCborParser()
187
+
188
+ // Tag 122 (Constructor 1, 1 field)
189
+ const result = parseWithSourceMap('d87a81182a') // Just 42
190
+
191
+ const tagEntry = result.sourceMap.find(e => e.path === '')
192
+ expect(tagEntry?.type).toBe('tag(122)')
193
+ expect(tagEntry?.children).toEqual(['.value'])
194
+
195
+ const arrayEntry = result.sourceMap.find(e => e.path === '.value')
196
+ expect(arrayEntry?.majorType).toBe(4)
197
+ expect(arrayEntry?.parent).toBe('')
198
+ })
199
+
200
+ it('should create source maps for extended constructors (1280-1400)', () => {
201
+ const { parseWithSourceMap } = useCborParser()
202
+
203
+ // Tag 1283 (Constructor 10)
204
+ const result = parseWithSourceMap('d9050383010203')
205
+
206
+ const tagEntry = result.sourceMap.find(e => e.path === '')
207
+ expect(tagEntry?.type).toBe('tag(1283)')
208
+ expect(tagEntry?.children).toEqual(['.value'])
209
+
210
+ const arrayEntry = result.sourceMap.find(e => e.path === '.value')
211
+ expect(arrayEntry?.majorType).toBe(4)
212
+ expect(arrayEntry?.parent).toBe('')
213
+ })
214
+
215
+ it('should create source maps for alternative constructor (tag 102)', () => {
216
+ const { parseWithSourceMap } = useCborParser()
217
+
218
+ // Tag 102 with [200, [99]]
219
+ const result = parseWithSourceMap('d8668218c8811863')
220
+
221
+ const tagEntry = result.sourceMap.find(e => e.path === '')
222
+ expect(tagEntry?.type).toBe('tag(102)')
223
+ expect(tagEntry?.children).toEqual(['.value'])
224
+
225
+ // Value is array [200, [99]]
226
+ const valueEntry = result.sourceMap.find(e => e.path === '.value')
227
+ expect(valueEntry?.majorType).toBe(4)
228
+ expect(valueEntry?.parent).toBe('')
229
+ })
230
+ })
231
+
232
+ describe('Parent-Child Relationship Validation', () => {
233
+ it('should maintain correct parent-child links', () => {
234
+ const { parseWithSourceMap } = useCborParser()
235
+ const result = parseWithSourceMap('d87981d87980')
236
+
237
+ // Verify bidirectional relationships
238
+ const outerTag = result.sourceMap.find(e => e.path === '')
239
+ expect(outerTag?.children).toContain('.value')
240
+
241
+ const array = result.sourceMap.find(e => e.path === '.value')
242
+ expect(array?.parent).toBe('')
243
+ expect(array?.children).toContain('.value[0]')
244
+
245
+ const innerTag = result.sourceMap.find(e => e.path === '.value[0]')
246
+ expect(innerTag?.parent).toBe('.value')
247
+ expect(innerTag?.children).toContain('.value[0].value')
248
+
249
+ const emptyArray = result.sourceMap.find(e => e.path === '.value[0].value')
250
+ expect(emptyArray?.parent).toBe('.value[0]')
251
+ })
252
+
253
+ it('should have all children referenced by parents', () => {
254
+ const { parseWithSourceMap } = useCborParser()
255
+ const result = parseWithSourceMap('d87983010203')
256
+
257
+ // Find all entries with children
258
+ const entriesWithChildren = result.sourceMap.filter(e => e.children && e.children.length > 0)
259
+
260
+ // Verify all children exist in source map
261
+ for (const entry of entriesWithChildren) {
262
+ for (const childPath of entry.children!) {
263
+ const childEntry = result.sourceMap.find(e => e.path === childPath)
264
+ expect(childEntry).toBeDefined()
265
+ expect(childEntry?.parent).toBe(entry.path)
266
+ }
267
+ }
268
+ })
269
+ })
270
+
271
+ describe('Byte Range Validation', () => {
272
+ it('should have correct byte offsets for nested tags', () => {
273
+ const { parseWithSourceMap } = useCborParser()
274
+ // d8 79 81 d8 79 80
275
+ // 0 1 2 3 4 5
276
+ const result = parseWithSourceMap('d87981d87980')
277
+
278
+ const outerTag = result.sourceMap.find(e => e.path === '')
279
+ expect(outerTag?.start).toBe(0)
280
+ expect(outerTag?.end).toBe(2) // Header only (d8 79)
281
+
282
+ const array = result.sourceMap.find(e => e.path === '.value')
283
+ expect(array?.start).toBe(2)
284
+ expect(array?.end).toBe(3) // Header only (81)
285
+
286
+ const innerTag = result.sourceMap.find(e => e.path === '.value[0]')
287
+ expect(innerTag?.start).toBe(3)
288
+ expect(innerTag?.end).toBe(5) // Header only (d8 79)
289
+
290
+ const emptyArray = result.sourceMap.find(e => e.path === '.value[0].value')
291
+ expect(emptyArray?.start).toBe(5)
292
+ expect(emptyArray?.end).toBe(6) // Header only (80)
293
+ })
294
+
295
+ it('should have non-overlapping value ranges for siblings', () => {
296
+ const { parseWithSourceMap } = useCborParser()
297
+ // Tag 121 with [1, 2, 3]
298
+ const result = parseWithSourceMap('d87983010203')
299
+
300
+ const element0 = result.sourceMap.find(e => e.path === '.value[0]')
301
+ const element1 = result.sourceMap.find(e => e.path === '.value[1]')
302
+ const element2 = result.sourceMap.find(e => e.path === '.value[2]')
303
+
304
+ expect(element0).toBeDefined()
305
+ expect(element1).toBeDefined()
306
+ expect(element2).toBeDefined()
307
+
308
+ // Siblings should not overlap
309
+ expect(element0!.end).toBeLessThanOrEqual(element1!.start)
310
+ expect(element1!.end).toBeLessThanOrEqual(element2!.start)
311
+ })
312
+ })
313
+
314
+ describe('Edge Cases', () => {
315
+ it('should handle tag with empty array', () => {
316
+ const { parseWithSourceMap } = useCborParser()
317
+ const result = parseWithSourceMap('d87980') // Tag 121, []
318
+
319
+ expect(result.sourceMap.length).toBeGreaterThanOrEqual(2)
320
+
321
+ const tagEntry = result.sourceMap.find(e => e.path === '')
322
+ expect(tagEntry?.children).toEqual(['.value'])
323
+
324
+ const arrayEntry = result.sourceMap.find(e => e.path === '.value')
325
+ expect(arrayEntry?.parent).toBe('')
326
+ expect(arrayEntry?.children).toBeUndefined() // Empty array has no children
327
+ })
328
+
329
+ it('should handle tag in map value', () => {
330
+ const { parseWithSourceMap } = useCborParser()
331
+ // Map with {"key": Tag 121 [42]}
332
+ const result = parseWithSourceMap('a1636b6579d87981182a')
333
+
334
+ const mapEntry = result.sourceMap.find(e => e.path === '')
335
+ expect(mapEntry?.majorType).toBe(5)
336
+
337
+ const tagEntry = result.sourceMap.find(e => e.path === '.key')
338
+ expect(tagEntry?.majorType).toBe(6)
339
+ expect(tagEntry?.children).toEqual(['.key.value'])
340
+
341
+ const arrayEntry = result.sourceMap.find(e => e.path === '.key.value')
342
+ expect(arrayEntry?.majorType).toBe(4)
343
+ expect(arrayEntry?.parent).toBe('.key')
344
+ })
345
+
346
+ it('should handle array of tags', () => {
347
+ const { parseWithSourceMap } = useCborParser()
348
+ // [Tag 121 [], Tag 121 []]
349
+ const result = parseWithSourceMap('82d87980d87980')
350
+
351
+ const tag0 = result.sourceMap.find(e => e.path === '[0]')
352
+ expect(tag0?.majorType).toBe(6)
353
+ expect(tag0?.children).toEqual(['[0].value'])
354
+
355
+ const tag1 = result.sourceMap.find(e => e.path === '[1]')
356
+ expect(tag1?.majorType).toBe(6)
357
+ expect(tag1?.children).toEqual(['[1].value'])
358
+ })
359
+ })
360
+ })