@futpib/parser 1.0.1 → 1.0.3

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 (425) hide show
  1. package/.github/copilot-instructions.md +149 -0
  2. package/.github/workflows/copilot-setup-steps.yml +18 -0
  3. package/.github/workflows/main.yml +29 -8
  4. package/.yarn/releases/yarn-4.9.4.cjs +942 -0
  5. package/.yarnrc.yml +1 -1
  6. package/build/allSettledStream.js +32 -14
  7. package/build/allSettledStream.test.js +32 -0
  8. package/build/androidPackage.d.ts +39 -0
  9. package/build/androidPackageParser.d.ts +17 -0
  10. package/build/androidPackageParser.js +185 -0
  11. package/build/androidPackageParser.test.js +22 -0
  12. package/build/androidPackageUnparser.d.ts +4 -0
  13. package/build/androidPackageUnparser.js +94 -0
  14. package/build/androidPackageUnparser.test.js +26 -0
  15. package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
  16. package/build/arbitrarilySlicedAsyncInterable.js +3 -3
  17. package/build/arbitrarilySlicedAsyncInterator.js +2 -1
  18. package/build/arbitraryDalvikBytecode.d.ts +4 -0
  19. package/build/arbitraryDalvikBytecode.js +640 -0
  20. package/build/arbitraryDalvikExecutable.d.ts +3 -0
  21. package/build/arbitraryDalvikExecutable.js +282 -0
  22. package/build/arbitraryDosDateTime.js +1 -0
  23. package/build/arbitraryZipStream.js +1 -1
  24. package/build/arrayParser.js +2 -2
  25. package/build/arrayParser.test.js +3 -3
  26. package/build/arrayUnparser.d.ts +1 -1
  27. package/build/backsmali.d.ts +3 -0
  28. package/build/backsmali.js +50 -0
  29. package/build/bsonParser.js +6 -2
  30. package/build/customInvariant.d.ts +2 -1
  31. package/build/customInvariant.js +4 -6
  32. package/build/dalvikBytecodeParser/formatParsers.d.ts +171 -0
  33. package/build/dalvikBytecodeParser/formatParsers.js +304 -0
  34. package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
  35. package/build/dalvikBytecodeParser/formatSizes.js +34 -0
  36. package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
  37. package/build/dalvikBytecodeParser/operationFormats.js +225 -0
  38. package/build/dalvikBytecodeParser.d.ts +1207 -0
  39. package/build/dalvikBytecodeParser.js +1289 -0
  40. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
  41. package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
  42. package/build/dalvikBytecodeUnparser.d.ts +3 -0
  43. package/build/dalvikBytecodeUnparser.js +642 -0
  44. package/build/dalvikBytecodeUnparser.test.js +25 -0
  45. package/build/dalvikExecutable.d.ts +215 -0
  46. package/build/dalvikExecutable.js +56 -0
  47. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
  48. package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
  49. package/build/dalvikExecutableParser/typeParsers.d.ts +11 -0
  50. package/build/dalvikExecutableParser/typeParsers.js +39 -0
  51. package/build/dalvikExecutableParser/typedNumbers.d.ts +106 -0
  52. package/build/dalvikExecutableParser/typedNumbers.js +18 -0
  53. package/build/dalvikExecutableParser.d.ts +5 -0
  54. package/build/dalvikExecutableParser.js +1757 -0
  55. package/build/dalvikExecutableParser.test.js +72 -0
  56. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +275 -0
  57. package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
  58. package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
  59. package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
  60. package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
  61. package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
  62. package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
  63. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
  64. package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
  65. package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
  66. package/build/dalvikExecutableUnparser/utils.js +108 -0
  67. package/build/dalvikExecutableUnparser.d.ts +4 -0
  68. package/build/dalvikExecutableUnparser.js +406 -0
  69. package/build/dalvikExecutableUnparser.test.js +31 -0
  70. package/build/debugLogInputParser.d.ts +4 -0
  71. package/build/debugLogInputParser.js +16 -0
  72. package/build/debugLogParser.js +14 -3
  73. package/build/disjunctionParser.d.ts +2 -1
  74. package/build/disjunctionParser.js +6 -4
  75. package/build/elementTerminatedArrayParser.d.ts +3 -0
  76. package/build/elementTerminatedArrayParser.js +18 -0
  77. package/build/elementTerminatedArrayParser.test.js +52 -0
  78. package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
  79. package/build/elementTerminatedSequenceArrayParser.js +32 -0
  80. package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
  81. package/build/elementTerminatedSequenceParser.d.ts +3 -0
  82. package/build/elementTerminatedSequenceParser.js +27 -0
  83. package/build/elementTerminatedSequenceParser.test.js +34 -0
  84. package/build/endOfInputParser.d.ts +1 -1
  85. package/build/exactElementParser.js +10 -5
  86. package/build/exactElementSwitchParser.d.ts +3 -0
  87. package/build/exactElementSwitchParser.js +22 -0
  88. package/build/exactSequenceParser.d.ts +2 -1
  89. package/build/exactSequenceParser.js +12 -2
  90. package/build/fetchCid.d.ts +1 -0
  91. package/build/fetchCid.js +103 -0
  92. package/build/fetchCid.test.js +16 -0
  93. package/build/fixedLengthSequenceParser.d.ts +1 -0
  94. package/build/fixedLengthSequenceParser.js +18 -1
  95. package/build/fixedLengthSequenceParser.test.js +41 -0
  96. package/build/hasExecutable.d.ts +1 -0
  97. package/build/hasExecutable.js +8 -0
  98. package/build/highResolutionTimer.d.ts +16 -0
  99. package/build/highResolutionTimer.js +42 -0
  100. package/build/inputReader.d.ts +11 -0
  101. package/build/inputReader.js +37 -0
  102. package/build/inputReader.test.js +161 -8
  103. package/build/inputReaderState.d.ts +10 -0
  104. package/build/inputReaderState.js +16 -0
  105. package/build/inspect.d.ts +1 -0
  106. package/build/inspect.js +7 -0
  107. package/build/javaKeyStoreParser.test.js +8 -8
  108. package/build/jsonParser.d.ts +2 -0
  109. package/build/jsonParser.js +19 -22
  110. package/build/lazyMessageError.d.ts +48 -0
  111. package/build/lazyMessageError.js +53 -0
  112. package/build/lazyMessageError.test.d.ts +1 -0
  113. package/build/lazyMessageError.test.js +15 -0
  114. package/build/leb128Parser.d.ts +7 -0
  115. package/build/leb128Parser.js +82 -0
  116. package/build/leb128Parser.test.d.ts +1 -0
  117. package/build/leb128Parser.test.js +107 -0
  118. package/build/lookaheadParser.d.ts +2 -0
  119. package/build/lookaheadParser.js +14 -0
  120. package/build/negativeLookaheadParser.js +22 -16
  121. package/build/negativeLookaheadParser.test.d.ts +1 -0
  122. package/build/negativeLookaheadParser.test.js +30 -0
  123. package/build/noStackCaptureOverheadError.d.ts +4 -0
  124. package/build/noStackCaptureOverheadError.js +9 -0
  125. package/build/noStackCaptureOverheadError.test.d.ts +1 -0
  126. package/build/noStackCaptureOverheadError.test.js +15 -0
  127. package/build/nonEmptyArrayParser.d.ts +2 -0
  128. package/build/nonEmptyArrayParser.js +32 -0
  129. package/build/nonEmptyArrayParser.test.d.ts +1 -0
  130. package/build/nonEmptyArrayParser.test.js +17 -0
  131. package/build/optionalParser.js +2 -2
  132. package/build/parser.d.ts +11 -1
  133. package/build/parser.js +82 -32
  134. package/build/parser.test.js +141 -25
  135. package/build/parserAccessorParser.js +9 -1
  136. package/build/parserConsumedSequenceParser.d.ts +1 -1
  137. package/build/parserConsumedSequenceParser.js +21 -16
  138. package/build/parserContext.d.ts +22 -6
  139. package/build/parserContext.js +113 -57
  140. package/build/parserContext.test.js +33 -2
  141. package/build/parserCreatorCompose.d.ts +1 -0
  142. package/build/parserCreatorCompose.js +8 -2
  143. package/build/parserError.d.ts +605 -40
  144. package/build/parserError.js +98 -53
  145. package/build/parserImplementationInvariant.d.ts +1 -1
  146. package/build/parserImplementationInvariant.js +2 -2
  147. package/build/parserInputCompanion.d.ts +15 -0
  148. package/build/parserInputCompanion.js +38 -0
  149. package/build/promiseCompose.d.ts +1 -1
  150. package/build/promiseCompose.js +11 -1
  151. package/build/promiseSettled.d.ts +1 -0
  152. package/build/promiseSettled.js +4 -0
  153. package/build/separatedArrayParser.d.ts +2 -0
  154. package/build/separatedArrayParser.js +39 -0
  155. package/build/separatedArrayParser.test.d.ts +1 -0
  156. package/build/separatedArrayParser.test.js +21 -0
  157. package/build/separatedNonEmptyArrayParser.d.ts +2 -0
  158. package/build/separatedNonEmptyArrayParser.js +40 -0
  159. package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
  160. package/build/separatedNonEmptyArrayParser.test.js +66 -0
  161. package/build/sequenceBuffer.d.ts +10 -0
  162. package/build/sequenceBuffer.js +54 -2
  163. package/build/sequenceBuffer.test.js +57 -0
  164. package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
  165. package/build/sequenceTerminatedSequenceParser.js +32 -0
  166. package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
  167. package/build/sequenceTerminatedSequenceParser.test.js +37 -0
  168. package/build/sequenceUnparser.d.ts +1 -1
  169. package/build/skipParser.d.ts +1 -1
  170. package/build/skipParser.js +4 -2
  171. package/build/skipToParser.d.ts +2 -0
  172. package/build/skipToParser.js +11 -0
  173. package/build/sliceBoundedParser.d.ts +1 -1
  174. package/build/sliceBoundedParser.js +7 -2
  175. package/build/sliceBoundedParser.test.js +30 -1
  176. package/build/smali.d.ts +1 -0
  177. package/build/smali.js +21 -0
  178. package/build/smaliParser.d.ts +68 -0
  179. package/build/smaliParser.js +2081 -0
  180. package/build/smaliParser.test.d.ts +1 -0
  181. package/build/smaliParser.test.js +410 -0
  182. package/build/stringFromAsyncIterable.d.ts +1 -0
  183. package/build/stringFromAsyncIterable.js +7 -0
  184. package/build/terminatedArrayParser.d.ts +3 -1
  185. package/build/terminatedArrayParser.js +79 -2
  186. package/build/terminatedArrayParser.test.d.ts +1 -0
  187. package/build/terminatedArrayParser.test.js +131 -0
  188. package/build/toAsyncIterable.d.ts +1 -0
  189. package/build/toAsyncIterable.js +7 -0
  190. package/build/toAsyncIterator.d.ts +1 -0
  191. package/build/toAsyncIterator.js +33 -0
  192. package/build/tupleParser.d.ts +4 -0
  193. package/build/tupleParser.js +1 -5
  194. package/build/unionParser.d.ts +2 -1
  195. package/build/unionParser.js +29 -14
  196. package/build/unionParser.test.d.ts +1 -0
  197. package/build/unionParser.test.js +60 -0
  198. package/build/unparser.d.ts +3 -3
  199. package/build/unparser.js +6 -4
  200. package/build/unparser.test.js +7 -19
  201. package/build/unparserContext.d.ts +2 -2
  202. package/build/unparserContext.js +2 -3
  203. package/build/unparserError.d.ts +2 -1
  204. package/build/unparserError.js +2 -1
  205. package/build/unparserImplementationInvariant.d.ts +1 -1
  206. package/build/unparserOutputCompanion.d.ts +1 -1
  207. package/build/unparserOutputCompanion.js +1 -1
  208. package/build/zipParser.d.ts +7 -2
  209. package/build/zipParser.js +36 -12
  210. package/build/zipUnparser.d.ts +7 -4
  211. package/build/zipUnparser.js +64 -45
  212. package/build/zipUnparser.test.js +15 -15
  213. package/package.json +33 -24
  214. package/src/allSettledStream.test.ts +40 -0
  215. package/src/allSettledStream.ts +47 -15
  216. package/src/androidPackage.ts +48 -0
  217. package/src/androidPackageParser.test.ts +27 -0
  218. package/src/{apkParser.test.ts.md → androidPackageParser.test.ts.md} +4 -4
  219. package/src/androidPackageParser.test.ts.snap +0 -0
  220. package/src/androidPackageParser.ts +398 -0
  221. package/src/androidPackageUnparser.test.ts +34 -0
  222. package/src/androidPackageUnparser.ts +126 -0
  223. package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
  224. package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
  225. package/src/arbitraryDalvikBytecode.ts +992 -0
  226. package/src/arbitraryDalvikExecutable.ts +434 -0
  227. package/src/arbitraryDosDateTime.ts +1 -0
  228. package/src/arbitraryZipStream.ts +1 -1
  229. package/src/arrayParser.test.ts +3 -3
  230. package/src/arrayParser.ts +2 -2
  231. package/src/arrayUnparser.ts +2 -2
  232. package/src/backsmali.ts +74 -0
  233. package/src/bsonParser.test.ts +12 -14
  234. package/src/bsonParser.ts +13 -2
  235. package/src/customInvariant.ts +8 -12
  236. package/src/dalvikBytecodeParser/formatParsers.ts +780 -0
  237. package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
  238. package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
  239. package/src/dalvikBytecodeParser.ts +2873 -0
  240. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
  241. package/src/dalvikBytecodeUnparser.test.ts +44 -0
  242. package/src/dalvikBytecodeUnparser.ts +758 -0
  243. package/src/dalvikExecutable.ts +282 -0
  244. package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
  245. package/src/dalvikExecutableParser/typeParsers.ts +74 -0
  246. package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
  247. package/src/dalvikExecutableParser.test.ts +89 -0
  248. package/src/dalvikExecutableParser.test.ts.md +634 -0
  249. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  250. package/src/dalvikExecutableParser.ts +3245 -0
  251. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +363 -0
  252. package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
  253. package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
  254. package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
  255. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
  256. package/src/dalvikExecutableUnparser/utils.ts +149 -0
  257. package/src/dalvikExecutableUnparser.test.ts +57 -0
  258. package/src/dalvikExecutableUnparser.ts +581 -0
  259. package/src/debugLogInputParser.ts +28 -0
  260. package/src/debugLogParser.ts +19 -3
  261. package/src/disjunctionParser.ts +12 -7
  262. package/src/elementTerminatedArrayParser.test.ts +99 -0
  263. package/src/elementTerminatedArrayParser.ts +31 -0
  264. package/src/elementTerminatedSequenceArrayParser.test.ts +52 -0
  265. package/src/elementTerminatedSequenceArrayParser.ts +52 -0
  266. package/src/elementTerminatedSequenceParser.test.ts +52 -0
  267. package/src/elementTerminatedSequenceParser.ts +43 -0
  268. package/src/endOfInputParser.ts +1 -1
  269. package/src/exactElementParser.ts +17 -11
  270. package/src/exactElementSwitchParser.ts +41 -0
  271. package/src/exactSequenceParser.ts +23 -2
  272. package/src/fetchCid.test.ts +20 -0
  273. package/src/fetchCid.ts +121 -0
  274. package/src/fixedLengthSequenceParser.test.ts +75 -0
  275. package/src/fixedLengthSequenceParser.ts +28 -1
  276. package/src/hasExecutable.ts +11 -0
  277. package/src/highResolutionTimer.ts +49 -0
  278. package/src/inputReader.test.ts +204 -8
  279. package/src/inputReader.ts +76 -3
  280. package/src/inputReaderState.ts +33 -0
  281. package/src/inspect.ts +9 -0
  282. package/src/javaKeyStoreParser.test.ts +12 -15
  283. package/src/javaKeyStoreParser.ts +2 -6
  284. package/src/jsonParser.test.ts +2 -4
  285. package/src/jsonParser.ts +46 -62
  286. package/src/lazyMessageError.test.ts +21 -0
  287. package/src/lazyMessageError.ts +88 -0
  288. package/src/leb128Parser.test.ts +173 -0
  289. package/src/leb128Parser.ts +125 -0
  290. package/src/lookaheadParser.ts +19 -0
  291. package/src/negativeLookaheadParser.test.ts +49 -0
  292. package/src/negativeLookaheadParser.ts +27 -15
  293. package/src/noStackCaptureOverheadError.test.ts +17 -0
  294. package/src/noStackCaptureOverheadError.ts +12 -0
  295. package/src/nonEmptyArrayParser.test.ts +21 -0
  296. package/src/nonEmptyArrayParser.ts +44 -0
  297. package/src/optionalParser.ts +3 -2
  298. package/src/parser.test.ts +203 -31
  299. package/src/parser.test.ts.md +34 -27
  300. package/src/parser.test.ts.snap +0 -0
  301. package/src/parser.ts +172 -45
  302. package/src/parserAccessorParser.ts +12 -2
  303. package/src/parserConsumedSequenceParser.ts +26 -17
  304. package/src/parserContext.test.ts +37 -2
  305. package/src/parserContext.ts +185 -79
  306. package/src/parserCreatorCompose.ts +20 -2
  307. package/src/parserError.ts +144 -61
  308. package/src/parserImplementationInvariant.ts +3 -3
  309. package/src/parserInputCompanion.ts +55 -0
  310. package/src/promiseCompose.ts +17 -3
  311. package/src/promiseSettled.ts +6 -0
  312. package/src/separatedArrayParser.test.ts +34 -0
  313. package/src/separatedArrayParser.ts +55 -0
  314. package/src/separatedNonEmptyArrayParser.test.ts +117 -0
  315. package/src/separatedNonEmptyArrayParser.ts +61 -0
  316. package/src/sequenceBuffer.test.ts +70 -0
  317. package/src/sequenceBuffer.ts +88 -2
  318. package/src/sequenceTerminatedSequenceParser.test.ts +58 -0
  319. package/src/sequenceTerminatedSequenceParser.ts +62 -0
  320. package/src/sequenceUnparser.ts +2 -2
  321. package/src/skipParser.ts +7 -5
  322. package/src/skipToParser.ts +16 -0
  323. package/src/sliceBoundedParser.test.ts +35 -1
  324. package/src/sliceBoundedParser.ts +19 -1
  325. package/src/smali.ts +29 -0
  326. package/src/smaliParser.test.ts +443 -0
  327. package/src/smaliParser.test.ts.md +3907 -0
  328. package/src/smaliParser.test.ts.snap +0 -0
  329. package/src/smaliParser.ts +3348 -0
  330. package/src/stringFromAsyncIterable.ts +9 -0
  331. package/src/terminatedArrayParser.test.ts +258 -0
  332. package/src/terminatedArrayParser.ts +109 -6
  333. package/src/toAsyncIterable.ts +7 -0
  334. package/src/toAsyncIterator.ts +48 -0
  335. package/src/tupleParser.ts +8 -5
  336. package/src/uint8Array.ts +2 -3
  337. package/src/unionParser.test.ts +78 -0
  338. package/src/unionParser.ts +47 -21
  339. package/src/unparser.test.ts +18 -34
  340. package/src/unparser.ts +13 -9
  341. package/src/unparserContext.ts +9 -13
  342. package/src/unparserError.ts +2 -1
  343. package/src/unparserImplementationInvariant.ts +1 -1
  344. package/src/unparserOutputCompanion.ts +1 -1
  345. package/src/zip.ts +2 -6
  346. package/src/zipParser.ts +71 -20
  347. package/src/zipUnparser.test.ts +19 -19
  348. package/src/zipUnparser.ts +139 -90
  349. package/tsconfig.json +7 -1
  350. package/xo.config.ts +15 -0
  351. package/.yarn/releases/yarn-4.5.3.cjs +0 -934
  352. package/build/apk.d.ts +0 -39
  353. package/build/apkParser.d.ts +0 -16
  354. package/build/apkParser.js +0 -164
  355. package/build/apkParser.test.js +0 -22
  356. package/build/apkUnparser.d.ts +0 -4
  357. package/build/apkUnparser.js +0 -90
  358. package/build/apkUnparser.test.js +0 -26
  359. package/build/arbitraryDosDate.d.ts +0 -2
  360. package/build/arbitraryDosDate.js +0 -8
  361. package/build/arbitraryZipEntry.d.ts +0 -3
  362. package/build/arbitraryZipEntry.js +0 -26
  363. package/build/createDisjunctionParser.d.ts +0 -2
  364. package/build/createDisjunctionParser.js +0 -47
  365. package/build/createExactParser.d.ts +0 -2
  366. package/build/createExactParser.js +0 -12
  367. package/build/createSequentialUnionParser.d.ts +0 -2
  368. package/build/createSequentialUnionParser.js +0 -69
  369. package/build/fixedLengthChunkParser.d.ts +0 -2
  370. package/build/fixedLengthChunkParser.js +0 -12
  371. package/build/fixedLengthParser.d.ts +0 -2
  372. package/build/fixedLengthParser.js +0 -12
  373. package/build/inputChunkBuffer.d.ts +0 -15
  374. package/build/inputChunkBuffer.js +0 -40
  375. package/build/inputChunkBuffer.test.js +0 -34
  376. package/build/inputCompanion.d.ts +0 -18
  377. package/build/inputCompanion.js +0 -28
  378. package/build/invariantDefined.d.ts +0 -1
  379. package/build/invariantDefined.js +0 -5
  380. package/build/invariantIdentity.d.ts +0 -3
  381. package/build/invariantIdentity.js +0 -5
  382. package/build/javaKeystoreParser.d.ts +0 -2
  383. package/build/javaKeystoreParser.js +0 -7
  384. package/build/jsonParser2.d.ts +0 -3
  385. package/build/jsonParser2.js +0 -52
  386. package/build/jsonParser2.test.js +0 -22
  387. package/build/negativeLookahead.d.ts +0 -2
  388. package/build/negativeLookahead.js +0 -18
  389. package/build/parserCompose.d.ts +0 -3
  390. package/build/parserCompose.js +0 -7
  391. package/build/parserImplementationInvariantInvariant.d.ts +0 -3
  392. package/build/parserImplementationInvariantInvariant.js +0 -15
  393. package/build/parserInvariant.d.ts +0 -4
  394. package/build/parserInvariant.js +0 -11
  395. package/build/promiseFish.d.ts +0 -1
  396. package/build/promiseFish.js +0 -3
  397. package/build/sequenceParser.d.ts +0 -3
  398. package/build/sequenceParser.js +0 -10
  399. package/build/terminatedSequenceParser.d.ts +0 -2
  400. package/build/terminatedSequenceParser.js +0 -24
  401. package/build/unparserInputCompanion.d.ts +0 -15
  402. package/build/unparserInputCompanion.js +0 -13
  403. package/build/zipEntry.d.ts +0 -28
  404. package/build/zipFile.d.ts +0 -32
  405. package/build/zipFileEntry.d.ts +0 -6
  406. package/src/apk.ts +0 -48
  407. package/src/apkParser.test.ts +0 -30
  408. package/src/apkParser.test.ts.snap +0 -0
  409. package/src/apkParser.ts +0 -392
  410. package/src/apkUnparser.test.ts +0 -37
  411. package/src/apkUnparser.ts +0 -120
  412. package/src/invariantDefined.ts +0 -6
  413. package/src/invariantIdentity.ts +0 -8
  414. /package/build/{apk.js → androidPackage.js} +0 -0
  415. /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
  416. /package/build/{apkUnparser.test.d.ts → androidPackageUnparser.test.d.ts} +0 -0
  417. /package/build/{arbitraryDosPermissions.d.ts → dalvikBytecodeUnparser.test.d.ts} +0 -0
  418. /package/build/{arbitraryDosPermissions.js → dalvikExecutableParser.test.d.ts} +0 -0
  419. /package/build/{inputChunkBuffer.test.d.ts → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
  420. /package/build/{jsonParser2.test.d.ts → dalvikExecutableUnparser.test.d.ts} +0 -0
  421. /package/build/{parserParsingInvariant.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
  422. /package/build/{parserParsingInvariant.js → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
  423. /package/build/{zipEntry.js → elementTerminatedSequenceParser.test.d.ts} +0 -0
  424. /package/build/{zipFile.js → fetchCid.test.d.ts} +0 -0
  425. /package/build/{zipFileEntry.js → fixedLengthSequenceParser.test.d.ts} +0 -0
@@ -0,0 +1,758 @@
1
+ import { type Unparser, type UnparserResult } from './unparser.js';
2
+ import { type UnparserContext } from './unparserContext.js';
3
+ import { type DalvikBytecode, type DalvikBytecodeOperation } from './dalvikBytecodeParser.js';
4
+ import {
5
+ isoIndexIntoStringIds,
6
+ isoIndexIntoTypeIds,
7
+ isoIndexIntoMethodIds,
8
+ isoIndexIntoFieldIds,
9
+ isoIndexIntoPrototypeIds,
10
+ } from './dalvikExecutableParser/typedNumbers.js';
11
+ import {
12
+ ubyteUnparser,
13
+ dalvikBytecodeFormat10tUnparser,
14
+ dalvikBytecodeFormat10xUnparser,
15
+ dalvikBytecodeFormat11xUnparser,
16
+ dalvikBytecodeFormat11nUnparser,
17
+ dalvikBytecodeFormat12xUnparser,
18
+ dalvikBytecodeFormat12xReversedUnparser,
19
+ dalvikBytecodeFormat20tUnparser,
20
+ dalvikBytecodeFormat21cUnparser,
21
+ dalvikBytecodeFormat21hUnparser,
22
+ dalvikBytecodeFormat21tUnparser,
23
+ dalvikBytecodeFormat21sUnparser,
24
+ dalvikBytecodeFormat22bUnparser,
25
+ dalvikBytecodeFormat22cUnparser,
26
+ dalvikBytecodeFormat22sUnparser,
27
+ dalvikBytecodeFormat22tUnparser,
28
+ dalvikBytecodeFormat22tCommutativeUnparser,
29
+ dalvikBytecodeFormat22xUnparser,
30
+ dalvikBytecodeFormat23xUnparser,
31
+ dalvikBytecodeFormat30tUnparser,
32
+ dalvikBytecodeFormat31iUnparser,
33
+ dalvikBytecodeFormat31cUnparser,
34
+ dalvikBytecodeFormat31tUnparser,
35
+ dalvikBytecodeFormat32xUnparser,
36
+ dalvikBytecodeFormat35cUnparser,
37
+ dalvikBytecodeFormat3rcUnparser,
38
+ dalvikBytecodeFormat51lUnparser,
39
+ dalvikBytecodeFormat45ccUnparser,
40
+ dalvikBytecodeFormat4rccUnparser,
41
+ dalvikBytecodeOperationPackedSwitchPayloadUnparser,
42
+ dalvikBytecodeOperationSparseSwitchPayloadUnparser,
43
+ dalvikBytecodeOperationFillArrayDataPayloadUnparser,
44
+ ushortUnparser,
45
+ } from './dalvikBytecodeUnparser/formatUnparsers.js';
46
+
47
+ // Reverse opcode mapping: operation name → opcode
48
+ const operationToOpcodeMap: Map<string, number> = new Map([
49
+ // nop is multi-byte (0x0000 or payload instructions)
50
+ [ 'nop', 0x00 ],
51
+
52
+ // Move operations
53
+ [ 'move', 0x01 ],
54
+ [ 'move/from16', 0x02 ],
55
+ [ 'move-wide', 0x04 ],
56
+ [ 'move-wide/from16', 0x05 ],
57
+ [ 'move-wide/16', 0x06 ],
58
+ [ 'move-object', 0x07 ],
59
+ [ 'move-object/from16', 0x08 ],
60
+ [ 'move-result', 0x0A ],
61
+ [ 'move-result-wide', 0x0B ],
62
+ [ 'move-result-object', 0x0C ],
63
+ [ 'move-exception', 0x0D ],
64
+
65
+ // Return operations
66
+ [ 'return-void', 0x0E ],
67
+ [ 'return', 0x0F ],
68
+ [ 'return-wide', 0x10 ],
69
+ [ 'return-object', 0x11 ],
70
+
71
+ // Const operations
72
+ [ 'const/4', 0x12 ],
73
+ [ 'const/16', 0x13 ],
74
+ [ 'const', 0x14 ],
75
+ [ 'const/high16', 0x15 ],
76
+ [ 'const-wide/16', 0x16 ],
77
+ [ 'const-wide/32', 0x17 ],
78
+ [ 'const-wide', 0x18 ],
79
+ [ 'const-wide/high16', 0x19 ],
80
+ [ 'const-string', 0x1A ],
81
+ [ 'const-string/jumbo', 0x1B ],
82
+ [ 'const-class', 0x1C ],
83
+
84
+ // Monitor operations
85
+ [ 'monitor-enter', 0x1D ],
86
+ [ 'monitor-exit', 0x1E ],
87
+
88
+ // Type operations
89
+ [ 'check-cast', 0x1F ],
90
+ [ 'instance-of', 0x20 ],
91
+
92
+ // Array operations
93
+ [ 'array-length', 0x21 ],
94
+ [ 'new-instance', 0x22 ],
95
+ [ 'new-array', 0x23 ],
96
+ [ 'filled-new-array', 0x24 ],
97
+ [ 'filled-new-array/range', 0x25 ],
98
+ [ 'fill-array-data', 0x26 ],
99
+
100
+ // Throw
101
+ [ 'throw', 0x27 ],
102
+
103
+ // Goto operations
104
+ [ 'goto', 0x28 ],
105
+ [ 'goto/16', 0x29 ],
106
+ [ 'goto/32', 0x2A ],
107
+ [ 'packed-switch', 0x2B ],
108
+ [ 'sparse-switch', 0x2C ],
109
+
110
+ // Compare operations
111
+ [ 'cmpl-float', 0x2D ],
112
+ [ 'cmpg-float', 0x2E ],
113
+ [ 'cmpl-double', 0x2F ],
114
+ [ 'cmpg-double', 0x30 ],
115
+ [ 'cmp-long', 0x31 ],
116
+
117
+ // If-test operations
118
+ [ 'if-eq', 0x32 ],
119
+ [ 'if-ne', 0x33 ],
120
+ [ 'if-lt', 0x34 ],
121
+ [ 'if-ge', 0x35 ],
122
+ [ 'if-gt', 0x36 ],
123
+ [ 'if-le', 0x37 ],
124
+
125
+ // If-test-zero operations
126
+ [ 'if-eqz', 0x38 ],
127
+ [ 'if-nez', 0x39 ],
128
+ [ 'if-ltz', 0x3A ],
129
+ [ 'if-gez', 0x3B ],
130
+ [ 'if-gtz', 0x3C ],
131
+ [ 'if-lez', 0x3D ],
132
+
133
+ // Array element operations
134
+ [ 'aget', 0x44 ],
135
+ [ 'aget-wide', 0x45 ],
136
+ [ 'aget-object', 0x46 ],
137
+ [ 'aget-boolean', 0x47 ],
138
+ [ 'aget-byte', 0x48 ],
139
+ [ 'aget-char', 0x49 ],
140
+ [ 'aget-short', 0x4A ],
141
+ [ 'aput', 0x4B ],
142
+ [ 'aput-wide', 0x4C ],
143
+ [ 'aput-object', 0x4D ],
144
+ [ 'aput-boolean', 0x4E ],
145
+ [ 'aput-byte', 0x4F ],
146
+ [ 'aput-char', 0x50 ],
147
+ [ 'aput-short', 0x51 ],
148
+
149
+ // Instance field operations
150
+ [ 'iget', 0x52 ],
151
+ [ 'iget-wide', 0x53 ],
152
+ [ 'iget-object', 0x54 ],
153
+ [ 'iget-boolean', 0x55 ],
154
+ [ 'iget-byte', 0x56 ],
155
+ [ 'iget-char', 0x57 ],
156
+ [ 'iget-short', 0x58 ],
157
+ [ 'iput', 0x59 ],
158
+ [ 'iput-wide', 0x5A ],
159
+ [ 'iput-object', 0x5B ],
160
+ [ 'iput-boolean', 0x5C ],
161
+ [ 'iput-byte', 0x5D ],
162
+ [ 'iput-char', 0x5E ],
163
+ [ 'iput-short', 0x5F ],
164
+
165
+ // Static field operations
166
+ [ 'sget', 0x60 ],
167
+ [ 'sget-wide', 0x61 ],
168
+ [ 'sget-object', 0x62 ],
169
+ [ 'sget-boolean', 0x63 ],
170
+ [ 'sget-byte', 0x64 ],
171
+ [ 'sget-char', 0x65 ],
172
+ [ 'sget-short', 0x66 ],
173
+ [ 'sput', 0x67 ],
174
+ [ 'sput-wide', 0x68 ],
175
+ [ 'sput-object', 0x69 ],
176
+ [ 'sput-boolean', 0x6A ],
177
+ [ 'sput-byte', 0x6B ],
178
+ [ 'sput-char', 0x6C ],
179
+ [ 'sput-short', 0x6D ],
180
+
181
+ // Invoke operations
182
+ [ 'invoke-virtual', 0x6E ],
183
+ [ 'invoke-super', 0x6F ],
184
+ [ 'invoke-direct', 0x70 ],
185
+ [ 'invoke-static', 0x71 ],
186
+ [ 'invoke-interface', 0x72 ],
187
+ [ 'invoke-virtual/range', 0x74 ],
188
+ [ 'invoke-super/range', 0x75 ],
189
+ [ 'invoke-direct/range', 0x76 ],
190
+ [ 'invoke-static/range', 0x77 ],
191
+ [ 'invoke-interface/range', 0x78 ],
192
+
193
+ // Unary operations
194
+ [ 'neg-int', 0x7B ],
195
+ [ 'not-int', 0x7C ],
196
+ [ 'neg-long', 0x7D ],
197
+ [ 'not-long', 0x7E ],
198
+ [ 'neg-float', 0x7F ],
199
+ [ 'neg-double', 0x80 ],
200
+ [ 'int-to-long', 0x81 ],
201
+ [ 'int-to-float', 0x82 ],
202
+ [ 'int-to-double', 0x83 ],
203
+ [ 'long-to-int', 0x84 ],
204
+ [ 'long-to-float', 0x85 ],
205
+ [ 'long-to-double', 0x86 ],
206
+ [ 'float-to-int', 0x87 ],
207
+ [ 'float-to-long', 0x88 ],
208
+ [ 'float-to-double', 0x89 ],
209
+ [ 'double-to-int', 0x8A ],
210
+ [ 'double-to-long', 0x8B ],
211
+ [ 'double-to-float', 0x8C ],
212
+ [ 'int-to-byte', 0x8D ],
213
+ [ 'int-to-char', 0x8E ],
214
+ [ 'int-to-short', 0x8F ],
215
+
216
+ // Binary operations
217
+ [ 'add-int', 0x90 ],
218
+ [ 'sub-int', 0x91 ],
219
+ [ 'mul-int', 0x92 ],
220
+ [ 'div-int', 0x93 ],
221
+ [ 'rem-int', 0x94 ],
222
+ [ 'and-int', 0x95 ],
223
+ [ 'or-int', 0x96 ],
224
+ [ 'xor-int', 0x97 ],
225
+ [ 'shl-int', 0x98 ],
226
+ [ 'shr-int', 0x99 ],
227
+ [ 'ushr-int', 0x9A ],
228
+ [ 'add-long', 0x9B ],
229
+ [ 'sub-long', 0x9C ],
230
+ [ 'mul-long', 0x9D ],
231
+ [ 'div-long', 0x9E ],
232
+ [ 'rem-long', 0x9F ],
233
+ [ 'and-long', 0xA0 ],
234
+ [ 'or-long', 0xA1 ],
235
+ [ 'xor-long', 0xA2 ],
236
+ [ 'shl-long', 0xA3 ],
237
+ [ 'shr-long', 0xA4 ],
238
+ [ 'ushr-long', 0xA5 ],
239
+ [ 'add-float', 0xA6 ],
240
+ [ 'sub-float', 0xA7 ],
241
+ [ 'mul-float', 0xA8 ],
242
+ [ 'div-float', 0xA9 ],
243
+ [ 'add-double', 0xAB ],
244
+ [ 'sub-double', 0xAC ],
245
+ [ 'mul-double', 0xAD ],
246
+ [ 'div-double', 0xAE ],
247
+ [ 'rem-double', 0xAF ],
248
+
249
+ // Binary operations in place (2addr)
250
+ [ 'add-int/2addr', 0xB0 ],
251
+ [ 'sub-int/2addr', 0xB1 ],
252
+ [ 'mul-int/2addr', 0xB2 ],
253
+ [ 'div-int/2addr', 0xB3 ],
254
+ [ 'rem-int/2addr', 0xB4 ],
255
+ [ 'and-int/2addr', 0xB5 ],
256
+ [ 'or-int/2addr', 0xB6 ],
257
+ [ 'xor-int/2addr', 0xB7 ],
258
+ [ 'shl-int/2addr', 0xB8 ],
259
+ [ 'shr-int/2addr', 0xB9 ],
260
+ [ 'ushr-int/2addr', 0xBA ],
261
+ [ 'add-long/2addr', 0xBB ],
262
+ [ 'sub-long/2addr', 0xBC ],
263
+ [ 'mul-long/2addr', 0xBD ],
264
+ [ 'div-long/2addr', 0xBE ],
265
+ [ 'rem-long/2addr', 0xBF ],
266
+ [ 'and-long/2addr', 0xC0 ],
267
+ [ 'or-long/2addr', 0xC1 ],
268
+ [ 'xor-long/2addr', 0xC2 ],
269
+ [ 'shl-long/2addr', 0xC3 ],
270
+ [ 'shr-long/2addr', 0xC4 ],
271
+ [ 'ushr-long/2addr', 0xC5 ],
272
+ [ 'add-float/2addr', 0xC6 ],
273
+ [ 'sub-float/2addr', 0xC7 ],
274
+ [ 'mul-float/2addr', 0xC8 ],
275
+ [ 'div-float/2addr', 0xC9 ],
276
+ [ 'rem-float/2addr', 0xCA ],
277
+ [ 'add-double/2addr', 0xCB ],
278
+ [ 'sub-double/2addr', 0xCC ],
279
+ [ 'mul-double/2addr', 0xCD ],
280
+ [ 'div-double/2addr', 0xCE ],
281
+ [ 'rem-double/2addr', 0xCF ],
282
+
283
+ // Binary operations with literal16
284
+ [ 'add-int/lit16', 0xD0 ],
285
+ [ 'rsub-int', 0xD1 ],
286
+ [ 'mul-int/lit16', 0xD2 ],
287
+ [ 'div-int/lit16', 0xD3 ],
288
+ [ 'rem-int/lit16', 0xD4 ],
289
+ [ 'and-int/lit16', 0xD5 ],
290
+ [ 'or-int/lit16', 0xD6 ],
291
+ [ 'xor-int/lit16', 0xD7 ],
292
+
293
+ // Binary operations with literal8
294
+ [ 'add-int/lit8', 0xD8 ],
295
+ [ 'rsub-int/lit8', 0xD9 ],
296
+ [ 'mul-int/lit8', 0xDA ],
297
+ [ 'div-int/lit8', 0xDB ],
298
+ [ 'rem-int/lit8', 0xDC ],
299
+ [ 'and-int/lit8', 0xDD ],
300
+ [ 'or-int/lit8', 0xDE ],
301
+ [ 'xor-int/lit8', 0xDF ],
302
+ [ 'shl-int/lit8', 0xE0 ],
303
+ [ 'shr-int/lit8', 0xE1 ],
304
+ [ 'ushr-int/lit8', 0xE2 ],
305
+
306
+ // Invoke polymorphic
307
+ [ 'invoke-polymorphic', 0xFA ],
308
+ [ 'invoke-polymorphic/range', 0xFB ],
309
+ [ 'const-method-handle', 0xFE ],
310
+
311
+ // Note: Payload instructions don't have single-byte opcodes
312
+ // They use multi-byte identifiers: 0x0100, 0x0200, 0x0300
313
+ ]);
314
+
315
+ export const dalvikBytecodeUnparser: Unparser<DalvikBytecode, Uint8Array> = async function * (input, unparserContext) {
316
+ for (const operation of input) {
317
+ yield * dalvikBytecodeOperationUnparser(operation, unparserContext);
318
+ }
319
+ };
320
+
321
+ // Type guards for payload operations
322
+ function isPackedSwitchPayload(op: DalvikBytecodeOperation): op is { operation: 'packed-switch-payload'; value: number; branchOffsets: number[] } {
323
+ return typeof op === 'object' && op !== null && 'operation' in op && op.operation === 'packed-switch-payload';
324
+ }
325
+
326
+ function isSparseSwitchPayload(op: DalvikBytecodeOperation): op is { operation: 'sparse-switch-payload'; keys: number[]; branchOffsets: number[] } {
327
+ return typeof op === 'object' && op !== null && 'operation' in op && op.operation === 'sparse-switch-payload';
328
+ }
329
+
330
+ function isFillArrayDataPayload(op: DalvikBytecodeOperation): op is { operation: 'fill-array-data-payload'; elementWidth: number; data: number[] } {
331
+ return typeof op === 'object' && op !== null && 'operation' in op && op.operation === 'fill-array-data-payload';
332
+ }
333
+
334
+ const dalvikBytecodeOperationUnparser: Unparser<DalvikBytecodeOperation, Uint8Array> = async function * (operation, unparserContext) {
335
+ if (!operation || typeof operation !== 'object' || !('operation' in operation)) {
336
+ throw new Error('Invalid operation');
337
+ }
338
+
339
+ const operationName = operation.operation;
340
+
341
+ // Handle payload instructions (multi-byte opcodes)
342
+ if (isPackedSwitchPayload(operation)) {
343
+ yield * dalvikBytecodeOperationPackedSwitchPayloadUnparser(operation, unparserContext);
344
+ return;
345
+ }
346
+
347
+ if (isSparseSwitchPayload(operation)) {
348
+ yield * dalvikBytecodeOperationSparseSwitchPayloadUnparser(operation, unparserContext);
349
+ return;
350
+ }
351
+
352
+ if (isFillArrayDataPayload(operation)) {
353
+ yield * dalvikBytecodeOperationFillArrayDataPayloadUnparser(operation, unparserContext);
354
+ return;
355
+ }
356
+
357
+ // Handle nop (can be 0x00_00 or just 0x00)
358
+ if (operationName === 'nop') {
359
+ yield * ushortUnparser(0x00_00, unparserContext);
360
+ return;
361
+ }
362
+
363
+ // Get opcode for regular operations
364
+ const opcode = operationToOpcodeMap.get(operationName);
365
+ if (opcode === undefined) {
366
+ throw new Error(`Unknown operation: ${operationName}`);
367
+ }
368
+
369
+ // Write opcode
370
+ yield * ubyteUnparser(opcode, unparserContext);
371
+
372
+ // Write operation-specific data based on operation type
373
+ yield * unparseOperationData(operation, unparserContext);
374
+ };
375
+
376
+ // Helper to check if operation has specific fields
377
+ function hasRegisters(op: DalvikBytecodeOperation): op is DalvikBytecodeOperation & { registers: number[] } {
378
+ return 'registers' in op;
379
+ }
380
+
381
+ function hasValue(op: DalvikBytecodeOperation): op is DalvikBytecodeOperation & { value: number | bigint } {
382
+ return 'value' in op;
383
+ }
384
+
385
+ function hasBranchOffset(op: DalvikBytecodeOperation): op is DalvikBytecodeOperation & { branchOffset: number } {
386
+ return 'branchOffset' in op;
387
+ }
388
+
389
+ async function * unparseOperationData(operation: DalvikBytecodeOperation, unparserContext: UnparserContext<Uint8Array, number>): UnparserResult<Uint8Array, number> {
390
+ if (!('operation' in operation)) {
391
+ throw new Error('Invalid operation structure');
392
+ }
393
+
394
+ const operationName = operation.operation;
395
+
396
+ // The operation data varies by instruction format
397
+ // We need to determine which format unparser to call based on the operation type
398
+
399
+ // Format 10x operations (no additional data besides zero byte)
400
+ if (operationName === 'nop' || operationName === 'return-void') {
401
+ yield * dalvikBytecodeFormat10xUnparser(undefined, unparserContext);
402
+ return;
403
+ }
404
+
405
+ // Format 11x operations (single register)
406
+ if (operationName === 'move-result' || operationName === 'move-result-wide' ||
407
+ operationName === 'move-result-object' || operationName === 'move-exception' ||
408
+ operationName === 'return' || operationName === 'return-wide' ||
409
+ operationName === 'return-object' || operationName === 'monitor-enter' ||
410
+ operationName === 'monitor-exit' || operationName === 'throw') {
411
+ if (!hasRegisters(operation)) {
412
+ throw new Error(`Operation ${operationName} missing registers field`);
413
+ }
414
+ yield * dalvikBytecodeFormat11xUnparser({ registers: operation.registers }, unparserContext);
415
+ return;
416
+ }
417
+
418
+ // array-length uses format 12x but reverses registers in parser
419
+ if (operationName === 'array-length') {
420
+ if (!hasRegisters(operation)) {
421
+ throw new Error(`Operation ${operationName} missing registers field`);
422
+ }
423
+ yield * dalvikBytecodeFormat12xReversedUnparser({ registers: operation.registers }, unparserContext);
424
+ return;
425
+ }
426
+
427
+ // Format 12x operations (two registers in nibbles)
428
+ if (operationName === 'move' || operationName === 'move-wide' || operationName === 'move-object' ||
429
+ operationName === 'neg-int' || operationName === 'not-int' ||
430
+ operationName === 'neg-long' || operationName === 'not-long' ||
431
+ operationName === 'neg-float' || operationName === 'neg-double' ||
432
+ operationName === 'int-to-long' || operationName === 'int-to-float' || operationName === 'int-to-double' ||
433
+ operationName === 'long-to-int' || operationName === 'long-to-float' || operationName === 'long-to-double' ||
434
+ operationName === 'float-to-int' || operationName === 'float-to-long' || operationName === 'float-to-double' ||
435
+ operationName === 'double-to-int' || operationName === 'double-to-long' || operationName === 'double-to-float' ||
436
+ operationName === 'int-to-byte' || operationName === 'int-to-char' || operationName === 'int-to-short' ||
437
+ operationName === 'add-int/2addr' || operationName === 'sub-int/2addr' || operationName === 'mul-int/2addr' ||
438
+ operationName === 'div-int/2addr' || operationName === 'rem-int/2addr' || operationName === 'and-int/2addr' ||
439
+ operationName === 'or-int/2addr' || operationName === 'xor-int/2addr' || operationName === 'shl-int/2addr' ||
440
+ operationName === 'shr-int/2addr' || operationName === 'ushr-int/2addr' ||
441
+ operationName === 'add-long/2addr' || operationName === 'sub-long/2addr' || operationName === 'mul-long/2addr' ||
442
+ operationName === 'div-long/2addr' || operationName === 'rem-long/2addr' || operationName === 'and-long/2addr' ||
443
+ operationName === 'or-long/2addr' || operationName === 'xor-long/2addr' || operationName === 'shl-long/2addr' ||
444
+ operationName === 'shr-long/2addr' || operationName === 'ushr-long/2addr' ||
445
+ operationName === 'add-float/2addr' || operationName === 'sub-float/2addr' || operationName === 'mul-float/2addr' ||
446
+ operationName === 'div-float/2addr' || operationName === 'rem-float/2addr' ||
447
+ operationName === 'add-double/2addr' || operationName === 'sub-double/2addr' || operationName === 'mul-double/2addr' ||
448
+ operationName === 'div-double/2addr' || operationName === 'rem-double/2addr') {
449
+ if (!hasRegisters(operation)) {
450
+ throw new Error(`Operation ${operationName} missing registers field`);
451
+ }
452
+ yield * dalvikBytecodeFormat12xUnparser({ registers: operation.registers }, unparserContext);
453
+ return;
454
+ }
455
+
456
+ // Format 11n (const/4)
457
+ if (operationName === 'const/4') {
458
+ if (!hasValue(operation) || !hasRegisters(operation)) {
459
+ throw new Error(`Operation ${operationName} missing value or registers field`);
460
+ }
461
+ yield * dalvikBytecodeFormat11nUnparser({ value: operation.value as number, registers: operation.registers }, unparserContext);
462
+ return;
463
+ }
464
+
465
+ // Format 21s (const/16, const-wide/16)
466
+ if (operationName === 'const/16') {
467
+ if (!hasValue(operation) || !hasRegisters(operation)) {
468
+ throw new Error(`Operation ${operationName} missing value or registers field`);
469
+ }
470
+ yield * dalvikBytecodeFormat21sUnparser({ registers: operation.registers, value: operation.value as number }, unparserContext);
471
+ return;
472
+ }
473
+
474
+ if (operationName === 'const-wide/16') {
475
+ if (!hasValue(operation) || !hasRegisters(operation)) {
476
+ throw new Error(`Operation ${operationName} missing value or registers field`);
477
+ }
478
+ // Value is bigint, but format 21s expects a signed 16-bit number
479
+ // The parser sign-extends the 16-bit value to 64 bits, so we need to extract the low 16 bits
480
+ const value = Number((operation.value as bigint) & 0xFFFFn);
481
+ // Convert unsigned 16-bit to signed 16-bit
482
+ const signedValue = value > 32767 ? value - 65536 : value;
483
+ yield * dalvikBytecodeFormat21sUnparser({ registers: operation.registers, value: signedValue }, unparserContext);
484
+ return;
485
+ }
486
+
487
+ // Format 31i (const, const-wide/32)
488
+ if (operationName === 'const' || operationName === 'const-wide/32') {
489
+ if (!hasValue(operation) || !hasRegisters(operation)) {
490
+ throw new Error(`Operation ${operationName} missing value or registers field`);
491
+ }
492
+ // For const-wide/32, value is bigint but we need to convert to signed 32-bit number
493
+ const value = typeof operation.value === 'bigint'
494
+ ? Number(BigInt.asIntN(32, operation.value))
495
+ : operation.value as number;
496
+ yield * dalvikBytecodeFormat31iUnparser({ value, registers: operation.registers }, unparserContext);
497
+ return;
498
+ }
499
+
500
+ // Format 21h (const/high16, const-wide/high16)
501
+ if (operationName === 'const/high16' || operationName === 'const-wide/high16') {
502
+ if (!hasValue(operation) || !hasRegisters(operation)) {
503
+ throw new Error(`Operation ${operationName} missing value or registers field`);
504
+ }
505
+ // The value is stored shifted left (16 bits for const/high16, 48 bits for const-wide/high16)
506
+ // Shift it back for unparsing. Use unsigned shift to handle negative values correctly.
507
+ const value = operationName === 'const-wide/high16'
508
+ ? Number((operation.value as bigint) >> 48n) & 0xFFFF
509
+ : ((operation.value as number) >>> 16) & 0xFFFF;
510
+ yield * dalvikBytecodeFormat21hUnparser({ value, registers: operation.registers }, unparserContext);
511
+ return;
512
+ }
513
+
514
+ // Format 51l (const-wide)
515
+ if (operationName === 'const-wide') {
516
+ if (!hasValue(operation) || !hasRegisters(operation)) {
517
+ throw new Error(`Operation ${operationName} missing value or registers field`);
518
+ }
519
+ yield * dalvikBytecodeFormat51lUnparser({ value: operation.value as bigint, registers: operation.registers }, unparserContext);
520
+ return;
521
+ }
522
+
523
+ // Format 21c (const-string, const-class, check-cast, new-instance)
524
+ if (operationName === 'const-string' || operationName === 'const-class' ||
525
+ operationName === 'check-cast' || operationName === 'new-instance') {
526
+ if (!hasRegisters(operation)) {
527
+ throw new Error(`Operation ${operationName} missing registers field`);
528
+ }
529
+ // Extract and unwrap the index from stringIndex or typeIndex fields
530
+ const index = 'stringIndex' in operation ? isoIndexIntoStringIds.unwrap(operation.stringIndex) :
531
+ 'typeIndex' in operation ? isoIndexIntoTypeIds.unwrap(operation.typeIndex) : 0;
532
+ yield * dalvikBytecodeFormat21cUnparser({ index, registers: operation.registers }, unparserContext);
533
+ return;
534
+ }
535
+
536
+ // Format 22c (instance-of, new-array, iget*, iput*)
537
+ if (operationName === 'instance-of' || operationName === 'new-array' ||
538
+ operationName.startsWith('iget') || operationName.startsWith('iput')) {
539
+ if (!hasRegisters(operation)) {
540
+ throw new Error(`Operation ${operationName} missing registers field`);
541
+ }
542
+ // Extract and unwrap the index from typeIndex or fieldIndex fields
543
+ const index = 'typeIndex' in operation ? isoIndexIntoTypeIds.unwrap(operation.typeIndex) :
544
+ 'fieldIndex' in operation ? isoIndexIntoFieldIds.unwrap(operation.fieldIndex) : 0;
545
+ yield * dalvikBytecodeFormat22cUnparser({ registers: operation.registers, index }, unparserContext);
546
+ return;
547
+ }
548
+
549
+ // Format 21c (sget*, sput* - static field operations)
550
+ if (operationName.startsWith('sget') || operationName.startsWith('sput')) {
551
+ if (!hasRegisters(operation)) {
552
+ throw new Error(`Operation ${operationName} missing registers field`);
553
+ }
554
+ // Extract and unwrap the index from fieldIndex field
555
+ const index = 'fieldIndex' in operation ? isoIndexIntoFieldIds.unwrap(operation.fieldIndex) : 0;
556
+ yield * dalvikBytecodeFormat21cUnparser({ index, registers: operation.registers }, unparserContext);
557
+ return;
558
+ }
559
+
560
+ // Format 23x (aget*, aput*, binary operations)
561
+ if (operationName.startsWith('aget') || operationName.startsWith('aput') ||
562
+ operationName === 'add-int' || operationName === 'sub-int' || operationName === 'mul-int' ||
563
+ operationName === 'div-int' || operationName === 'rem-int' || operationName === 'and-int' ||
564
+ operationName === 'or-int' || operationName === 'xor-int' || operationName === 'shl-int' ||
565
+ operationName === 'shr-int' || operationName === 'ushr-int' ||
566
+ operationName === 'add-long' || operationName === 'sub-long' || operationName === 'mul-long' ||
567
+ operationName === 'div-long' || operationName === 'rem-long' || operationName === 'and-long' ||
568
+ operationName === 'or-long' || operationName === 'xor-long' || operationName === 'shl-long' ||
569
+ operationName === 'shr-long' || operationName === 'ushr-long' ||
570
+ operationName === 'add-float' || operationName === 'sub-float' || operationName === 'mul-float' ||
571
+ operationName === 'div-float' ||
572
+ operationName === 'add-double' || operationName === 'sub-double' || operationName === 'mul-double' ||
573
+ operationName === 'div-double' || operationName === 'rem-double' ||
574
+ operationName === 'cmp-long' || operationName === 'cmpl-float' || operationName === 'cmpg-float' ||
575
+ operationName === 'cmpl-double' || operationName === 'cmpg-double') {
576
+ if (!hasRegisters(operation)) {
577
+ throw new Error(`Operation ${operationName} missing registers field`);
578
+ }
579
+ yield * dalvikBytecodeFormat23xUnparser({ registers: operation.registers }, unparserContext);
580
+ return;
581
+ }
582
+
583
+ // Format 22x (move/from16, move-wide/from16, move-object/from16)
584
+ if (operationName === 'move/from16' || operationName === 'move-wide/from16' ||
585
+ operationName === 'move-object/from16') {
586
+ if (!hasRegisters(operation)) {
587
+ throw new Error(`Operation ${operationName} missing registers field`);
588
+ }
589
+ yield * dalvikBytecodeFormat22xUnparser({ registers: operation.registers }, unparserContext);
590
+ return;
591
+ }
592
+
593
+ // Format 32x (move-wide/16)
594
+ if (operationName === 'move-wide/16') {
595
+ if (!hasRegisters(operation)) {
596
+ throw new Error(`Operation ${operationName} missing registers field`);
597
+ }
598
+ yield * dalvikBytecodeFormat32xUnparser({ registers: operation.registers }, unparserContext);
599
+ return;
600
+ }
601
+
602
+ // Format 10t (goto)
603
+ if (operationName === 'goto') {
604
+ if (!hasBranchOffset(operation)) {
605
+ throw new Error(`Operation ${operationName} missing branchOffset field`);
606
+ }
607
+ yield * dalvikBytecodeFormat10tUnparser({ branchOffset: operation.branchOffset }, unparserContext);
608
+ return;
609
+ }
610
+
611
+ // Format 20t (goto/16)
612
+ if (operationName === 'goto/16') {
613
+ if (!hasBranchOffset(operation)) {
614
+ throw new Error(`Operation ${operationName} missing branchOffset field`);
615
+ }
616
+ yield * dalvikBytecodeFormat20tUnparser({ branchOffset: operation.branchOffset }, unparserContext);
617
+ return;
618
+ }
619
+
620
+ // Format 30t (goto/32)
621
+ if (operationName === 'goto/32') {
622
+ if (!hasBranchOffset(operation)) {
623
+ throw new Error(`Operation ${operationName} missing branchOffset field`);
624
+ }
625
+ yield * dalvikBytecodeFormat30tUnparser({ branchOffset: operation.branchOffset }, unparserContext);
626
+ return;
627
+ }
628
+
629
+ // Format 22t (if-* operations)
630
+ if (operationName.startsWith('if-') && !operationName.endsWith('z')) {
631
+ if (!hasBranchOffset(operation) || !hasRegisters(operation)) {
632
+ throw new Error(`Operation ${operationName} missing branchOffset or registers field`);
633
+ }
634
+ // Commutative operations (if-eq, if-ne) have sorted registers, so don't reverse
635
+ const isCommutative = operationName === 'if-eq' || operationName === 'if-ne';
636
+ const unparser = isCommutative ? dalvikBytecodeFormat22tCommutativeUnparser : dalvikBytecodeFormat22tUnparser;
637
+ yield * unparser({ branchOffset: operation.branchOffset, registers: operation.registers }, unparserContext);
638
+ return;
639
+ }
640
+
641
+ // Format 21t (if-*z operations)
642
+ if (operationName.startsWith('if-') && operationName.endsWith('z')) {
643
+ if (!hasBranchOffset(operation) || !hasRegisters(operation)) {
644
+ throw new Error(`Operation ${operationName} missing branchOffset or registers field`);
645
+ }
646
+ yield * dalvikBytecodeFormat21tUnparser({ branchOffset: operation.branchOffset, registers: operation.registers }, unparserContext);
647
+ return;
648
+ }
649
+
650
+ // Format 31t (packed-switch, sparse-switch, fill-array-data)
651
+ if (operationName === 'packed-switch' || operationName === 'sparse-switch' ||
652
+ operationName === 'fill-array-data') {
653
+ if (!hasBranchOffset(operation) || !hasRegisters(operation)) {
654
+ throw new Error(`Operation ${operationName} missing branchOffset or registers field`);
655
+ }
656
+ yield * dalvikBytecodeFormat31tUnparser({ branchOffset: operation.branchOffset, registers: operation.registers }, unparserContext);
657
+ return;
658
+ }
659
+
660
+ // Format 22b (binary operations with literal8)
661
+ if (operationName.endsWith('/lit8')) {
662
+ if (!hasValue(operation) || !hasRegisters(operation)) {
663
+ throw new Error(`Operation ${operationName} missing value or registers field`);
664
+ }
665
+ yield * dalvikBytecodeFormat22bUnparser({ registers: operation.registers, value: operation.value as number }, unparserContext);
666
+ return;
667
+ }
668
+
669
+ // Format 22s (binary operations with literal16, rsub-int)
670
+ if (operationName.endsWith('/lit16') || operationName === 'rsub-int') {
671
+ if (!hasValue(operation) || !hasRegisters(operation)) {
672
+ throw new Error(`Operation ${operationName} missing value or registers field`);
673
+ }
674
+ yield * dalvikBytecodeFormat22sUnparser({ value: operation.value as number, registers: operation.registers }, unparserContext);
675
+ return;
676
+ }
677
+
678
+ // Format 45cc (invoke-polymorphic)
679
+ // Must be checked before generic invoke-* handler
680
+ if (operationName === 'invoke-polymorphic') {
681
+ if (!hasRegisters(operation)) {
682
+ throw new Error(`Operation ${operationName} missing registers field`);
683
+ }
684
+ const methodIndex = 'methodIndex' in operation ? isoIndexIntoMethodIds.unwrap(operation.methodIndex) : 0;
685
+ const protoIndex = 'protoIndex' in operation ? isoIndexIntoPrototypeIds.unwrap(operation.protoIndex) : 0;
686
+ yield * dalvikBytecodeFormat45ccUnparser({
687
+ methodIndex,
688
+ protoIndex,
689
+ registers: operation.registers
690
+ }, unparserContext);
691
+ return;
692
+ }
693
+
694
+ // Format 4rcc (invoke-polymorphic/range)
695
+ // Must be checked before generic /range handler
696
+ if (operationName === 'invoke-polymorphic/range') {
697
+ if (!hasRegisters(operation)) {
698
+ throw new Error(`Operation ${operationName} missing registers field`);
699
+ }
700
+ const methodIndex = 'methodIndex' in operation ? isoIndexIntoMethodIds.unwrap(operation.methodIndex) : 0;
701
+ const protoIndex = 'protoIndex' in operation ? isoIndexIntoPrototypeIds.unwrap(operation.protoIndex) : 0;
702
+ yield * dalvikBytecodeFormat4rccUnparser({
703
+ methodIndex,
704
+ protoIndex,
705
+ registers: operation.registers
706
+ }, unparserContext);
707
+ return;
708
+ }
709
+
710
+ // Format 35c (invoke-*, filled-new-array)
711
+ if ((operationName.startsWith('invoke-') && !operationName.endsWith('/range')) ||
712
+ operationName === 'filled-new-array') {
713
+ if (!hasRegisters(operation)) {
714
+ throw new Error(`Operation ${operationName} missing registers field`);
715
+ }
716
+ // Extract and unwrap the index from methodIndex or typeIndex fields
717
+ const index = 'methodIndex' in operation ? isoIndexIntoMethodIds.unwrap(operation.methodIndex) :
718
+ 'typeIndex' in operation ? isoIndexIntoTypeIds.unwrap(operation.typeIndex) : 0;
719
+ yield * dalvikBytecodeFormat35cUnparser({ index, registers: operation.registers }, unparserContext);
720
+ return;
721
+ }
722
+
723
+ // Format 3rc (invoke-*/range, filled-new-array/range)
724
+ if (operationName.endsWith('/range')) {
725
+ if (!hasRegisters(operation)) {
726
+ throw new Error(`Operation ${operationName} missing registers field`);
727
+ }
728
+ // Extract and unwrap the index from methodIndex or typeIndex fields
729
+ const index = 'methodIndex' in operation ? isoIndexIntoMethodIds.unwrap(operation.methodIndex) :
730
+ 'typeIndex' in operation ? isoIndexIntoTypeIds.unwrap(operation.typeIndex) : 0;
731
+ yield * dalvikBytecodeFormat3rcUnparser({ index, registers: operation.registers }, unparserContext);
732
+ return;
733
+ }
734
+
735
+ // Format 31c (const-string/jumbo)
736
+ if (operationName === 'const-string/jumbo') {
737
+ if (!hasRegisters(operation)) {
738
+ throw new Error(`Operation ${operationName} missing registers field`);
739
+ }
740
+ // Extract and unwrap the index from stringIndex field
741
+ const index = 'stringIndex' in operation ? isoIndexIntoStringIds.unwrap(operation.stringIndex) : 0;
742
+ yield * dalvikBytecodeFormat31cUnparser({ index, registers: operation.registers }, unparserContext);
743
+ return;
744
+ }
745
+
746
+ // Format 21c (const-method-handle)
747
+ if (operationName === 'const-method-handle') {
748
+ if (!hasRegisters(operation)) {
749
+ throw new Error(`Operation ${operationName} missing registers field`);
750
+ }
751
+ // Extract and unwrap the index from methodIndex field
752
+ const index = 'methodIndex' in operation ? isoIndexIntoMethodIds.unwrap(operation.methodIndex) : 0;
753
+ yield * dalvikBytecodeFormat21cUnparser({ index, registers: operation.registers }, unparserContext);
754
+ return;
755
+ }
756
+
757
+ throw new Error(`Unhandled operation format for: ${operationName}`);
758
+ }