@futpib/parser 1.0.2 → 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 (284) 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 +1 -1
  7. package/build/allSettledStream.test.js +2 -2
  8. package/build/androidPackageParser.d.ts +1 -1
  9. package/build/androidPackageParser.js +5 -3
  10. package/build/androidPackageParser.test.js +7 -7
  11. package/build/androidPackageUnparser.d.ts +2 -2
  12. package/build/androidPackageUnparser.js +18 -14
  13. package/build/androidPackageUnparser.test.js +7 -7
  14. package/build/arbitrarilySlicedAsyncInterator.js +2 -1
  15. package/build/arbitraryDalvikBytecode.d.ts +4 -0
  16. package/build/arbitraryDalvikBytecode.js +640 -0
  17. package/build/arbitraryDalvikExecutable.d.ts +3 -0
  18. package/build/arbitraryDalvikExecutable.js +282 -0
  19. package/build/arbitraryDosDateTime.js +1 -0
  20. package/build/arbitraryZipStream.js +1 -1
  21. package/build/arrayParser.js +2 -2
  22. package/build/arrayUnparser.d.ts +1 -1
  23. package/build/backsmali.d.ts +3 -1
  24. package/build/backsmali.js +31 -3
  25. package/build/customInvariant.d.ts +2 -1
  26. package/build/customInvariant.js +4 -6
  27. package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
  28. package/build/dalvikBytecodeParser/formatParsers.js +146 -11
  29. package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
  30. package/build/dalvikBytecodeParser/formatSizes.js +34 -0
  31. package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
  32. package/build/dalvikBytecodeParser/operationFormats.js +225 -0
  33. package/build/dalvikBytecodeParser.d.ts +1105 -5
  34. package/build/dalvikBytecodeParser.js +658 -205
  35. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
  36. package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
  37. package/build/dalvikBytecodeUnparser.d.ts +3 -0
  38. package/build/dalvikBytecodeUnparser.js +642 -0
  39. package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
  40. package/build/dalvikBytecodeUnparser.test.js +25 -0
  41. package/build/dalvikExecutable.d.ts +65 -8
  42. package/build/dalvikExecutable.js +36 -0
  43. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
  44. package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
  45. package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
  46. package/build/dalvikExecutableParser/typeParsers.js +16 -11
  47. package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
  48. package/build/dalvikExecutableParser/typedNumbers.js +0 -1
  49. package/build/dalvikExecutableParser.d.ts +2 -2
  50. package/build/dalvikExecutableParser.js +655 -337
  51. package/build/dalvikExecutableParser.test.js +24 -22
  52. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
  53. package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
  54. package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
  55. package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
  56. package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
  57. package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
  58. package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
  59. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
  60. package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
  61. package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
  62. package/build/dalvikExecutableUnparser/utils.js +108 -0
  63. package/build/dalvikExecutableUnparser.d.ts +4 -0
  64. package/build/dalvikExecutableUnparser.js +406 -0
  65. package/build/dalvikExecutableUnparser.test.d.ts +1 -0
  66. package/build/dalvikExecutableUnparser.test.js +31 -0
  67. package/build/debugLogInputParser.js +1 -1
  68. package/build/disjunctionParser.d.ts +2 -2
  69. package/build/disjunctionParser.js +2 -2
  70. package/build/elementTerminatedArrayParser.d.ts +2 -2
  71. package/build/elementTerminatedArrayParser.js +1 -1
  72. package/build/elementTerminatedArrayParser.test.js +5 -5
  73. package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
  74. package/build/elementTerminatedSequenceArrayParser.js +1 -1
  75. package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
  76. package/build/elementTerminatedSequenceParser.d.ts +2 -2
  77. package/build/elementTerminatedSequenceParser.js +1 -1
  78. package/build/elementTerminatedSequenceParser.test.js +2 -2
  79. package/build/endOfInputParser.d.ts +1 -1
  80. package/build/exactElementSwitchParser.d.ts +3 -0
  81. package/build/exactElementSwitchParser.js +22 -0
  82. package/build/fetchCid.js +2 -6
  83. package/build/fetchCid.test.d.ts +1 -0
  84. package/build/fetchCid.test.js +16 -0
  85. package/build/fixedLengthSequenceParser.test.js +2 -2
  86. package/build/hasExecutable.js +2 -2
  87. package/build/highResolutionTimer.js +1 -1
  88. package/build/inputReader.d.ts +1 -1
  89. package/build/inputReader.test.js +33 -45
  90. package/build/javaKeyStoreParser.test.js +6 -6
  91. package/build/jsonParser.js +8 -8
  92. package/build/lazyMessageError.d.ts +48 -0
  93. package/build/lazyMessageError.js +53 -0
  94. package/build/lazyMessageError.test.d.ts +1 -0
  95. package/build/lazyMessageError.test.js +15 -0
  96. package/build/leb128Parser.d.ts +1 -1
  97. package/build/leb128Parser.js +10 -10
  98. package/build/leb128Parser.test.js +7 -7
  99. package/build/negativeLookaheadParser.js +2 -2
  100. package/build/negativeLookaheadParser.test.js +4 -4
  101. package/build/noStackCaptureOverheadError.d.ts +4 -0
  102. package/build/noStackCaptureOverheadError.js +9 -0
  103. package/build/noStackCaptureOverheadError.test.d.ts +1 -0
  104. package/build/noStackCaptureOverheadError.test.js +15 -0
  105. package/build/nonEmptyArrayParser.js +2 -2
  106. package/build/nonEmptyArrayParser.test.js +2 -1
  107. package/build/optionalParser.js +2 -2
  108. package/build/parser.d.ts +2 -1
  109. package/build/parser.js +23 -8
  110. package/build/parser.test.js +78 -29
  111. package/build/parserConsumedSequenceParser.d.ts +1 -1
  112. package/build/parserConsumedSequenceParser.js +2 -2
  113. package/build/parserContext.d.ts +8 -6
  114. package/build/parserContext.js +60 -33
  115. package/build/parserContext.test.js +7 -3
  116. package/build/parserError.d.ts +603 -44
  117. package/build/parserError.js +98 -53
  118. package/build/parserImplementationInvariant.d.ts +1 -1
  119. package/build/parserImplementationInvariant.js +2 -2
  120. package/build/parserInputCompanion.js +2 -2
  121. package/build/promiseCompose.js +1 -2
  122. package/build/separatedArrayParser.js +2 -2
  123. package/build/separatedNonEmptyArrayParser.d.ts +2 -0
  124. package/build/separatedNonEmptyArrayParser.js +40 -0
  125. package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
  126. package/build/separatedNonEmptyArrayParser.test.js +66 -0
  127. package/build/sequenceBuffer.js +1 -1
  128. package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
  129. package/build/sequenceTerminatedSequenceParser.js +3 -3
  130. package/build/sequenceTerminatedSequenceParser.test.js +1 -1
  131. package/build/sequenceUnparser.d.ts +1 -1
  132. package/build/skipToParser.d.ts +1 -1
  133. package/build/skipToParser.js +2 -2
  134. package/build/sliceBoundedParser.test.js +4 -9
  135. package/build/smali.d.ts +1 -1
  136. package/build/smali.js +6 -2
  137. package/build/smaliParser.d.ts +62 -6
  138. package/build/smaliParser.js +1721 -296
  139. package/build/smaliParser.test.js +338 -43
  140. package/build/stringFromAsyncIterable.d.ts +1 -0
  141. package/build/stringFromAsyncIterable.js +7 -0
  142. package/build/terminatedArrayParser.js +4 -4
  143. package/build/terminatedArrayParser.test.js +7 -7
  144. package/build/toAsyncIterator.js +4 -4
  145. package/build/unionParser.d.ts +1 -1
  146. package/build/unionParser.js +2 -2
  147. package/build/unionParser.test.js +3 -3
  148. package/build/unparser.d.ts +3 -3
  149. package/build/unparser.js +6 -4
  150. package/build/unparser.test.js +7 -19
  151. package/build/unparserContext.d.ts +2 -2
  152. package/build/unparserContext.js +2 -3
  153. package/build/unparserError.d.ts +2 -1
  154. package/build/unparserError.js +2 -1
  155. package/build/unparserImplementationInvariant.d.ts +1 -1
  156. package/build/unparserOutputCompanion.d.ts +1 -1
  157. package/build/unparserOutputCompanion.js +1 -1
  158. package/build/zipParser.js +1 -1
  159. package/build/zipUnparser.d.ts +3 -3
  160. package/build/zipUnparser.js +9 -19
  161. package/build/zipUnparser.test.js +1 -1
  162. package/package.json +19 -26
  163. package/src/allSettledStream.test.ts +2 -2
  164. package/src/allSettledStream.ts +3 -3
  165. package/src/androidPackageParser.test.ts +17 -19
  166. package/src/androidPackageParser.ts +129 -171
  167. package/src/androidPackageUnparser.test.ts +19 -21
  168. package/src/androidPackageUnparser.ts +23 -17
  169. package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
  170. package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
  171. package/src/arbitraryDalvikBytecode.ts +992 -0
  172. package/src/arbitraryDalvikExecutable.ts +434 -0
  173. package/src/arbitraryDosDateTime.ts +1 -0
  174. package/src/arbitraryZipStream.ts +1 -1
  175. package/src/arrayParser.ts +2 -2
  176. package/src/arrayUnparser.ts +2 -2
  177. package/src/backsmali.ts +48 -4
  178. package/src/bsonParser.test.ts +12 -14
  179. package/src/customInvariant.ts +8 -12
  180. package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
  181. package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
  182. package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
  183. package/src/dalvikBytecodeParser.ts +1042 -243
  184. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
  185. package/src/dalvikBytecodeUnparser.test.ts +44 -0
  186. package/src/dalvikBytecodeUnparser.ts +758 -0
  187. package/src/dalvikExecutable.ts +110 -48
  188. package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
  189. package/src/dalvikExecutableParser/typeParsers.ts +23 -14
  190. package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
  191. package/src/dalvikExecutableParser.test.ts +60 -60
  192. package/src/dalvikExecutableParser.test.ts.md +6 -6
  193. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  194. package/src/dalvikExecutableParser.ts +911 -434
  195. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
  196. package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
  197. package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
  198. package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
  199. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
  200. package/src/dalvikExecutableUnparser/utils.ts +149 -0
  201. package/src/dalvikExecutableUnparser.test.ts +57 -0
  202. package/src/dalvikExecutableUnparser.ts +581 -0
  203. package/src/debugLogInputParser.ts +1 -1
  204. package/src/disjunctionParser.ts +5 -5
  205. package/src/elementTerminatedArrayParser.test.ts +8 -8
  206. package/src/elementTerminatedArrayParser.ts +2 -2
  207. package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
  208. package/src/elementTerminatedSequenceArrayParser.ts +2 -2
  209. package/src/elementTerminatedSequenceParser.test.ts +4 -6
  210. package/src/elementTerminatedSequenceParser.ts +2 -2
  211. package/src/endOfInputParser.ts +1 -1
  212. package/src/exactElementSwitchParser.ts +41 -0
  213. package/src/fetchCid.test.ts +20 -0
  214. package/src/fetchCid.ts +3 -7
  215. package/src/fixedLengthSequenceParser.test.ts +10 -12
  216. package/src/hasExecutable.ts +2 -2
  217. package/src/highResolutionTimer.ts +1 -1
  218. package/src/inputReader.test.ts +39 -52
  219. package/src/inputReader.ts +2 -4
  220. package/src/inputReaderState.ts +1 -1
  221. package/src/inspect.ts +1 -1
  222. package/src/javaKeyStoreParser.test.ts +12 -14
  223. package/src/javaKeyStoreParser.ts +2 -6
  224. package/src/jsonParser.test.ts +2 -4
  225. package/src/jsonParser.ts +34 -38
  226. package/src/lazyMessageError.test.ts +21 -0
  227. package/src/lazyMessageError.ts +88 -0
  228. package/src/leb128Parser.test.ts +25 -23
  229. package/src/leb128Parser.ts +19 -19
  230. package/src/negativeLookaheadParser.test.ts +7 -11
  231. package/src/negativeLookaheadParser.ts +2 -2
  232. package/src/noStackCaptureOverheadError.test.ts +17 -0
  233. package/src/noStackCaptureOverheadError.ts +12 -0
  234. package/src/nonEmptyArrayParser.test.ts +3 -2
  235. package/src/nonEmptyArrayParser.ts +2 -2
  236. package/src/optionalParser.ts +2 -2
  237. package/src/parser.test.ts +96 -43
  238. package/src/parser.test.ts.md +13 -6
  239. package/src/parser.test.ts.snap +0 -0
  240. package/src/parser.ts +35 -12
  241. package/src/parserAccessorParser.ts +1 -1
  242. package/src/parserConsumedSequenceParser.ts +3 -3
  243. package/src/parserContext.test.ts +7 -3
  244. package/src/parserContext.ts +82 -48
  245. package/src/parserError.ts +143 -63
  246. package/src/parserImplementationInvariant.ts +3 -3
  247. package/src/parserInputCompanion.ts +2 -2
  248. package/src/promiseCompose.ts +2 -2
  249. package/src/separatedArrayParser.ts +3 -3
  250. package/src/separatedNonEmptyArrayParser.test.ts +117 -0
  251. package/src/separatedNonEmptyArrayParser.ts +61 -0
  252. package/src/sequenceBuffer.test.ts +9 -9
  253. package/src/sequenceBuffer.ts +4 -4
  254. package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
  255. package/src/sequenceTerminatedSequenceParser.ts +4 -4
  256. package/src/sequenceUnparser.ts +2 -2
  257. package/src/skipToParser.ts +2 -2
  258. package/src/sliceBoundedParser.test.ts +4 -12
  259. package/src/sliceBoundedParser.ts +2 -2
  260. package/src/smali.ts +8 -3
  261. package/src/smaliParser.test.ts +377 -66
  262. package/src/smaliParser.test.ts.md +1635 -48
  263. package/src/smaliParser.test.ts.snap +0 -0
  264. package/src/smaliParser.ts +2751 -569
  265. package/src/stringFromAsyncIterable.ts +9 -0
  266. package/src/terminatedArrayParser.test.ts +11 -11
  267. package/src/terminatedArrayParser.ts +5 -7
  268. package/src/toAsyncIterator.ts +8 -8
  269. package/src/uint8Array.ts +2 -3
  270. package/src/unionParser.test.ts +22 -23
  271. package/src/unionParser.ts +6 -8
  272. package/src/unparser.test.ts +18 -34
  273. package/src/unparser.ts +13 -9
  274. package/src/unparserContext.ts +9 -13
  275. package/src/unparserError.ts +2 -1
  276. package/src/unparserImplementationInvariant.ts +1 -1
  277. package/src/unparserOutputCompanion.ts +1 -1
  278. package/src/zip.ts +2 -6
  279. package/src/zipParser.ts +10 -18
  280. package/src/zipUnparser.test.ts +1 -1
  281. package/src/zipUnparser.ts +52 -64
  282. package/tsconfig.json +7 -1
  283. package/xo.config.ts +15 -0
  284. package/.yarn/releases/yarn-4.5.3.cjs +0 -934
@@ -1,5 +1,6 @@
1
1
  import invariant from 'invariant';
2
- import { MUtf8Decoder } from "mutf-8";
2
+ import { MUtf8Decoder } from 'mutf-8';
3
+ import { type Iso } from 'monocle-ts';
3
4
  import { createExactElementParser } from './exactElementParser.js';
4
5
  import { createExactSequenceParser } from './exactSequenceParser.js';
5
6
  import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
@@ -11,19 +12,69 @@ import { createTupleParser } from './tupleParser.js';
11
12
  import { createParserAccessorParser } from './parserAccessorParser.js';
12
13
  import { createSkipToParser } from './skipToParser.js';
13
14
  import { createLookaheadParser } from './lookaheadParser.js';
14
- import { getIsoTypedNumberArray, IndexIntoFieldIds, IndexIntoMethodIds, IndexIntoPrototypeIds, IndexIntoStringIds, IndexIntoTypeIds, isoIndexIntoFieldIds, isoIndexIntoMethodIds, isoIndexIntoPrototypeIds, isoIndexIntoStringIds, isoIndexIntoTypeIds, isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler, isoOffsetToAnnotationItem, isoOffsetToAnnotationsDirectoryItem, isoOffsetToAnnotationSetItem, isoOffsetToAnnotationSetRefListItem, isoOffsetToClassDataItem, isoOffsetToCodeItem, isoOffsetToDebugInfoItem, isoOffsetToEncodedArrayItem, isoOffsetToStringDataItem, isoOffsetToTypeList, OffsetFromEncodedCatchHandlerListToEncodedCatchHandler, OffsetToAnnotationItem, OffsetToAnnotationsDirectoryItem, OffsetToAnnotationSetItem, OffsetToAnnotationSetRefListItem, OffsetToClassDataItem, OffsetToCodeItem, OffsetToDebugInfoItem, OffsetToEncodedArrayItem, OffsetToStringDataItem, OffsetToTypeList, TypedNumberArray } from './dalvikExecutableParser/typedNumbers.js';
15
- import { Iso } from 'monocle-ts';
15
+ import {
16
+ getIsoTypedNumberArray,
17
+ type IndexIntoFieldIds,
18
+ type IndexIntoMethodIds,
19
+ type IndexIntoPrototypeIds,
20
+ type IndexIntoStringIds,
21
+ type IndexIntoTypeIds,
22
+ isoIndexIntoFieldIds,
23
+ isoIndexIntoMethodIds,
24
+ isoIndexIntoPrototypeIds,
25
+ isoIndexIntoStringIds,
26
+ isoIndexIntoTypeIds,
27
+ isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler,
28
+ isoOffsetToAnnotationItem,
29
+ isoOffsetToAnnotationsDirectoryItem,
30
+ isoOffsetToAnnotationSetItem,
31
+ isoOffsetToAnnotationSetRefListItem,
32
+ isoOffsetToClassDataItem,
33
+ isoOffsetToCodeItem,
34
+ isoOffsetToDebugInfoItem,
35
+ isoOffsetToEncodedArrayItem,
36
+ isoOffsetToStringDataItem,
37
+ isoOffsetToTypeList,
38
+ type OffsetFromEncodedCatchHandlerListToEncodedCatchHandler,
39
+ type OffsetToAnnotationItem,
40
+ type OffsetToAnnotationsDirectoryItem,
41
+ type OffsetToAnnotationSetItem,
42
+ type OffsetToAnnotationSetRefListItem,
43
+ type OffsetToClassDataItem,
44
+ type OffsetToCodeItem,
45
+ type OffsetToDebugInfoItem,
46
+ type OffsetToEncodedArrayItem,
47
+ type OffsetToStringDataItem,
48
+ type OffsetToTypeList,
49
+ type TypedNumberArray,
50
+ } from './dalvikExecutableParser/typedNumbers.js';
16
51
  import { sleb128NumberParser, uleb128NumberParser } from './leb128Parser.js';
17
52
  import { createDisjunctionParser } from './disjunctionParser.js';
18
53
  import { createElementTerminatedSequenceParser } from './elementTerminatedSequenceParser.js';
19
54
  import { createElementTerminatedArrayParserUnsafe } from './elementTerminatedArrayParser.js';
20
- import { createDalvikBytecodeParser, DalvikBytecode, DalvikBytecodeOperation, DalvikBytecodeOperationResolvers, resolveDalvikBytecodeOperation } from './dalvikBytecodeParser.js';
21
- import { ubyteParser, uintParser, uleb128p1NumberParser, ushortParser } from './dalvikExecutableParser/typeParsers.js';
22
- import { DalvikExecutable, DalvikExecutableAccessFlags, DalvikExecutableAnnotation, DalvikExecutableClassAnnotations, DalvikExecutableClassData, DalvikExecutableClassFieldAnnotation, DalvikExecutableClassMethodAnnotation, DalvikExecutableClassParameterAnnotation, DalvikExecutableCode, DalvikExecutableDebugInfo, DalvikExecutableEncodedValue } from './dalvikExecutable.js';
55
+ import {
56
+ createDalvikBytecodeParser, type DalvikBytecode, type DalvikBytecodeOperation, type DalvikBytecodeOperationResolvers, resolveDalvikBytecodeOperation,
57
+ } from './dalvikBytecodeParser.js';
58
+ import {
59
+ byteParser, ubyteParser, uintParser, uleb128p1NumberParser, ushortParser,
60
+ } from './dalvikExecutableParser/typeParsers.js';
61
+ import {
62
+ type DalvikExecutable,
63
+ type DalvikExecutableAccessFlags,
64
+ type DalvikExecutableAnnotation,
65
+ type DalvikExecutableClassAnnotations,
66
+ type DalvikExecutableClassData,
67
+ type DalvikExecutableClassFieldAnnotation,
68
+ type DalvikExecutableClassMethodAnnotation,
69
+ type DalvikExecutableClassParameterAnnotation,
70
+ type DalvikExecutableCode,
71
+ type DalvikExecutableDebugInfo,
72
+ type DalvikExecutableEncodedValue,
73
+ } from './dalvikExecutable.js';
23
74
 
24
75
  // https://source.android.com/docs/core/runtime/dex-format
25
76
 
26
- const createByteAlignParser = (byteAlignment: number): Parser<void, Uint8Array> => async (parserContext) => {
77
+ const createByteAlignParser = (byteAlignment: number): Parser<void, Uint8Array> => async parserContext => {
27
78
  const toSkip = (byteAlignment - (parserContext.position % byteAlignment)) % byteAlignment;
28
79
 
29
80
  parserContext.skip(toSkip);
@@ -46,8 +97,8 @@ const dalvikExecutableHeaderVersionParser: Parser<number, Uint8Array> = promiseC
46
97
  );
47
98
 
48
99
  type SizeOffset = {
49
- size: number,
50
- offset: number,
100
+ size: number;
101
+ offset: number;
51
102
  };
52
103
 
53
104
  const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = promiseCompose(
@@ -59,21 +110,21 @@ const sizeOffsetParser: Parser<SizeOffset, Uint8Array> = promiseCompose(
59
110
  );
60
111
 
61
112
  type DalvikExecutableHeaderItem = {
62
- version: number,
63
- checksum: number,
64
- sha1Hash: Uint8Array,
65
- fileSize: number,
66
- headerSize: number,
67
- endianTag: number,
68
- link: SizeOffset,
69
- mapOffset: number,
70
- stringIds: SizeOffset,
71
- typeIds: SizeOffset,
72
- prototypeIds: SizeOffset,
73
- fieldIds: SizeOffset,
74
- methodIds: SizeOffset,
75
- classDefinitions: SizeOffset,
76
- data: SizeOffset,
113
+ version: number;
114
+ checksum: number;
115
+ sha1Hash: Uint8Array;
116
+ fileSize: number;
117
+ headerSize: number;
118
+ endianTag: number;
119
+ link: SizeOffset;
120
+ mapOffset: number;
121
+ stringIds: SizeOffset;
122
+ typeIds: SizeOffset;
123
+ prototypeIds: SizeOffset;
124
+ fieldIds: SizeOffset;
125
+ methodIds: SizeOffset;
126
+ classDefinitions: SizeOffset;
127
+ data: SizeOffset;
77
128
  };
78
129
 
79
130
  const dalvikExecutableHeaderItemParser: Parser<DalvikExecutableHeaderItem, Uint8Array> = promiseCompose(
@@ -133,7 +184,7 @@ type DalvikExecutableStringIdItem = OffsetToStringDataItem;
133
184
 
134
185
  const dalvikExecutableStringIdItemParser: Parser<DalvikExecutableStringIdItem, Uint8Array> = promiseCompose(
135
186
  cloneParser(uintParser),
136
- (offset) => isoOffsetToStringDataItem.wrap(offset),
187
+ offset => isoOffsetToStringDataItem.wrap(offset),
137
188
  );
138
189
 
139
190
  type DalvikExecutableStringIdItems = TypedNumberArray<IndexIntoStringIds, DalvikExecutableStringIdItem>;
@@ -159,7 +210,7 @@ type DalvikExecutableTypeIdItem = IndexIntoStringIds;
159
210
 
160
211
  const dalvikExecutableTypeIdItemParser: Parser<DalvikExecutableTypeIdItem, Uint8Array> = promiseCompose(
161
212
  cloneParser(uintParser),
162
- (index) => isoIndexIntoStringIds.wrap(index),
213
+ index => isoIndexIntoStringIds.wrap(index),
163
214
  );
164
215
 
165
216
  type DalvikExecutableTypeIdItems = TypedNumberArray<IndexIntoTypeIds, DalvikExecutableTypeIdItem>;
@@ -233,7 +284,7 @@ const createSkipToThenItemByOffsetParser = <Offset, Item>({
233
284
  isoOffset: Iso<Offset, number>;
234
285
  parserName: string;
235
286
  }): Parser<Map<Offset, Item>, Uint8Array> => {
236
- const skipToThenItemByOffsetParser: Parser<Map<Offset, Item>, Uint8Array> = async (parserContext) => {
287
+ const skipToThenItemByOffsetParser: Parser<Map<Offset, Item>, Uint8Array> = async parserContext => {
237
288
  const itemByOffset = new Map<Offset, Item>();
238
289
 
239
290
  if (size === 0) {
@@ -338,54 +389,62 @@ const createSkipToThenMethodIdItemsParser = ({ size, offset }: SizeOffset): Pars
338
389
  )
339
390
  );
340
391
 
392
+ const parseAccessFlagsCommon = (flags: number): DalvikExecutableAccessFlags => ({
393
+ public: Boolean(flags & 0b0000_0001),
394
+ private: Boolean(flags & 0b0000_0010),
395
+ protected: Boolean(flags & 0b0000_0100),
396
+ static: Boolean(flags & 0b0000_1000),
397
+ final: Boolean(flags & 0b0001_0000),
398
+ synchronized: Boolean(flags & 0b0010_0000),
399
+ volatile: false,
400
+ bridge: false,
401
+ transient: Boolean(flags & 0b1000_0000),
402
+ varargs: Boolean(flags & 0b1000_0000),
403
+ native: Boolean(flags & 0b0000_0001_0000_0000),
404
+ interface: Boolean(flags & 0b0000_0010_0000_0000),
405
+ abstract: Boolean(flags & 0b0000_0100_0000_0000),
406
+ strict: Boolean(flags & 0b0000_1000_0000_0000),
407
+ synthetic: Boolean(flags & 0b0001_0000_0000_0000),
408
+ annotation: Boolean(flags & 0b0010_0000_0000_0000),
409
+ enum: Boolean(flags & 0b0100_0000_0000_0000),
410
+ constructor: Boolean(flags & 0b0000_0001_0000_0000_0000_0000),
411
+ declaredSynchronized: Boolean(flags & 0b0000_0010_0000_0000_0000_0000),
412
+ });
413
+
414
+ const parseAccessFlags = (flags: number): DalvikExecutableAccessFlags => parseAccessFlagsCommon(flags);
415
+
416
+ const parseFieldAccessFlags = (flags: number): DalvikExecutableAccessFlags => ({
417
+ ...parseAccessFlagsCommon(flags),
418
+ volatile: Boolean(flags & 0b0100_0000),
419
+ varargs: false, // Varargs is only for methods, not fields
420
+ bridge: false,
421
+ });
422
+
423
+ const parseMethodAccessFlags = (flags: number): DalvikExecutableAccessFlags => ({
424
+ ...parseAccessFlagsCommon(flags),
425
+ volatile: false,
426
+ transient: false, // Transient is only for fields, not methods
427
+ bridge: Boolean(flags & 0b0100_0000),
428
+ });
429
+
341
430
  const uintAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
342
431
  uintParser,
343
- (flags) => ({
344
- public: Boolean(flags & 0b00000001),
345
- private: Boolean(flags & 0b00000010),
346
- protected: Boolean(flags & 0b00000100),
347
- static: Boolean(flags & 0b00001000),
348
- final: Boolean(flags & 0b00010000),
349
- synchronized: Boolean(flags & 0b00100000),
350
- volatile: Boolean(flags & 0b01000000),
351
- bridge: Boolean(flags & 0b01000000),
352
- transient: Boolean(flags & 0b10000000),
353
- varargs: Boolean(flags & 0b10000000),
354
- native: false,
355
- interface: false,
356
- abstract: false,
357
- strict: false,
358
- synthetic: false,
359
- annotation: false,
360
- enum: false,
361
- constructor: false,
362
- declaredSynchronized: false,
363
- }),
432
+ parseAccessFlags,
364
433
  );
365
434
 
366
435
  const uleb128AccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
367
436
  uleb128NumberParser,
368
- flags => ({
369
- public: Boolean(flags & 0b00000001),
370
- private: Boolean(flags & 0b00000010),
371
- protected: Boolean(flags & 0b00000100),
372
- static: Boolean(flags & 0b00001000),
373
- final: Boolean(flags & 0b00010000),
374
- synchronized: Boolean(flags & 0b00100000),
375
- volatile: Boolean(flags & 0b01000000),
376
- bridge: Boolean(flags & 0b01000000),
377
- transient: Boolean(flags & 0b10000000),
378
- varargs: Boolean(flags & 0b10000000),
379
- native: Boolean(flags & 0b00000001_00000000),
380
- interface: Boolean(flags & 0b00000010_00000000),
381
- abstract: Boolean(flags & 0b00000100_00000000),
382
- strict: Boolean(flags & 0b00001000_00000000),
383
- synthetic: Boolean(flags & 0b00010000_00000000),
384
- annotation: Boolean(flags & 0b00100000_00000000),
385
- enum: Boolean(flags & 0b01000000_00000000),
386
- constructor: Boolean(flags & 0b00000001_00000000_00000000),
387
- declaredSynchronized: Boolean(flags & 0b00000010_00000000_00000000),
388
- }),
437
+ parseAccessFlags,
438
+ );
439
+
440
+ const uleb128FieldAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
441
+ uleb128NumberParser,
442
+ parseFieldAccessFlags,
443
+ );
444
+
445
+ const uleb128MethodAccessFlagsParser: Parser<DalvikExecutableAccessFlags, Uint8Array> = promiseCompose(
446
+ uleb128NumberParser,
447
+ parseMethodAccessFlags,
389
448
  );
390
449
 
391
450
  type DalvikExecutableClassDefinitionItem = {
@@ -399,7 +458,7 @@ type DalvikExecutableClassDefinitionItem = {
399
458
  staticValuesOffset: OffsetToEncodedArrayItem;
400
459
  };
401
460
 
402
- const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX = 0xffffffff;
461
+ const DEX_CLASS_DEFINITION_ITEM_SOURCE_FILE_NO_INDEX = 0xFF_FF_FF_FF;
403
462
 
404
463
  const createSkipToThenClassDefinitionItemsParser = ({ size, offset }: SizeOffset): Parser<DalvikExecutableClassDefinitionItem[], Uint8Array> => (
405
464
  size === 0
@@ -470,9 +529,7 @@ type DalvikExecutableStringDataItem = {
470
529
  const stringDataItemParser: Parser<DalvikExecutableStringDataItem, Uint8Array> = promiseCompose(
471
530
  createTupleParser([
472
531
  uleb128NumberParser,
473
- createElementTerminatedSequenceParser(
474
- 0,
475
- ),
532
+ createElementTerminatedSequenceParser(0),
476
533
  ]),
477
534
  ([ utf16Size, data ]) => ({
478
535
  utf16Size,
@@ -506,7 +563,7 @@ type DalvikExecutableTypeItem = IndexIntoTypeIds;
506
563
 
507
564
  const dalvikExecutableTypeItemParser: Parser<DalvikExecutableTypeItem, Uint8Array> = promiseCompose(
508
565
  cloneParser(ushortParser),
509
- (index) => isoIndexIntoTypeIds.wrap(index),
566
+ index => isoIndexIntoTypeIds.wrap(index),
510
567
  );
511
568
 
512
569
  type DalvikExecutableTypeList = TypedNumberArray<IndexIntoTypeIds, DalvikExecutableTypeItem>;
@@ -523,7 +580,7 @@ const dalvikExecutableTypeListParser: Parser<DalvikExecutableTypeList, Uint8Arra
523
580
  dalvikExecutableTypeItemParser,
524
581
  size,
525
582
  ),
526
- (typeItems) => isoDalvikExecutableTypeList.wrap(typeItems),
583
+ typeItems => isoDalvikExecutableTypeList.wrap(typeItems),
527
584
  ),
528
585
  )();
529
586
 
@@ -669,7 +726,7 @@ type DalvikExecutableEncodedFieldDiff = {
669
726
  const encodedFieldParser: Parser<DalvikExecutableEncodedFieldDiff, Uint8Array> = promiseCompose(
670
727
  createTupleParser([
671
728
  uleb128NumberParser,
672
- uleb128AccessFlagsParser,
729
+ uleb128FieldAccessFlagsParser,
673
730
  ]),
674
731
  ([ fieldIndexDiff, accessFlags ]) => ({ fieldIndexDiff, accessFlags }),
675
732
  );
@@ -684,7 +741,7 @@ const createEncodedFieldsParser = (fieldsSize: number): Parser<DalvikExecutableE
684
741
  encodedFieldParser,
685
742
  fieldsSize,
686
743
  ),
687
- (encodedFields) => {
744
+ encodedFields => {
688
745
  let previousFieldIndex = 0;
689
746
  return encodedFields.map(({ fieldIndexDiff, accessFlags }) => {
690
747
  previousFieldIndex += fieldIndexDiff;
@@ -705,7 +762,7 @@ type DalvikExecutableEncodedMethodDiff = {
705
762
  const encodedMethodParser: Parser<DalvikExecutableEncodedMethodDiff, Uint8Array> = promiseCompose(
706
763
  createTupleParser([
707
764
  uleb128NumberParser,
708
- uleb128AccessFlagsParser,
765
+ uleb128MethodAccessFlagsParser,
709
766
  uleb128NumberParser,
710
767
  ]),
711
768
  ([
@@ -730,7 +787,7 @@ const createEncodedMethodsParser = (methodsSize: number): Parser<DalvikExecutabl
730
787
  encodedMethodParser,
731
788
  methodsSize,
732
789
  ),
733
- (encodedMethods) => {
790
+ encodedMethods => {
734
791
  let previousMethodIndex = 0;
735
792
  return encodedMethods.map(({ methodIndexDiff, accessFlags, codeOffset }) => {
736
793
  previousMethodIndex += methodIndexDiff;
@@ -744,10 +801,10 @@ const createEncodedMethodsParser = (methodsSize: number): Parser<DalvikExecutabl
744
801
  );
745
802
 
746
803
  type DalvikExecutableClassDataItem = {
747
- staticFields: DalvikExecutableEncodedField[],
748
- instanceFields: DalvikExecutableEncodedField[],
749
- directMethods: DalvikExecutableEncodedMethod[],
750
- virtualMethods: DalvikExecutableEncodedMethod[],
804
+ staticFields: DalvikExecutableEncodedField[];
805
+ instanceFields: DalvikExecutableEncodedField[];
806
+ directMethods: DalvikExecutableEncodedMethod[];
807
+ virtualMethods: DalvikExecutableEncodedMethod[];
751
808
  };
752
809
 
753
810
  const classDataItemParser: Parser<DalvikExecutableClassDataItem, Uint8Array> = parserCreatorCompose(
@@ -793,11 +850,33 @@ const createSkipToThenClassDataItemsParser = (sizeOffset: SizeOffset): Parser<Da
793
850
  parserName: 'skipToThenClassDataItemsParser',
794
851
  });
795
852
 
853
+ // Internal type for encoded values with type tags during parsing
854
+ type DalvikExecutableTaggedEncodedValue =
855
+ | { type: 'byte'; value: number }
856
+ | { type: 'short'; value: number }
857
+ | { type: 'char'; value: number }
858
+ | { type: 'int'; value: number }
859
+ | { type: 'long'; value: bigint }
860
+ | { type: 'float'; value: number }
861
+ | { type: 'double'; value: number }
862
+ | { type: 'methodType'; value: IndexIntoPrototypeIds }
863
+ | { type: 'methodHandle'; value: number }
864
+ | { type: 'string'; value: IndexIntoStringIds }
865
+ | { type: 'type'; value: IndexIntoTypeIds }
866
+ | { type: 'field'; value: IndexIntoFieldIds }
867
+ | { type: 'method'; value: IndexIntoMethodIds }
868
+ | { type: 'enum'; value: IndexIntoFieldIds }
869
+ | { type: 'array'; value: DalvikExecutableTaggedEncodedValue[] }
870
+ | { type: 'annotation'; value: DalvikExecutableEncodedAnnotation }
871
+ // eslint-disable-next-line @typescript-eslint/no-restricted-types
872
+ | { type: 'null'; value: null }
873
+ | { type: 'boolean'; value: boolean };
874
+
796
875
  const createByteWith5LeastSignificantBitsEqualParser = (leastSignificant5: number): Parser<number, Uint8Array> => {
797
- const byteWith5LeastSignificantBitsEqualParser: Parser<number, Uint8Array> = async (parserContext) => {
876
+ const byteWith5LeastSignificantBitsEqualParser: Parser<number, Uint8Array> = async parserContext => {
798
877
  const byte = await parserContext.read(0);
799
878
  parserContext.invariant(
800
- (byte & 0b00011111) === leastSignificant5,
879
+ (byte & 0b0001_1111) === leastSignificant5,
801
880
  'Expected byte with 5 least significant bits equal to %s, but got %s',
802
881
  leastSignificant5.toString(2).padStart(8, '0'),
803
882
  byte.toString(2).padStart(8, '0'),
@@ -812,20 +891,20 @@ const createByteWith5LeastSignificantBitsEqualParser = (leastSignificant5: numbe
812
891
 
813
892
  const createEncodedValueArgParser = (valueType: number): Parser<number, Uint8Array> => promiseCompose(
814
893
  createByteWith5LeastSignificantBitsEqualParser(valueType),
815
- (byte) => byte >> 5,
894
+ byte => byte >> 5,
816
895
  );
817
896
 
818
- const encodedValueByteParser: Parser<number, Uint8Array> = promiseCompose(
897
+ const encodedValueByteParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
819
898
  createTupleParser([
820
899
  createExactElementParser(0),
821
- ubyteParser,
900
+ byteParser,
822
901
  ]),
823
- ([ _, value ]) => value,
902
+ ([ _, value ]) => ({ type: 'byte' as const, value }),
824
903
  );
825
904
 
826
905
  setParserName(encodedValueByteParser, 'encodedValueByteParser');
827
906
 
828
- const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose(
907
+ const encodedValueShortParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
829
908
  () => createEncodedValueArgParser(0x02),
830
909
  sizeSubOne => {
831
910
  const size = sizeSubOne + 1;
@@ -833,9 +912,9 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
833
912
  if (size === 1) {
834
913
  return promiseCompose(
835
914
  createFixedLengthSequenceParser(size),
836
- (uint8Array) => {
915
+ uint8Array => {
837
916
  const buffer = Buffer.from(uint8Array);
838
- return buffer.readInt8(0);
917
+ return { type: 'short' as const, value: buffer.readInt8(0) };
839
918
  },
840
919
  );
841
920
  }
@@ -844,9 +923,9 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
844
923
 
845
924
  return promiseCompose(
846
925
  createFixedLengthSequenceParser(size),
847
- (uint8Array) => {
926
+ uint8Array => {
848
927
  const buffer = Buffer.from(uint8Array);
849
- return buffer.readInt16LE(0);
928
+ return { type: 'short' as const, value: buffer.readInt16LE(0) };
850
929
  },
851
930
  );
852
931
  },
@@ -854,7 +933,7 @@ const encodedValueShortParser: Parser<number, Uint8Array> = parserCreatorCompose
854
933
 
855
934
  setParserName(encodedValueShortParser, 'encodedValueShortParser');
856
935
 
857
- const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
936
+ const encodedValueCharParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
858
937
  () => createEncodedValueArgParser(0x03),
859
938
  sizeSubOne => {
860
939
  const size = sizeSubOne + 1;
@@ -862,9 +941,9 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
862
941
  if (size == 1) {
863
942
  return promiseCompose(
864
943
  createFixedLengthSequenceParser(size),
865
- (uint8Array) => {
866
- const buffer = Buffer.from([ 0, ...uint8Array ]);
867
- return buffer.readUInt16LE(0);
944
+ uint8Array => {
945
+ const buffer = Buffer.from([ ...uint8Array, 0 ]);
946
+ return { type: 'char' as const, value: buffer.readUInt16LE(0) };
868
947
  },
869
948
  );
870
949
  }
@@ -873,9 +952,9 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
873
952
 
874
953
  return promiseCompose(
875
954
  createFixedLengthSequenceParser(size),
876
- (uint8Array) => {
955
+ uint8Array => {
877
956
  const buffer = Buffer.from(uint8Array);
878
- return buffer.readUInt16LE(0);
957
+ return { type: 'char' as const, value: buffer.readUInt16LE(0) };
879
958
  },
880
959
  );
881
960
  },
@@ -883,7 +962,7 @@ const encodedValueCharParser: Parser<number, Uint8Array> = parserCreatorCompose(
883
962
 
884
963
  setParserName(encodedValueCharParser, 'encodedValueCharParser');
885
964
 
886
- const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
965
+ const encodedValueIntParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
887
966
  () => createEncodedValueArgParser(0x04),
888
967
  sizeSubOne => {
889
968
  const size = sizeSubOne + 1;
@@ -891,9 +970,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
891
970
  if (size === 1) {
892
971
  return promiseCompose(
893
972
  createFixedLengthSequenceParser(size),
894
- (uint8Array) => {
973
+ uint8Array => {
895
974
  const buffer = Buffer.from(uint8Array);
896
- return buffer.readInt8(0);
975
+ return { type: 'int' as const, value: buffer.readInt8(0) };
897
976
  },
898
977
  );
899
978
  }
@@ -901,9 +980,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
901
980
  if (size === 2) {
902
981
  return promiseCompose(
903
982
  createFixedLengthSequenceParser(size),
904
- (uint8Array) => {
983
+ uint8Array => {
905
984
  const buffer = Buffer.from(uint8Array);
906
- return buffer.readInt16LE(0);
985
+ return { type: 'int' as const, value: buffer.readInt16LE(0) };
907
986
  },
908
987
  );
909
988
  }
@@ -911,13 +990,13 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
911
990
  if (size === 3) {
912
991
  return promiseCompose(
913
992
  createFixedLengthSequenceParser(size),
914
- (uint8Array) => {
915
- const firstByte = uint8Array[0];
916
- const firstBit = (firstByte & 0b10000000) >> 7;
917
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
993
+ uint8Array => {
994
+ const lastByte = uint8Array[uint8Array.length - 1];
995
+ const signBit = (lastByte & 0b1000_0000) >> 7;
996
+ const extensionByte = signBit === 1 ? 0xFF : 0x00;
918
997
 
919
- const buffer = Buffer.from([ extensionByte, ...uint8Array ]);
920
- return buffer.readInt32LE(0);
998
+ const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
999
+ return { type: 'int' as const, value: buffer.readInt32LE(0) };
921
1000
  },
922
1001
  );
923
1002
  }
@@ -926,9 +1005,9 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
926
1005
 
927
1006
  return promiseCompose(
928
1007
  createFixedLengthSequenceParser(size),
929
- (uint8Array) => {
1008
+ uint8Array => {
930
1009
  const buffer = Buffer.from(uint8Array);
931
- return buffer.readInt32LE(0);
1010
+ return { type: 'int' as const, value: buffer.readInt32LE(0) };
932
1011
  },
933
1012
  );
934
1013
  },
@@ -936,7 +1015,7 @@ const encodedValueIntParser: Parser<number, Uint8Array> = parserCreatorCompose(
936
1015
 
937
1016
  setParserName(encodedValueIntParser, 'encodedValueIntParser');
938
1017
 
939
- const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
1018
+ const encodedValueLongParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
940
1019
  () => createEncodedValueArgParser(0x06),
941
1020
  sizeSubOne => {
942
1021
  const size = sizeSubOne + 1;
@@ -944,9 +1023,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
944
1023
  if (size === 1) {
945
1024
  return promiseCompose(
946
1025
  createFixedLengthSequenceParser(size),
947
- (uint8Array) => {
1026
+ uint8Array => {
948
1027
  const buffer = Buffer.from(uint8Array);
949
- return BigInt(buffer.readInt8(0));
1028
+ return { type: 'long' as const, value: BigInt(buffer.readInt8(0)) };
950
1029
  },
951
1030
  );
952
1031
  }
@@ -954,9 +1033,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
954
1033
  if (size === 2) {
955
1034
  return promiseCompose(
956
1035
  createFixedLengthSequenceParser(size),
957
- (uint8Array) => {
1036
+ uint8Array => {
958
1037
  const buffer = Buffer.from(uint8Array);
959
- return BigInt(buffer.readInt16LE(0));
1038
+ return { type: 'long' as const, value: BigInt(buffer.readInt16LE(0)) };
960
1039
  },
961
1040
  );
962
1041
  }
@@ -964,13 +1043,13 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
964
1043
  if (size === 3) {
965
1044
  return promiseCompose(
966
1045
  createFixedLengthSequenceParser(size),
967
- (uint8Array) => {
968
- const firstByte = uint8Array[0];
969
- const firstBit = (firstByte & 0b10000000) >> 7;
970
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
1046
+ uint8Array => {
1047
+ const lastByte = uint8Array[size - 1];
1048
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
1049
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
971
1050
 
972
- const buffer = Buffer.from([ extensionByte, ...uint8Array ]);
973
- return BigInt(buffer.readInt32LE(0));
1051
+ const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
1052
+ return { type: 'long' as const, value: BigInt(buffer.readInt32LE(0)) };
974
1053
  },
975
1054
  );
976
1055
  }
@@ -978,9 +1057,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
978
1057
  if (size === 4) {
979
1058
  return promiseCompose(
980
1059
  createFixedLengthSequenceParser(size),
981
- (uint8Array) => {
1060
+ uint8Array => {
982
1061
  const buffer = Buffer.from(uint8Array);
983
- return BigInt(buffer.readInt32LE(0));
1062
+ return { type: 'long' as const, value: BigInt(buffer.readInt32LE(0)) };
984
1063
  },
985
1064
  );
986
1065
  }
@@ -988,13 +1067,41 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
988
1067
  if (size === 5) {
989
1068
  return promiseCompose(
990
1069
  createFixedLengthSequenceParser(size),
991
- (uint8Array) => {
992
- const firstByte = uint8Array[0];
993
- const firstBit = (firstByte & 0b10000000) >> 7;
994
- const extensionByte = firstBit === 1 ? 0xff : 0x00;
1070
+ uint8Array => {
1071
+ const lastByte = uint8Array[size - 1];
1072
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
1073
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
1074
+
1075
+ const buffer = Buffer.from([ ...uint8Array, extensionByte, extensionByte, extensionByte ]);
1076
+ return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
1077
+ },
1078
+ );
1079
+ }
1080
+
1081
+ if (size === 6) {
1082
+ return promiseCompose(
1083
+ createFixedLengthSequenceParser(size),
1084
+ uint8Array => {
1085
+ const lastByte = uint8Array[size - 1];
1086
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
1087
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
995
1088
 
996
- const buffer = Buffer.from([ extensionByte, extensionByte, extensionByte, ...uint8Array ]);
997
- return BigInt(buffer.readBigInt64LE(0));
1089
+ const buffer = Buffer.from([ ...uint8Array, extensionByte, extensionByte ]);
1090
+ return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
1091
+ },
1092
+ );
1093
+ }
1094
+
1095
+ if (size === 7) {
1096
+ return promiseCompose(
1097
+ createFixedLengthSequenceParser(size),
1098
+ uint8Array => {
1099
+ const lastByte = uint8Array[size - 1];
1100
+ const firstBit = (lastByte & 0b1000_0000) >> 7;
1101
+ const extensionByte = firstBit === 1 ? 0xFF : 0x00;
1102
+
1103
+ const buffer = Buffer.from([ ...uint8Array, extensionByte ]);
1104
+ return { type: 'long' as const, value: BigInt(buffer.readBigInt64LE(0)) };
998
1105
  },
999
1106
  );
1000
1107
  }
@@ -1003,9 +1110,9 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
1003
1110
 
1004
1111
  return promiseCompose(
1005
1112
  createFixedLengthSequenceParser(size),
1006
- (uint8Array) => {
1113
+ uint8Array => {
1007
1114
  const buffer = Buffer.from(uint8Array);
1008
- return buffer.readBigInt64LE(0);
1115
+ return { type: 'long' as const, value: buffer.readBigInt64LE(0) };
1009
1116
  },
1010
1117
  );
1011
1118
  },
@@ -1013,7 +1120,7 @@ const encodedValueLongParser: Parser<bigint, Uint8Array> = parserCreatorCompose(
1013
1120
 
1014
1121
  setParserName(encodedValueLongParser, 'encodedValueLongParser');
1015
1122
 
1016
- const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose(
1123
+ const encodedValueFloatParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1017
1124
  () => createEncodedValueArgParser(0x10),
1018
1125
  sizeSubOne => {
1019
1126
  const size = sizeSubOne + 1;
@@ -1021,9 +1128,9 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
1021
1128
  if (size === 1) {
1022
1129
  return promiseCompose(
1023
1130
  createFixedLengthSequenceParser(size),
1024
- (uint8Array) => {
1025
- const buffer = Buffer.from([ ...uint8Array, 0, 0, 0 ]);
1026
- return buffer.readFloatLE(0);
1131
+ uint8Array => {
1132
+ const buffer = Buffer.from([ 0, 0, 0, ...uint8Array ]);
1133
+ return { type: 'float' as const, value: buffer.readFloatLE(0) };
1027
1134
  },
1028
1135
  );
1029
1136
  }
@@ -1031,9 +1138,19 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
1031
1138
  if (size === 2) {
1032
1139
  return promiseCompose(
1033
1140
  createFixedLengthSequenceParser(size),
1034
- (uint8Array) => {
1035
- const buffer = Buffer.from([ ...uint8Array, 0, 0 ]);
1036
- return buffer.readFloatLE(0);
1141
+ uint8Array => {
1142
+ const buffer = Buffer.from([ 0, 0, ...uint8Array ]);
1143
+ return { type: 'float' as const, value: buffer.readFloatLE(0) };
1144
+ },
1145
+ );
1146
+ }
1147
+
1148
+ if (size === 3) {
1149
+ return promiseCompose(
1150
+ createFixedLengthSequenceParser(size),
1151
+ uint8Array => {
1152
+ const buffer = Buffer.from([ 0, ...uint8Array ]);
1153
+ return { type: 'float' as const, value: buffer.readFloatLE(0) };
1037
1154
  },
1038
1155
  );
1039
1156
  }
@@ -1042,9 +1159,9 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
1042
1159
 
1043
1160
  return promiseCompose(
1044
1161
  createFixedLengthSequenceParser(size),
1045
- (uint8Array) => {
1162
+ uint8Array => {
1046
1163
  const buffer = Buffer.from(uint8Array);
1047
- return buffer.readFloatLE(0);
1164
+ return { type: 'float' as const, value: buffer.readFloatLE(0) };
1048
1165
  },
1049
1166
  );
1050
1167
  },
@@ -1052,7 +1169,7 @@ const encodedValueFloatParser: Parser<number, Uint8Array> = parserCreatorCompose
1052
1169
 
1053
1170
  setParserName(encodedValueFloatParser, 'encodedValueFloatParser');
1054
1171
 
1055
- const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompose(
1172
+ const encodedValueDoubleParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1056
1173
  () => createEncodedValueArgParser(0x11),
1057
1174
  sizeSubOne => {
1058
1175
  const size = sizeSubOne + 1;
@@ -1060,9 +1177,9 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
1060
1177
  if (size === 1) {
1061
1178
  return promiseCompose(
1062
1179
  createFixedLengthSequenceParser(size),
1063
- (uint8Array) => {
1064
- const buffer = Buffer.from([ ...uint8Array, 0, 0, 0, 0, 0, 0, 0 ]);
1065
- return buffer.readDoubleLE(0);
1180
+ uint8Array => {
1181
+ const buffer = Buffer.from([ 0, 0, 0, 0, 0, 0, 0, ...uint8Array ]);
1182
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1066
1183
  },
1067
1184
  );
1068
1185
  }
@@ -1070,9 +1187,19 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
1070
1187
  if (size === 2) {
1071
1188
  return promiseCompose(
1072
1189
  createFixedLengthSequenceParser(size),
1073
- (uint8Array) => {
1074
- const buffer = Buffer.from([ ...uint8Array, 0, 0, 0, 0, 0, 0 ]);
1075
- return buffer.readDoubleLE(0);
1190
+ uint8Array => {
1191
+ const buffer = Buffer.from([ 0, 0, 0, 0, 0, 0, ...uint8Array ]);
1192
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1193
+ },
1194
+ );
1195
+ }
1196
+
1197
+ if (size === 3) {
1198
+ return promiseCompose(
1199
+ createFixedLengthSequenceParser(size),
1200
+ uint8Array => {
1201
+ const buffer = Buffer.from([ 0, 0, 0, 0, 0, ...uint8Array ]);
1202
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1076
1203
  },
1077
1204
  );
1078
1205
  }
@@ -1080,9 +1207,39 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
1080
1207
  if (size === 4) {
1081
1208
  return promiseCompose(
1082
1209
  createFixedLengthSequenceParser(size),
1083
- (uint8Array) => {
1084
- const buffer = Buffer.from([ ...uint8Array, 0, 0, 0, 0 ]);
1085
- return buffer.readDoubleLE(0);
1210
+ uint8Array => {
1211
+ const buffer = Buffer.from([ 0, 0, 0, 0, ...uint8Array ]);
1212
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1213
+ },
1214
+ );
1215
+ }
1216
+
1217
+ if (size === 5) {
1218
+ return promiseCompose(
1219
+ createFixedLengthSequenceParser(size),
1220
+ uint8Array => {
1221
+ const buffer = Buffer.from([ 0, 0, 0, ...uint8Array ]);
1222
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1223
+ },
1224
+ );
1225
+ }
1226
+
1227
+ if (size === 6) {
1228
+ return promiseCompose(
1229
+ createFixedLengthSequenceParser(size),
1230
+ uint8Array => {
1231
+ const buffer = Buffer.from([ 0, 0, ...uint8Array ]);
1232
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1233
+ },
1234
+ );
1235
+ }
1236
+
1237
+ if (size === 7) {
1238
+ return promiseCompose(
1239
+ createFixedLengthSequenceParser(size),
1240
+ uint8Array => {
1241
+ const buffer = Buffer.from([ 0, ...uint8Array ]);
1242
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1086
1243
  },
1087
1244
  );
1088
1245
  }
@@ -1091,9 +1248,9 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
1091
1248
 
1092
1249
  return promiseCompose(
1093
1250
  createFixedLengthSequenceParser(size),
1094
- (uint8Array) => {
1251
+ uint8Array => {
1095
1252
  const buffer = Buffer.from(uint8Array);
1096
- return buffer.readDoubleLE(0);
1253
+ return { type: 'double' as const, value: buffer.readDoubleLE(0) };
1097
1254
  },
1098
1255
  );
1099
1256
  },
@@ -1101,7 +1258,7 @@ const encodedValueDoubleParser: Parser<number, Uint8Array> = parserCreatorCompos
1101
1258
 
1102
1259
  setParserName(encodedValueDoubleParser, 'encodedValueDoubleParser');
1103
1260
 
1104
- const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1261
+ const encodedValueMethodTypeParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1105
1262
  () => createEncodedValueArgParser(0x15),
1106
1263
  sizeSubOne => {
1107
1264
  const size = sizeSubOne + 1;
@@ -1109,9 +1266,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
1109
1266
  if (size === 1) {
1110
1267
  return promiseCompose(
1111
1268
  createFixedLengthSequenceParser(size),
1112
- (uint8Array) => {
1269
+ uint8Array => {
1113
1270
  const buffer = Buffer.from(uint8Array);
1114
- return buffer.readUint8(0);
1271
+ return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUint8(0)) };
1115
1272
  },
1116
1273
  );
1117
1274
  }
@@ -1119,9 +1276,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
1119
1276
  if (size === 2) {
1120
1277
  return promiseCompose(
1121
1278
  createFixedLengthSequenceParser(size),
1122
- (uint8Array) => {
1279
+ uint8Array => {
1123
1280
  const buffer = Buffer.from(uint8Array);
1124
- return buffer.readUInt16LE(0);
1281
+ return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt16LE(0)) };
1125
1282
  },
1126
1283
  );
1127
1284
  }
@@ -1130,9 +1287,9 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
1130
1287
 
1131
1288
  return promiseCompose(
1132
1289
  createFixedLengthSequenceParser(size),
1133
- (uint8Array) => {
1290
+ uint8Array => {
1134
1291
  const buffer = Buffer.from(uint8Array);
1135
- return buffer.readUInt32LE(0);
1292
+ return { type: 'methodType' as const, value: isoIndexIntoPrototypeIds.wrap(buffer.readUInt32LE(0)) };
1136
1293
  },
1137
1294
  );
1138
1295
  },
@@ -1140,7 +1297,7 @@ const encodedValueMethodTypeParser: Parser<number, Uint8Array> = parserCreatorCo
1140
1297
 
1141
1298
  setParserName(encodedValueMethodTypeParser, 'encodedValueMethodTypeParser');
1142
1299
 
1143
- const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreatorCompose(
1300
+ const encodedValueMethodHandleParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1144
1301
  () => createEncodedValueArgParser(0x16),
1145
1302
  sizeSubOne => {
1146
1303
  const size = sizeSubOne + 1;
@@ -1148,9 +1305,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
1148
1305
  if (size === 1) {
1149
1306
  return promiseCompose(
1150
1307
  createFixedLengthSequenceParser(size),
1151
- (uint8Array) => {
1308
+ uint8Array => {
1152
1309
  const buffer = Buffer.from(uint8Array);
1153
- return buffer.readUInt8(0);
1310
+ return { type: 'methodHandle' as const, value: buffer.readUInt8(0) };
1154
1311
  },
1155
1312
  );
1156
1313
  }
@@ -1158,9 +1315,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
1158
1315
  if (size === 2) {
1159
1316
  return promiseCompose(
1160
1317
  createFixedLengthSequenceParser(size),
1161
- (uint8Array) => {
1318
+ uint8Array => {
1162
1319
  const buffer = Buffer.from(uint8Array);
1163
- return buffer.readUInt16LE(0);
1320
+ return { type: 'methodHandle' as const, value: buffer.readUInt16LE(0) };
1164
1321
  },
1165
1322
  );
1166
1323
  }
@@ -1169,9 +1326,9 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
1169
1326
 
1170
1327
  return promiseCompose(
1171
1328
  createFixedLengthSequenceParser(size),
1172
- (uint8Array) => {
1329
+ uint8Array => {
1173
1330
  const buffer = Buffer.from(uint8Array);
1174
- return buffer.readUInt32LE(0);
1331
+ return { type: 'methodHandle' as const, value: buffer.readUInt32LE(0) };
1175
1332
  },
1176
1333
  );
1177
1334
  },
@@ -1179,7 +1336,7 @@ const encodedValueMethodHandleParser: Parser<number, Uint8Array> = parserCreator
1179
1336
 
1180
1337
  setParserName(encodedValueMethodHandleParser, 'encodedValueMethodHandleParser');
1181
1338
 
1182
- const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompose(
1339
+ const encodedValueStringParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1183
1340
  () => createEncodedValueArgParser(0x17),
1184
1341
  sizeSubOne => {
1185
1342
  const size = sizeSubOne + 1;
@@ -1187,9 +1344,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
1187
1344
  if (size === 1) {
1188
1345
  return promiseCompose(
1189
1346
  createFixedLengthSequenceParser(size),
1190
- (uint8Array) => {
1347
+ uint8Array => {
1191
1348
  const buffer = Buffer.from(uint8Array);
1192
- return buffer.readUInt8(0);
1349
+ return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt8(0)) };
1193
1350
  },
1194
1351
  );
1195
1352
  }
@@ -1197,9 +1354,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
1197
1354
  if (size === 2) {
1198
1355
  return promiseCompose(
1199
1356
  createFixedLengthSequenceParser(size),
1200
- (uint8Array) => {
1357
+ uint8Array => {
1201
1358
  const buffer = Buffer.from(uint8Array);
1202
- return buffer.readUInt16LE(0);
1359
+ return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt16LE(0)) };
1203
1360
  },
1204
1361
  );
1205
1362
  }
@@ -1208,9 +1365,9 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
1208
1365
 
1209
1366
  return promiseCompose(
1210
1367
  createFixedLengthSequenceParser(size),
1211
- (uint8Array) => {
1368
+ uint8Array => {
1212
1369
  const buffer = Buffer.from(uint8Array);
1213
- return buffer.readUInt32LE(0);
1370
+ return { type: 'string' as const, value: isoIndexIntoStringIds.wrap(buffer.readUInt32LE(0)) };
1214
1371
  },
1215
1372
  );
1216
1373
  },
@@ -1218,7 +1375,7 @@ const encodedValueStringParser: Parser<number, Uint8Array> = parserCreatorCompos
1218
1375
 
1219
1376
  setParserName(encodedValueStringParser, 'encodedValueStringParser');
1220
1377
 
1221
- const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1378
+ const encodedValueTypeParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1222
1379
  () => createEncodedValueArgParser(0x18),
1223
1380
  sizeSubOne => {
1224
1381
  const size = sizeSubOne + 1;
@@ -1226,9 +1383,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1226
1383
  if (size === 1) {
1227
1384
  return promiseCompose(
1228
1385
  createFixedLengthSequenceParser(size),
1229
- (uint8Array) => {
1386
+ uint8Array => {
1230
1387
  const buffer = Buffer.from(uint8Array);
1231
- return buffer.readUInt8(0);
1388
+ return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt8(0)) };
1232
1389
  },
1233
1390
  );
1234
1391
  }
@@ -1236,9 +1393,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1236
1393
  if (size === 2) {
1237
1394
  return promiseCompose(
1238
1395
  createFixedLengthSequenceParser(size),
1239
- (uint8Array) => {
1396
+ uint8Array => {
1240
1397
  const buffer = Buffer.from(uint8Array);
1241
- return buffer.readUInt16LE(0);
1398
+ return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt16LE(0)) };
1242
1399
  },
1243
1400
  );
1244
1401
  }
@@ -1247,9 +1404,9 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1247
1404
 
1248
1405
  return promiseCompose(
1249
1406
  createFixedLengthSequenceParser(size),
1250
- (uint8Array) => {
1407
+ uint8Array => {
1251
1408
  const buffer = Buffer.from(uint8Array);
1252
- return buffer.readUInt32LE(0);
1409
+ return { type: 'type' as const, value: isoIndexIntoTypeIds.wrap(buffer.readUInt32LE(0)) };
1253
1410
  },
1254
1411
  );
1255
1412
  },
@@ -1257,7 +1414,7 @@ const encodedValueTypeParser: Parser<number, Uint8Array> = parserCreatorCompose(
1257
1414
 
1258
1415
  setParserName(encodedValueTypeParser, 'encodedValueTypeParser');
1259
1416
 
1260
- const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose(
1417
+ const encodedValueFieldParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1261
1418
  () => createEncodedValueArgParser(0x19),
1262
1419
  sizeSubOne => {
1263
1420
  const size = sizeSubOne + 1;
@@ -1265,9 +1422,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
1265
1422
  if (size === 1) {
1266
1423
  return promiseCompose(
1267
1424
  createFixedLengthSequenceParser(size),
1268
- (uint8Array) => {
1425
+ uint8Array => {
1269
1426
  const buffer = Buffer.from(uint8Array);
1270
- return buffer.readUInt8(0);
1427
+ return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
1271
1428
  },
1272
1429
  );
1273
1430
  }
@@ -1275,9 +1432,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
1275
1432
  if (size === 2) {
1276
1433
  return promiseCompose(
1277
1434
  createFixedLengthSequenceParser(size),
1278
- (uint8Array) => {
1435
+ uint8Array => {
1279
1436
  const buffer = Buffer.from(uint8Array);
1280
- return buffer.readUInt16LE(0);
1437
+ return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
1281
1438
  },
1282
1439
  );
1283
1440
  }
@@ -1286,9 +1443,9 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
1286
1443
 
1287
1444
  return promiseCompose(
1288
1445
  createFixedLengthSequenceParser(size),
1289
- (uint8Array) => {
1446
+ uint8Array => {
1290
1447
  const buffer = Buffer.from(uint8Array);
1291
- return buffer.readUInt32LE(0);
1448
+ return { type: 'field' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
1292
1449
  },
1293
1450
  );
1294
1451
  },
@@ -1296,17 +1453,17 @@ const encodedValueFieldParser: Parser<number, Uint8Array> = parserCreatorCompose
1296
1453
 
1297
1454
  setParserName(encodedValueFieldParser, 'encodedValueFieldParser');
1298
1455
 
1299
- const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompose(
1300
- () => createEncodedValueArgParser(0x1a),
1456
+ const encodedValueMethodParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1457
+ () => createEncodedValueArgParser(0x1A),
1301
1458
  sizeSubOne => {
1302
1459
  const size = sizeSubOne + 1;
1303
1460
 
1304
1461
  if (size === 1) {
1305
1462
  return promiseCompose(
1306
1463
  createFixedLengthSequenceParser(size),
1307
- (uint8Array) => {
1464
+ uint8Array => {
1308
1465
  const buffer = Buffer.from(uint8Array);
1309
- return buffer.readUInt8(0);
1466
+ return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt8(0)) };
1310
1467
  },
1311
1468
  );
1312
1469
  }
@@ -1314,9 +1471,9 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
1314
1471
  if (size === 2) {
1315
1472
  return promiseCompose(
1316
1473
  createFixedLengthSequenceParser(size),
1317
- (uint8Array) => {
1474
+ uint8Array => {
1318
1475
  const buffer = Buffer.from(uint8Array);
1319
- return buffer.readUInt16LE(0);
1476
+ return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt16LE(0)) };
1320
1477
  },
1321
1478
  );
1322
1479
  }
@@ -1325,9 +1482,9 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
1325
1482
 
1326
1483
  return promiseCompose(
1327
1484
  createFixedLengthSequenceParser(size),
1328
- (uint8Array) => {
1485
+ uint8Array => {
1329
1486
  const buffer = Buffer.from(uint8Array);
1330
- return buffer.readUInt32LE(0);
1487
+ return { type: 'method' as const, value: isoIndexIntoMethodIds.wrap(buffer.readUInt32LE(0)) };
1331
1488
  },
1332
1489
  );
1333
1490
  },
@@ -1335,17 +1492,17 @@ const encodedValueMethodParser: Parser<number, Uint8Array> = parserCreatorCompos
1335
1492
 
1336
1493
  setParserName(encodedValueMethodParser, 'encodedValueMethodParser');
1337
1494
 
1338
- const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
1339
- () => createEncodedValueArgParser(0x1b),
1495
+ const encodedValueEnumParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1496
+ () => createEncodedValueArgParser(0x1B),
1340
1497
  sizeSubOne => {
1341
1498
  const size = sizeSubOne + 1;
1342
1499
 
1343
1500
  if (size === 1) {
1344
1501
  return promiseCompose(
1345
1502
  createFixedLengthSequenceParser(size),
1346
- (uint8Array) => {
1503
+ uint8Array => {
1347
1504
  const buffer = Buffer.from(uint8Array);
1348
- return buffer.readUInt8(0);
1505
+ return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt8(0)) };
1349
1506
  },
1350
1507
  );
1351
1508
  }
@@ -1353,9 +1510,9 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
1353
1510
  if (size === 2) {
1354
1511
  return promiseCompose(
1355
1512
  createFixedLengthSequenceParser(size),
1356
- (uint8Array) => {
1513
+ uint8Array => {
1357
1514
  const buffer = Buffer.from(uint8Array);
1358
- return buffer.readUInt16LE(0);
1515
+ return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt16LE(0)) };
1359
1516
  },
1360
1517
  );
1361
1518
  }
@@ -1364,9 +1521,9 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
1364
1521
 
1365
1522
  return promiseCompose(
1366
1523
  createFixedLengthSequenceParser(size),
1367
- (uint8Array) => {
1524
+ uint8Array => {
1368
1525
  const buffer = Buffer.from(uint8Array);
1369
- return buffer.readUInt32LE(0);
1526
+ return { type: 'enum' as const, value: isoIndexIntoFieldIds.wrap(buffer.readUInt32LE(0)) };
1370
1527
  },
1371
1528
  );
1372
1529
  },
@@ -1374,11 +1531,11 @@ const encodedValueEnumParser: Parser<number, Uint8Array> = parserCreatorCompose(
1374
1531
 
1375
1532
  setParserName(encodedValueEnumParser, 'encodedValueEnumParser');
1376
1533
 
1377
- type DalvikExecutableEncodedArray = DalvikExecutableEncodedValue[];
1534
+ type DalvikExecutableEncodedArray = DalvikExecutableTaggedEncodedValue[];
1378
1535
 
1379
- const encodedArrayParser: Parser<DalvikExecutableEncodedArray, Uint8Array> = parserCreatorCompose(
1536
+ const encodedArrayParser: Parser<DalvikExecutableTaggedEncodedValue[], Uint8Array> = parserCreatorCompose(
1380
1537
  () => uleb128NumberParser,
1381
- (size) => createQuantifierParser(
1538
+ size => createQuantifierParser(
1382
1539
  encodedValueParser,
1383
1540
  size,
1384
1541
  ),
@@ -1386,24 +1543,24 @@ const encodedArrayParser: Parser<DalvikExecutableEncodedArray, Uint8Array> = par
1386
1543
 
1387
1544
  setParserName(encodedArrayParser, 'encodedArrayParser');
1388
1545
 
1389
- const encodedValueArrayParser: Parser<DalvikExecutableEncodedValue[], Uint8Array> = promiseCompose(
1546
+ const encodedValueArrayParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
1390
1547
  createTupleParser([
1391
1548
  parserCreatorCompose(
1392
- () => createEncodedValueArgParser(0x1c),
1549
+ () => createEncodedValueArgParser(0x1C),
1393
1550
  valueArg => parserContext => {
1394
1551
  parserContext.invariant(valueArg === 0, '(encodedValueArrayParser) valueArg: %s', valueArg);
1395
1552
  },
1396
1553
  )(),
1397
1554
  encodedArrayParser,
1398
1555
  ]),
1399
- ([ _, array ]) => array,
1556
+ ([ _, array ]) => ({ type: 'array' as const, value: array }),
1400
1557
  );
1401
1558
 
1402
1559
  setParserName(encodedValueArrayParser, 'encodedValueArrayParser');
1403
1560
 
1404
1561
  type DalvikExecutableAnnotationElement = {
1405
1562
  nameIndex: IndexIntoStringIds;
1406
- value: DalvikExecutableEncodedValue;
1563
+ value: DalvikExecutableTaggedEncodedValue;
1407
1564
  };
1408
1565
 
1409
1566
  type DalvikExecutableEncodedAnnotation = {
@@ -1455,39 +1612,39 @@ const encodedAnnotationParser: Parser<DalvikExecutableEncodedAnnotation, Uint8Ar
1455
1612
 
1456
1613
  setParserName(encodedAnnotationParser, 'encodedAnnotationParser');
1457
1614
 
1458
- const encodedValueAnnotationParser: Parser<DalvikExecutableEncodedAnnotation, Uint8Array> = promiseCompose(
1615
+ const encodedValueAnnotationParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
1459
1616
  createTupleParser([
1460
1617
  parserCreatorCompose(
1461
- () => createEncodedValueArgParser(0x1d),
1618
+ () => createEncodedValueArgParser(0x1D),
1462
1619
  valueArg => parserContext => {
1463
1620
  parserContext.invariant(valueArg === 0, '(encodedValueAnnotationParser) valueArg: %s', valueArg);
1464
1621
  },
1465
1622
  )(),
1466
1623
  encodedAnnotationParser,
1467
1624
  ]),
1468
- ([ _, annotation ]) => annotation,
1625
+ ([ _, annotation ]) => ({ type: 'annotation' as const, value: annotation }),
1469
1626
  );
1470
1627
 
1471
1628
  setParserName(encodedValueAnnotationParser, 'encodedValueAnnotationParser');
1472
1629
 
1473
- const encodedValueNullParser: Parser<null, Uint8Array> = parserCreatorCompose(
1474
- () => createEncodedValueArgParser(0x1e),
1630
+ const encodedValueNullParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = parserCreatorCompose(
1631
+ () => createEncodedValueArgParser(0x1E),
1475
1632
  valueArg => parserContext => {
1476
1633
  parserContext.invariant(valueArg === 0, '(encodedValueNullParser) valueArg: %s', valueArg);
1477
- return null;
1634
+ return ({ type: 'null' as const, value: null });
1478
1635
  },
1479
1636
  )();
1480
1637
 
1481
1638
  setParserName(encodedValueNullParser, 'encodedValueNullParser');
1482
1639
 
1483
- const encodedValueBooleanParser: Parser<boolean, Uint8Array> = promiseCompose(
1484
- createEncodedValueArgParser(0x1f),
1485
- (value) => Boolean(value),
1640
+ const encodedValueBooleanParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = promiseCompose(
1641
+ createEncodedValueArgParser(0x1F),
1642
+ valueArg => ({ type: 'boolean' as const, value: Boolean(valueArg) }),
1486
1643
  );
1487
1644
 
1488
1645
  setParserName(encodedValueBooleanParser, 'encodedValueBooleanParser');
1489
1646
 
1490
- const encodedValueParser: Parser<DalvikExecutableEncodedValue, Uint8Array> = createDisjunctionParser([
1647
+ const encodedValueParser: Parser<DalvikExecutableTaggedEncodedValue, Uint8Array> = createDisjunctionParser([
1491
1648
  encodedValueByteParser,
1492
1649
  encodedValueShortParser,
1493
1650
  encodedValueCharParser,
@@ -1555,8 +1712,8 @@ const encodedTypeAddressPairParser: Parser<DalvikExecutableEncodedTypeAddressPai
1555
1712
  );
1556
1713
 
1557
1714
  type DalvikExecutableEncodedCatchHandler_ = {
1558
- handlers: DalvikExecutableEncodedTypeAddressPair_[],
1559
- catchAllAddress: undefined | number,
1715
+ handlers: DalvikExecutableEncodedTypeAddressPair_[];
1716
+ catchAllAddress: undefined | number;
1560
1717
  };
1561
1718
 
1562
1719
  const encodedCatchHandlerParser: Parser<DalvikExecutableEncodedCatchHandler_, Uint8Array> = parserCreatorCompose(
@@ -1584,16 +1741,14 @@ setParserName(encodedCatchHandlerParser, 'encodedCatchHandlerParser');
1584
1741
 
1585
1742
  type DalvikExecutableEncodedCatchHandlerByRelativeOffset = Map<OffsetFromEncodedCatchHandlerListToEncodedCatchHandler, DalvikExecutableEncodedCatchHandler_>;
1586
1743
 
1587
- const encodedCatchHandlerListParser: Parser<DalvikExecutableEncodedCatchHandlerByRelativeOffset, Uint8Array> = async (parserContext) => {
1744
+ const encodedCatchHandlerListParser: Parser<DalvikExecutableEncodedCatchHandlerByRelativeOffset, Uint8Array> = async parserContext => {
1588
1745
  const listOffset = parserContext.position;
1589
1746
  const handlers: DalvikExecutableEncodedCatchHandlerByRelativeOffset = new Map();
1590
1747
 
1591
1748
  const size = await uleb128NumberParser(parserContext);
1592
1749
 
1593
1750
  for (let i = 0; i < size; i += 1) {
1594
- const handlerRelativeOffset = isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler.wrap(
1595
- parserContext.position - listOffset,
1596
- );
1751
+ const handlerRelativeOffset = isoOffsetFromEncodedCatchHandlerListToEncodedCatchHandler.wrap(parserContext.position - listOffset);
1597
1752
  const handler = await encodedCatchHandlerParser(parserContext);
1598
1753
 
1599
1754
  handlers.set(handlerRelativeOffset, handler);
@@ -1639,51 +1794,47 @@ const createDalvikExecutableCodeItemParser = <Instructions>({
1639
1794
  triesSize,
1640
1795
  debugInfoOffset,
1641
1796
  instructionsSize,
1642
- ]) => {
1643
- return promiseCompose(
1644
- createTupleParser([
1645
- createInstructionsParser(instructionsSize * 2),
1646
- (
1647
- (
1648
- triesSize !== 0
1649
- && instructionsSize % 2 === 1
1650
- )
1651
- ? byteAlign4Parser
1652
- : () => undefined
1653
- ),
1654
- (
1655
- triesSize !== 0
1656
- ? createQuantifierParser(
1657
- tryItemParser,
1658
- triesSize,
1659
- )
1660
- : () => []
1661
- ),
1797
+ ]) => promiseCompose(
1798
+ createTupleParser([
1799
+ createInstructionsParser(instructionsSize * 2),
1800
+ (
1662
1801
  (
1663
1802
  triesSize !== 0
1664
- ? encodedCatchHandlerListParser
1665
- : () => new Map()
1666
- ),
1667
- ]),
1668
- ([
1669
- instructions,
1670
- _padding,
1671
- tryItems,
1672
- handlers,
1673
- ]) => {
1674
- return {
1675
- registersSize,
1676
- insSize,
1677
- outsSize,
1678
- triesSize,
1679
- debugInfoOffset: isoOffsetToDebugInfoItem.wrap(debugInfoOffset),
1680
- instructions,
1681
- tryItems,
1682
- handlers,
1683
- };
1684
- },
1685
- );
1686
- },
1803
+ && instructionsSize % 2 === 1
1804
+ )
1805
+ ? byteAlign4Parser
1806
+ : () => undefined
1807
+ ),
1808
+ (
1809
+ triesSize === 0
1810
+ ? () => []
1811
+ : createQuantifierParser(
1812
+ tryItemParser,
1813
+ triesSize,
1814
+ )
1815
+ ),
1816
+ (
1817
+ triesSize === 0
1818
+ ? () => new Map()
1819
+ : encodedCatchHandlerListParser
1820
+ ),
1821
+ ]),
1822
+ ([
1823
+ instructions,
1824
+ _padding,
1825
+ tryItems,
1826
+ handlers,
1827
+ ]) => ({
1828
+ registersSize,
1829
+ insSize,
1830
+ outsSize,
1831
+ triesSize,
1832
+ debugInfoOffset: isoOffsetToDebugInfoItem.wrap(debugInfoOffset),
1833
+ instructions,
1834
+ tryItems,
1835
+ handlers,
1836
+ }),
1837
+ ),
1687
1838
  )();
1688
1839
 
1689
1840
  setParserName(dalvikExecutableCodeItemParser, 'dalvikExecutableCodeItemParser');
@@ -1721,15 +1872,15 @@ type DalvikExecutableDebugByteCodeValueItem =
1721
1872
  | {
1722
1873
  type: 'startLocal';
1723
1874
  registerNum: number;
1724
- nameIndex: IndexIntoStringIds;
1725
- typeIndex: IndexIntoTypeIds;
1875
+ nameIndex: undefined | IndexIntoStringIds;
1876
+ typeIndex: undefined | IndexIntoTypeIds;
1726
1877
  }
1727
1878
  | {
1728
1879
  type: 'startLocalExtended';
1729
1880
  registerNum: number;
1730
- nameIndex: IndexIntoStringIds;
1731
- typeIndex: IndexIntoTypeIds;
1732
- signatureIndex: IndexIntoStringIds;
1881
+ nameIndex: undefined | IndexIntoStringIds;
1882
+ typeIndex: undefined | IndexIntoTypeIds;
1883
+ signatureIndex: undefined | IndexIntoStringIds;
1733
1884
  }
1734
1885
  | {
1735
1886
  type: 'endLocal';
@@ -1747,7 +1898,7 @@ type DalvikExecutableDebugByteCodeValueItem =
1747
1898
  }
1748
1899
  | {
1749
1900
  type: 'setFile';
1750
- nameIndex: IndexIntoStringIds;
1901
+ nameIndex: undefined | IndexIntoStringIds;
1751
1902
  }
1752
1903
  | {
1753
1904
  type: 'special';
@@ -1759,62 +1910,81 @@ const dalvikExecutableDebugByteCodeValueParser: Parser<DalvikExecutableDebugByte
1759
1910
  () => ubyteParser,
1760
1911
  (value): Parser<DalvikExecutableDebugByteCodeValueItem, Uint8Array> => {
1761
1912
  switch (value) {
1762
- case 0x01: return promiseCompose(
1913
+ case 0x01: { return promiseCompose(
1763
1914
  uleb128NumberParser,
1764
- (addressDiff) => ({ type: 'advancePc', addressDiff }),
1915
+ addressDiff => ({ type: 'advancePc', addressDiff }),
1765
1916
  );
1766
- case 0x02: return promiseCompose(
1917
+ }
1918
+
1919
+ case 0x02: { return promiseCompose(
1767
1920
  sleb128NumberParser,
1768
- (lineDiff) => ({ type: 'advanceLine', lineDiff }),
1921
+ lineDiff => ({ type: 'advanceLine', lineDiff }),
1769
1922
  );
1770
- case 0x03: return promiseCompose(
1923
+ }
1924
+
1925
+ case 0x03: { return promiseCompose(
1771
1926
  createTupleParser([
1772
1927
  uleb128NumberParser,
1773
- uleb128NumberParser,
1774
- uleb128NumberParser,
1928
+ uleb128p1NumberParser,
1929
+ uleb128p1NumberParser,
1775
1930
  ]),
1776
- ([ registerNum, nameIndex, typeIndex ]) => ({
1931
+ ([ registerNumber, nameIndex, typeIndex ]) => ({
1777
1932
  type: 'startLocal',
1778
- registerNum,
1779
- nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
1780
- typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
1933
+ registerNum: registerNumber,
1934
+ nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
1935
+ typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
1781
1936
  }),
1782
1937
  );
1783
- case 0x04: return promiseCompose(
1938
+ }
1939
+
1940
+ case 0x04: { return promiseCompose(
1784
1941
  createTupleParser([
1785
1942
  uleb128NumberParser,
1786
- uleb128NumberParser,
1787
- uleb128NumberParser,
1788
- uleb128NumberParser,
1943
+ uleb128p1NumberParser,
1944
+ uleb128p1NumberParser,
1945
+ uleb128p1NumberParser,
1789
1946
  ]),
1790
- ([ registerNum, nameIndex, typeIndex, signatureIndex ]) => ({
1947
+ ([ registerNumber, nameIndex, typeIndex, signatureIndex ]) => ({
1791
1948
  type: 'startLocalExtended',
1792
- registerNum,
1793
- nameIndex: isoIndexIntoStringIds.wrap(nameIndex),
1794
- typeIndex: isoIndexIntoTypeIds.wrap(typeIndex),
1795
- signatureIndex: isoIndexIntoStringIds.wrap(signatureIndex),
1949
+ registerNum: registerNumber,
1950
+ nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex),
1951
+ typeIndex: typeIndex === -1 ? undefined : isoIndexIntoTypeIds.wrap(typeIndex),
1952
+ signatureIndex: signatureIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(signatureIndex),
1796
1953
  }),
1797
1954
  );
1798
- case 0x05: return promiseCompose(
1955
+ }
1956
+
1957
+ case 0x05: { return promiseCompose(
1799
1958
  uleb128NumberParser,
1800
- (registerNum) => ({ type: 'endLocal', registerNum }),
1959
+ registerNumber => ({ type: 'endLocal', registerNum: registerNumber }),
1801
1960
  );
1802
- case 0x06: return promiseCompose(
1961
+ }
1962
+
1963
+ case 0x06: { return promiseCompose(
1803
1964
  uleb128NumberParser,
1804
- (registerNum) => ({ type: 'restartLocal', registerNum }),
1965
+ registerNumber => ({ type: 'restartLocal', registerNum: registerNumber }),
1805
1966
  );
1806
- case 0x07: return () => ({ type: 'setPrologueEnd' });
1807
- case 0x08: return () => ({ type: 'setEpilogueBegin' });
1808
- case 0x09: return promiseCompose(
1809
- uleb128NumberParser,
1810
- (nameIndex) => ({ type: 'setFile', nameIndex: isoIndexIntoStringIds.wrap(nameIndex) }),
1967
+ }
1968
+
1969
+ case 0x07: { return () => ({ type: 'setPrologueEnd' });
1970
+ }
1971
+
1972
+ case 0x08: { return () => ({ type: 'setEpilogueBegin' });
1973
+ }
1974
+
1975
+ case 0x09: { return promiseCompose(
1976
+ uleb128p1NumberParser,
1977
+ nameIndex => ({ type: 'setFile', nameIndex: nameIndex === -1 ? undefined : isoIndexIntoStringIds.wrap(nameIndex) }),
1811
1978
  );
1812
- default: return parserContext => {
1813
- parserContext.invariant(value >= 0x0a, 'Unexpected special value: %s', value);
1979
+ }
1980
+
1981
+ default: { return parserContext => {
1982
+ parserContext.invariant(value >= 0x0A, 'Unexpected special value: %s', value);
1814
1983
  return { type: 'special', value };
1815
1984
  };
1985
+ }
1816
1986
  }
1817
- }
1987
+ },
1818
1988
  )();
1819
1989
 
1820
1990
  setParserName(dalvikExecutableDebugByteCodeValueParser, 'dalvikExecutableDebugByteCodeValueParser');
@@ -1830,7 +2000,7 @@ setParserName(debugByteCodeParser, 'debugByteCodeParser');
1830
2000
 
1831
2001
  type DalvikExecutableDebugInfoItem = {
1832
2002
  lineStart: number;
1833
- parameterNames: (undefined | IndexIntoStringIds)[];
2003
+ parameterNames: Array<undefined | IndexIntoStringIds>;
1834
2004
  bytecode: DalvikExecutableDebugByteCodeItem;
1835
2005
  };
1836
2006
 
@@ -1880,12 +2050,19 @@ type DalvikExecutableAnnotationItemVisibility =
1880
2050
 
1881
2051
  const dalvikExecutableAnnotationItemVisibilityParser: Parser<DalvikExecutableAnnotationItemVisibility, Uint8Array> = promiseCompose(
1882
2052
  ubyteParser,
1883
- (visibility) => {
2053
+ visibility => {
1884
2054
  switch (visibility) {
1885
- case 0x00: return 'build';
1886
- case 0x01: return 'runtime';
1887
- case 0x02: return 'system';
1888
- default: invariant(false, 'Unexpected visibility: %s', visibility);
2055
+ case 0x00: { return 'build';
2056
+ }
2057
+
2058
+ case 0x01: { return 'runtime';
2059
+ }
2060
+
2061
+ case 0x02: { return 'system';
2062
+ }
2063
+
2064
+ default: { invariant(false, 'Unexpected visibility: %s', visibility);
2065
+ }
1889
2066
  }
1890
2067
  },
1891
2068
  );
@@ -1924,19 +2101,19 @@ type DalvikExecutableHeaderAndMap = {
1924
2101
 
1925
2102
  const dalvikExecutableHeaderAndMapParser: Parser<DalvikExecutableHeaderAndMap, Uint8Array> = parserCreatorCompose(
1926
2103
  () => dalvikExecutableHeaderItemParser,
1927
- (headerItem) => promiseCompose(
2104
+ headerItem => promiseCompose(
1928
2105
  createLookaheadParser(createDalvikExecutableMapListParser(headerItem.mapOffset)),
1929
- (mapList) => ({ headerItem, mapList }),
2106
+ mapList => ({ headerItem, mapList }),
1930
2107
  ),
1931
2108
  )();
1932
2109
 
1933
2110
  type DalvikExecutableAnnotationOffsetItem = {
1934
2111
  annotationOffset: OffsetToAnnotationItem;
1935
- }
2112
+ };
1936
2113
 
1937
2114
  const dalvikExecutableAnnotationOffsetItemParser: Parser<DalvikExecutableAnnotationOffsetItem, Uint8Array> = promiseCompose(
1938
2115
  uintParser,
1939
- (annotationOffset) => ({
2116
+ annotationOffset => ({
1940
2117
  annotationOffset: isoOffsetToAnnotationItem.wrap(annotationOffset),
1941
2118
  }),
1942
2119
  );
@@ -1955,7 +2132,7 @@ const dalvikExecutableAnnotationSetItemParser: Parser<DalvikExecutableAnnotation
1955
2132
  dalvikExecutableAnnotationOffsetItemParser,
1956
2133
  size,
1957
2134
  ),
1958
- (entries) => ({ entries }),
2135
+ entries => ({ entries }),
1959
2136
  ),
1960
2137
  )();
1961
2138
 
@@ -1973,7 +2150,7 @@ type DalvikExecutableAnnotationSetRefItem = OffsetToAnnotationSetItem;
1973
2150
 
1974
2151
  const dalvikExecutableAnnotationSetRefItemParser: Parser<DalvikExecutableAnnotationSetRefItem, Uint8Array> = promiseCompose(
1975
2152
  uintParser,
1976
- (annotationsOffset) => isoOffsetToAnnotationSetItem.wrap(annotationsOffset),
2153
+ annotationsOffset => isoOffsetToAnnotationSetItem.wrap(annotationsOffset),
1977
2154
  );
1978
2155
 
1979
2156
  type DalvikExecutableAnnotationSetRefList = {
@@ -1990,7 +2167,7 @@ const dalvikExecutableAnnotationSetRefListParser: Parser<DalvikExecutableAnnotat
1990
2167
  dalvikExecutableAnnotationSetRefItemParser,
1991
2168
  size,
1992
2169
  ),
1993
- (list) => ({ list }),
2170
+ list => ({ list }),
1994
2171
  ),
1995
2172
  )();
1996
2173
 
@@ -2030,30 +2207,73 @@ type DalvikExecutableMapItemType =
2030
2207
 
2031
2208
  const dalvikExecutableMapItemTypeParser: Parser<DalvikExecutableMapItemType, Uint8Array> = promiseCompose(
2032
2209
  ushortParser,
2033
- (type) => {
2210
+ type => {
2034
2211
  switch (type) {
2035
- case 0x0000: return 'headerItem';
2036
- case 0x0001: return 'stringIdItem';
2037
- case 0x0002: return 'typeIdItem';
2038
- case 0x0003: return 'prototypeIdItem';
2039
- case 0x0004: return 'fieldIdItem';
2040
- case 0x0005: return 'methodIdItem';
2041
- case 0x0006: return 'classDefinitionItem';
2042
- case 0x0007: return 'callSiteIdItem';
2043
- case 0x0008: return 'methodHandleItem';
2044
- case 0x1000: return 'mapList';
2045
- case 0x1001: return 'typeList';
2046
- case 0x1002: return 'annotationSetRefList';
2047
- case 0x1003: return 'annotationSetItem';
2048
- case 0x2000: return 'classDataItem';
2049
- case 0x2001: return 'codeItem';
2050
- case 0x2002: return 'stringDataItem';
2051
- case 0x2003: return 'debugInfoItem';
2052
- case 0x2004: return 'annotationItem';
2053
- case 0x2005: return 'encodedArrayItem';
2054
- case 0x2006: return 'annotationsDirectoryItem';
2055
- case 0xF000: return 'hiddenApiClassDataItem';
2056
- default: invariant(false, 'Unexpected map item type: %s', type);
2212
+ case 0x00_00: { return 'headerItem';
2213
+ }
2214
+
2215
+ case 0x00_01: { return 'stringIdItem';
2216
+ }
2217
+
2218
+ case 0x00_02: { return 'typeIdItem';
2219
+ }
2220
+
2221
+ case 0x00_03: { return 'prototypeIdItem';
2222
+ }
2223
+
2224
+ case 0x00_04: { return 'fieldIdItem';
2225
+ }
2226
+
2227
+ case 0x00_05: { return 'methodIdItem';
2228
+ }
2229
+
2230
+ case 0x00_06: { return 'classDefinitionItem';
2231
+ }
2232
+
2233
+ case 0x00_07: { return 'callSiteIdItem';
2234
+ }
2235
+
2236
+ case 0x00_08: { return 'methodHandleItem';
2237
+ }
2238
+
2239
+ case 0x10_00: { return 'mapList';
2240
+ }
2241
+
2242
+ case 0x10_01: { return 'typeList';
2243
+ }
2244
+
2245
+ case 0x10_02: { return 'annotationSetRefList';
2246
+ }
2247
+
2248
+ case 0x10_03: { return 'annotationSetItem';
2249
+ }
2250
+
2251
+ case 0x20_00: { return 'classDataItem';
2252
+ }
2253
+
2254
+ case 0x20_01: { return 'codeItem';
2255
+ }
2256
+
2257
+ case 0x20_02: { return 'stringDataItem';
2258
+ }
2259
+
2260
+ case 0x20_03: { return 'debugInfoItem';
2261
+ }
2262
+
2263
+ case 0x20_04: { return 'annotationItem';
2264
+ }
2265
+
2266
+ case 0x20_05: { return 'encodedArrayItem';
2267
+ }
2268
+
2269
+ case 0x20_06: { return 'annotationsDirectoryItem';
2270
+ }
2271
+
2272
+ case 0xF0_00: { return 'hiddenApiClassDataItem';
2273
+ }
2274
+
2275
+ default: { invariant(false, 'Unexpected map item type: %s', type);
2276
+ }
2057
2277
  }
2058
2278
  },
2059
2279
  );
@@ -2078,12 +2298,10 @@ type DalvikExecutableMapList = DalvikExecutableMapItem[];
2078
2298
 
2079
2299
  const dalvikExecutableMapListParser: Parser<DalvikExecutableMapList, Uint8Array> = parserCreatorCompose(
2080
2300
  () => uintParser,
2081
- size => {
2082
- return createQuantifierParser(
2083
- dalvikExecutableMapItemParser,
2084
- size,
2085
- );
2086
- },
2301
+ size => createQuantifierParser(
2302
+ dalvikExecutableMapItemParser,
2303
+ size,
2304
+ ),
2087
2305
  )();
2088
2306
 
2089
2307
  setParserName(dalvikExecutableMapListParser, 'dalvikExecutableMapListParser');
@@ -2142,6 +2360,7 @@ type DalvikExecutableData<Instructions> = {
2142
2360
  encodedArrayItemByOffset: DalvikExecutableEncodedArrayItemByOffset;
2143
2361
  annotationsDirectoryItemByOffset: DalvikExecutableAnnotationsDirectoryItemByOffset;
2144
2362
  hiddenApiClassDataItems: DalvikExecutableHiddenApiClassDataItem[];
2363
+ link: undefined | Uint8Array;
2145
2364
  };
2146
2365
 
2147
2366
  const createDalvikExecutableDataParser = <Instructions>({
@@ -2151,15 +2370,15 @@ const createDalvikExecutableDataParser = <Instructions>({
2151
2370
  }: DalvikExecutableHeaderAndMap & {
2152
2371
  createInstructionsParser: CreateInstructionsParser<Instructions>;
2153
2372
  }): Parser<DalvikExecutableData<Instructions>, Uint8Array> => {
2154
- const dalvikExecutableDataParser: Parser<DalvikExecutableData<Instructions>, Uint8Array> = async (parserContext) => {
2373
+ const dalvikExecutableDataParser: Parser<DalvikExecutableData<Instructions>, Uint8Array> = async parserContext => {
2155
2374
  let stringIdItems: DalvikExecutableStringIdItems = isoDalvikExecutableStringIdItems.wrap([]);
2156
2375
  let typeIdItems: DalvikExecutableTypeIdItems = isoDalvikExecutableTypeIdItems.wrap([]);
2157
2376
  let prototypeIdItems: DalvikExecutablePrototypeIdItems = isoDalvikExecutablePrototypeIdItems.wrap([]);
2158
2377
  let fieldIdItems: DalvikExecutableFieldIdItems = isoDalvikExecutableFieldIdItems.wrap([]);
2159
2378
  let methodIdItems: DalvikExecutableMethodIdItems = isoDalvikExecutableMethodIdItems.wrap([]);
2160
2379
  let classDefinitionItems: DalvikExecutableClassDefinitionItem[] = [];
2161
- let callSiteIdItems: DalvikExecutableCallSiteIdItem[] = [];
2162
- let methodHandleItems: DalvikExecutableMethodHandleItem[] = [];
2380
+ const callSiteIdItems: DalvikExecutableCallSiteIdItem[] = [];
2381
+ const methodHandleItems: DalvikExecutableMethodHandleItem[] = [];
2163
2382
  let typeListByOffset: DalvikExecutableTypeListByOffset = new Map();
2164
2383
  let annotationSetRefListItemByOffset: DalvikExecutableAnnotationSetRefListItemByOffset = new Map();
2165
2384
  let annotationSetItemByOffset: DalvikExecutableAnnotationSetItemByOffset = new Map();
@@ -2170,9 +2389,19 @@ const createDalvikExecutableDataParser = <Instructions>({
2170
2389
  let annotationItemByOffset: DalvikExecutableAnnotationItemByOffset = new Map();
2171
2390
  let encodedArrayItemByOffset: DalvikExecutableEncodedArrayItemByOffset = new Map();
2172
2391
  let annotationsDirectoryItemByOffset: DalvikExecutableAnnotationsDirectoryItemByOffset = new Map();
2173
- let hiddenApiClassDataItems: DalvikExecutableHiddenApiClassDataItem[] = [];
2392
+ const hiddenApiClassDataItems: DalvikExecutableHiddenApiClassDataItem[] = [];
2393
+
2394
+ // Track if link has been parsed
2395
+ let link: undefined | Uint8Array = undefined;
2396
+ let linkParsed = false;
2174
2397
 
2175
2398
  for (const dexMapItem of mapList) {
2399
+ // Parse link data before any map item that comes after it in the file
2400
+ // Link data is not included in the map items, but is referenced in the header
2401
+ if (!linkParsed && headerItem.link.size > 0 && headerItem.link.offset < dexMapItem.offset) {
2402
+ link = await createRawDataParser(headerItem.link)(parserContext);
2403
+ linkParsed = true;
2404
+ }
2176
2405
  if (dexMapItem.type === 'headerItem') {
2177
2406
  continue;
2178
2407
  }
@@ -2216,6 +2445,7 @@ const createDalvikExecutableDataParser = <Instructions>({
2216
2445
  }
2217
2446
 
2218
2447
  if (dexMapItem.type === 'mapList') {
2448
+ // Re-parse the map itself to consume it from the input
2219
2449
  await createDalvikExecutableMapListParser(dexMapItem.offset)(parserContext);
2220
2450
  continue;
2221
2451
  }
@@ -2280,6 +2510,12 @@ const createDalvikExecutableDataParser = <Instructions>({
2280
2510
  invariant(false, 'Unexpected map item type: %s', dexMapItem.type);
2281
2511
  }
2282
2512
 
2513
+ // Parse link data after the loop if it hasn't been parsed yet
2514
+ // This handles the case where link comes after all map items
2515
+ if (!linkParsed && headerItem.link.size > 0) {
2516
+ link = await createRawDataParser(headerItem.link)(parserContext);
2517
+ }
2518
+
2283
2519
  return {
2284
2520
  headerItem,
2285
2521
  stringIdItems,
@@ -2302,6 +2538,7 @@ const createDalvikExecutableDataParser = <Instructions>({
2302
2538
  encodedArrayItemByOffset,
2303
2539
  annotationsDirectoryItemByOffset,
2304
2540
  hiddenApiClassDataItems,
2541
+ link,
2305
2542
  };
2306
2543
  };
2307
2544
 
@@ -2320,41 +2557,36 @@ const createDalvikExecutableParser = <Instructions>({
2320
2557
  headerItem,
2321
2558
  mapList,
2322
2559
  }) => promiseCompose(
2323
- createTupleParser([
2324
- createDalvikExecutableDataParser({
2325
- headerItem,
2326
- mapList,
2327
- createInstructionsParser,
2328
- }),
2329
- createRawDataParser(headerItem.link),
2330
- ]),
2331
- async ([
2332
- {
2333
- headerItem: _headerItem,
2334
- stringIdItems,
2335
- typeIdItems,
2336
- prototypeIdItems,
2337
- fieldIdItems,
2338
- methodIdItems,
2339
- classDefinitionItems,
2340
- // callSiteIdItems,
2341
- // methodHandleItems,
2342
- mapList: _mapList,
2343
- typeListByOffset,
2344
- annotationSetRefListItemByOffset,
2345
- annotationSetItemByOffset,
2346
- classDataItemByOffset,
2347
- codeItemByOffset,
2348
- stringDataItemStringByOffset,
2349
- debugInfoItemByOffset,
2350
- annotationItemByOffset,
2351
- encodedArrayItemByOffset,
2352
- annotationsDirectoryItemByOffset,
2353
- // hiddenApiClassDataItems,
2354
- },
2560
+ createDalvikExecutableDataParser({
2561
+ headerItem,
2562
+ mapList,
2563
+ createInstructionsParser,
2564
+ }),
2565
+ async ({
2566
+ headerItem: _headerItem,
2567
+ stringIdItems,
2568
+ typeIdItems,
2569
+ prototypeIdItems,
2570
+ fieldIdItems,
2571
+ methodIdItems,
2572
+ classDefinitionItems,
2573
+ // CallSiteIdItems,
2574
+ // methodHandleItems,
2575
+ mapList: _mapList,
2576
+ typeListByOffset,
2577
+ annotationSetRefListItemByOffset,
2578
+ annotationSetItemByOffset,
2579
+ classDataItemByOffset,
2580
+ codeItemByOffset,
2581
+ stringDataItemStringByOffset,
2582
+ debugInfoItemByOffset,
2583
+ annotationItemByOffset,
2584
+ encodedArrayItemByOffset,
2585
+ annotationsDirectoryItemByOffset,
2586
+ // HiddenApiClassDataItems,
2355
2587
  link,
2356
- ]) => {
2357
- const strings = stringIdItems.map((stringId) => {
2588
+ }) => {
2589
+ const strings = stringIdItems.map(stringId => {
2358
2590
  const stringOffset = stringId;
2359
2591
  const string = stringDataItemStringByOffset.get(stringOffset);
2360
2592
  invariant(string !== undefined, 'String must be there. String offset: %s', stringOffset);
@@ -2362,7 +2594,7 @@ const createDalvikExecutableParser = <Instructions>({
2362
2594
  return string;
2363
2595
  });
2364
2596
 
2365
- const types = typeIdItems.map((typeId) => {
2597
+ const types = typeIdItems.map(typeId => {
2366
2598
  const type = strings.at(typeId);
2367
2599
  invariant(type, 'Type string must be there. Type id: %s', typeId);
2368
2600
 
@@ -2374,7 +2606,7 @@ const createDalvikExecutableParser = <Instructions>({
2374
2606
  ]);
2375
2607
 
2376
2608
  for (const [ offset, typeIndexes ] of typeListByOffset) {
2377
- const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map((typeIndex) => {
2609
+ const typeNames = isoDalvikExecutableTypeList.unwrap(typeIndexes).map(typeIndex => {
2378
2610
  const type = types.at(typeIndex);
2379
2611
  invariant(type, 'Type must be there. Type id: %s', typeIndex);
2380
2612
 
@@ -2384,7 +2616,7 @@ const createDalvikExecutableParser = <Instructions>({
2384
2616
  resolvedTypeListByOffset.set(offset, typeNames);
2385
2617
  }
2386
2618
 
2387
- const prototypes = prototypeIdItems.map((prototypeId) => {
2619
+ const prototypes = prototypeIdItems.map(prototypeId => {
2388
2620
  const shorty = strings.at(prototypeId.shortyIndex);
2389
2621
  invariant(shorty, 'Shorty must be there. Shorty id: %s', prototypeId.shortyIndex);
2390
2622
 
@@ -2397,7 +2629,7 @@ const createDalvikExecutableParser = <Instructions>({
2397
2629
  return { shorty, returnType, parameters };
2398
2630
  });
2399
2631
 
2400
- const fields = fieldIdItems.map((fieldId) => {
2632
+ const fields = fieldIdItems.map(fieldId => {
2401
2633
  const class_ = types.at(fieldId.classIndex);
2402
2634
  invariant(class_, 'Class must be there. Class id: %s', fieldId.classIndex);
2403
2635
 
@@ -2410,7 +2642,7 @@ const createDalvikExecutableParser = <Instructions>({
2410
2642
  return { class: class_, type, name };
2411
2643
  });
2412
2644
 
2413
- const methods = methodIdItems.map((methodId) => {
2645
+ const methods = methodIdItems.map(methodId => {
2414
2646
  const class_ = types.at(methodId.classIndex);
2415
2647
  invariant(class_, 'Class must be there. Class id: %s', methodId.classIndex);
2416
2648
 
@@ -2430,7 +2662,7 @@ const createDalvikExecutableParser = <Instructions>({
2430
2662
  for (const [ offset, debugInfoItem ] of debugInfoItemByOffset) {
2431
2663
  debugInfoByOffset.set(offset, {
2432
2664
  lineStart: debugInfoItem.lineStart,
2433
- parameterNames: debugInfoItem.parameterNames.map((index) => {
2665
+ parameterNames: debugInfoItem.parameterNames.map(index => {
2434
2666
  if (index === undefined) {
2435
2667
  return undefined;
2436
2668
  }
@@ -2440,23 +2672,30 @@ const createDalvikExecutableParser = <Instructions>({
2440
2672
 
2441
2673
  return string;
2442
2674
  }),
2443
- bytecode: debugInfoItem.bytecode.map((value) => {
2675
+ bytecode: debugInfoItem.bytecode.map(value => {
2444
2676
  switch (value.type) {
2445
- case 'startLocal': return {
2677
+ case 'startLocal': { return {
2446
2678
  type: 'startLocal',
2447
2679
  registerNum: value.registerNum,
2448
2680
  name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
2449
2681
  type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
2450
2682
  };
2451
- case 'startLocalExtended': return {
2683
+ }
2684
+
2685
+ case 'startLocalExtended': { return {
2452
2686
  type: 'startLocalExtended',
2453
2687
  registerNum: value.registerNum,
2454
2688
  name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex),
2455
2689
  type_: value.typeIndex === undefined ? undefined : types.at(value.typeIndex),
2456
2690
  signature: value.signatureIndex === undefined ? undefined : strings.at(value.signatureIndex),
2457
2691
  };
2458
- case 'setFile': return { type: 'setFile', name: strings.at(value.nameIndex) };
2459
- default: return value;
2692
+ }
2693
+
2694
+ case 'setFile': { return { type: 'setFile', name: value.nameIndex === undefined ? undefined : strings.at(value.nameIndex) };
2695
+ }
2696
+
2697
+ default: { return value;
2698
+ }
2460
2699
  }
2461
2700
  }),
2462
2701
  });
@@ -2473,15 +2712,14 @@ const createDalvikExecutableParser = <Instructions>({
2473
2712
  registersSize: codeItem.registersSize,
2474
2713
  insSize: codeItem.insSize,
2475
2714
  outsSize: codeItem.outsSize,
2476
- debugInfo: debugInfo,
2715
+ debugInfo,
2477
2716
  instructions: codeItem.instructions,
2478
- tries: codeItem.tryItems.map((tryItem) => {
2717
+ tries: codeItem.tryItems.map(tryItem => {
2479
2718
  const handler_ = codeItem.handlers.get(tryItem.handlerOffset);
2480
2719
  invariant(handler_, 'Handler must be there. Handler offset: %s', tryItem.handlerOffset);
2481
2720
 
2482
2721
  const handler = {
2483
- ...handler_,
2484
- handlers: handler_.handlers.map((encodedHandler) => {
2722
+ handlers: handler_.handlers.map(encodedHandler => {
2485
2723
  const type = types.at(encodedHandler.typeIndex);
2486
2724
  invariant(type, 'Type must be there. Type id: %s', encodedHandler.typeIndex);
2487
2725
 
@@ -2490,6 +2728,7 @@ const createDalvikExecutableParser = <Instructions>({
2490
2728
  address: encodedHandler.address,
2491
2729
  };
2492
2730
  }),
2731
+ catchAllAddress: handler_.catchAllAddress,
2493
2732
  };
2494
2733
 
2495
2734
  return {
@@ -2508,28 +2747,28 @@ const createDalvikExecutableParser = <Instructions>({
2508
2747
  const resolvers: DalvikBytecodeOperationResolvers = {
2509
2748
  resolveIndexIntoStringIds(indexIntoStringIds) {
2510
2749
  const string = strings.at(indexIntoStringIds);
2511
- invariant(string, 'String must be there. String id: %s', indexIntoStringIds);
2750
+ invariant(string !== undefined, 'String must be there. String id: %s', indexIntoStringIds);
2512
2751
 
2513
2752
  return string;
2514
2753
  },
2515
2754
 
2516
2755
  resolveIndexIntoTypeIds(indexIntoTypeIds) {
2517
2756
  const type = types.at(indexIntoTypeIds);
2518
- invariant(type, 'Type must be there. Type id: %s', indexIntoTypeIds);
2757
+ invariant(type !== undefined, 'Type must be there. Type id: %s', indexIntoTypeIds);
2519
2758
 
2520
2759
  return type;
2521
2760
  },
2522
2761
 
2523
2762
  resolveIndexIntoMethodIds(indexIntoMethodIds) {
2524
2763
  const method = methods.at(indexIntoMethodIds);
2525
- invariant(method, 'Method must be there. Method id: %s', indexIntoMethodIds);
2764
+ invariant(method !== undefined, 'Method must be there. Method id: %s', indexIntoMethodIds);
2526
2765
 
2527
2766
  return method;
2528
2767
  },
2529
2768
 
2530
2769
  resolveIndexIntoFieldIds(indexIntoFieldIds) {
2531
2770
  const field = fields.at(indexIntoFieldIds);
2532
- invariant(field, 'Field must be there. Field id: %s', indexIntoFieldIds);
2771
+ invariant(field !== undefined, 'Field must be there. Field id: %s', indexIntoFieldIds);
2533
2772
 
2534
2773
  return field;
2535
2774
  },
@@ -2548,15 +2787,13 @@ const createDalvikExecutableParser = <Instructions>({
2548
2787
 
2549
2788
  return {
2550
2789
  ...rest,
2551
- instructions: instructions.map((instruction: DalvikBytecodeOperation) => {
2552
- return resolveDalvikBytecodeOperation(instruction, resolvers);
2553
- }) as Instructions,
2790
+ instructions: instructions.map((instruction: DalvikBytecodeOperation) => resolveDalvikBytecodeOperation(instruction, resolvers)) as Instructions,
2554
2791
  };
2555
2792
  }
2556
2793
 
2557
2794
  for (const [ offset, classDataItem ] of classDataItemByOffset) {
2558
2795
  classDataByOffset.set(offset, {
2559
- staticFields: classDataItem.staticFields.map((encodedField) => {
2796
+ staticFields: classDataItem.staticFields.map(encodedField => {
2560
2797
  const field = fields.at(encodedField.fieldIndex);
2561
2798
  invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
2562
2799
 
@@ -2566,7 +2803,7 @@ const createDalvikExecutableParser = <Instructions>({
2566
2803
  };
2567
2804
  }),
2568
2805
 
2569
- instanceFields: classDataItem.instanceFields.map((encodedField) => {
2806
+ instanceFields: classDataItem.instanceFields.map(encodedField => {
2570
2807
  const field = fields.at(encodedField.fieldIndex);
2571
2808
  invariant(field, 'Field must be there. Field id: %s', encodedField.fieldIndex);
2572
2809
 
@@ -2576,7 +2813,7 @@ const createDalvikExecutableParser = <Instructions>({
2576
2813
  };
2577
2814
  }),
2578
2815
 
2579
- directMethods: classDataItem.directMethods.map((method) => {
2816
+ directMethods: classDataItem.directMethods.map(method => {
2580
2817
  const method_ = methods.at(method.methodIndex);
2581
2818
  invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
2582
2819
 
@@ -2590,7 +2827,7 @@ const createDalvikExecutableParser = <Instructions>({
2590
2827
  };
2591
2828
  }),
2592
2829
 
2593
- virtualMethods: classDataItem.virtualMethods.map((method) => {
2830
+ virtualMethods: classDataItem.virtualMethods.map(method => {
2594
2831
  const method_ = methods.at(method.methodIndex);
2595
2832
  invariant(method_, 'Method must be there. Method id: %s', method.methodIndex);
2596
2833
 
@@ -2606,6 +2843,176 @@ const createDalvikExecutableParser = <Instructions>({
2606
2843
  });
2607
2844
  }
2608
2845
 
2846
+ // Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for static values
2847
+ // Resolves internal index types to actual values while preserving type tags
2848
+ function resolveTaggedEncodedValueForStaticValues(taggedValue: DalvikExecutableTaggedEncodedValue): DalvikExecutableEncodedValue {
2849
+ const { type, value } = taggedValue;
2850
+
2851
+ // For primitive types, keep the type tag and value
2852
+ if (
2853
+ type === 'byte'
2854
+ || type === 'short'
2855
+ || type === 'char'
2856
+ || type === 'int'
2857
+ || type === 'float'
2858
+ || type === 'double'
2859
+ || type === 'long'
2860
+ || type === 'boolean'
2861
+ || type === 'null'
2862
+ || type === 'methodHandle'
2863
+ ) {
2864
+ return { type, value } as DalvikExecutableEncodedValue;
2865
+ }
2866
+
2867
+ // For types that reference the pool, resolve the index to the actual value
2868
+ if (type === 'methodType') {
2869
+ const prototype = prototypes.at(value);
2870
+ invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
2871
+ return { type, value: prototype };
2872
+ }
2873
+
2874
+ if (type === 'string') {
2875
+ const string = strings.at(value);
2876
+ invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
2877
+ return { type, value: string };
2878
+ }
2879
+
2880
+ if (type === 'type') {
2881
+ const typeString = types.at(value);
2882
+ invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
2883
+ return { type, value: typeString };
2884
+ }
2885
+
2886
+ if (type === 'field' || type === 'enum') {
2887
+ const field = fields.at(value);
2888
+ invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
2889
+ return { type, value: field };
2890
+ }
2891
+
2892
+ if (type === 'method') {
2893
+ const method = methods.at(value);
2894
+ invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
2895
+ return { type, value: method };
2896
+ }
2897
+
2898
+ if (type === 'array') {
2899
+ return { type, value: value.map(resolveTaggedEncodedValueForStaticValues) };
2900
+ }
2901
+
2902
+ if (type === 'annotation') {
2903
+ // Resolve the encoded annotation
2904
+ const annotationType = types.at(value.typeIndex);
2905
+ invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
2906
+
2907
+ const resolvedElements = value.elements.map(element => {
2908
+ const name = strings.at(element.nameIndex);
2909
+ invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
2910
+
2911
+ return {
2912
+ name,
2913
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
2914
+ };
2915
+ });
2916
+
2917
+ const annotation: DalvikExecutableAnnotation = {
2918
+ visibility: 'build', // Default visibility for embedded annotations
2919
+ type: annotationType,
2920
+ elements: resolvedElements,
2921
+ };
2922
+
2923
+ return { type, value: annotation };
2924
+ }
2925
+
2926
+ // This should never happen
2927
+ throw new Error(`Unknown encoded value type: ${type}`);
2928
+ }
2929
+
2930
+ // Resolve TaggedEncodedValue to DalvikExecutableEncodedValue for annotation elements
2931
+ // Resolves internal index types to actual values while preserving type tags
2932
+ function resolveTaggedEncodedValueForAnnotations(taggedValue: DalvikExecutableTaggedEncodedValue): DalvikExecutableEncodedValue {
2933
+ const { type, value } = taggedValue;
2934
+
2935
+ // For primitive types, keep the type tag and value
2936
+ if (
2937
+ type === 'byte'
2938
+ || type === 'short'
2939
+ || type === 'char'
2940
+ || type === 'int'
2941
+ || type === 'float'
2942
+ || type === 'double'
2943
+ || type === 'long'
2944
+ || type === 'boolean'
2945
+ || type === 'null'
2946
+ || type === 'methodHandle'
2947
+ ) {
2948
+ return { type, value } as DalvikExecutableEncodedValue;
2949
+ }
2950
+
2951
+ // For types that reference the pool, resolve the index to the actual value
2952
+ if (type === 'methodType') {
2953
+ const prototype = prototypes.at(value);
2954
+ invariant(prototype, 'Prototype must be there. Prototype id: %s', isoIndexIntoPrototypeIds.unwrap(value));
2955
+ return { type, value: prototype };
2956
+ }
2957
+
2958
+ if (type === 'string') {
2959
+ const string = strings.at(value);
2960
+ invariant(string !== undefined, 'String must be there. String id: %s', isoIndexIntoStringIds.unwrap(value));
2961
+ return { type, value: string };
2962
+ }
2963
+
2964
+ if (type === 'type') {
2965
+ const typeString = types.at(value);
2966
+ invariant(typeString !== undefined, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value));
2967
+ return { type, value: typeString };
2968
+ }
2969
+
2970
+ if (type === 'field' || type === 'enum') {
2971
+ const field = fields.at(value);
2972
+ invariant(field, 'Field must be there. Field id: %s', isoIndexIntoFieldIds.unwrap(value));
2973
+ return { type, value: field };
2974
+ }
2975
+
2976
+ if (type === 'method') {
2977
+ const method = methods.at(value);
2978
+ invariant(method, 'Method must be there. Method id: %s', isoIndexIntoMethodIds.unwrap(value));
2979
+ return { type, value: method };
2980
+ }
2981
+
2982
+ // For arrays, recursively resolve elements
2983
+ if (type === 'array') {
2984
+ return { type, value: value.map(resolveTaggedEncodedValueForAnnotations) };
2985
+ }
2986
+
2987
+ // For annotations
2988
+ if (type === 'annotation') {
2989
+ // Resolve the encoded annotation (subannotation)
2990
+ const annotationType = types.at(value.typeIndex);
2991
+ invariant(annotationType, 'Type must be there. Type id: %s', isoIndexIntoTypeIds.unwrap(value.typeIndex));
2992
+
2993
+ const resolvedElements = value.elements.map(element => {
2994
+ const name = strings.at(element.nameIndex);
2995
+ invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
2996
+
2997
+ return {
2998
+ name,
2999
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
3000
+ };
3001
+ });
3002
+
3003
+ const annotation: DalvikExecutableAnnotation = {
3004
+ visibility: 'build', // Default visibility for embedded annotations
3005
+ type: annotationType,
3006
+ elements: resolvedElements,
3007
+ };
3008
+
3009
+ return { type, value: annotation };
3010
+ }
3011
+
3012
+ // This should never happen
3013
+ throw new Error(`Unknown encoded value type: ${type}`);
3014
+ }
3015
+
2609
3016
  function resolveAnnotationOffsetItem({ annotationOffset }: DalvikExecutableAnnotationOffsetItem): DalvikExecutableAnnotation {
2610
3017
  const annotationItem = annotationItemByOffset.get(annotationOffset);
2611
3018
  invariant(annotationItem, 'Annotation must be there. Annotation offset: %s', annotationOffset);
@@ -2613,13 +3020,13 @@ const createDalvikExecutableParser = <Instructions>({
2613
3020
  const type = types.at(annotationItem.encodedAnnotation.typeIndex);
2614
3021
  invariant(type, 'Type must be there. Type id: %s', annotationItem.encodedAnnotation.typeIndex);
2615
3022
 
2616
- const elements = annotationItem.encodedAnnotation.elements.map((element) => {
3023
+ const elements = annotationItem.encodedAnnotation.elements.map(element => {
2617
3024
  const name = strings.at(element.nameIndex);
2618
3025
  invariant(name, 'Name string must be there. String offset: %s', element.nameIndex);
2619
3026
 
2620
3027
  return {
2621
3028
  name,
2622
- value: element.value,
3029
+ value: resolveTaggedEncodedValueForAnnotations(element.value),
2623
3030
  };
2624
3031
  });
2625
3032
 
@@ -2631,10 +3038,20 @@ const createDalvikExecutableParser = <Instructions>({
2631
3038
  }
2632
3039
 
2633
3040
  function resolveAnnotationSetItem(annotationSetItem: undefined | DalvikExecutableAnnotationSetItem): undefined | DalvikExecutableAnnotation[] {
2634
- return annotationSetItem?.entries.map(resolveAnnotationOffsetItem);
3041
+ if (!annotationSetItem) {
3042
+ return undefined;
3043
+ }
3044
+
3045
+ const annotationSet = annotationSetItem.entries.map(resolveAnnotationOffsetItem);
3046
+
3047
+ if (!annotationSet.length) {
3048
+ return [];
3049
+ }
3050
+
3051
+ return annotationSet;
2635
3052
  }
2636
3053
 
2637
- const classDefinitions = classDefinitionItems.map((classDefinitionItem) => {
3054
+ const classDefinitions = classDefinitionItems.map(classDefinitionItem => {
2638
3055
  const class_ = types.at(classDefinitionItem.classIndex);
2639
3056
  invariant(class_, 'Class must be there. Class id: %s', classDefinitionItem.classIndex);
2640
3057
 
@@ -2669,23 +3086,33 @@ const createDalvikExecutableParser = <Instructions>({
2669
3086
  classAnnotationSetItem
2670
3087
  ? resolveAnnotationSetItem(classAnnotationSetItem)
2671
3088
  : undefined
2672
- );
3089
+ ) ?? [];
2673
3090
 
2674
- const fieldAnnotations: DalvikExecutableClassFieldAnnotation[] = annotationsDirectoryItem.fieldAnnotations.map((fieldAnnotation) => {
3091
+ const fieldAnnotations: DalvikExecutableClassFieldAnnotation[] = annotationsDirectoryItem.fieldAnnotations.flatMap(fieldAnnotation => {
2675
3092
  const field = fields.at(fieldAnnotation.fieldIndex);
2676
3093
  invariant(field, 'Field must be there. Field id: %s', fieldAnnotation.fieldIndex);
2677
3094
 
2678
- const annotations = annotationSetItemByOffset.get(fieldAnnotation.annotationsOffset);
3095
+ const annotationSetItem = annotationSetItemByOffset.get(fieldAnnotation.annotationsOffset);
2679
3096
  invariant(
2680
- isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 || annotations,
3097
+ isoOffsetToAnnotationSetItem.unwrap(fieldAnnotation.annotationsOffset) === 0 || annotationSetItem,
2681
3098
  'Annotations must be there. Annotations offset: %s',
2682
3099
  fieldAnnotation.annotationsOffset,
2683
3100
  );
2684
3101
 
2685
- return { field, annotations: annotations?.entries.map(resolveAnnotationOffsetItem) };
3102
+ const annotations = resolveAnnotationSetItem(annotationSetItem);
3103
+
3104
+ // Skip fields with no annotations (undefined or empty array)
3105
+ if (!annotations || annotations.length === 0) {
3106
+ return [];
3107
+ }
3108
+
3109
+ return [{
3110
+ field,
3111
+ annotations,
3112
+ }];
2686
3113
  });
2687
3114
 
2688
- const methodAnnotations: DalvikExecutableClassMethodAnnotation[] = annotationsDirectoryItem.methodAnnotations.map((methodAnnotation) => {
3115
+ const methodAnnotations: DalvikExecutableClassMethodAnnotation[] = annotationsDirectoryItem.methodAnnotations.flatMap(methodAnnotation => {
2689
3116
  const method = methods.at(methodAnnotation.methodIndex);
2690
3117
  invariant(method, 'Method must be there. Method id: %s', methodAnnotation.methodIndex);
2691
3118
 
@@ -2696,10 +3123,20 @@ const createDalvikExecutableParser = <Instructions>({
2696
3123
  methodAnnotation.annotationsOffset,
2697
3124
  );
2698
3125
 
2699
- return { method, annotations: resolveAnnotationSetItem(annotationSetItem) };
3126
+ const annotations = resolveAnnotationSetItem(annotationSetItem) ?? [];
3127
+
3128
+ // Skip methods with no annotations
3129
+ if (annotations.length === 0) {
3130
+ return [];
3131
+ }
3132
+
3133
+ return [{
3134
+ method,
3135
+ annotations,
3136
+ }];
2700
3137
  });
2701
3138
 
2702
- const parameterAnnotations: DalvikExecutableClassParameterAnnotation[] = annotationsDirectoryItem.parameterAnnotations.map((parameterAnnotation) => {
3139
+ const parameterAnnotations: DalvikExecutableClassParameterAnnotation[] = annotationsDirectoryItem.parameterAnnotations.flatMap(parameterAnnotation => {
2703
3140
  const method = methods.at(parameterAnnotation.methodIndex);
2704
3141
  invariant(method, 'Method must be there. Method id: %s', parameterAnnotation.methodIndex);
2705
3142
 
@@ -2710,7 +3147,7 @@ const createDalvikExecutableParser = <Instructions>({
2710
3147
  parameterAnnotation.annotationsOffset,
2711
3148
  );
2712
3149
 
2713
- const annotations = annotationSetRefList?.list.map((annotationSetRefItem) => {
3150
+ const annotations: DalvikExecutableClassParameterAnnotation['annotations'] = annotationSetRefList?.list.map(annotationSetRefItem => {
2714
3151
  const annotationSetItem = annotationSetItemByOffset.get(annotationSetRefItem);
2715
3152
  invariant(
2716
3153
  isoOffsetToAnnotationSetItem.unwrap(annotationSetRefItem) === 0 || annotationSetItem,
@@ -2718,8 +3155,10 @@ const createDalvikExecutableParser = <Instructions>({
2718
3155
  annotationSetRefItem,
2719
3156
  );
2720
3157
 
2721
- return resolveAnnotationSetItem(annotationSetItem);
2722
- });
3158
+ const annotationSet = resolveAnnotationSetItem(annotationSetItem);
3159
+
3160
+ return annotationSet ?? [];
3161
+ }) ?? [];
2723
3162
 
2724
3163
  return { method, annotations };
2725
3164
  });
@@ -2734,12 +3173,32 @@ const createDalvikExecutableParser = <Instructions>({
2734
3173
 
2735
3174
  const classData = classDataByOffset.get(classDefinitionItem.classDataOffset);
2736
3175
 
2737
- const staticValues = isoOffsetToEncodedArrayItem.unwrap(classDefinitionItem.staticValuesOffset) === 0 ? [] : encodedArrayItemByOffset.get(classDefinitionItem.staticValuesOffset);
2738
- invariant(staticValues, 'Static values must be there. Static values offset: %s', classDefinitionItem.staticValuesOffset);
3176
+ const staticValuesTagged = isoOffsetToEncodedArrayItem.unwrap(classDefinitionItem.staticValuesOffset) === 0 ? [] : encodedArrayItemByOffset.get(classDefinitionItem.staticValuesOffset);
3177
+ invariant(staticValuesTagged, 'Static values must be there. Static values offset: %s', classDefinitionItem.staticValuesOffset);
3178
+
3179
+ const staticValues = staticValuesTagged.map(resolveTaggedEncodedValueForStaticValues);
3180
+
3181
+ const allMembers = [
3182
+ ...classData?.staticFields ?? [],
3183
+ ...classData?.instanceFields ?? [],
3184
+ ...classData?.directMethods ?? [],
3185
+ // ...classData?.virtualMethods ?? [], // TODO?
3186
+ ];
3187
+
3188
+ const allMembersAreSynthetic = (
3189
+ allMembers.every(member => member.accessFlags.synthetic)
3190
+ && allMembers.length > 0
3191
+ );
3192
+
3193
+ const accessFlags = {
3194
+ ...classDefinitionItem.accessFlags,
3195
+ // Use the synthetic flag from the class definition, or compute it from members if not set
3196
+ synthetic: classDefinitionItem.accessFlags.synthetic || allMembersAreSynthetic,
3197
+ };
2739
3198
 
2740
3199
  return {
2741
3200
  class: class_,
2742
- accessFlags: classDefinitionItem.accessFlags,
3201
+ accessFlags,
2743
3202
  superclass,
2744
3203
  interfaces,
2745
3204
  sourceFile,
@@ -2749,6 +3208,24 @@ const createDalvikExecutableParser = <Instructions>({
2749
3208
  };
2750
3209
  });
2751
3210
 
3211
+ // Sort parameter annotations in each class by method index in classData
3212
+ for (const classDef of classDefinitions) {
3213
+ if (classDef.annotations?.parameterAnnotations && classDef.classData) {
3214
+ const allMethods = [...(classDef.classData.directMethods ?? []), ...(classDef.classData.virtualMethods ?? [])];
3215
+ classDef.annotations.parameterAnnotations.sort((a, b) => {
3216
+ const indexA = allMethods.findIndex(m =>
3217
+ m.method.name === a.method.name &&
3218
+ m.method.prototype.shorty === a.method.prototype.shorty
3219
+ );
3220
+ const indexB = allMethods.findIndex(m =>
3221
+ m.method.name === b.method.name &&
3222
+ m.method.prototype.shorty === b.method.prototype.shorty
3223
+ );
3224
+ return indexA - indexB;
3225
+ });
3226
+ }
3227
+ }
3228
+
2752
3229
  return {
2753
3230
  classDefinitions,
2754
3231
  link,