@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,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CBOR Collection Parser Tests
|
|
3
|
+
* Major Type 4 (Arrays) and Major Type 5 (Maps)
|
|
4
|
+
* Following RFC 8949 specification
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect } from 'vitest'
|
|
8
|
+
import { useCborCollection } from '../composables/useCborCollection'
|
|
9
|
+
|
|
10
|
+
describe('useCborCollection', () => {
|
|
11
|
+
describe('parseArray (Major Type 4)', () => {
|
|
12
|
+
describe('Empty and Small Arrays', () => {
|
|
13
|
+
it('should parse empty array', () => {
|
|
14
|
+
const { parseArray } = useCborCollection()
|
|
15
|
+
|
|
16
|
+
// RFC 8949: [] = 0x80
|
|
17
|
+
const result = parseArray('80')
|
|
18
|
+
expect(result.value).toEqual([])
|
|
19
|
+
expect(result.bytesRead).toBe(1)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
it('should parse array with small integers [1, 2, 3]', () => {
|
|
23
|
+
const { parseArray } = useCborCollection()
|
|
24
|
+
|
|
25
|
+
// RFC 8949: [1, 2, 3] = 0x83 0x01 0x02 0x03
|
|
26
|
+
const result = parseArray('83010203')
|
|
27
|
+
expect(result.value).toEqual([1, 2, 3])
|
|
28
|
+
expect(result.bytesRead).toBe(4)
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('should parse array with mixed values [1, 23, 100]', () => {
|
|
32
|
+
const { parseArray } = useCborCollection()
|
|
33
|
+
|
|
34
|
+
// [1, 23, 100] = 0x83 0x01 0x17 0x18 0x64
|
|
35
|
+
const result = parseArray('8301171864')
|
|
36
|
+
expect(result.value).toEqual([1, 23, 100])
|
|
37
|
+
expect(result.bytesRead).toBe(5)
|
|
38
|
+
})
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
describe('Arrays with Strings', () => {
|
|
42
|
+
it('should parse array with text strings ["a", "b", "c"]', () => {
|
|
43
|
+
const { parseArray } = useCborCollection()
|
|
44
|
+
|
|
45
|
+
// ["a", "b", "c"] = 0x83 0x61 0x61 0x61 0x62 0x61 0x63
|
|
46
|
+
const result = parseArray('83616161626163')
|
|
47
|
+
expect(result.value).toEqual(['a', 'b', 'c'])
|
|
48
|
+
expect(result.bytesRead).toBe(7)
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('should parse array with empty string [""]', () => {
|
|
52
|
+
const { parseArray } = useCborCollection()
|
|
53
|
+
|
|
54
|
+
// [""] = 0x81 0x60
|
|
55
|
+
const result = parseArray('8160')
|
|
56
|
+
expect(result.value).toEqual([''])
|
|
57
|
+
expect(result.bytesRead).toBe(2)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('should parse array with UTF-8 strings ["Hello", "世界"]', () => {
|
|
61
|
+
const { parseArray } = useCborCollection()
|
|
62
|
+
|
|
63
|
+
// ["Hello", "世界"]
|
|
64
|
+
// "Hello" = 0x65 "H" "e" "l" "l" "o"
|
|
65
|
+
// "世界" = 0x66 0xe4 0xb8 0x96 0xe7 0x95 0x8c
|
|
66
|
+
const result = parseArray('826548656c6c6f66e4b896e7958c')
|
|
67
|
+
expect(result.value).toEqual(['Hello', '世界'])
|
|
68
|
+
expect(result.bytesRead).toBe(14)
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
describe('Nested Arrays', () => {
|
|
73
|
+
it('should parse nested array [[1, 2], [3, 4]]', () => {
|
|
74
|
+
const { parseArray } = useCborCollection()
|
|
75
|
+
|
|
76
|
+
// [[1, 2], [3, 4]] = 0x82 [0x82 0x01 0x02] [0x82 0x03 0x04]
|
|
77
|
+
const result = parseArray('828201028203 04')
|
|
78
|
+
expect(result.value).toEqual([[1, 2], [3, 4]])
|
|
79
|
+
expect(result.bytesRead).toBe(7)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('should parse deeply nested arrays [[[1]]]', () => {
|
|
83
|
+
const { parseArray } = useCborCollection()
|
|
84
|
+
|
|
85
|
+
// [[[1]]] = 0x81 0x81 0x81 0x01
|
|
86
|
+
const result = parseArray('81818101')
|
|
87
|
+
expect(result.value).toEqual([[[1]]])
|
|
88
|
+
expect(result.bytesRead).toBe(4)
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('should parse mixed nested structure [1, [2, 3], 4]', () => {
|
|
92
|
+
const { parseArray } = useCborCollection()
|
|
93
|
+
|
|
94
|
+
// [1, [2, 3], 4] = 0x83 0x01 [0x82 0x02 0x03] 0x04
|
|
95
|
+
const result = parseArray('83018202 0304')
|
|
96
|
+
expect(result.value).toEqual([1, [2, 3], 4])
|
|
97
|
+
expect(result.bytesRead).toBe(6)
|
|
98
|
+
})
|
|
99
|
+
})
|
|
100
|
+
|
|
101
|
+
describe('Arrays with 1-byte Length Encoding', () => {
|
|
102
|
+
it('should parse array with 24 elements (1-byte length)', () => {
|
|
103
|
+
const { parseArray } = useCborCollection()
|
|
104
|
+
|
|
105
|
+
// Array of 24 zeros = 0x98 0x18 + 24 times 0x00
|
|
106
|
+
const hex = '9818' + '00'.repeat(24)
|
|
107
|
+
const result = parseArray(hex)
|
|
108
|
+
expect(result.value).toHaveLength(24)
|
|
109
|
+
expect(result.value.every(v => v === 0)).toBe(true)
|
|
110
|
+
expect(result.bytesRead).toBe(2 + 24)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('should parse array with 100 integers (1-byte length)', () => {
|
|
114
|
+
const { parseArray } = useCborCollection()
|
|
115
|
+
|
|
116
|
+
// Array of 100 ones = 0x98 0x64 + 100 times 0x01
|
|
117
|
+
const hex = '9864' + '01'.repeat(100)
|
|
118
|
+
const result = parseArray(hex)
|
|
119
|
+
expect(result.value).toHaveLength(100)
|
|
120
|
+
expect(result.value.every(v => v === 1)).toBe(true)
|
|
121
|
+
expect(result.bytesRead).toBe(2 + 100)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
describe('Indefinite-Length Arrays', () => {
|
|
126
|
+
it('should parse indefinite-length array [_ 1, 2, 3]', () => {
|
|
127
|
+
const { parseArray } = useCborCollection()
|
|
128
|
+
|
|
129
|
+
// [_ 1, 2, 3] = 0x9f 0x01 0x02 0x03 0xff (break)
|
|
130
|
+
const result = parseArray('9f010203ff')
|
|
131
|
+
expect(Array.isArray(result.value)).toBe(true)
|
|
132
|
+
const arr = result.value as any[]
|
|
133
|
+
expect(arr[0]).toBe(1)
|
|
134
|
+
expect(arr[1]).toBe(2)
|
|
135
|
+
expect(arr[2]).toBe(3)
|
|
136
|
+
expect(result.bytesRead).toBe(5)
|
|
137
|
+
})
|
|
138
|
+
|
|
139
|
+
it('should parse indefinite-length empty array [_]', () => {
|
|
140
|
+
const { parseArray } = useCborCollection()
|
|
141
|
+
|
|
142
|
+
// [_] = 0x9f 0xff
|
|
143
|
+
const result = parseArray('9fff')
|
|
144
|
+
expect(Array.isArray(result.value)).toBe(true)
|
|
145
|
+
expect(result.value).toHaveLength(0)
|
|
146
|
+
expect(result.bytesRead).toBe(2)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('should parse indefinite-length nested array [_ 1, [2, 3], [4, 5]]', () => {
|
|
150
|
+
const { parseArray } = useCborCollection()
|
|
151
|
+
|
|
152
|
+
// [_ 1, [2, 3], [4, 5]] = 0x9f 0x01 0x82 0x02 0x03 0x82 0x04 0x05 0xff
|
|
153
|
+
const result = parseArray('9f018202038204 05ff')
|
|
154
|
+
expect(Array.isArray(result.value)).toBe(true)
|
|
155
|
+
const arr = result.value as any[]
|
|
156
|
+
expect(arr[0]).toBe(1)
|
|
157
|
+
expect(arr[1]).toEqual([2, 3])
|
|
158
|
+
expect(arr[2]).toEqual([4, 5])
|
|
159
|
+
expect(result.bytesRead).toBe(9)
|
|
160
|
+
})
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
describe('Real Cardano Examples', () => {
|
|
164
|
+
it('should parse Cardano UTXO array structure', () => {
|
|
165
|
+
const { parseArray } = useCborCollection()
|
|
166
|
+
|
|
167
|
+
// Simplified Cardano UTXO: [[txHash, outputIndex]]
|
|
168
|
+
// Array of 1 element: [32-byte hash, integer 0]
|
|
169
|
+
// 0x81 = array(1)
|
|
170
|
+
// 0x82 = array(2) - the UTXO pair
|
|
171
|
+
// 0x5820 = bytes(32) - transaction hash
|
|
172
|
+
// 32 bytes of hash data
|
|
173
|
+
// 0x00 = integer 0 (output index)
|
|
174
|
+
const txHash = '48bd01d51e580cde15afa6d28f63d89c9137b93a910e5941192e26b129061067'
|
|
175
|
+
const hex = `81825820${txHash}00`
|
|
176
|
+
|
|
177
|
+
const result = parseArray(hex)
|
|
178
|
+
expect(result.value).toHaveLength(1)
|
|
179
|
+
expect(Array.isArray(result.value[0])).toBe(true)
|
|
180
|
+
expect(result.value[0]).toHaveLength(2)
|
|
181
|
+
expect(result.value[0][1]).toBe(0) // output index
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
it('should parse Cardano amount array [lovelace]', () => {
|
|
185
|
+
const { parseArray } = useCborCollection()
|
|
186
|
+
|
|
187
|
+
// Array with Cardano amounts: [1000000, 2000000, 5000000]
|
|
188
|
+
// 1000000 = 0x1a 0x000f4240
|
|
189
|
+
// 2000000 = 0x1a 0x001e8480
|
|
190
|
+
// 5000000 = 0x1a 0x004c4b40
|
|
191
|
+
const result = parseArray('831a000f42401a001e84801a004c4b40')
|
|
192
|
+
expect(result.value).toEqual([1000000, 2000000, 5000000])
|
|
193
|
+
expect(result.bytesRead).toBe(16)
|
|
194
|
+
})
|
|
195
|
+
})
|
|
196
|
+
})
|
|
197
|
+
|
|
198
|
+
describe('parseMap (Major Type 5)', () => {
|
|
199
|
+
describe('Empty and Small Maps', () => {
|
|
200
|
+
it('should parse empty map {}', () => {
|
|
201
|
+
const { parseMap } = useCborCollection()
|
|
202
|
+
|
|
203
|
+
// RFC 8949: {} = 0xa0
|
|
204
|
+
const result = parseMap('a0')
|
|
205
|
+
expect(result.value).toEqual(new Map())
|
|
206
|
+
expect(result.bytesRead).toBe(1)
|
|
207
|
+
})
|
|
208
|
+
|
|
209
|
+
it('should parse map with one key-value pair {"a": 1}', () => {
|
|
210
|
+
const { parseMap } = useCborCollection()
|
|
211
|
+
|
|
212
|
+
// {"a": 1} = 0xa1 0x61 "a" 0x01
|
|
213
|
+
const result = parseMap('a16161 01')
|
|
214
|
+
expect(result.value).toEqual(new Map([['a', 1]]))
|
|
215
|
+
expect(result.bytesRead).toBe(4)
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
it('should parse map with multiple pairs {"a": 1, "b": 2}', () => {
|
|
219
|
+
const { parseMap } = useCborCollection()
|
|
220
|
+
|
|
221
|
+
// {"a": 1, "b": 2} = 0xa2 0x61 "a" 0x01 0x61 "b" 0x02
|
|
222
|
+
const result = parseMap('a26161016162 02')
|
|
223
|
+
expect(result.value).toEqual(new Map([['a', 1], ['b', 2]]))
|
|
224
|
+
expect(result.bytesRead).toBe(7)
|
|
225
|
+
})
|
|
226
|
+
|
|
227
|
+
it('should parse map with integer keys {1: "a", 2: "b"}', () => {
|
|
228
|
+
const { parseMap } = useCborCollection()
|
|
229
|
+
|
|
230
|
+
// {1: "a", 2: "b"} = 0xa2 0x01 0x61 "a" 0x02 0x61 "b"
|
|
231
|
+
const result = parseMap('a2016161026162')
|
|
232
|
+
expect(result.value).toEqual(new Map([[1, 'a'], [2, 'b']]))
|
|
233
|
+
expect(result.bytesRead).toBe(7)
|
|
234
|
+
})
|
|
235
|
+
})
|
|
236
|
+
|
|
237
|
+
describe('Maps with Different Value Types', () => {
|
|
238
|
+
it('should parse map with string values {"name": "Alice", "age": "30"}', () => {
|
|
239
|
+
const { parseMap } = useCborCollection()
|
|
240
|
+
|
|
241
|
+
// {"name": "Alice", "age": "30"}
|
|
242
|
+
// "name" = 0x64 0x6e 0x61 0x6d 0x65
|
|
243
|
+
// "Alice" = 0x65 0x41 0x6c 0x69 0x63 0x65
|
|
244
|
+
// "age" = 0x63 0x61 0x67 0x65
|
|
245
|
+
// "30" = 0x62 0x33 0x30
|
|
246
|
+
const result = parseMap('a2646e616d656541 6c696365636167656233 30')
|
|
247
|
+
expect(result.value).toEqual(new Map([['name', 'Alice'], ['age', '30']]))
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
it('should parse map with mixed value types {"count": 42, "active": true}', () => {
|
|
251
|
+
const { parseMap } = useCborCollection()
|
|
252
|
+
|
|
253
|
+
// {"count": 42, "active": true}
|
|
254
|
+
// Note: true requires simple value parser, will parse integer for now
|
|
255
|
+
// "count" = 0x65 0x63 0x6f 0x75 0x6e 0x74
|
|
256
|
+
// 42 = 0x18 0x2a
|
|
257
|
+
const result = parseMap('a165636f756e74182a')
|
|
258
|
+
expect(result.value).toEqual(new Map([['count', 42]]))
|
|
259
|
+
expect(result.bytesRead).toBe(9)
|
|
260
|
+
})
|
|
261
|
+
})
|
|
262
|
+
|
|
263
|
+
describe('Nested Maps', () => {
|
|
264
|
+
it('should parse nested map {"outer": {"inner": 1}}', () => {
|
|
265
|
+
const { parseMap } = useCborCollection()
|
|
266
|
+
|
|
267
|
+
// {"outer": {"inner": 1}}
|
|
268
|
+
// "outer" = 0x65 0x6f 0x75 0x74 0x65 0x72
|
|
269
|
+
// {"inner": 1} = 0xa1 0x65 0x69 0x6e 0x6e 0x65 0x72 0x01
|
|
270
|
+
const result = parseMap('a1656f75746572a1 65696e6e657201')
|
|
271
|
+
expect(result.value).toEqual(new Map([['outer', new Map([['inner', 1]])]]))
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
it('should parse map with array value {"numbers": [1, 2, 3]}', () => {
|
|
275
|
+
const { parseMap } = useCborCollection()
|
|
276
|
+
|
|
277
|
+
// {"numbers": [1, 2, 3]}
|
|
278
|
+
// "numbers" = 0x67 0x6e 0x75 0x6d 0x62 0x65 0x72 0x73
|
|
279
|
+
// [1, 2, 3] = 0x83 0x01 0x02 0x03
|
|
280
|
+
const result = parseMap('a1676e756d62657273 83010203')
|
|
281
|
+
expect(result.value).toEqual(new Map([['numbers', [1, 2, 3]]]))
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
describe('Indefinite-Length Maps', () => {
|
|
286
|
+
it('should parse indefinite-length map {_ "a": 1, "b": 2}', () => {
|
|
287
|
+
const { parseMap } = useCborCollection()
|
|
288
|
+
|
|
289
|
+
// {_ "a": 1, "b": 2} = 0xbf 0x61 "a" 0x01 0x61 "b" 0x02 0xff
|
|
290
|
+
const result = parseMap('bf61610161620 2ff')
|
|
291
|
+
expect(result.value).toEqual(new Map([['a', 1], ['b', 2]]))
|
|
292
|
+
expect(result.bytesRead).toBe(8)
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('should parse indefinite-length empty map {_}', () => {
|
|
296
|
+
const { parseMap } = useCborCollection()
|
|
297
|
+
|
|
298
|
+
// {_} = 0xbf 0xff
|
|
299
|
+
const result = parseMap('bfff')
|
|
300
|
+
expect(result.value).toEqual(new Map())
|
|
301
|
+
expect(result.bytesRead).toBe(2)
|
|
302
|
+
})
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
describe('Real Cardano Examples', () => {
|
|
306
|
+
it('should parse Cardano balance object {"lovelace": 1000000}', () => {
|
|
307
|
+
const { parseMap } = useCborCollection()
|
|
308
|
+
|
|
309
|
+
// {"lovelace": 1000000}
|
|
310
|
+
// "lovelace" = 0x68 0x6c 0x6f 0x76 0x65 0x6c 0x61 0x63 0x65
|
|
311
|
+
// 1000000 = 0x1a 0x000f4240
|
|
312
|
+
const result = parseMap('a1686c6f76656c6163 651a000f4240')
|
|
313
|
+
expect(result.value).toEqual(new Map([['lovelace', 1000000]]))
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it('should parse Cardano metadata map {"msg": "Hello"}', () => {
|
|
317
|
+
const { parseMap } = useCborCollection()
|
|
318
|
+
|
|
319
|
+
// {"msg": "Hello"}
|
|
320
|
+
// "msg" = 0x63 0x6d 0x73 0x67
|
|
321
|
+
// "Hello" = 0x65 0x48 0x65 0x6c 0x6c 0x6f
|
|
322
|
+
const result = parseMap('a1636d73676548656c 6c6f')
|
|
323
|
+
expect(result.value).toEqual(new Map([['msg', 'Hello']]))
|
|
324
|
+
})
|
|
325
|
+
|
|
326
|
+
it('should parse Cardano UTXO map structure', () => {
|
|
327
|
+
const { parseMap } = useCborCollection()
|
|
328
|
+
|
|
329
|
+
// Simplified: {"amount": 5000000, "address": "addr1..."}
|
|
330
|
+
// "amount" = 0x66 0x61 0x6d 0x6f 0x75 0x6e 0x74
|
|
331
|
+
// 5000000 = 0x1a 0x004c4b40
|
|
332
|
+
// "address" = 0x67 0x61 0x64 0x64 0x72 0x65 0x73 0x73
|
|
333
|
+
// "addr1" = 0x65 0x61 0x64 0x64 0x72 0x31
|
|
334
|
+
const result = parseMap('a266616d6f756e741a 004c4b4067616464726573736561646472 31')
|
|
335
|
+
expect(result.value).toEqual(new Map([['amount', 5000000], ['address', 'addr1']]))
|
|
336
|
+
})
|
|
337
|
+
})
|
|
338
|
+
})
|
|
339
|
+
|
|
340
|
+
describe('Error Handling', () => {
|
|
341
|
+
it('should throw error for invalid major type in parseArray', () => {
|
|
342
|
+
const { parseArray } = useCborCollection()
|
|
343
|
+
|
|
344
|
+
// 0x00 = integer 0, not an array
|
|
345
|
+
expect(() => parseArray('00')).toThrow('Expected major type 4 (array)')
|
|
346
|
+
})
|
|
347
|
+
|
|
348
|
+
it('should throw error for invalid major type in parseMap', () => {
|
|
349
|
+
const { parseMap } = useCborCollection()
|
|
350
|
+
|
|
351
|
+
// 0x80 = empty array, not a map
|
|
352
|
+
expect(() => parseMap('80')).toThrow('Expected major type 5 (map)')
|
|
353
|
+
})
|
|
354
|
+
|
|
355
|
+
it('should throw error for truncated array data', () => {
|
|
356
|
+
const { parseArray } = useCborCollection()
|
|
357
|
+
|
|
358
|
+
// 0x83 = array(3), but only 2 elements provided
|
|
359
|
+
expect(() => parseArray('830102')).toThrow()
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('should throw error for truncated map data', () => {
|
|
363
|
+
const { parseMap } = useCborCollection()
|
|
364
|
+
|
|
365
|
+
// 0xa2 = map(2 pairs), but only 1 pair provided
|
|
366
|
+
expect(() => parseMap('a2616101')).toThrow()
|
|
367
|
+
})
|
|
368
|
+
})
|
|
369
|
+
})
|