@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,434 @@
1
+ import * as fc from 'fast-check';
2
+ import {
3
+ type DalvikExecutable,
4
+ type DalvikExecutableClassDefinition,
5
+ type DalvikExecutableAccessFlags,
6
+ type DalvikExecutableClassData,
7
+ type DalvikExecutableField,
8
+ type DalvikExecutableFieldWithAccess,
9
+ type DalvikExecutableMethod,
10
+ type DalvikExecutableMethodWithAccess,
11
+ type DalvikExecutablePrototype,
12
+ type DalvikExecutableCode,
13
+ type DalvikExecutableDebugInfo,
14
+ type DalvikExecutableAnnotation,
15
+ type DalvikExecutableClassAnnotations,
16
+ type DalvikExecutableClassFieldAnnotation,
17
+ type DalvikExecutableClassMethodAnnotation,
18
+ type DalvikExecutableClassParameterAnnotation,
19
+ type DalvikExecutableEncodedValue,
20
+ } from './dalvikExecutable.js';
21
+
22
+ // Local type definitions for non-exported types
23
+
24
+ type DalvikExecutableAnnotationItemVisibility = 'build' | 'runtime' | 'system';
25
+
26
+ type DalvikExecutableAnnotationElement = {
27
+ name: string;
28
+ value: DalvikExecutableEncodedValue;
29
+ };
30
+
31
+ type DalvikExecutableDebugByteCodeValue =
32
+ | { type: 'advancePc'; addressDiff: number }
33
+ | { type: 'advanceLine'; lineDiff: number }
34
+ | { type: 'startLocal'; registerNum: number; name: undefined | string; type_: undefined | string }
35
+ | { type: 'startLocalExtended'; registerNum: number; name: undefined | string; type_: undefined | string; signature: undefined | string }
36
+ | { type: 'endLocal'; registerNum: number }
37
+ | { type: 'restartLocal'; registerNum: number }
38
+ | { type: 'setPrologueEnd' }
39
+ | { type: 'setEpilogueBegin' }
40
+ | { type: 'setFile'; name: undefined | string }
41
+ | { type: 'special'; value: number };
42
+
43
+ // String generators for valid Dalvik identifiers and type descriptors
44
+
45
+ const arbitraryJavaIdentifier = fc.stringMatching(/^[a-zA-Z_][a-zA-Z0-9_]*$/);
46
+
47
+ const arbitraryPrimitiveType = fc.oneof(
48
+ fc.constant('V'), // void
49
+ fc.constant('Z'), // boolean
50
+ fc.constant('B'), // byte
51
+ fc.constant('S'), // short
52
+ fc.constant('C'), // char
53
+ fc.constant('I'), // int
54
+ fc.constant('J'), // long
55
+ fc.constant('F'), // float
56
+ fc.constant('D'), // double
57
+ );
58
+
59
+ const arbitraryDalvikClassName: fc.Arbitrary<string> = fc.tuple(
60
+ fc.array(arbitraryJavaIdentifier, { minLength: 1, maxLength: 3 }),
61
+ arbitraryJavaIdentifier,
62
+ ).map(([packages, className]) => `L${packages.join('/')}/${className};`);
63
+
64
+ const arbitraryDalvikTypeName: fc.Arbitrary<string> = fc.oneof(
65
+ arbitraryPrimitiveType,
66
+ arbitraryDalvikClassName,
67
+ arbitraryPrimitiveType.map(p => `[${p}`), // array of primitive
68
+ arbitraryDalvikClassName.map(c => `[${c}`), // array of object
69
+ );
70
+
71
+ const arbitraryDalvikMethodName = fc.oneof(
72
+ arbitraryJavaIdentifier,
73
+ fc.constant('<init>'),
74
+ fc.constant('<clinit>'),
75
+ );
76
+
77
+ const arbitraryDalvikFieldName = arbitraryJavaIdentifier;
78
+
79
+ // Access flags generator - common flags for all contexts
80
+ const arbitraryDalvikExecutableAccessFlagsCommon: fc.Arbitrary<DalvikExecutableAccessFlags> = fc.record({
81
+ public: fc.boolean(),
82
+ private: fc.boolean(),
83
+ protected: fc.boolean(),
84
+ static: fc.boolean(),
85
+ final: fc.boolean(),
86
+ synchronized: fc.boolean(),
87
+ volatile: fc.constant(false),
88
+ bridge: fc.constant(false),
89
+ transient: fc.constant(false),
90
+ varargs: fc.constant(false),
91
+ native: fc.boolean(),
92
+ interface: fc.boolean(),
93
+ abstract: fc.boolean(),
94
+ strict: fc.boolean(),
95
+ synthetic: fc.boolean(),
96
+ annotation: fc.boolean(),
97
+ enum: fc.boolean(),
98
+ constructor: fc.boolean(),
99
+ declaredSynchronized: fc.boolean(),
100
+ });
101
+
102
+ // Access flags for fields - volatile and transient are valid (0x40 and 0x80)
103
+ const arbitraryDalvikExecutableFieldAccessFlags: fc.Arbitrary<DalvikExecutableAccessFlags> = fc.record({
104
+ public: fc.boolean(),
105
+ private: fc.boolean(),
106
+ protected: fc.boolean(),
107
+ static: fc.boolean(),
108
+ final: fc.boolean(),
109
+ synchronized: fc.boolean(),
110
+ volatile: fc.boolean(),
111
+ bridge: fc.constant(false),
112
+ transient: fc.boolean(),
113
+ varargs: fc.constant(false),
114
+ native: fc.boolean(),
115
+ interface: fc.boolean(),
116
+ abstract: fc.boolean(),
117
+ strict: fc.boolean(),
118
+ synthetic: fc.boolean(),
119
+ annotation: fc.boolean(),
120
+ enum: fc.boolean(),
121
+ constructor: fc.boolean(),
122
+ declaredSynchronized: fc.boolean(),
123
+ });
124
+
125
+ // Access flags for methods - bridge and varargs are valid (0x40 and 0x80)
126
+ const arbitraryDalvikExecutableMethodAccessFlags: fc.Arbitrary<DalvikExecutableAccessFlags> = fc.record({
127
+ public: fc.boolean(),
128
+ private: fc.boolean(),
129
+ protected: fc.boolean(),
130
+ static: fc.boolean(),
131
+ final: fc.boolean(),
132
+ synchronized: fc.boolean(),
133
+ volatile: fc.constant(false),
134
+ bridge: fc.boolean(),
135
+ transient: fc.constant(false),
136
+ varargs: fc.boolean(),
137
+ native: fc.boolean(),
138
+ interface: fc.boolean(),
139
+ abstract: fc.boolean(),
140
+ strict: fc.boolean(),
141
+ synthetic: fc.boolean(),
142
+ annotation: fc.boolean(),
143
+ enum: fc.boolean(),
144
+ constructor: fc.boolean(),
145
+ declaredSynchronized: fc.boolean(),
146
+ });
147
+
148
+ // Generic access flags for class-level (uses common)
149
+ const arbitraryDalvikExecutableAccessFlags: fc.Arbitrary<DalvikExecutableAccessFlags> = arbitraryDalvikExecutableAccessFlagsCommon;
150
+
151
+ // Field generator
152
+ const arbitraryDalvikExecutableField: fc.Arbitrary<DalvikExecutableField> = fc.record({
153
+ class: arbitraryDalvikClassName,
154
+ type: arbitraryDalvikTypeName,
155
+ name: arbitraryDalvikFieldName,
156
+ });
157
+
158
+ const arbitraryDalvikExecutableFieldWithAccess: fc.Arbitrary<DalvikExecutableFieldWithAccess> = fc.record({
159
+ field: arbitraryDalvikExecutableField,
160
+ accessFlags: arbitraryDalvikExecutableFieldAccessFlags,
161
+ });
162
+
163
+ // Prototype generator
164
+ const arbitraryShorty: fc.Arbitrary<string> = fc.tuple(
165
+ arbitraryPrimitiveType, // return type
166
+ fc.array(fc.oneof(fc.constant('L'), arbitraryPrimitiveType), { maxLength: 5 }), // parameters
167
+ ).map(([returnType, params]) => returnType + params.join(''));
168
+
169
+ const arbitraryDalvikExecutablePrototype: fc.Arbitrary<DalvikExecutablePrototype> = arbitraryShorty.chain(shorty => {
170
+ const returnTypeChar = shorty[0];
171
+ const paramChars = shorty.slice(1).split('');
172
+
173
+ const returnType = returnTypeChar === 'L' ? arbitraryDalvikClassName : fc.constant(returnTypeChar);
174
+ const parameters = fc.tuple(
175
+ ...paramChars.map(char => char === 'L' ? arbitraryDalvikClassName : fc.constant(char))
176
+ );
177
+
178
+ return fc.record({
179
+ shorty: fc.constant(shorty),
180
+ returnType,
181
+ parameters,
182
+ });
183
+ });
184
+
185
+ // Method generator
186
+ const arbitraryDalvikExecutableMethod: fc.Arbitrary<DalvikExecutableMethod> = fc.record({
187
+ class: arbitraryDalvikClassName,
188
+ prototype: arbitraryDalvikExecutablePrototype,
189
+ name: arbitraryDalvikMethodName,
190
+ });
191
+
192
+ // Encoded value generator (recursive)
193
+ // DalvikExecutableEncodedValue is now a tagged union with type information
194
+ const arbitraryDalvikExecutableEncodedValue: fc.Arbitrary<DalvikExecutableEncodedValue> = fc.letrec(tie => ({
195
+ value: fc.oneof(
196
+ fc.record({ type: fc.constant('byte' as const), value: fc.integer({ min: -128, max: 127 }) }),
197
+ fc.record({ type: fc.constant('short' as const), value: fc.integer({ min: -32768, max: 32767 }) }),
198
+ fc.record({ type: fc.constant('char' as const), value: fc.integer({ min: 0, max: 65535 }) }),
199
+ fc.record({ type: fc.constant('int' as const), value: fc.integer({ min: -2147483648, max: 2147483647 }) }),
200
+ fc.record({ type: fc.constant('long' as const), value: fc.bigInt({ min: -9223372036854775808n, max: 9223372036854775807n }) }),
201
+ fc.record({ type: fc.constant('float' as const), value: fc.float() }),
202
+ fc.record({ type: fc.constant('double' as const), value: fc.double() }),
203
+ fc.record({ type: fc.constant('methodType' as const), value: arbitraryDalvikExecutablePrototype }),
204
+ fc.record({ type: fc.constant('methodHandle' as const), value: fc.nat(255) }),
205
+ fc.record({ type: fc.constant('string' as const), value: fc.string() }),
206
+ fc.record({ type: fc.constant('type' as const), value: arbitraryDalvikClassName }),
207
+ fc.record({ type: fc.constant('field' as const), value: arbitraryDalvikExecutableField }),
208
+ fc.record({ type: fc.constant('method' as const), value: arbitraryDalvikExecutableMethod }),
209
+ fc.record({ type: fc.constant('enum' as const), value: arbitraryDalvikExecutableField }),
210
+ fc.record({ type: fc.constant('array' as const), value: fc.array(tie('value') as fc.Arbitrary<DalvikExecutableEncodedValue>, { maxLength: 3 }) }),
211
+ // Note: We skip 'annotation' type here to avoid deep recursion complexity
212
+ fc.record({ type: fc.constant('null' as const), value: fc.constant(null) }),
213
+ fc.record({ type: fc.constant('boolean' as const), value: fc.boolean() }),
214
+ ),
215
+ })).value;
216
+
217
+ // Annotation generators
218
+ const arbitraryAnnotationVisibility: fc.Arbitrary<DalvikExecutableAnnotationItemVisibility> = fc.oneof(
219
+ fc.constant('build' as const),
220
+ fc.constant('runtime' as const),
221
+ fc.constant('system' as const),
222
+ );
223
+
224
+ const arbitraryDalvikExecutableAnnotationElement: fc.Arbitrary<DalvikExecutableAnnotationElement> = fc.record({
225
+ name: arbitraryJavaIdentifier,
226
+ value: arbitraryDalvikExecutableEncodedValue,
227
+ });
228
+
229
+ const arbitraryDalvikExecutableAnnotation: fc.Arbitrary<DalvikExecutableAnnotation> = fc.record({
230
+ visibility: arbitraryAnnotationVisibility,
231
+ type: arbitraryDalvikClassName,
232
+ elements: fc.array(arbitraryDalvikExecutableAnnotationElement, { maxLength: 3 }),
233
+ });
234
+
235
+ // Debug info generators
236
+ const arbitraryDalvikExecutableDebugByteCodeValue: fc.Arbitrary<DalvikExecutableDebugByteCodeValue> = fc.oneof(
237
+ fc.record({
238
+ type: fc.constant('advancePc' as const),
239
+ addressDiff: fc.nat({ max: 255 }),
240
+ }),
241
+ fc.record({
242
+ type: fc.constant('advanceLine' as const),
243
+ lineDiff: fc.integer({ min: -128, max: 127 }),
244
+ }),
245
+ fc.record({
246
+ type: fc.constant('startLocal' as const),
247
+ registerNum: fc.nat({ max: 255 }),
248
+ name: fc.option(arbitraryJavaIdentifier, { nil: undefined }),
249
+ type_: fc.option(arbitraryDalvikTypeName, { nil: undefined }),
250
+ }),
251
+ fc.record({
252
+ type: fc.constant('startLocalExtended' as const),
253
+ registerNum: fc.nat({ max: 255 }),
254
+ name: fc.option(arbitraryJavaIdentifier, { nil: undefined }),
255
+ type_: fc.option(arbitraryDalvikTypeName, { nil: undefined }),
256
+ signature: fc.option(fc.string(), { nil: undefined }),
257
+ }),
258
+ fc.record({
259
+ type: fc.constant('endLocal' as const),
260
+ registerNum: fc.nat({ max: 255 }),
261
+ }),
262
+ fc.record({
263
+ type: fc.constant('restartLocal' as const),
264
+ registerNum: fc.nat({ max: 255 }),
265
+ }),
266
+ fc.record({
267
+ type: fc.constant('setPrologueEnd' as const),
268
+ }),
269
+ fc.record({
270
+ type: fc.constant('setEpilogueBegin' as const),
271
+ }),
272
+ fc.record({
273
+ type: fc.constant('setFile' as const),
274
+ name: fc.option(fc.string(), { nil: undefined }),
275
+ }),
276
+ fc.record({
277
+ type: fc.constant('special' as const),
278
+ // Special opcodes must be >= 0x0A (values 0x00-0x09 are specific debug opcodes)
279
+ value: fc.integer({ min: 0x0A, max: 255 }),
280
+ }),
281
+ );
282
+
283
+ const arbitraryDalvikExecutableDebugInfo: fc.Arbitrary<DalvikExecutableDebugInfo> = fc.record({
284
+ lineStart: fc.nat({ max: 65535 }),
285
+ parameterNames: fc.array(fc.option(arbitraryJavaIdentifier, { nil: undefined }), { maxLength: 5 }),
286
+ bytecode: fc.array(arbitraryDalvikExecutableDebugByteCodeValue, { maxLength: 10 }),
287
+ });
288
+
289
+ // Try-catch handler generators
290
+ interface DalvikExecutableTry {
291
+ startAddress: number;
292
+ instructionCount: number;
293
+ handler: DalvikExecutableEncodedCatchHandler;
294
+ }
295
+
296
+ interface DalvikExecutableEncodedCatchHandler {
297
+ handlers: DalvikExecutableEncodedTypeAddressPair[];
298
+ catchAllAddress: undefined | number;
299
+ }
300
+
301
+ interface DalvikExecutableEncodedTypeAddressPair {
302
+ type: string;
303
+ address: number;
304
+ }
305
+
306
+ const arbitraryDalvikExecutableEncodedTypeAddressPair: fc.Arbitrary<DalvikExecutableEncodedTypeAddressPair> = fc.record({
307
+ type: arbitraryDalvikClassName,
308
+ address: fc.nat({ max: 65535 }),
309
+ });
310
+
311
+ const arbitraryDalvikExecutableEncodedCatchHandler: fc.Arbitrary<DalvikExecutableEncodedCatchHandler> = fc.record({
312
+ handlers: fc.array(arbitraryDalvikExecutableEncodedTypeAddressPair, { maxLength: 3 }),
313
+ catchAllAddress: fc.option(fc.nat({ max: 65535 }), { nil: undefined }),
314
+ }).filter(handler => {
315
+ // A handler must have at least one typed handler OR a catch-all address
316
+ return handler.handlers.length > 0 || handler.catchAllAddress !== undefined;
317
+ });
318
+
319
+ const arbitraryDalvikExecutableTry: fc.Arbitrary<DalvikExecutableTry> = fc.record({
320
+ startAddress: fc.nat({ max: 65535 }),
321
+ instructionCount: fc.nat({ max: 255 }),
322
+ handler: arbitraryDalvikExecutableEncodedCatchHandler,
323
+ });
324
+
325
+ // Generic factory function for DalvikExecutable
326
+ export const createArbitraryDalvikExecutable = <Instructions>(
327
+ arbitraryInstructions: fc.Arbitrary<Instructions>,
328
+ ): fc.Arbitrary<DalvikExecutable<Instructions>> => {
329
+ // Code generator using provided instructions arbitrary
330
+ const arbitraryDalvikExecutableCode: fc.Arbitrary<DalvikExecutableCode<Instructions>> = fc.record({
331
+ registersSize: fc.nat({ max: 65535 }),
332
+ insSize: fc.nat({ max: 255 }),
333
+ outsSize: fc.nat({ max: 255 }),
334
+ debugInfo: fc.option(arbitraryDalvikExecutableDebugInfo, { nil: undefined }),
335
+ instructions: arbitraryInstructions,
336
+ tries: fc.array(arbitraryDalvikExecutableTry, { maxLength: 2 }),
337
+ });
338
+
339
+ // Method with access and code
340
+ const arbitraryDalvikExecutableMethodWithAccess: fc.Arbitrary<DalvikExecutableMethodWithAccess<Instructions>> = fc.record({
341
+ method: arbitraryDalvikExecutableMethod,
342
+ accessFlags: arbitraryDalvikExecutableMethodAccessFlags,
343
+ code: fc.option(arbitraryDalvikExecutableCode, { nil: undefined }),
344
+ });
345
+
346
+ // Annotation collections
347
+ const arbitraryDalvikExecutableClassFieldAnnotation: fc.Arbitrary<DalvikExecutableClassFieldAnnotation> = fc.record({
348
+ field: arbitraryDalvikExecutableField,
349
+ annotations: fc.option(fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }), { nil: undefined }),
350
+ });
351
+
352
+ const arbitraryDalvikExecutableClassMethodAnnotation: fc.Arbitrary<DalvikExecutableClassMethodAnnotation> = fc.record({
353
+ method: arbitraryDalvikExecutableMethod,
354
+ annotations: fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }),
355
+ });
356
+
357
+ const arbitraryDalvikExecutableClassParameterAnnotation: fc.Arbitrary<DalvikExecutableClassParameterAnnotation> = fc.record({
358
+ method: arbitraryDalvikExecutableMethod,
359
+ annotations: fc.array(
360
+ fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }),
361
+ { maxLength: 3 }
362
+ ),
363
+ });
364
+
365
+ const arbitraryDalvikExecutableClassAnnotations: fc.Arbitrary<DalvikExecutableClassAnnotations> = fc.record({
366
+ classAnnotations: fc.array(arbitraryDalvikExecutableAnnotation, { maxLength: 2 }),
367
+ fieldAnnotations: fc.array(arbitraryDalvikExecutableClassFieldAnnotation, { maxLength: 2 }),
368
+ methodAnnotations: fc.array(arbitraryDalvikExecutableClassMethodAnnotation, { maxLength: 2 }),
369
+ parameterAnnotations: fc.array(arbitraryDalvikExecutableClassParameterAnnotation, { maxLength: 2 }),
370
+ }).map(annotations => ({
371
+ ...annotations,
372
+ // Filter out field/method/parameter annotations with undefined or empty annotations array
373
+ // In DEX format, fields/methods/parameters with no annotations should not appear in the annotations directory at all
374
+ fieldAnnotations: annotations.fieldAnnotations.filter(fa => fa.annotations !== undefined && fa.annotations.length > 0),
375
+ methodAnnotations: annotations.methodAnnotations.filter(ma => ma.annotations.length > 0),
376
+ parameterAnnotations: annotations.parameterAnnotations.filter(pa => pa.annotations.length > 0 && pa.annotations.some(paramAnnots => paramAnnots.length > 0)),
377
+ }));
378
+
379
+ // Class data
380
+ const arbitraryDalvikExecutableClassData: fc.Arbitrary<DalvikExecutableClassData<Instructions>> = fc.record({
381
+ staticFields: fc.array(arbitraryDalvikExecutableFieldWithAccess, { maxLength: 3 }),
382
+ instanceFields: fc.array(arbitraryDalvikExecutableFieldWithAccess, { maxLength: 3 }),
383
+ directMethods: fc.array(arbitraryDalvikExecutableMethodWithAccess, { maxLength: 3 }),
384
+ virtualMethods: fc.array(arbitraryDalvikExecutableMethodWithAccess, { maxLength: 3 }),
385
+ }).filter(classData =>
386
+ // Filter out empty classData (all arrays empty) as it's semantically equivalent to undefined
387
+ classData.staticFields.length > 0 ||
388
+ classData.instanceFields.length > 0 ||
389
+ classData.directMethods.length > 0 ||
390
+ classData.virtualMethods.length > 0
391
+ );
392
+
393
+ // Class definition
394
+ const arbitraryDalvikExecutableClassDefinition: fc.Arbitrary<DalvikExecutableClassDefinition<Instructions>> = fc.record({
395
+ class: arbitraryDalvikClassName,
396
+ accessFlags: arbitraryDalvikExecutableAccessFlags,
397
+ superclass: arbitraryDalvikClassName,
398
+ interfaces: fc.array(arbitraryDalvikClassName, { maxLength: 3 }),
399
+ sourceFile: fc.option(fc.stringMatching(/^[a-zA-Z0-9_]+\.java$/), { nil: undefined }),
400
+ annotations: fc.option(arbitraryDalvikExecutableClassAnnotations, { nil: undefined }),
401
+ staticValues: fc.array(arbitraryDalvikExecutableEncodedValue, { maxLength: 3 }),
402
+ classData: fc.option(arbitraryDalvikExecutableClassData, { nil: undefined }),
403
+ }).map(classDef => {
404
+ // Match parser logic: if all members are synthetic, set class synthetic to true
405
+ const allMembers = [
406
+ ...classDef.classData?.staticFields ?? [],
407
+ ...classDef.classData?.instanceFields ?? [],
408
+ ...classDef.classData?.directMethods ?? [],
409
+ // Note: virtualMethods are not included to match parser behavior
410
+ ];
411
+ const allMembersAreSynthetic = (
412
+ allMembers.every(member => member.accessFlags.synthetic)
413
+ && allMembers.length > 0
414
+ );
415
+
416
+ if (allMembersAreSynthetic) {
417
+ return {
418
+ ...classDef,
419
+ accessFlags: {
420
+ ...classDef.accessFlags,
421
+ synthetic: true,
422
+ },
423
+ };
424
+ }
425
+
426
+ return classDef;
427
+ });
428
+
429
+ // Root DalvikExecutable
430
+ return fc.record({
431
+ classDefinitions: fc.array(arbitraryDalvikExecutableClassDefinition, { minLength: 1, maxLength: 3 }),
432
+ link: fc.option(fc.uint8Array({ minLength: 1, maxLength: 10 }), { nil: undefined }),
433
+ });
434
+ };
@@ -3,6 +3,7 @@ import * as fc from 'fast-check';
3
3
  export const arbitraryDosDateTime = fc.date({
4
4
  min: new Date(Date.UTC(1980, 0, 1)),
5
5
  max: new Date(Date.UTC(2099, 11, 31)),
6
+ noInvalidDate: true,
6
7
  }).map(date => {
7
8
  date.setSeconds(0);
8
9
  date.setMilliseconds(0);
@@ -6,7 +6,7 @@ function addZipEntryToZip(zip: JSZip, zipEntry: ZipEntry) {
6
6
  const options = {
7
7
  comment: zipEntry.comment,
8
8
  date: zipEntry.date,
9
- // unixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
9
+ // UnixPermissions: zipEntry.permissions.type === 'unix' ? zipEntry.permissions.unixPermissions : undefined,
10
10
  // dosPermissions: zipEntry.permissions.type === 'dos' ? zipEntry.permissions.dosPermissions : undefined,
11
11
  };
12
12
 
@@ -1,11 +1,11 @@
1
1
  import test from 'ava';
2
2
  import { createArrayParser } from './arrayParser.js';
3
- import { type Parser, runParser } from './parser.js';
3
+ import { type Parser, runParserWithRemainingInput } from './parser.js';
4
4
  import { stringParserInputCompanion } from './parserInputCompanion.js';
5
5
 
6
6
  test('does not loop forever with a child parser that does not consume anything', async t => {
7
7
  const parser: Parser<undefined[], string> = createArrayParser(async () => undefined);
8
- const result = await runParser(parser, 'foo', stringParserInputCompanion);
8
+ const { output } = await runParserWithRemainingInput(parser, 'foo', stringParserInputCompanion);
9
9
 
10
- t.deepEqual(result, []);
10
+ t.deepEqual(output, []);
11
11
  });
@@ -1,5 +1,5 @@
1
1
  import { getParserName, type Parser, setParserName } from './parser.js';
2
- import { ParserParsingFailedError } from './parserError.js';
2
+ import { isParserParsingFailedError } from './parserError.js';
3
3
 
4
4
  export const createArrayParser = <ElementOutput, Sequence>(
5
5
  elementParser: Parser<ElementOutput, Sequence>,
@@ -19,7 +19,7 @@ export const createArrayParser = <ElementOutput, Sequence>(
19
19
  elements.push(element);
20
20
  elementParserContext.unlookahead();
21
21
  } catch (error) {
22
- if (error instanceof ParserParsingFailedError) {
22
+ if (isParserParsingFailedError(error)) {
23
23
  return elements;
24
24
  }
25
25
 
@@ -1,4 +1,4 @@
1
- import { Unparser } from "./unparser.js";
1
+ import { type Unparser } from './unparser.js';
2
2
 
3
3
  export const createArrayUnparser = <ElementInput, Sequence>(
4
4
  elementUnparser: Unparser<ElementInput, Sequence>,
@@ -10,4 +10,4 @@ export const createArrayUnparser = <ElementInput, Sequence>(
10
10
  };
11
11
 
12
12
  return arrayUnparser;
13
- }
13
+ };
@@ -0,0 +1,74 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { execa } from 'execa';
4
+ import { temporaryDirectory, temporaryFile } from 'tempy';
5
+ import { smaliClass } from './smali.js';
6
+
7
+ export async function baksmaliClass(
8
+ dexStream: Uint8Array | AsyncIterable<Uint8Array>,
9
+ smaliFilePath: string,
10
+ ): Promise<string> {
11
+ const inputFilePath = temporaryFile();
12
+ const outputDirectoryPath = temporaryDirectory();
13
+
14
+ await fs.writeFile(inputFilePath, dexStream);
15
+
16
+ await execa('baksmali', [
17
+ 'disassemble',
18
+ '--classes',
19
+ 'L' + smaliFilePath + ';',
20
+ '--output',
21
+ outputDirectoryPath,
22
+ inputFilePath,
23
+ ]);
24
+
25
+ await fs.unlink(inputFilePath);
26
+
27
+ const smaliFilePath_ = path.join(outputDirectoryPath, smaliFilePath + '.smali');
28
+
29
+ const smali = await fs.readFile(smaliFilePath_, 'utf8');
30
+
31
+ await fs.rm(outputDirectoryPath, {
32
+ recursive: true,
33
+ });
34
+
35
+ return smali;
36
+ }
37
+
38
+ export async function backsmaliSmaliIsolateClass(
39
+ dexStream: Uint8Array | AsyncIterable<Uint8Array>,
40
+ smaliFilePath: string,
41
+ ): Promise<Uint8Array> {
42
+ const smali = await baksmaliClass(dexStream, smaliFilePath);
43
+ return smaliClass(smali);
44
+ }
45
+
46
+ export async function baksmaliListClasses(dexStream: Uint8Array | AsyncIterable<Uint8Array>): Promise<string[]> {
47
+ const inputFilePath = temporaryFile();
48
+
49
+ await fs.writeFile(inputFilePath, dexStream);
50
+
51
+ const result = await execa('baksmali', [
52
+ 'list',
53
+ 'classes',
54
+ inputFilePath,
55
+ ]);
56
+
57
+ await fs.unlink(inputFilePath);
58
+
59
+ if (result.stderr) {
60
+ throw new Error(`baksmali error: ${result.stderr}`);
61
+ }
62
+
63
+ const classes = result.stdout
64
+ .split('\n')
65
+ .filter(line => line.trim())
66
+ .map(line => line.trim())
67
+ .map(class_ => (
68
+ class_
69
+ .replace(/^L/, '')
70
+ .replace(/;$/, '')
71
+ ));
72
+
73
+ return classes;
74
+ }
@@ -8,21 +8,19 @@ import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
8
8
  testProp(
9
9
  'bson',
10
10
  [
11
- arbitrarilySlicedAsyncIterator(
12
- fc
13
- .json()
14
- .filter(jsonString => {
15
- // BSON.serialize does not support non-object top-level values
16
- const jsonValue = JSON.parse(jsonString);
11
+ arbitrarilySlicedAsyncIterator(fc
12
+ .json()
13
+ .filter(jsonString => {
14
+ // BSON.serialize does not support non-object top-level values
15
+ const jsonValue = JSON.parse(jsonString);
17
16
 
18
- return (
19
- jsonValue !== null
20
- && typeof jsonValue === 'object'
21
- && !Array.isArray(jsonValue)
22
- );
23
- })
24
- .map(jsonString => BSON.serialize(JSON.parse(jsonString))),
25
- ),
17
+ return (
18
+ jsonValue !== null
19
+ && typeof jsonValue === 'object'
20
+ && !Array.isArray(jsonValue)
21
+ );
22
+ })
23
+ .map(jsonString => BSON.serialize(JSON.parse(jsonString)))),
26
24
  ],
27
25
  async (t, [ bsonUint8Array, bsonUint8ArrayChunkIterator ]) => {
28
26
  const expected = BSON.deserialize(bsonUint8Array);
package/src/bsonParser.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { type JsonObject, type JsonValue } from 'type-fest';
2
2
  import { getParserName, setParserName, type Parser } from './parser.js';
3
- import { invariantDefined } from './invariantDefined.js';
4
3
  import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
5
4
  import { promiseCompose } from './promiseCompose.js';
6
5
  import { createTupleParser } from './tupleParser.js';
@@ -34,9 +33,17 @@ const cstringParser: Parser<string, Uint8Array> = promiseCompose(
34
33
  );
35
34
 
36
35
  const doubleParser: Parser<number, Uint8Array> = promiseCompose(buffer8Parser, buffer => buffer.readDoubleLE(0));
36
+
37
+ setParserName(doubleParser, 'doubleParser');
38
+
37
39
  const int32Parser: Parser<number, Uint8Array> = promiseCompose(buffer4Parser, buffer => buffer.readInt32LE(0));
40
+
41
+ setParserName(int32Parser, 'int32Parser');
42
+
38
43
  const uint32Parser: Parser<number, Uint8Array> = promiseCompose(buffer4Parser, buffer => buffer.readUInt32LE(0));
39
44
 
45
+ setParserName(uint32Parser, 'uint32Parser');
46
+
40
47
  const createFixedLengthStringParser = (length: number): Parser<string, Uint8Array> => promiseCompose(
41
48
  createFixedLengthBufferParser(length),
42
49
  buffer => buffer.toString('utf8'),
@@ -56,6 +63,8 @@ const bsonStringParser: Parser<string, Uint8Array> = async parserContext => {
56
63
  return createFixedLengthNullTerminatedStringParser(stringSize - 1)(parserContext);
57
64
  };
58
65
 
66
+ setParserName(bsonStringParser, 'bsonStringParser');
67
+
59
68
  const bsonArrayParser = promiseCompose(
60
69
  createTupleParser([
61
70
  createSkipParser(4),
@@ -64,8 +73,10 @@ const bsonArrayParser = promiseCompose(
64
73
  ([ _, elements ]) => elements.map(([ _, value ]) => value),
65
74
  );
66
75
 
76
+ setParserName(bsonArrayParser, 'bsonArrayParser');
77
+
67
78
  const bsonBooleanParser: Parser<boolean, Uint8Array> = async parserContext => {
68
- const booleanValue = invariantDefined(await parserContext.read(0), 'Unexpected end of input');
79
+ const booleanValue = await parserContext.read(0);
69
80
 
70
81
  return booleanValue === 1;
71
82
  };