@futpib/parser 1.0.1 → 1.0.2

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 (304) hide show
  1. package/build/allSettledStream.js +32 -14
  2. package/build/allSettledStream.test.js +32 -0
  3. package/build/androidPackage.d.ts +39 -0
  4. package/build/androidPackageParser.d.ts +17 -0
  5. package/build/androidPackageParser.js +183 -0
  6. package/build/{apkParser.test.js → androidPackageParser.test.js} +6 -6
  7. package/build/androidPackageUnparser.d.ts +4 -0
  8. package/build/{apkUnparser.js → androidPackageUnparser.js} +23 -23
  9. package/build/androidPackageUnparser.test.js +26 -0
  10. package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
  11. package/build/arbitrarilySlicedAsyncInterable.js +3 -3
  12. package/build/arrayParser.test.js +3 -3
  13. package/build/backsmali.d.ts +1 -0
  14. package/build/backsmali.js +22 -0
  15. package/build/bsonParser.js +6 -2
  16. package/build/customInvariant.d.ts +1 -1
  17. package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
  18. package/build/dalvikBytecodeParser/formatParsers.js +169 -0
  19. package/build/dalvikBytecodeParser.d.ts +107 -0
  20. package/build/dalvikBytecodeParser.js +836 -0
  21. package/build/dalvikExecutable.d.ts +158 -0
  22. package/build/dalvikExecutable.js +20 -0
  23. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
  24. package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
  25. package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
  26. package/build/dalvikExecutableParser/typeParsers.js +34 -0
  27. package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
  28. package/build/dalvikExecutableParser/typedNumbers.js +19 -0
  29. package/build/dalvikExecutableParser.d.ts +5 -0
  30. package/build/dalvikExecutableParser.js +1439 -0
  31. package/build/dalvikExecutableParser.test.js +70 -0
  32. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
  33. package/build/debugLogInputParser.d.ts +4 -0
  34. package/build/debugLogInputParser.js +16 -0
  35. package/build/debugLogParser.js +14 -3
  36. package/build/disjunctionParser.d.ts +2 -1
  37. package/build/disjunctionParser.js +4 -2
  38. package/build/elementTerminatedArrayParser.d.ts +3 -0
  39. package/build/elementTerminatedArrayParser.js +18 -0
  40. package/build/elementTerminatedArrayParser.test.js +52 -0
  41. package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
  42. package/build/elementTerminatedSequenceArrayParser.js +32 -0
  43. package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
  44. package/build/elementTerminatedSequenceParser.d.ts +3 -0
  45. package/build/elementTerminatedSequenceParser.js +27 -0
  46. package/build/elementTerminatedSequenceParser.test.js +34 -0
  47. package/build/exactElementParser.js +10 -5
  48. package/build/exactSequenceParser.d.ts +2 -1
  49. package/build/exactSequenceParser.js +12 -2
  50. package/build/fetchCid.d.ts +1 -0
  51. package/build/fetchCid.js +107 -0
  52. package/build/fixedLengthSequenceParser.d.ts +1 -0
  53. package/build/fixedLengthSequenceParser.js +18 -1
  54. package/build/fixedLengthSequenceParser.test.js +41 -0
  55. package/build/hasExecutable.d.ts +1 -0
  56. package/build/hasExecutable.js +8 -0
  57. package/build/highResolutionTimer.d.ts +16 -0
  58. package/build/highResolutionTimer.js +42 -0
  59. package/build/inputReader.d.ts +11 -0
  60. package/build/inputReader.js +37 -0
  61. package/build/inputReader.test.js +165 -0
  62. package/build/inputReaderState.d.ts +10 -0
  63. package/build/inputReaderState.js +16 -0
  64. package/build/inspect.d.ts +1 -0
  65. package/build/inspect.js +7 -0
  66. package/build/javaKeyStoreParser.test.js +2 -2
  67. package/build/jsonParser.d.ts +2 -0
  68. package/build/jsonParser.js +11 -14
  69. package/build/leb128Parser.d.ts +7 -0
  70. package/build/leb128Parser.js +82 -0
  71. package/build/leb128Parser.test.js +107 -0
  72. package/build/lookaheadParser.d.ts +2 -0
  73. package/build/lookaheadParser.js +14 -0
  74. package/build/negativeLookaheadParser.js +21 -15
  75. package/build/negativeLookaheadParser.test.js +30 -0
  76. package/build/nonEmptyArrayParser.d.ts +2 -0
  77. package/build/nonEmptyArrayParser.js +32 -0
  78. package/build/nonEmptyArrayParser.test.js +16 -0
  79. package/build/parser.d.ts +10 -1
  80. package/build/parser.js +66 -31
  81. package/build/parser.test.js +79 -12
  82. package/build/parserAccessorParser.js +9 -1
  83. package/build/parserConsumedSequenceParser.js +20 -15
  84. package/build/parserContext.d.ts +14 -0
  85. package/build/parserContext.js +56 -27
  86. package/build/parserContext.test.js +27 -0
  87. package/build/parserCreatorCompose.d.ts +1 -0
  88. package/build/parserCreatorCompose.js +8 -2
  89. package/build/parserError.d.ts +6 -0
  90. package/build/parserError.js +6 -6
  91. package/build/parserInputCompanion.d.ts +15 -0
  92. package/build/parserInputCompanion.js +38 -0
  93. package/build/promiseCompose.d.ts +1 -1
  94. package/build/promiseCompose.js +12 -1
  95. package/build/promiseSettled.d.ts +1 -0
  96. package/build/promiseSettled.js +4 -0
  97. package/build/separatedArrayParser.d.ts +2 -0
  98. package/build/separatedArrayParser.js +39 -0
  99. package/build/separatedArrayParser.test.d.ts +1 -0
  100. package/build/separatedArrayParser.test.js +21 -0
  101. package/build/sequenceBuffer.d.ts +10 -0
  102. package/build/sequenceBuffer.js +54 -2
  103. package/build/sequenceBuffer.test.js +57 -0
  104. package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
  105. package/build/sequenceTerminatedSequenceParser.js +32 -0
  106. package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
  107. package/build/sequenceTerminatedSequenceParser.test.js +37 -0
  108. package/build/skipParser.d.ts +1 -1
  109. package/build/skipParser.js +4 -2
  110. package/build/skipToParser.d.ts +2 -0
  111. package/build/skipToParser.js +11 -0
  112. package/build/sliceBoundedParser.d.ts +1 -1
  113. package/build/sliceBoundedParser.js +7 -2
  114. package/build/sliceBoundedParser.test.js +35 -1
  115. package/build/smali.d.ts +1 -0
  116. package/build/smali.js +17 -0
  117. package/build/smaliParser.d.ts +12 -0
  118. package/build/smaliParser.js +656 -0
  119. package/build/smaliParser.test.d.ts +1 -0
  120. package/build/smaliParser.test.js +115 -0
  121. package/build/terminatedArrayParser.d.ts +3 -1
  122. package/build/terminatedArrayParser.js +79 -2
  123. package/build/terminatedArrayParser.test.d.ts +1 -0
  124. package/build/terminatedArrayParser.test.js +131 -0
  125. package/build/toAsyncIterable.d.ts +1 -0
  126. package/build/toAsyncIterable.js +7 -0
  127. package/build/toAsyncIterator.d.ts +1 -0
  128. package/build/toAsyncIterator.js +33 -0
  129. package/build/tupleParser.d.ts +4 -0
  130. package/build/tupleParser.js +1 -5
  131. package/build/unionParser.d.ts +2 -1
  132. package/build/unionParser.js +27 -12
  133. package/build/unionParser.test.d.ts +1 -0
  134. package/build/unionParser.test.js +60 -0
  135. package/build/zipParser.d.ts +7 -2
  136. package/build/zipParser.js +36 -12
  137. package/build/zipUnparser.d.ts +4 -1
  138. package/build/zipUnparser.js +55 -26
  139. package/build/zipUnparser.test.js +14 -14
  140. package/package.json +23 -7
  141. package/src/allSettledStream.test.ts +40 -0
  142. package/src/allSettledStream.ts +47 -15
  143. package/src/androidPackage.ts +48 -0
  144. package/src/{apkParser.test.ts → androidPackageParser.test.ts} +6 -7
  145. package/src/{apkParser.test.ts.md → androidPackageParser.test.ts.md} +4 -4
  146. package/src/androidPackageParser.test.ts.snap +0 -0
  147. package/src/androidPackageParser.ts +440 -0
  148. package/src/androidPackageUnparser.test.ts +36 -0
  149. package/src/androidPackageUnparser.ts +120 -0
  150. package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
  151. package/src/arrayParser.test.ts +3 -3
  152. package/src/backsmali.ts +30 -0
  153. package/src/bsonParser.ts +13 -2
  154. package/src/customInvariant.ts +1 -1
  155. package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
  156. package/src/dalvikBytecodeParser.ts +2074 -0
  157. package/src/dalvikExecutable.ts +220 -0
  158. package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
  159. package/src/dalvikExecutableParser/typeParsers.ts +65 -0
  160. package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
  161. package/src/dalvikExecutableParser.test.ts +89 -0
  162. package/src/dalvikExecutableParser.test.ts.md +634 -0
  163. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  164. package/src/dalvikExecutableParser.ts +2768 -0
  165. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
  166. package/src/debugLogInputParser.ts +28 -0
  167. package/src/debugLogParser.ts +19 -3
  168. package/src/disjunctionParser.ts +10 -5
  169. package/src/elementTerminatedArrayParser.test.ts +99 -0
  170. package/src/elementTerminatedArrayParser.ts +31 -0
  171. package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
  172. package/src/elementTerminatedSequenceArrayParser.ts +52 -0
  173. package/src/elementTerminatedSequenceParser.test.ts +54 -0
  174. package/src/elementTerminatedSequenceParser.ts +43 -0
  175. package/src/exactElementParser.ts +17 -11
  176. package/src/exactSequenceParser.ts +23 -2
  177. package/src/fetchCid.ts +125 -0
  178. package/src/fixedLengthSequenceParser.test.ts +77 -0
  179. package/src/fixedLengthSequenceParser.ts +28 -1
  180. package/src/hasExecutable.ts +11 -0
  181. package/src/highResolutionTimer.ts +49 -0
  182. package/src/inputReader.test.ts +209 -0
  183. package/src/inputReader.ts +75 -0
  184. package/src/inputReaderState.ts +33 -0
  185. package/src/inspect.ts +9 -0
  186. package/src/javaKeyStoreParser.test.ts +2 -3
  187. package/src/jsonParser.ts +13 -25
  188. package/src/leb128Parser.test.ts +171 -0
  189. package/src/leb128Parser.ts +125 -0
  190. package/src/lookaheadParser.ts +19 -0
  191. package/src/negativeLookaheadParser.test.ts +53 -0
  192. package/src/negativeLookaheadParser.ts +26 -14
  193. package/src/nonEmptyArrayParser.test.ts +20 -0
  194. package/src/nonEmptyArrayParser.ts +44 -0
  195. package/src/optionalParser.ts +1 -0
  196. package/src/parser.test.ts +131 -12
  197. package/src/parser.test.ts.md +21 -21
  198. package/src/parser.test.ts.snap +0 -0
  199. package/src/parser.ts +149 -45
  200. package/src/parserAccessorParser.ts +12 -2
  201. package/src/parserConsumedSequenceParser.ts +25 -16
  202. package/src/parserContext.test.ts +31 -0
  203. package/src/parserContext.ts +109 -37
  204. package/src/parserCreatorCompose.ts +20 -2
  205. package/src/parserError.ts +9 -6
  206. package/src/parserInputCompanion.ts +55 -0
  207. package/src/promiseCompose.ts +17 -3
  208. package/src/promiseSettled.ts +6 -0
  209. package/src/separatedArrayParser.test.ts +34 -0
  210. package/src/separatedArrayParser.ts +55 -0
  211. package/src/sequenceBuffer.test.ts +70 -0
  212. package/src/sequenceBuffer.ts +88 -2
  213. package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
  214. package/src/sequenceTerminatedSequenceParser.ts +62 -0
  215. package/src/skipParser.ts +7 -5
  216. package/src/skipToParser.ts +16 -0
  217. package/src/sliceBoundedParser.test.ts +43 -1
  218. package/src/sliceBoundedParser.ts +19 -1
  219. package/src/smali.ts +24 -0
  220. package/src/smaliParser.test.ts +132 -0
  221. package/src/smaliParser.test.ts.md +2320 -0
  222. package/src/smaliParser.test.ts.snap +0 -0
  223. package/src/smaliParser.ts +1166 -0
  224. package/src/terminatedArrayParser.test.ts +258 -0
  225. package/src/terminatedArrayParser.ts +108 -3
  226. package/src/toAsyncIterable.ts +7 -0
  227. package/src/toAsyncIterator.ts +48 -0
  228. package/src/tupleParser.ts +8 -5
  229. package/src/unionParser.test.ts +79 -0
  230. package/src/unionParser.ts +44 -16
  231. package/src/zipParser.ts +77 -18
  232. package/src/zipUnparser.test.ts +18 -18
  233. package/src/zipUnparser.ts +88 -27
  234. package/build/apk.d.ts +0 -39
  235. package/build/apkParser.d.ts +0 -16
  236. package/build/apkParser.js +0 -164
  237. package/build/apkUnparser.d.ts +0 -4
  238. package/build/apkUnparser.test.js +0 -26
  239. package/build/arbitraryDosDate.d.ts +0 -2
  240. package/build/arbitraryDosDate.js +0 -8
  241. package/build/arbitraryZipEntry.d.ts +0 -3
  242. package/build/arbitraryZipEntry.js +0 -26
  243. package/build/createDisjunctionParser.d.ts +0 -2
  244. package/build/createDisjunctionParser.js +0 -47
  245. package/build/createExactParser.d.ts +0 -2
  246. package/build/createExactParser.js +0 -12
  247. package/build/createSequentialUnionParser.d.ts +0 -2
  248. package/build/createSequentialUnionParser.js +0 -69
  249. package/build/fixedLengthChunkParser.d.ts +0 -2
  250. package/build/fixedLengthChunkParser.js +0 -12
  251. package/build/fixedLengthParser.d.ts +0 -2
  252. package/build/fixedLengthParser.js +0 -12
  253. package/build/inputChunkBuffer.d.ts +0 -15
  254. package/build/inputChunkBuffer.js +0 -40
  255. package/build/inputChunkBuffer.test.js +0 -34
  256. package/build/inputCompanion.d.ts +0 -18
  257. package/build/inputCompanion.js +0 -28
  258. package/build/invariantDefined.d.ts +0 -1
  259. package/build/invariantDefined.js +0 -5
  260. package/build/invariantIdentity.d.ts +0 -3
  261. package/build/invariantIdentity.js +0 -5
  262. package/build/javaKeystoreParser.d.ts +0 -2
  263. package/build/javaKeystoreParser.js +0 -7
  264. package/build/jsonParser2.d.ts +0 -3
  265. package/build/jsonParser2.js +0 -52
  266. package/build/jsonParser2.test.js +0 -22
  267. package/build/negativeLookahead.d.ts +0 -2
  268. package/build/negativeLookahead.js +0 -18
  269. package/build/parserCompose.d.ts +0 -3
  270. package/build/parserCompose.js +0 -7
  271. package/build/parserImplementationInvariantInvariant.d.ts +0 -3
  272. package/build/parserImplementationInvariantInvariant.js +0 -15
  273. package/build/parserInvariant.d.ts +0 -4
  274. package/build/parserInvariant.js +0 -11
  275. package/build/promiseFish.d.ts +0 -1
  276. package/build/promiseFish.js +0 -3
  277. package/build/sequenceParser.d.ts +0 -3
  278. package/build/sequenceParser.js +0 -10
  279. package/build/terminatedSequenceParser.d.ts +0 -2
  280. package/build/terminatedSequenceParser.js +0 -24
  281. package/build/unparserInputCompanion.d.ts +0 -15
  282. package/build/unparserInputCompanion.js +0 -13
  283. package/build/zipEntry.d.ts +0 -28
  284. package/build/zipFile.d.ts +0 -32
  285. package/build/zipFileEntry.d.ts +0 -6
  286. package/src/apk.ts +0 -48
  287. package/src/apkParser.test.ts.snap +0 -0
  288. package/src/apkParser.ts +0 -392
  289. package/src/apkUnparser.test.ts +0 -37
  290. package/src/apkUnparser.ts +0 -120
  291. package/src/invariantDefined.ts +0 -6
  292. package/src/invariantIdentity.ts +0 -8
  293. /package/build/{apk.js → androidPackage.js} +0 -0
  294. /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
  295. /package/build/{apkUnparser.test.d.ts → androidPackageUnparser.test.d.ts} +0 -0
  296. /package/build/{arbitraryDosPermissions.d.ts → dalvikExecutableParser.test.d.ts} +0 -0
  297. /package/build/{arbitraryDosPermissions.js → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
  298. /package/build/{inputChunkBuffer.test.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
  299. /package/build/{jsonParser2.test.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
  300. /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceParser.test.d.ts} +0 -0
  301. /package/build/{parserParsingInvariant.js → fixedLengthSequenceParser.test.d.ts} +0 -0
  302. /package/build/{zipEntry.js → leb128Parser.test.d.ts} +0 -0
  303. /package/build/{zipFile.js → negativeLookaheadParser.test.d.ts} +0 -0
  304. /package/build/{zipFileEntry.js → nonEmptyArrayParser.test.d.ts} +0 -0
@@ -0,0 +1,1166 @@
1
+ import invariant from "invariant";
2
+ import { DalvikBytecode, DalvikBytecodeOperation, dalvikBytecodeOperationCompanion } from "./dalvikBytecodeParser.js";
3
+ import { DalvikExecutableAccessFlags, DalvikExecutableClassData, DalvikExecutableClassDefinition, DalvikExecutableCode, DalvikExecutableField, DalvikExecutableFieldWithAccess, DalvikExecutableMethod, DalvikExecutableMethodWithAccess, DalvikExecutablePrototype, isDalvikExecutableField, isDalvikExecutableMethod } from "./dalvikExecutable.js";
4
+ import { createExactSequenceParser } from "./exactSequenceParser.js";
5
+ import { cloneParser, Parser, setParserName } from "./parser.js";
6
+ import { ParserContext } from "./parserContext.js";
7
+ import { promiseCompose } from "./promiseCompose.js";
8
+ import { createTupleParser } from "./tupleParser.js";
9
+ import { createUnionParser } from "./unionParser.js";
10
+ import { createArrayParser } from "./arrayParser.js";
11
+ import { jsonNumberParser, jsonStringParser } from "./jsonParser.js";
12
+ import { createNonEmptyArrayParser } from "./nonEmptyArrayParser.js";
13
+ import { createOptionalParser } from "./optionalParser.js";
14
+ import { createNegativeLookaheadParser } from "./negativeLookaheadParser.js";
15
+ import { createSeparatedArrayParser } from "./separatedArrayParser.js";
16
+ import { smaliMemberNameParser, smaliTypeDescriptorParser } from "./dalvikExecutableParser/stringSyntaxParser.js";
17
+ import { createDisjunctionParser } from "./disjunctionParser.js";
18
+
19
+ const smaliNewlinesParser: Parser<void, string> = promiseCompose(
20
+ createNonEmptyArrayParser(createExactSequenceParser('\n')),
21
+ (_newlines) => undefined,
22
+ );
23
+
24
+ const smaliOptionalIndentationParser: Parser<void, string> = promiseCompose(
25
+ createArrayParser(createExactSequenceParser(' ')),
26
+ (_indentation) => undefined,
27
+ );
28
+
29
+ const smaliCommentParser: Parser<string, string> = promiseCompose(
30
+ createTupleParser([
31
+ createExactSequenceParser('#'),
32
+ (async (parserContext: ParserContext<string, string>) => {
33
+ const characters: string[] = [];
34
+
35
+ while (true) {
36
+ const character = await parserContext.peek(0);
37
+
38
+ parserContext.invariant(character !== undefined, 'Unexpected end of input');
39
+
40
+ invariant(character !== undefined, 'Unexpected end of input');
41
+
42
+ if (character !== '\n') {
43
+ characters.push(character);
44
+
45
+ parserContext.skip(1);
46
+
47
+ continue;
48
+ }
49
+
50
+ break;
51
+ }
52
+
53
+ return characters.join('');
54
+ }),
55
+ ]),
56
+ ([
57
+ _hash,
58
+ comment,
59
+ ]) => comment,
60
+ );
61
+
62
+ const smaliCommentsOrNewlinesParser: Parser<string[], string> = promiseCompose(
63
+ createArrayParser(createUnionParser<undefined | string, string, string>([
64
+ smaliNewlinesParser,
65
+ smaliCommentParser,
66
+ ])),
67
+ (newlinesOrComments) => newlinesOrComments.filter((newlineOrComment): newlineOrComment is string => typeof newlineOrComment === 'string'),
68
+ );
69
+
70
+ const smaliIdentifierParser: Parser<string, string> = async (parserContext: ParserContext<string, string>) => {
71
+ const characters: string[] = [];
72
+
73
+ while (true) {
74
+ const character = await parserContext.peek(0);
75
+
76
+ parserContext.invariant(character !== undefined, 'Unexpected end of input');
77
+
78
+ invariant(character !== undefined, 'Unexpected end of input');
79
+
80
+ if (
81
+ character === '_'
82
+ || (
83
+ character >= 'a' && character <= 'z'
84
+ )
85
+ || (
86
+ character >= 'A' && character <= 'Z'
87
+ )
88
+ || (
89
+ character >= '0' && character <= '9'
90
+ )
91
+ ) {
92
+ parserContext.skip(1);
93
+
94
+ characters.push(character);
95
+
96
+ continue;
97
+ }
98
+
99
+ parserContext.invariant(characters.length > 0, 'Expected at least one character');
100
+
101
+ break;
102
+ }
103
+
104
+ return characters.join('');
105
+ };
106
+
107
+ setParserName(smaliIdentifierParser, 'smaliIdentifierParser');
108
+
109
+ const smaliQuotedStringParser: Parser<string, string> = jsonStringParser;
110
+
111
+ const smaliAccessFlagsParser: Parser<DalvikExecutableAccessFlags, string> = promiseCompose(
112
+ createSeparatedArrayParser(
113
+ createUnionParser<keyof DalvikExecutableAccessFlags, string>([
114
+ createExactSequenceParser('public'),
115
+ createExactSequenceParser('protected'),
116
+ createExactSequenceParser('private'),
117
+ createExactSequenceParser('final'),
118
+ createExactSequenceParser('brigde'),
119
+ createExactSequenceParser('synthetic'),
120
+ createExactSequenceParser('varargs'),
121
+ createExactSequenceParser('static'),
122
+ createExactSequenceParser('constructor'),
123
+ createExactSequenceParser('abstract'),
124
+ // ... TODO
125
+ ]),
126
+ createExactSequenceParser(' '),
127
+ ),
128
+ (accessFlagNames) => {
129
+ const accessFlags = {
130
+ public: false,
131
+ private: false,
132
+ protected: false,
133
+ static: false,
134
+ final: false,
135
+ synchronized: false,
136
+ volatile: false,
137
+ bridge: false,
138
+ transient: false,
139
+ varargs: false,
140
+ native: false,
141
+ interface: false,
142
+ abstract: false,
143
+ strict: false,
144
+ synthetic: false,
145
+ annotation: false,
146
+ enum: false,
147
+ constructor: false,
148
+ declaredSynchronized: false,
149
+ };
150
+
151
+ for (const accessFlagName of accessFlagNames) {
152
+ accessFlags[accessFlagName] = true;
153
+ }
154
+
155
+ return accessFlags;
156
+ },
157
+ );
158
+
159
+ const smaliClassDeclarationParser: Parser<Pick<DalvikExecutableClassDefinition<unknown>, 'accessFlags' | 'class'>, string> = promiseCompose(
160
+ createTupleParser([
161
+ smaliCommentsOrNewlinesParser,
162
+ createExactSequenceParser('.class '),
163
+ smaliAccessFlagsParser,
164
+ createExactSequenceParser(' '),
165
+ smaliTypeDescriptorParser,
166
+ createExactSequenceParser('\n'),
167
+ ]),
168
+ ([
169
+ _commentsOrNewlines,
170
+ _dotClass,
171
+ accessFlags,
172
+ _space,
173
+ classPath,
174
+ _newline,
175
+ ]) => ({
176
+ accessFlags,
177
+ class: classPath,
178
+ }),
179
+ );
180
+
181
+ setParserName(smaliClassDeclarationParser, 'smaliClassDeclarationParser');
182
+
183
+ const smaliSuperDeclarationParser: Parser<Pick<DalvikExecutableClassDefinition<unknown>, 'superclass'>, string> = promiseCompose(
184
+ createTupleParser([
185
+ createExactSequenceParser('.super '),
186
+ smaliTypeDescriptorParser,
187
+ createExactSequenceParser('\n'),
188
+ ]),
189
+ ([
190
+ _super,
191
+ superclass,
192
+ _newline,
193
+ ]) => ({
194
+ superclass,
195
+ }),
196
+ );
197
+
198
+ setParserName(smaliSuperDeclarationParser, 'smaliSuperDeclarationParser');
199
+
200
+ const smaliInterfaceDeclarationParser: Parser<string, string> = promiseCompose(
201
+ createTupleParser([
202
+ createExactSequenceParser('.implements '),
203
+ smaliTypeDescriptorParser,
204
+ createExactSequenceParser('\n'),
205
+ ]),
206
+ ([
207
+ _interface,
208
+ interface_,
209
+ _newline,
210
+ ]) => interface_,
211
+ );
212
+
213
+ setParserName(smaliInterfaceDeclarationParser, 'smaliInterfaceDeclarationParser');
214
+
215
+ const smaliSourceDeclarationParser: Parser<Pick<DalvikExecutableClassDefinition<unknown>, 'sourceFile'>, string> = promiseCompose(
216
+ createTupleParser([
217
+ createExactSequenceParser('.source '),
218
+ smaliQuotedStringParser,
219
+ createExactSequenceParser('\n'),
220
+ ]),
221
+ ([
222
+ _source,
223
+ sourceFile,
224
+ _newline,
225
+ ]) => ({
226
+ sourceFile,
227
+ }),
228
+ );
229
+
230
+ export const smaliFieldParser: Parser<DalvikExecutableFieldWithAccess, string> = promiseCompose(
231
+ createTupleParser([
232
+ createExactSequenceParser('.field '),
233
+ smaliAccessFlagsParser,
234
+ createExactSequenceParser(' '),
235
+ smaliMemberNameParser,
236
+ createExactSequenceParser(':'),
237
+ smaliTypeDescriptorParser,
238
+ createExactSequenceParser('\n'),
239
+ ]),
240
+ ([
241
+ _field,
242
+ accessFlags,
243
+ _space,
244
+ name,
245
+ _colon,
246
+ type,
247
+ ]) => {
248
+ return {
249
+ accessFlags,
250
+ field: {
251
+ class: 'FILLED_LATER',
252
+ type,
253
+ name,
254
+ },
255
+ };
256
+ },
257
+ );
258
+
259
+ setParserName(smaliFieldParser, 'smaliFieldParser');
260
+
261
+ type SmaliFields = Pick<DalvikExecutableClassData<DalvikBytecode>, 'instanceFields' | 'staticFields'>;
262
+
263
+ const smaliFieldsParser: Parser<SmaliFields, string> = promiseCompose(
264
+ createArrayParser<string[] | DalvikExecutableFieldWithAccess, string>(
265
+ createDisjunctionParser<string[] | DalvikExecutableFieldWithAccess, string, string>([
266
+ smaliFieldParser,
267
+ smaliCommentsOrNewlinesParser,
268
+ ]),
269
+ ),
270
+ (fieldsAndComments) => {
271
+ let type: 'staticField' | 'instanceField' = 'instanceField';
272
+
273
+ const staticFields: DalvikExecutableFieldWithAccess[] = [];
274
+ const instanceFields: DalvikExecutableFieldWithAccess[] = [];
275
+
276
+ for (const fieldOrComment of fieldsAndComments) {
277
+ if (Array.isArray(fieldOrComment)) {
278
+ for (const comment of fieldOrComment) {
279
+ if (comment === ' static fields') {
280
+ type = 'staticField';
281
+ }
282
+
283
+ if (comment === ' instance fields') {
284
+ type = 'instanceField';
285
+ }
286
+ }
287
+
288
+ continue;
289
+ }
290
+
291
+ invariant(typeof fieldOrComment === 'object', 'Expected field or comment');
292
+
293
+ const field = fieldOrComment as DalvikExecutableFieldWithAccess;
294
+
295
+ if (type === 'staticField') {
296
+ staticFields.push(field);
297
+
298
+ continue;
299
+ }
300
+
301
+ if (type === 'instanceField') {
302
+ instanceFields.push(field);
303
+
304
+ continue;
305
+ }
306
+
307
+ invariant(false, 'Expected field type');
308
+ }
309
+
310
+ return {
311
+ staticFields,
312
+ instanceFields,
313
+ };
314
+ }
315
+ );
316
+
317
+ setParserName(smaliFieldsParser, 'smaliFieldsParser');
318
+
319
+ const smaliShortyFieldTypeParser: Parser<string, string> = createUnionParser([
320
+ createExactSequenceParser('Z'),
321
+ createExactSequenceParser('B'),
322
+ createExactSequenceParser('S'),
323
+ createExactSequenceParser('C'),
324
+ createExactSequenceParser('I'),
325
+ createExactSequenceParser('J'),
326
+ createExactSequenceParser('F'),
327
+ createExactSequenceParser('D'),
328
+ ]);
329
+
330
+ setParserName(smaliShortyFieldTypeParser, 'smaliShortyFieldTypeParser');
331
+
332
+ const smaliShortyReturnTypeParser: Parser<string, string> = createUnionParser([
333
+ createExactSequenceParser('V'),
334
+ smaliShortyFieldTypeParser,
335
+ ]);
336
+
337
+ setParserName(smaliShortyReturnTypeParser, 'smaliShortyReturnTypeParser');
338
+
339
+ function shortyFromLongy(longy: string): string {
340
+ if (longy.startsWith('[')) {
341
+ return 'L';
342
+ }
343
+
344
+ return longy.slice(0, 1);
345
+ }
346
+
347
+ const smaliMethodPrototypeParser: Parser<DalvikExecutablePrototype, string> = promiseCompose(
348
+ createTupleParser([
349
+ createExactSequenceParser('('),
350
+ createArrayParser(smaliTypeDescriptorParser),
351
+ createExactSequenceParser(')'),
352
+ smaliTypeDescriptorParser,
353
+ ]),
354
+ ([
355
+ _openParenthesis,
356
+ parameters,
357
+ _closeParenthesis,
358
+ returnType,
359
+ ]) => ({
360
+ parameters,
361
+ returnType,
362
+ shorty: shortyFromLongy(returnType) + parameters.map((parameter) => {
363
+ if (parameter === 'V') {
364
+ return '';
365
+ }
366
+
367
+ return shortyFromLongy(parameter);
368
+ }).join(''),
369
+ }),
370
+ );
371
+
372
+ setParserName(smaliMethodPrototypeParser, 'smaliMethodPrototypeParser');
373
+
374
+ const smaliCodeRegistersParser: Parser<number, string> = promiseCompose(
375
+ createTupleParser([
376
+ createExactSequenceParser(' .registers '),
377
+ jsonNumberParser,
378
+ createExactSequenceParser('\n'),
379
+ ]),
380
+ ([
381
+ _registers,
382
+ registers,
383
+ _newline,
384
+ ]) => registers,
385
+ );
386
+
387
+ setParserName(smaliCodeRegistersParser, 'smaliCodeRegistersParser');
388
+
389
+ export const smaliAnnotationParser: Parser<unknown, string> = promiseCompose(
390
+ createTupleParser([
391
+ smaliOptionalIndentationParser,
392
+ createExactSequenceParser('.annotation '),
393
+ createUnionParser([
394
+ createExactSequenceParser('build'),
395
+ createExactSequenceParser('runtime'),
396
+ createExactSequenceParser('system'),
397
+ ]),
398
+ createExactSequenceParser(' '),
399
+ smaliTypeDescriptorParser,
400
+ createExactSequenceParser('\n'),
401
+ smaliOptionalIndentationParser,
402
+ createOptionalParser(
403
+ promiseCompose(
404
+ createTupleParser([
405
+ createExactSequenceParser('value = '),
406
+ createUnionParser([
407
+ smaliTypeDescriptorParser,
408
+ promiseCompose(
409
+ createTupleParser([
410
+ createExactSequenceParser('{\n'),
411
+ createSeparatedArrayParser(
412
+ promiseCompose(
413
+ createTupleParser([
414
+ smaliOptionalIndentationParser,
415
+ smaliTypeDescriptorParser,
416
+ ]),
417
+ ([
418
+ _indentation,
419
+ value,
420
+ ]) => value,
421
+ ),
422
+ createExactSequenceParser(',\n'),
423
+ ),
424
+ createExactSequenceParser('\n'),
425
+ smaliOptionalIndentationParser,
426
+ createExactSequenceParser('}'),
427
+ ]),
428
+ ([
429
+ _openBrace,
430
+ value,
431
+ _closeBrace,
432
+ ]) => value,
433
+ ),
434
+ promiseCompose(
435
+ createTupleParser([
436
+ createExactSequenceParser('{\n'),
437
+ createSeparatedArrayParser(
438
+ promiseCompose(
439
+ createTupleParser([
440
+ smaliOptionalIndentationParser,
441
+ smaliQuotedStringParser,
442
+ ]),
443
+ ([
444
+ _indentation,
445
+ value,
446
+ ]) => value,
447
+ ),
448
+ createExactSequenceParser(',\n'),
449
+ ),
450
+ createExactSequenceParser('\n'),
451
+ smaliOptionalIndentationParser,
452
+ createExactSequenceParser('}'),
453
+ ]),
454
+ ([
455
+ _openBrace,
456
+ value,
457
+ _closeBrace,
458
+ ]) => value,
459
+ ),
460
+ ]),
461
+ createExactSequenceParser('\n'),
462
+ ]),
463
+ ([
464
+ _indentation,
465
+ value,
466
+ _newline,
467
+ ]) => value,
468
+ ),
469
+ ),
470
+ smaliOptionalIndentationParser,
471
+ createExactSequenceParser('.end annotation\n'),
472
+ ]),
473
+ ([
474
+ _indentation0,
475
+ _annotation,
476
+ _accessFlags,
477
+ _space,
478
+ type,
479
+ _newline,
480
+ _indentation1,
481
+ value,
482
+ _endAnnotation,
483
+ ]) => ({
484
+ type,
485
+ value,
486
+ // accessFlags,
487
+ }),
488
+ );
489
+
490
+ setParserName(smaliAnnotationParser, 'smaliAnnotationParser');
491
+
492
+ const smaliCodeLineParser: Parser<number, string> = promiseCompose(
493
+ createTupleParser([
494
+ createExactSequenceParser(' .line '),
495
+ jsonNumberParser,
496
+ createExactSequenceParser('\n'),
497
+ ]),
498
+ ([
499
+ _line,
500
+ line,
501
+ _newline,
502
+ ]) => line,
503
+ );
504
+
505
+ setParserName(smaliCodeLineParser, 'smaliCodeLineParser');
506
+
507
+ type SmaliRegister = {
508
+ prefix: 'v' | 'p';
509
+ index: number;
510
+ };
511
+
512
+ function isSmaliRegister(value: unknown): value is SmaliRegister {
513
+ return (
514
+ value !== null
515
+ && typeof value === 'object'
516
+ && 'prefix' in value
517
+ && 'index' in value
518
+ && typeof (value as SmaliRegister).prefix === 'string'
519
+ && typeof (value as SmaliRegister).index === 'number'
520
+ );
521
+ }
522
+
523
+ const smaliParametersRegisterParser: Parser<SmaliRegister, string> = promiseCompose(
524
+ createUnionParser<['v' | 'p', number], string>([
525
+ createTupleParser([
526
+ createExactSequenceParser('v'),
527
+ jsonNumberParser,
528
+ ]),
529
+ createTupleParser([
530
+ createExactSequenceParser('p'),
531
+ jsonNumberParser,
532
+ ]),
533
+ ]),
534
+ ([
535
+ prefix,
536
+ index,
537
+ ]) => ({
538
+ prefix,
539
+ index,
540
+ }),
541
+ );
542
+
543
+ setParserName(smaliParametersRegisterParser, 'smaliParametersRegisterParser');
544
+
545
+ const smaliCodeLocalParser: Parser<SmaliRegister, string> = promiseCompose(
546
+ createTupleParser([
547
+ createExactSequenceParser(' .local '),
548
+ smaliParametersRegisterParser,
549
+ createOptionalParser(
550
+ createTupleParser([
551
+ createExactSequenceParser(','),
552
+ createArrayParser(createExactSequenceParser(' ')),
553
+ jsonStringParser,
554
+ createExactSequenceParser(':'),
555
+ smaliTypeDescriptorParser,
556
+ ]),
557
+ ),
558
+ createExactSequenceParser('\n'),
559
+ ]),
560
+ ([
561
+ _local,
562
+ local,
563
+ _newlocal,
564
+ ]) => local,
565
+ );
566
+
567
+ setParserName(smaliCodeLocalParser, 'smaliCodeLocalParser');
568
+
569
+ export const smaliCodeParameterParser: Parser<SmaliRegister, string> = promiseCompose(
570
+ createTupleParser([
571
+ createExactSequenceParser(' .param '),
572
+ smaliParametersRegisterParser,
573
+ createOptionalParser(
574
+ createTupleParser([
575
+ createExactSequenceParser(','),
576
+ createArrayParser(createExactSequenceParser(' ')),
577
+ jsonStringParser,
578
+ createArrayParser(createExactSequenceParser(' ')),
579
+ ]),
580
+ ),
581
+ createOptionalParser(smaliCommentParser),
582
+ createExactSequenceParser('\n'),
583
+ ]),
584
+ ([
585
+ _param,
586
+ parameter,
587
+ _newparam,
588
+ _commentOrNewline,
589
+ ]) => parameter,
590
+ );
591
+
592
+ setParserName(smaliCodeParameterParser, 'smaliCodeParameterParser');
593
+
594
+ const smaliCodeLabelParser: Parser<string, string> = promiseCompose(
595
+ createTupleParser([
596
+ createExactSequenceParser(' :'),
597
+ smaliIdentifierParser,
598
+ createExactSequenceParser('\n'),
599
+ ]),
600
+ ([
601
+ _label,
602
+ label,
603
+ _newlabel,
604
+ ]) => label,
605
+ );
606
+
607
+ setParserName(smaliCodeLabelParser, 'smaliCodeLabelParser');
608
+
609
+ const smaliParametersRegistersParser: Parser<SmaliRegister[], string> = promiseCompose(
610
+ createTupleParser([
611
+ createExactSequenceParser('{'),
612
+ createArrayParser(
613
+ promiseCompose(
614
+ createTupleParser([
615
+ smaliParametersRegisterParser,
616
+ createOptionalParser(createExactSequenceParser(', ')),
617
+ ]),
618
+ ([
619
+ parameter,
620
+ _comma,
621
+ ]) => parameter,
622
+ ),
623
+ ),
624
+ createExactSequenceParser('}'),
625
+ ]),
626
+ ([
627
+ _openBrace,
628
+ parameters,
629
+ _closeBrace,
630
+ ]) => parameters,
631
+ );
632
+
633
+ setParserName(smaliParametersRegistersParser, 'smaliParametersRegistersParser');
634
+
635
+ const smaliParametersStringParser: Parser<string, string> = cloneParser(smaliQuotedStringParser);
636
+
637
+ setParserName(smaliParametersStringParser, 'smaliParametersStringParser');
638
+
639
+ const smaliParametersIntegerParser: Parser<number | bigint, string> = promiseCompose(
640
+ createTupleParser([
641
+ createExactSequenceParser('0x'),
642
+ async parserContext => {
643
+ const characters: string[] = [];
644
+
645
+ while (true) {
646
+ const character = await parserContext.peek(0);
647
+
648
+ parserContext.invariant(character !== undefined, 'Unexpected end of input');
649
+
650
+ invariant(character !== undefined, 'Unexpected end of input');
651
+
652
+ if (
653
+ (character >= '0' && character <= '9')
654
+ || (character >= 'a' && character <= 'f')
655
+ || (character >= 'A' && character <= 'F')
656
+ ) {
657
+ characters.push(character);
658
+
659
+ parserContext.skip(1);
660
+
661
+ continue;
662
+ }
663
+
664
+ break;
665
+ }
666
+
667
+ return characters.join('');
668
+ },
669
+ createOptionalParser(createExactSequenceParser('L')),
670
+ ]),
671
+ ([
672
+ _0x,
673
+ value,
674
+ optionalL,
675
+ ]) => {
676
+ if (optionalL) {
677
+ return BigInt('0x' + value);
678
+ }
679
+
680
+ return parseInt(value, 16);
681
+ },
682
+ );
683
+
684
+ setParserName(smaliParametersIntegerParser, 'smaliParametersIntegerParser');
685
+
686
+ const smaliParametersLabelParser: Parser<string, string> = promiseCompose(
687
+ createTupleParser([
688
+ createExactSequenceParser(':'),
689
+ smaliIdentifierParser,
690
+ ]),
691
+ ([
692
+ _label,
693
+ label,
694
+ ]) => label,
695
+ );
696
+
697
+ setParserName(smaliParametersLabelParser, 'smaliParametersLabelParser');
698
+
699
+ const smaliParametersTypeParser: Parser<string, string> = cloneParser(smaliTypeDescriptorParser);
700
+
701
+ setParserName(smaliParametersTypeParser, 'smaliParametersTypeParser');
702
+
703
+ const smaliParametersMethodParser: Parser<DalvikExecutableMethod, string> = promiseCompose(
704
+ createTupleParser([
705
+ smaliTypeDescriptorParser,
706
+ createExactSequenceParser('->'),
707
+ smaliMemberNameParser,
708
+ smaliMethodPrototypeParser,
709
+ ]),
710
+ ([
711
+ classPath,
712
+ _separator,
713
+ methodName,
714
+ prototype,
715
+ ]) => ({
716
+ class: classPath,
717
+ prototype,
718
+ name: methodName,
719
+ })
720
+ );
721
+
722
+ setParserName(smaliParametersMethodParser, 'smaliParametersMethodParser');
723
+
724
+ const smaliParametersFieldParser: Parser<DalvikExecutableField, string> = promiseCompose(
725
+ createTupleParser([
726
+ smaliTypeDescriptorParser,
727
+ createExactSequenceParser('->'),
728
+ smaliMemberNameParser,
729
+ createExactSequenceParser(':'),
730
+ smaliTypeDescriptorParser,
731
+ ]),
732
+ ([
733
+ classPath,
734
+ _separator,
735
+ fieldName,
736
+ _colon,
737
+ type,
738
+ ]) => ({
739
+ class: classPath,
740
+ name: fieldName,
741
+ type,
742
+ })
743
+ );
744
+
745
+ setParserName(smaliParametersFieldParser, 'smaliParametersFieldParser');
746
+
747
+ type SmaliCodeOperationParameter =
748
+ | SmaliRegister
749
+ | SmaliRegister[]
750
+ | string
751
+ | DalvikExecutableMethod
752
+ ;
753
+
754
+ const smaliCodeOperationParametersParser: Parser<SmaliCodeOperationParameter[], string> = createArrayParser(
755
+ promiseCompose(
756
+ createTupleParser([
757
+ createUnionParser<SmaliCodeOperationParameter, string>([
758
+ smaliParametersRegisterParser,
759
+ smaliParametersRegistersParser,
760
+ smaliParametersStringParser,
761
+ smaliParametersIntegerParser,
762
+ smaliParametersLabelParser,
763
+ promiseCompose(
764
+ createTupleParser([
765
+ createNegativeLookaheadParser(smaliParametersMethodParser),
766
+ createNegativeLookaheadParser(smaliParametersFieldParser),
767
+ smaliParametersTypeParser,
768
+ ]),
769
+ ([
770
+ _notMethod,
771
+ _notField,
772
+ type,
773
+ ]) => type,
774
+ ),
775
+ smaliParametersMethodParser,
776
+ smaliParametersFieldParser,
777
+ ]),
778
+ createOptionalParser(createExactSequenceParser(', ')),
779
+ ]),
780
+ ([
781
+ parameter,
782
+ _comma,
783
+ ]) => parameter,
784
+ ),
785
+ );
786
+
787
+ setParserName(smaliCodeOperationParametersParser, 'smaliCodeOperationParametersParser');
788
+
789
+ const smaliCodeOperationNameParser: Parser<string, string> = promiseCompose(
790
+ createTupleParser([
791
+ promiseCompose(
792
+ createSeparatedArrayParser(
793
+ smaliIdentifierParser,
794
+ createExactSequenceParser('-'),
795
+ ),
796
+ (parts) => parts.join('-'),
797
+ ),
798
+ createOptionalParser(
799
+ promiseCompose(
800
+ createTupleParser([
801
+ createExactSequenceParser('/'),
802
+ smaliIdentifierParser,
803
+ ]),
804
+ ([ slash, name ]) => slash + name,
805
+ ),
806
+ ),
807
+ ]),
808
+ ([
809
+ name,
810
+ optionalSlashName,
811
+ ]) => name + (optionalSlashName || ''),
812
+ );
813
+
814
+ setParserName(smaliCodeOperationNameParser, 'smaliCodeOperationNameParser');
815
+
816
+ const smaliCodeOperationParser: Parser<DalvikBytecodeOperation, string> = promiseCompose(
817
+ createTupleParser([
818
+ createExactSequenceParser(' '),
819
+ smaliCodeOperationNameParser,
820
+ promiseCompose(
821
+ createOptionalParser(createTupleParser([
822
+ createExactSequenceParser(' '),
823
+ smaliCodeOperationParametersParser,
824
+ ])),
825
+ (undefinedOrParameters) => undefinedOrParameters === undefined ? [] : undefinedOrParameters[1],
826
+ ),
827
+ createExactSequenceParser('\n'),
828
+ ]),
829
+ ([
830
+ _indent,
831
+ operation,
832
+ parameters,
833
+ _newline,
834
+ ]) => ({
835
+ operation,
836
+ parameters,
837
+ } as any), // TODO
838
+ );
839
+
840
+ setParserName(smaliCodeOperationParser, 'smaliCodeOperationParser');
841
+
842
+ const operationsWithTypeArgument = new Set<DalvikBytecodeOperation['operation']>([
843
+ 'new-instance',
844
+ 'check-cast',
845
+ 'instance-of',
846
+ ]);
847
+
848
+ const smaliAnnotatedCodeOperationParser: Parser<DalvikBytecodeOperation, string> = promiseCompose(
849
+ createTupleParser([
850
+ createArrayParser(smaliCodeLineParser),
851
+ createOptionalParser(smaliCodeLocalParser),
852
+ createArrayParser(smaliCodeLabelParser),
853
+ smaliCodeOperationParser,
854
+ ]),
855
+ ([
856
+ _lines,
857
+ _local,
858
+ _labels,
859
+ operation,
860
+ ]) => {
861
+ const operation_ = {
862
+ operation: operation.operation,
863
+ // line,
864
+ // local,
865
+ // label,
866
+ // parameters: (operation as any).parameters,
867
+ } as any; // TODO
868
+
869
+ for (const parameter of (operation as unknown as { parameters: unknown[]; }).parameters.flat() ?? []) {
870
+ if (isDalvikExecutableMethod(parameter)) {
871
+ operation_.method = parameter;
872
+
873
+ continue;
874
+ }
875
+
876
+ if (isDalvikExecutableField(parameter)) {
877
+ operation_.field = parameter;
878
+
879
+ continue;
880
+ }
881
+
882
+ if (isSmaliRegister(parameter)) {
883
+ if (!operation_.registers) {
884
+ operation_.registers = [];
885
+ }
886
+
887
+ operation_.registers.push(parameter);
888
+
889
+ continue;
890
+ }
891
+
892
+ if (typeof parameter === 'string') {
893
+ if (operationsWithTypeArgument.has(operation_.operation)) {
894
+ operation_.type = parameter;
895
+
896
+ continue;
897
+ }
898
+
899
+ operation_.string = parameter;
900
+
901
+ continue;
902
+ }
903
+
904
+ if (typeof parameter === 'number' || typeof parameter === 'bigint') {
905
+ operation_.value = parameter;
906
+
907
+ continue;
908
+ }
909
+
910
+ invariant(false, 'TODO: parameter: %s, operation: %s', JSON.stringify(parameter), JSON.stringify(operation));
911
+ }
912
+
913
+ if (operation_.registers) {
914
+ operation_.registers = operation_.registers.reverse();
915
+ }
916
+
917
+ return operation_;
918
+ },
919
+ );
920
+
921
+ setParserName(smaliCodeOperationParser, 'smaliCodeOperationParser');
922
+
923
+ const smaliExecutableCodeParser: Parser<DalvikExecutableCode<DalvikBytecode>, string> = promiseCompose(
924
+ createTupleParser([
925
+ smaliCodeRegistersParser,
926
+ createArrayParser(
927
+ smaliAnnotationParser,
928
+ ),
929
+ createOptionalParser(smaliCodeParameterParser),
930
+ createArrayParser(
931
+ promiseCompose(
932
+ createTupleParser([
933
+ createOptionalParser(smaliCommentsOrNewlinesParser),
934
+ smaliAnnotatedCodeOperationParser,
935
+ ]),
936
+ ([
937
+ _commentsOrNewlines,
938
+ operation,
939
+ ]) => operation,
940
+ ),
941
+ ),
942
+ ]),
943
+ ([
944
+ registersSize,
945
+ _annotations,
946
+ _parameters,
947
+ instructions,
948
+ ]) => {
949
+ return {
950
+ registersSize,
951
+ insSize: -1, // TODO
952
+ outsSize: -1, // TODO
953
+ debugInfo: undefined, // TODO
954
+ instructions,
955
+ tries: [], // TODO
956
+ // _annotations,
957
+ };
958
+ },
959
+ );
960
+
961
+ setParserName(smaliExecutableCodeParser, 'smaliExecutableCodeParser');
962
+
963
+ const smaliMethodParser: Parser<DalvikExecutableMethodWithAccess<DalvikBytecode>, string> = promiseCompose(
964
+ createTupleParser([
965
+ createExactSequenceParser('.method '),
966
+ smaliAccessFlagsParser,
967
+ createExactSequenceParser(' '),
968
+ smaliMemberNameParser,
969
+ smaliMethodPrototypeParser,
970
+ createExactSequenceParser('\n'),
971
+ smaliExecutableCodeParser,
972
+ createArrayParser(smaliCodeLineParser),
973
+ createExactSequenceParser('.end method\n'),
974
+ ]),
975
+ ([
976
+ _method,
977
+ accessFlags,
978
+ _space,
979
+ name,
980
+ prototype,
981
+ _newline,
982
+ code,
983
+ _lines,
984
+ _endMethod,
985
+ ]) => {
986
+ let insSize = 1;
987
+
988
+ for (const _parameter of prototype.parameters) {
989
+ insSize += 1; // TODO: two words for wide types
990
+ }
991
+
992
+ code.insSize = insSize;
993
+
994
+ for (const operation of code.instructions) {
995
+ const smaliRegisters = dalvikBytecodeOperationCompanion.getRegisters(operation) as unknown[] as SmaliRegister[]; // TODO
996
+
997
+ if (!smaliRegisters.length) {
998
+ continue;
999
+ }
1000
+
1001
+ const registers: number[] = smaliRegisters.map(({ prefix, index }) => {
1002
+ if (prefix === 'v') {
1003
+ return index;
1004
+ }
1005
+
1006
+ if (prefix === 'p') {
1007
+ return code.registersSize - insSize + index;
1008
+ }
1009
+
1010
+ invariant(false, 'Expected prefix to be v or p');
1011
+ });
1012
+
1013
+ (operation as any).registers = registers; // TODO
1014
+ }
1015
+
1016
+ let outsSize = 0;
1017
+
1018
+ for (const operation of code.instructions) {
1019
+ const registers = dalvikBytecodeOperationCompanion.getRegisters(operation);
1020
+
1021
+ outsSize = Math.max(outsSize, registers.length); // TODO: two words for wide types
1022
+ }
1023
+
1024
+ code.outsSize = outsSize;
1025
+
1026
+ return {
1027
+ accessFlags,
1028
+ method: {
1029
+ class: 'FILLED_LATER',
1030
+ prototype,
1031
+ name,
1032
+ },
1033
+ code,
1034
+ };
1035
+ },
1036
+ );
1037
+
1038
+ setParserName(smaliMethodParser, 'smaliMethodParser');
1039
+
1040
+ type SmaliMethods = Pick<DalvikExecutableClassData<DalvikBytecode>, 'directMethods' | 'virtualMethods'>;
1041
+
1042
+ const smaliMethodsParser: Parser<SmaliMethods, string> = promiseCompose(
1043
+ createArrayParser<string[] | DalvikExecutableMethodWithAccess<DalvikBytecode>, string>(
1044
+ createDisjunctionParser<string[] | DalvikExecutableMethodWithAccess<DalvikBytecode>, string, string>([
1045
+ smaliMethodParser,
1046
+ smaliCommentsOrNewlinesParser,
1047
+ ]),
1048
+ ),
1049
+ (methodsAndComments) => {
1050
+ let type: 'directMethod' | 'virtualMethod' = 'directMethod';
1051
+
1052
+ const directMethods: DalvikExecutableMethodWithAccess<DalvikBytecode>[] = [];
1053
+ const virtualMethods: DalvikExecutableMethodWithAccess<DalvikBytecode>[] = [];
1054
+
1055
+ for (const methodOrComment of methodsAndComments) {
1056
+ if (Array.isArray(methodOrComment)) {
1057
+ for (const comment of methodOrComment) {
1058
+ if (comment === ' direct methods') {
1059
+ type = 'directMethod';
1060
+ }
1061
+
1062
+ if (comment === ' virtual methods') {
1063
+ type = 'virtualMethod';
1064
+ }
1065
+ }
1066
+
1067
+ continue;
1068
+ }
1069
+
1070
+ invariant(typeof methodOrComment === 'object', 'Expected method or comment');
1071
+
1072
+ const method = methodOrComment as DalvikExecutableMethodWithAccess<DalvikBytecode>;
1073
+
1074
+ if (type === 'directMethod') {
1075
+ directMethods.push(method);
1076
+
1077
+ continue;
1078
+ }
1079
+
1080
+ if (type === 'virtualMethod') {
1081
+ virtualMethods.push(method);
1082
+
1083
+ continue;
1084
+ }
1085
+
1086
+ invariant(false, 'Expected method type');
1087
+ }
1088
+
1089
+ return {
1090
+ directMethods,
1091
+ virtualMethods,
1092
+ };
1093
+ }
1094
+ );
1095
+
1096
+ setParserName(smaliMethodsParser, 'smaliMethodsParser');
1097
+
1098
+ export const smaliParser: Parser<DalvikExecutableClassDefinition<DalvikBytecode>, string> = promiseCompose(
1099
+ createTupleParser([
1100
+ smaliClassDeclarationParser,
1101
+ smaliSuperDeclarationParser,
1102
+ smaliSourceDeclarationParser,
1103
+ smaliCommentsOrNewlinesParser,
1104
+ createArrayParser(smaliInterfaceDeclarationParser),
1105
+ smaliCommentsOrNewlinesParser,
1106
+ createOptionalParser(smaliFieldsParser),
1107
+ smaliMethodsParser,
1108
+ ]),
1109
+ ([
1110
+ {
1111
+ accessFlags,
1112
+ class: class_,
1113
+ },
1114
+ {
1115
+ superclass,
1116
+ },
1117
+ {
1118
+ sourceFile,
1119
+ },
1120
+ _commentsOrNewlines0,
1121
+ interfaces,
1122
+ _commentsOrNewlines1,
1123
+ fields,
1124
+ methods,
1125
+ ]) => ({
1126
+ accessFlags,
1127
+ class: class_,
1128
+ superclass,
1129
+ sourceFile,
1130
+ annotations: undefined, // TODO
1131
+ classData: {
1132
+ directMethods: methods.directMethods.map((method) => ({
1133
+ ...method,
1134
+ method: {
1135
+ ...method.method,
1136
+ class: class_,
1137
+ },
1138
+ })),
1139
+ virtualMethods: methods.virtualMethods.map((method) => ({
1140
+ ...method,
1141
+ method: {
1142
+ ...method.method,
1143
+ class: class_,
1144
+ },
1145
+ })),
1146
+ staticFields: (fields?.staticFields ?? []).map((field) => ({
1147
+ ...field,
1148
+ field: {
1149
+ ...field.field,
1150
+ class: class_,
1151
+ },
1152
+ })),
1153
+ instanceFields: (fields?.instanceFields ?? []).map((field) => ({
1154
+ ...field,
1155
+ field: {
1156
+ ...field.field,
1157
+ class: class_,
1158
+ },
1159
+ })),
1160
+ },
1161
+ interfaces,
1162
+ staticValues: [], // TODO
1163
+ }) as any, // TODO
1164
+ );
1165
+
1166
+ setParserName(smaliParser, 'smaliParser');