@futpib/parser 1.0.2 → 1.0.4

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 (311) 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/bash.d.ts +84 -0
  26. package/build/bash.js +1 -0
  27. package/build/bashParser.d.ts +6 -0
  28. package/build/bashParser.js +294 -0
  29. package/build/bashParser.test.d.ts +1 -0
  30. package/build/bashParser.test.js +181 -0
  31. package/build/customInvariant.d.ts +2 -1
  32. package/build/customInvariant.js +4 -6
  33. package/build/dalvikBytecodeParser/formatParsers.d.ts +76 -2
  34. package/build/dalvikBytecodeParser/formatParsers.js +146 -11
  35. package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
  36. package/build/dalvikBytecodeParser/formatSizes.js +34 -0
  37. package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
  38. package/build/dalvikBytecodeParser/operationFormats.js +225 -0
  39. package/build/dalvikBytecodeParser.d.ts +1105 -5
  40. package/build/dalvikBytecodeParser.js +658 -205
  41. package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
  42. package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
  43. package/build/dalvikBytecodeUnparser.d.ts +3 -0
  44. package/build/dalvikBytecodeUnparser.js +642 -0
  45. package/build/dalvikBytecodeUnparser.test.d.ts +1 -0
  46. package/build/dalvikBytecodeUnparser.test.js +25 -0
  47. package/build/dalvikExecutable.d.ts +65 -8
  48. package/build/dalvikExecutable.js +36 -0
  49. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +1 -1
  50. package/build/dalvikExecutableParser/stringSyntaxParser.js +17 -17
  51. package/build/dalvikExecutableParser/typeParsers.d.ts +2 -1
  52. package/build/dalvikExecutableParser/typeParsers.js +16 -11
  53. package/build/dalvikExecutableParser/typedNumbers.d.ts +85 -69
  54. package/build/dalvikExecutableParser/typedNumbers.js +0 -1
  55. package/build/dalvikExecutableParser.d.ts +2 -2
  56. package/build/dalvikExecutableParser.js +655 -337
  57. package/build/dalvikExecutableParser.test.js +24 -22
  58. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +223 -246
  59. package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
  60. package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
  61. package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
  62. package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
  63. package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
  64. package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
  65. package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
  66. package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
  67. package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
  68. package/build/dalvikExecutableUnparser/utils.js +108 -0
  69. package/build/dalvikExecutableUnparser.d.ts +4 -0
  70. package/build/dalvikExecutableUnparser.js +406 -0
  71. package/build/dalvikExecutableUnparser.test.d.ts +1 -0
  72. package/build/dalvikExecutableUnparser.test.js +31 -0
  73. package/build/debugLogInputParser.js +1 -1
  74. package/build/disjunctionParser.d.ts +2 -2
  75. package/build/disjunctionParser.js +2 -2
  76. package/build/elementTerminatedArrayParser.d.ts +2 -2
  77. package/build/elementTerminatedArrayParser.js +1 -1
  78. package/build/elementTerminatedArrayParser.test.js +5 -5
  79. package/build/elementTerminatedSequenceArrayParser.d.ts +2 -2
  80. package/build/elementTerminatedSequenceArrayParser.js +1 -1
  81. package/build/elementTerminatedSequenceArrayParser.test.js +2 -2
  82. package/build/elementTerminatedSequenceParser.d.ts +2 -2
  83. package/build/elementTerminatedSequenceParser.js +1 -1
  84. package/build/elementTerminatedSequenceParser.test.js +2 -2
  85. package/build/endOfInputParser.d.ts +1 -1
  86. package/build/exactElementSwitchParser.d.ts +3 -0
  87. package/build/exactElementSwitchParser.js +22 -0
  88. package/build/fetchCid.js +2 -6
  89. package/build/fetchCid.test.d.ts +1 -0
  90. package/build/fetchCid.test.js +16 -0
  91. package/build/fixedLengthSequenceParser.test.js +2 -2
  92. package/build/hasExecutable.js +2 -2
  93. package/build/highResolutionTimer.js +1 -1
  94. package/build/index.d.ts +24 -2
  95. package/build/index.js +22 -1
  96. package/build/inputReader.d.ts +1 -1
  97. package/build/inputReader.test.js +33 -45
  98. package/build/javaKeyStoreParser.test.js +6 -6
  99. package/build/jsonParser.js +8 -8
  100. package/build/lazyMessageError.d.ts +48 -0
  101. package/build/lazyMessageError.js +53 -0
  102. package/build/lazyMessageError.test.d.ts +1 -0
  103. package/build/lazyMessageError.test.js +15 -0
  104. package/build/leb128Parser.d.ts +1 -1
  105. package/build/leb128Parser.js +10 -10
  106. package/build/leb128Parser.test.js +7 -7
  107. package/build/negativeLookaheadParser.js +2 -2
  108. package/build/negativeLookaheadParser.test.js +4 -4
  109. package/build/noStackCaptureOverheadError.d.ts +4 -0
  110. package/build/noStackCaptureOverheadError.js +9 -0
  111. package/build/noStackCaptureOverheadError.test.d.ts +1 -0
  112. package/build/noStackCaptureOverheadError.test.js +15 -0
  113. package/build/nonEmptyArrayParser.js +2 -2
  114. package/build/nonEmptyArrayParser.test.js +2 -1
  115. package/build/optionalParser.js +2 -2
  116. package/build/parser.d.ts +2 -1
  117. package/build/parser.js +23 -8
  118. package/build/parser.test.js +78 -29
  119. package/build/parserConsumedSequenceParser.d.ts +1 -1
  120. package/build/parserConsumedSequenceParser.js +2 -2
  121. package/build/parserContext.d.ts +8 -6
  122. package/build/parserContext.js +60 -33
  123. package/build/parserContext.test.js +7 -3
  124. package/build/parserError.d.ts +603 -44
  125. package/build/parserError.js +98 -53
  126. package/build/parserImplementationInvariant.d.ts +1 -1
  127. package/build/parserImplementationInvariant.js +2 -2
  128. package/build/parserInputCompanion.js +2 -2
  129. package/build/promiseCompose.js +1 -2
  130. package/build/regexpParser.d.ts +2 -0
  131. package/build/regexpParser.js +71 -0
  132. package/build/regexpParser.test.d.ts +1 -0
  133. package/build/regexpParser.test.js +83 -0
  134. package/build/regularExpression.d.ts +63 -0
  135. package/build/regularExpression.js +1 -0
  136. package/build/regularExpressionParser.d.ts +3 -0
  137. package/build/regularExpressionParser.js +580 -0
  138. package/build/regularExpressionParser.test.d.ts +1 -0
  139. package/build/regularExpressionParser.test.js +89 -0
  140. package/build/separatedArrayParser.js +2 -2
  141. package/build/separatedNonEmptyArrayParser.d.ts +2 -0
  142. package/build/separatedNonEmptyArrayParser.js +40 -0
  143. package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
  144. package/build/separatedNonEmptyArrayParser.test.js +66 -0
  145. package/build/sequenceBuffer.js +1 -1
  146. package/build/sequenceTerminatedSequenceParser.d.ts +2 -2
  147. package/build/sequenceTerminatedSequenceParser.js +3 -3
  148. package/build/sequenceTerminatedSequenceParser.test.js +1 -1
  149. package/build/sequenceUnparser.d.ts +1 -1
  150. package/build/skipToParser.d.ts +1 -1
  151. package/build/skipToParser.js +2 -2
  152. package/build/sliceBoundedParser.test.js +4 -9
  153. package/build/smali.d.ts +1 -1
  154. package/build/smali.js +6 -2
  155. package/build/smaliParser.d.ts +62 -6
  156. package/build/smaliParser.js +1721 -296
  157. package/build/smaliParser.test.js +338 -43
  158. package/build/stringFromAsyncIterable.d.ts +1 -0
  159. package/build/stringFromAsyncIterable.js +7 -0
  160. package/build/terminatedArrayParser.js +4 -4
  161. package/build/terminatedArrayParser.test.js +7 -7
  162. package/build/toAsyncIterator.js +4 -4
  163. package/build/unionParser.d.ts +1 -1
  164. package/build/unionParser.js +2 -2
  165. package/build/unionParser.test.js +3 -3
  166. package/build/unparser.d.ts +3 -3
  167. package/build/unparser.js +6 -4
  168. package/build/unparser.test.js +7 -19
  169. package/build/unparserContext.d.ts +2 -2
  170. package/build/unparserContext.js +2 -3
  171. package/build/unparserError.d.ts +2 -1
  172. package/build/unparserError.js +2 -1
  173. package/build/unparserImplementationInvariant.d.ts +1 -1
  174. package/build/unparserOutputCompanion.d.ts +1 -1
  175. package/build/unparserOutputCompanion.js +1 -1
  176. package/build/zipParser.js +1 -1
  177. package/build/zipUnparser.d.ts +3 -3
  178. package/build/zipUnparser.js +9 -19
  179. package/build/zipUnparser.test.js +1 -1
  180. package/package.json +20 -26
  181. package/src/allSettledStream.test.ts +2 -2
  182. package/src/allSettledStream.ts +3 -3
  183. package/src/androidPackageParser.test.ts +17 -19
  184. package/src/androidPackageParser.ts +129 -171
  185. package/src/androidPackageUnparser.test.ts +19 -21
  186. package/src/androidPackageUnparser.ts +23 -17
  187. package/src/arbitrarilySlicedAsyncInterable.ts +1 -1
  188. package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
  189. package/src/arbitraryDalvikBytecode.ts +992 -0
  190. package/src/arbitraryDalvikExecutable.ts +434 -0
  191. package/src/arbitraryDosDateTime.ts +1 -0
  192. package/src/arbitraryZipStream.ts +1 -1
  193. package/src/arrayParser.ts +2 -2
  194. package/src/arrayUnparser.ts +2 -2
  195. package/src/backsmali.ts +48 -4
  196. package/src/bash.ts +120 -0
  197. package/src/bashParser.test.ts +332 -0
  198. package/src/bashParser.ts +461 -0
  199. package/src/bsonParser.test.ts +12 -14
  200. package/src/customInvariant.ts +8 -12
  201. package/src/dalvikBytecodeParser/formatParsers.ts +376 -17
  202. package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
  203. package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
  204. package/src/dalvikBytecodeParser.ts +1042 -243
  205. package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
  206. package/src/dalvikBytecodeUnparser.test.ts +44 -0
  207. package/src/dalvikBytecodeUnparser.ts +758 -0
  208. package/src/dalvikExecutable.ts +110 -48
  209. package/src/dalvikExecutableParser/stringSyntaxParser.ts +33 -33
  210. package/src/dalvikExecutableParser/typeParsers.ts +23 -14
  211. package/src/dalvikExecutableParser/typedNumbers.ts +19 -19
  212. package/src/dalvikExecutableParser.test.ts +60 -60
  213. package/src/dalvikExecutableParser.test.ts.md +6 -6
  214. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  215. package/src/dalvikExecutableParser.ts +911 -434
  216. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +256 -239
  217. package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
  218. package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
  219. package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
  220. package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
  221. package/src/dalvikExecutableUnparser/utils.ts +149 -0
  222. package/src/dalvikExecutableUnparser.test.ts +57 -0
  223. package/src/dalvikExecutableUnparser.ts +581 -0
  224. package/src/debugLogInputParser.ts +1 -1
  225. package/src/disjunctionParser.ts +5 -5
  226. package/src/elementTerminatedArrayParser.test.ts +8 -8
  227. package/src/elementTerminatedArrayParser.ts +2 -2
  228. package/src/elementTerminatedSequenceArrayParser.test.ts +4 -6
  229. package/src/elementTerminatedSequenceArrayParser.ts +2 -2
  230. package/src/elementTerminatedSequenceParser.test.ts +4 -6
  231. package/src/elementTerminatedSequenceParser.ts +2 -2
  232. package/src/endOfInputParser.ts +1 -1
  233. package/src/exactElementSwitchParser.ts +41 -0
  234. package/src/fetchCid.test.ts +20 -0
  235. package/src/fetchCid.ts +3 -7
  236. package/src/fixedLengthSequenceParser.test.ts +10 -12
  237. package/src/hasExecutable.ts +2 -2
  238. package/src/highResolutionTimer.ts +1 -1
  239. package/src/index.ts +113 -2
  240. package/src/inputReader.test.ts +39 -52
  241. package/src/inputReader.ts +2 -4
  242. package/src/inputReaderState.ts +1 -1
  243. package/src/inspect.ts +1 -1
  244. package/src/javaKeyStoreParser.test.ts +12 -14
  245. package/src/javaKeyStoreParser.ts +2 -6
  246. package/src/jsonParser.test.ts +2 -4
  247. package/src/jsonParser.ts +34 -38
  248. package/src/lazyMessageError.test.ts +21 -0
  249. package/src/lazyMessageError.ts +88 -0
  250. package/src/leb128Parser.test.ts +25 -23
  251. package/src/leb128Parser.ts +19 -19
  252. package/src/negativeLookaheadParser.test.ts +7 -11
  253. package/src/negativeLookaheadParser.ts +2 -2
  254. package/src/noStackCaptureOverheadError.test.ts +17 -0
  255. package/src/noStackCaptureOverheadError.ts +12 -0
  256. package/src/nonEmptyArrayParser.test.ts +3 -2
  257. package/src/nonEmptyArrayParser.ts +2 -2
  258. package/src/optionalParser.ts +2 -2
  259. package/src/parser.test.ts +96 -43
  260. package/src/parser.test.ts.md +13 -6
  261. package/src/parser.test.ts.snap +0 -0
  262. package/src/parser.ts +35 -12
  263. package/src/parserAccessorParser.ts +1 -1
  264. package/src/parserConsumedSequenceParser.ts +3 -3
  265. package/src/parserContext.test.ts +7 -3
  266. package/src/parserContext.ts +82 -48
  267. package/src/parserError.ts +143 -63
  268. package/src/parserImplementationInvariant.ts +3 -3
  269. package/src/parserInputCompanion.ts +2 -2
  270. package/src/promiseCompose.ts +2 -2
  271. package/src/regexpParser.test.ts +186 -0
  272. package/src/regexpParser.ts +94 -0
  273. package/src/regularExpression.ts +24 -0
  274. package/src/regularExpressionParser.test.ts +102 -0
  275. package/src/regularExpressionParser.ts +921 -0
  276. package/src/separatedArrayParser.ts +3 -3
  277. package/src/separatedNonEmptyArrayParser.test.ts +117 -0
  278. package/src/separatedNonEmptyArrayParser.ts +61 -0
  279. package/src/sequenceBuffer.test.ts +9 -9
  280. package/src/sequenceBuffer.ts +4 -4
  281. package/src/sequenceTerminatedSequenceParser.test.ts +3 -5
  282. package/src/sequenceTerminatedSequenceParser.ts +4 -4
  283. package/src/sequenceUnparser.ts +2 -2
  284. package/src/skipToParser.ts +2 -2
  285. package/src/sliceBoundedParser.test.ts +4 -12
  286. package/src/sliceBoundedParser.ts +2 -2
  287. package/src/smali.ts +8 -3
  288. package/src/smaliParser.test.ts +377 -66
  289. package/src/smaliParser.test.ts.md +1635 -48
  290. package/src/smaliParser.test.ts.snap +0 -0
  291. package/src/smaliParser.ts +2751 -569
  292. package/src/stringFromAsyncIterable.ts +9 -0
  293. package/src/terminatedArrayParser.test.ts +11 -11
  294. package/src/terminatedArrayParser.ts +5 -7
  295. package/src/toAsyncIterator.ts +8 -8
  296. package/src/uint8Array.ts +2 -3
  297. package/src/unionParser.test.ts +22 -23
  298. package/src/unionParser.ts +6 -8
  299. package/src/unparser.test.ts +18 -34
  300. package/src/unparser.ts +13 -9
  301. package/src/unparserContext.ts +9 -13
  302. package/src/unparserError.ts +2 -1
  303. package/src/unparserImplementationInvariant.ts +1 -1
  304. package/src/unparserOutputCompanion.ts +1 -1
  305. package/src/zip.ts +2 -6
  306. package/src/zipParser.ts +10 -18
  307. package/src/zipUnparser.test.ts +1 -1
  308. package/src/zipUnparser.ts +52 -64
  309. package/tsconfig.json +7 -1
  310. package/xo.config.ts +15 -0
  311. package/.yarn/releases/yarn-4.5.3.cjs +0 -934
@@ -0,0 +1,135 @@
1
+ import { type Unparser } from '../unparser.js';
2
+
3
+ async function* yieldAndCapture<T>(gen: AsyncIterable<T, T>): AsyncIterable<T, T> {
4
+ let value: T | undefined;
5
+ for await (value of gen) {
6
+ yield value;
7
+ }
8
+ return value!;
9
+ }
10
+ import {
11
+ type DalvikExecutableAnnotation,
12
+ type DalvikExecutableClassAnnotations,
13
+ type DalvikExecutableEncodedValue,
14
+ type DalvikExecutableField,
15
+ type DalvikExecutableMethod,
16
+ } from '../dalvikExecutable.js';
17
+ import { ubyteUnparser, uintUnparser } from '../dalvikBytecodeUnparser/formatUnparsers.js';
18
+ import { alignmentUnparser, uleb128Unparser } from './utils.js';
19
+ import { WriteLater } from '../unparserContext.js';
20
+
21
+ export function createAnnotationUnparsers(
22
+ getStringIndex: (str: string | undefined) => number,
23
+ getTypeIndex: (typeDescriptor: string | undefined) => number,
24
+ getFieldIndex: (field: DalvikExecutableField) => number,
25
+ getMethodIndex: (method: DalvikExecutableMethod) => number,
26
+ encodedValueUnparser: Unparser<DalvikExecutableEncodedValue, Uint8Array>,
27
+ ) {
28
+ const annotationItemUnparser: Unparser<DalvikExecutableAnnotation, Uint8Array> = async function * (input, unparserContext) {
29
+ const visibilityByte = input.visibility === 'build' ? 0x00 : input.visibility === 'runtime' ? 0x01 : 0x02;
30
+ yield * ubyteUnparser(visibilityByte, unparserContext);
31
+
32
+ const typeIndex = getTypeIndex(input.type);
33
+ yield * uleb128Unparser(typeIndex, unparserContext);
34
+
35
+ yield * uleb128Unparser(input.elements.length, unparserContext);
36
+
37
+ for (const element of input.elements) {
38
+ const nameIndex = getStringIndex(element.name);
39
+ yield * uleb128Unparser(nameIndex, unparserContext);
40
+ yield * encodedValueUnparser(element.value, unparserContext);
41
+ }
42
+ };
43
+
44
+ const annotationSetItemUnparser = (annotationItemOffsetWriteLaters: Array<WriteLater<Uint8Array, number>>): Unparser<DalvikExecutableAnnotation[], Uint8Array> => {
45
+ return async function * (input, unparserContext) {
46
+ yield * alignmentUnparser(4)(undefined, unparserContext);
47
+
48
+ yield * uintUnparser(input.length, unparserContext);
49
+
50
+ for (const annotation of input) {
51
+ const annotationOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
52
+ annotationItemOffsetWriteLaters.push(annotationOffsetWriteLater);
53
+ }
54
+ };
55
+ };
56
+
57
+ const annotationSetRefListUnparser = (annotationSetOffsetWriteLaters: Array<WriteLater<Uint8Array, number> | null>): Unparser<DalvikExecutableAnnotation[][], Uint8Array> => {
58
+ return async function * (input, unparserContext) {
59
+ yield * alignmentUnparser(4)(undefined, unparserContext);
60
+
61
+ yield * uintUnparser(input.length, unparserContext);
62
+
63
+ for (const annotationSet of input) {
64
+ if (annotationSet.length > 0) {
65
+ const annotationSetOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
66
+ annotationSetOffsetWriteLaters.push(annotationSetOffsetWriteLater);
67
+ } else {
68
+ annotationSetOffsetWriteLaters.push(null);
69
+ yield * uintUnparser(0, unparserContext);
70
+ }
71
+ }
72
+ };
73
+ };
74
+
75
+ const annotationsDirectoryItemUnparser = (annotationOffsetWriteLaters: {
76
+ classAnnotationsOffsetWriteLater?: WriteLater<Uint8Array, number>;
77
+ fieldAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number> | null>;
78
+ methodAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number>>;
79
+ parameterAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number>>;
80
+ }): Unparser<DalvikExecutableClassAnnotations, Uint8Array> => {
81
+ return async function * (input, unparserContext) {
82
+ yield * alignmentUnparser(4)(undefined, unparserContext);
83
+
84
+ if (input.classAnnotations.length > 0) {
85
+ const classAnnotationsOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
86
+ annotationOffsetWriteLaters.classAnnotationsOffsetWriteLater = classAnnotationsOffsetWriteLater;
87
+ } else {
88
+ yield * uintUnparser(0, unparserContext);
89
+ }
90
+
91
+ yield * uintUnparser(input.fieldAnnotations.length, unparserContext);
92
+ yield * uintUnparser(input.methodAnnotations.length, unparserContext);
93
+ yield * uintUnparser(input.parameterAnnotations.length, unparserContext);
94
+
95
+ annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters = [];
96
+ for (const fieldAnnotation of input.fieldAnnotations) {
97
+ const fieldIndex = getFieldIndex(fieldAnnotation.field);
98
+ yield * uintUnparser(fieldIndex, unparserContext);
99
+
100
+ if (fieldAnnotation.annotations && fieldAnnotation.annotations.length > 0) {
101
+ const annotationsOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
102
+ annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
103
+ } else {
104
+ annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters.push(null);
105
+ yield * uintUnparser(0, unparserContext);
106
+ }
107
+ }
108
+
109
+ annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters = [];
110
+ for (const methodAnnotation of input.methodAnnotations) {
111
+ const methodIndex = getMethodIndex(methodAnnotation.method);
112
+ yield * uintUnparser(methodIndex, unparserContext);
113
+
114
+ const annotationsOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
115
+ annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
116
+ }
117
+
118
+ annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters = [];
119
+ for (const paramAnnotation of input.parameterAnnotations) {
120
+ const methodIndex = getMethodIndex(paramAnnotation.method);
121
+ yield * uintUnparser(methodIndex, unparserContext);
122
+
123
+ const annotationsOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
124
+ annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters.push(annotationsOffsetWriteLater);
125
+ }
126
+ };
127
+ };
128
+
129
+ return {
130
+ annotationItemUnparser,
131
+ annotationSetItemUnparser,
132
+ annotationSetRefListUnparser,
133
+ annotationsDirectoryItemUnparser,
134
+ };
135
+ }
@@ -0,0 +1,189 @@
1
+ import {
2
+ type DalvikExecutableField,
3
+ type DalvikExecutableMethod,
4
+ type DalvikExecutablePrototype,
5
+ dalvikExecutableFieldEquals,
6
+ dalvikExecutableMethodEquals,
7
+ } from '../dalvikExecutable.js';
8
+
9
+ export class StringPoolBuilder {
10
+ private strings: string[] = [];
11
+ private stringToIndex = new Map<string, number>();
12
+
13
+ add(str: string): number {
14
+ const existing = this.stringToIndex.get(str);
15
+ if (existing !== undefined) {
16
+ return existing;
17
+ }
18
+
19
+ const index = this.strings.length;
20
+ this.strings.push(str);
21
+ this.stringToIndex.set(str, index);
22
+ return index;
23
+ }
24
+
25
+ getIndex(str: string): number | undefined {
26
+ return this.stringToIndex.get(str);
27
+ }
28
+
29
+ getStrings(): string[] {
30
+ return this.strings;
31
+ }
32
+
33
+ size(): number {
34
+ return this.strings.length;
35
+ }
36
+ }
37
+
38
+ export class TypePoolBuilder {
39
+ private types: string[] = [];
40
+ private typeToIndex = new Map<string, number>();
41
+
42
+ add(typeDescriptor: string): number {
43
+ const existing = this.typeToIndex.get(typeDescriptor);
44
+ if (existing !== undefined) {
45
+ return existing;
46
+ }
47
+
48
+ const index = this.types.length;
49
+ this.types.push(typeDescriptor);
50
+ this.typeToIndex.set(typeDescriptor, index);
51
+ return index;
52
+ }
53
+
54
+ getIndex(typeDescriptor: string): number | undefined {
55
+ return this.typeToIndex.get(typeDescriptor);
56
+ }
57
+
58
+ getTypes(): string[] {
59
+ return this.types;
60
+ }
61
+
62
+ size(): number {
63
+ return this.types.length;
64
+ }
65
+ }
66
+
67
+ function prototypeKey(proto: DalvikExecutablePrototype): string {
68
+ return `${proto.shorty}:${proto.returnType}:(${proto.parameters.join(',')})`;
69
+ }
70
+
71
+ export class ProtoPoolBuilder {
72
+ private protos: DalvikExecutablePrototype[] = [];
73
+ private protoToIndex = new Map<string, number>();
74
+
75
+ add(proto: DalvikExecutablePrototype): number {
76
+ const key = prototypeKey(proto);
77
+ const existing = this.protoToIndex.get(key);
78
+ if (existing !== undefined) {
79
+ return existing;
80
+ }
81
+
82
+ const index = this.protos.length;
83
+ this.protos.push(proto);
84
+ this.protoToIndex.set(key, index);
85
+ return index;
86
+ }
87
+
88
+ getIndex(proto: DalvikExecutablePrototype): number | undefined {
89
+ const key = prototypeKey(proto);
90
+ return this.protoToIndex.get(key);
91
+ }
92
+
93
+ getProtos(): DalvikExecutablePrototype[] {
94
+ return this.protos;
95
+ }
96
+
97
+ size(): number {
98
+ return this.protos.length;
99
+ }
100
+ }
101
+
102
+ function fieldKey(field: DalvikExecutableField): string {
103
+ return `${field.class}:${field.type}:${field.name}`;
104
+ }
105
+
106
+ export class FieldPoolBuilder {
107
+ private fields: DalvikExecutableField[] = [];
108
+ private fieldToIndex = new Map<string, number>();
109
+
110
+ add(field: DalvikExecutableField): number {
111
+ const key = fieldKey(field);
112
+ const existing = this.fieldToIndex.get(key);
113
+ if (existing !== undefined) {
114
+ return existing;
115
+ }
116
+
117
+ const index = this.fields.length;
118
+ this.fields.push(field);
119
+ this.fieldToIndex.set(key, index);
120
+ return index;
121
+ }
122
+
123
+ getIndex(field: DalvikExecutableField): number | undefined {
124
+ const key = fieldKey(field);
125
+ return this.fieldToIndex.get(key);
126
+ }
127
+
128
+ getFields(): DalvikExecutableField[] {
129
+ return this.fields;
130
+ }
131
+
132
+ size(): number {
133
+ return this.fields.length;
134
+ }
135
+ }
136
+
137
+ function methodKey(method: DalvikExecutableMethod): string {
138
+ const protoKey = prototypeKey(method.prototype);
139
+ return `${method.class}:${protoKey}:${method.name}`;
140
+ }
141
+
142
+ export class MethodPoolBuilder {
143
+ private methods: DalvikExecutableMethod[] = [];
144
+ private methodToIndex = new Map<string, number>();
145
+
146
+ add(method: DalvikExecutableMethod): number {
147
+ const key = methodKey(method);
148
+ const existing = this.methodToIndex.get(key);
149
+ if (existing !== undefined) {
150
+ return existing;
151
+ }
152
+
153
+ const index = this.methods.length;
154
+ this.methods.push(method);
155
+ this.methodToIndex.set(key, index);
156
+ return index;
157
+ }
158
+
159
+ getIndex(method: DalvikExecutableMethod): number | undefined {
160
+ const key = methodKey(method);
161
+ return this.methodToIndex.get(key);
162
+ }
163
+
164
+ getMethods(): DalvikExecutableMethod[] {
165
+ return this.methods;
166
+ }
167
+
168
+ size(): number {
169
+ return this.methods.length;
170
+ }
171
+ }
172
+
173
+ export interface PoolBuilders {
174
+ stringPool: StringPoolBuilder;
175
+ typePool: TypePoolBuilder;
176
+ protoPool: ProtoPoolBuilder;
177
+ fieldPool: FieldPoolBuilder;
178
+ methodPool: MethodPoolBuilder;
179
+ }
180
+
181
+ export function createPoolBuilders(): PoolBuilders {
182
+ return {
183
+ stringPool: new StringPoolBuilder(),
184
+ typePool: new TypePoolBuilder(),
185
+ protoPool: new ProtoPoolBuilder(),
186
+ fieldPool: new FieldPoolBuilder(),
187
+ methodPool: new MethodPoolBuilder(),
188
+ };
189
+ }
@@ -0,0 +1,297 @@
1
+ import {
2
+ type DalvikExecutable,
3
+ type DalvikExecutableAnnotation,
4
+ type DalvikExecutableClassAnnotations,
5
+ type DalvikExecutableClassData,
6
+ type DalvikExecutableClassDefinition,
7
+ type DalvikExecutableCode,
8
+ type DalvikExecutableDebugInfo,
9
+ type DalvikExecutableEncodedValue,
10
+ type DalvikExecutableField,
11
+ type DalvikExecutableMethod,
12
+ type DalvikExecutableMethodWithAccess,
13
+ type DalvikExecutablePrototype,
14
+ isDalvikExecutableField,
15
+ isDalvikExecutableMethod,
16
+ } from '../dalvikExecutable.js';
17
+ import { type DalvikBytecode } from '../dalvikBytecodeParser.js';
18
+ import { type PoolBuilders } from './poolBuilders.js';
19
+
20
+ export function scanForPoolReferences(
21
+ dalvikExecutable: DalvikExecutable<DalvikBytecode>,
22
+ poolBuilders: PoolBuilders,
23
+ ): void {
24
+ const { stringPool, typePool, protoPool, fieldPool, methodPool } = poolBuilders;
25
+
26
+ for (const classDef of dalvikExecutable.classDefinitions) {
27
+ scanClassDefinition(classDef);
28
+ }
29
+
30
+ function addString(str: string | undefined): void {
31
+ if (str !== undefined) {
32
+ stringPool.add(str);
33
+ }
34
+ }
35
+
36
+ function addType(typeDescriptor: string | undefined): void {
37
+ if (typeDescriptor !== undefined) {
38
+ typePool.add(typeDescriptor);
39
+ stringPool.add(typeDescriptor);
40
+ }
41
+ }
42
+
43
+ function addPrototype(proto: DalvikExecutablePrototype): void {
44
+ protoPool.add(proto);
45
+
46
+ addString(proto.shorty);
47
+ addType(proto.returnType);
48
+
49
+ for (const param of proto.parameters) {
50
+ addType(param);
51
+ }
52
+ }
53
+
54
+ function addField(field: DalvikExecutableField): void {
55
+ fieldPool.add(field);
56
+
57
+ addType(field.class);
58
+ addType(field.type);
59
+ addString(field.name);
60
+ }
61
+
62
+ function addMethod(method: DalvikExecutableMethod): void {
63
+ methodPool.add(method);
64
+
65
+ addType(method.class);
66
+ addPrototype(method.prototype);
67
+ addString(method.name);
68
+ }
69
+
70
+ function scanEncodedValue(value: DalvikExecutableEncodedValue): void {
71
+ const { type, value: innerValue } = value;
72
+
73
+ // Handle primitive types - they don't need pool entries
74
+ if (
75
+ type === 'byte'
76
+ || type === 'short'
77
+ || type === 'char'
78
+ || type === 'int'
79
+ || type === 'long'
80
+ || type === 'float'
81
+ || type === 'double'
82
+ || type === 'boolean'
83
+ || type === 'null'
84
+ || type === 'methodHandle'
85
+ ) {
86
+ return;
87
+ }
88
+
89
+ // Handle types that need pool entries
90
+ if (type === 'string') {
91
+ addString(innerValue);
92
+ return;
93
+ }
94
+
95
+ if (type === 'type') {
96
+ addType(innerValue);
97
+ return;
98
+ }
99
+
100
+ if (type === 'field' || type === 'enum') {
101
+ addField(innerValue);
102
+ return;
103
+ }
104
+
105
+ if (type === 'method') {
106
+ addMethod(innerValue);
107
+ return;
108
+ }
109
+
110
+ if (type === 'methodType') {
111
+ addPrototype(innerValue);
112
+ return;
113
+ }
114
+
115
+ // Handle arrays recursively
116
+ if (type === 'array') {
117
+ for (const element of innerValue) {
118
+ scanEncodedValue(element);
119
+ }
120
+ return;
121
+ }
122
+
123
+ // Handle annotations
124
+ if (type === 'annotation') {
125
+ scanAnnotation(innerValue);
126
+ }
127
+ }
128
+
129
+ function scanAnnotation(annotation: DalvikExecutableAnnotation): void {
130
+ addType(annotation.type);
131
+
132
+ for (const element of annotation.elements) {
133
+ addString(element.name);
134
+ scanEncodedValue(element.value);
135
+ }
136
+ }
137
+
138
+ function scanAnnotations(annotations: undefined | DalvikExecutableClassAnnotations): void {
139
+ if (!annotations) {
140
+ return;
141
+ }
142
+
143
+ for (const annotation of annotations.classAnnotations) {
144
+ scanAnnotation(annotation);
145
+ }
146
+
147
+ for (const fieldAnnotation of annotations.fieldAnnotations) {
148
+ addField(fieldAnnotation.field);
149
+
150
+ if (fieldAnnotation.annotations) {
151
+ for (const annotation of fieldAnnotation.annotations) {
152
+ scanAnnotation(annotation);
153
+ }
154
+ }
155
+ }
156
+
157
+ for (const methodAnnotation of annotations.methodAnnotations) {
158
+ addMethod(methodAnnotation.method);
159
+
160
+ for (const annotation of methodAnnotation.annotations) {
161
+ scanAnnotation(annotation);
162
+ }
163
+ }
164
+
165
+ for (const paramAnnotation of annotations.parameterAnnotations) {
166
+ addMethod(paramAnnotation.method);
167
+
168
+ for (const paramAnnotations of paramAnnotation.annotations) {
169
+ for (const annotation of paramAnnotations) {
170
+ scanAnnotation(annotation);
171
+ }
172
+ }
173
+ }
174
+ }
175
+
176
+ function scanDebugInfo(debugInfo: undefined | DalvikExecutableDebugInfo): void {
177
+ if (!debugInfo) {
178
+ return;
179
+ }
180
+
181
+ for (const paramName of debugInfo.parameterNames) {
182
+ addString(paramName);
183
+ }
184
+
185
+ for (const bytecode of debugInfo.bytecode) {
186
+ if (bytecode.type === 'startLocal' || bytecode.type === 'startLocalExtended') {
187
+ addString(bytecode.name);
188
+ addType(bytecode.type_);
189
+ }
190
+
191
+ if (bytecode.type === 'startLocalExtended') {
192
+ addString(bytecode.signature);
193
+ }
194
+
195
+ if (bytecode.type === 'setFile') {
196
+ addString(bytecode.name);
197
+ }
198
+ }
199
+ }
200
+
201
+ function scanCode(code: undefined | DalvikExecutableCode<DalvikBytecode>): void {
202
+ if (!code) {
203
+ return;
204
+ }
205
+
206
+ scanDebugInfo(code.debugInfo);
207
+
208
+ for (const operation of code.instructions) {
209
+ if ('methodIndex' in operation) {
210
+ const methodIndex = operation.methodIndex as unknown;
211
+ if (isDalvikExecutableMethod(methodIndex)) {
212
+ addMethod(methodIndex);
213
+ }
214
+ }
215
+
216
+ if ('fieldIndex' in operation) {
217
+ const fieldIndex = operation.fieldIndex as unknown;
218
+ if (isDalvikExecutableField(fieldIndex)) {
219
+ addField(fieldIndex);
220
+ }
221
+ }
222
+
223
+ if ('typeIndex' in operation) {
224
+ const typeIndex = operation.typeIndex as unknown;
225
+ if (typeof typeIndex === 'string') {
226
+ addType(typeIndex);
227
+ }
228
+ }
229
+
230
+ if ('stringIndex' in operation) {
231
+ const stringIndex = operation.stringIndex as unknown;
232
+ if (typeof stringIndex === 'string') {
233
+ addString(stringIndex);
234
+ }
235
+ }
236
+
237
+ if ('protoIndex' in operation) {
238
+ const protoIndex = operation.protoIndex as unknown;
239
+ if (typeof protoIndex === 'object' && protoIndex !== null && 'returnType' in protoIndex) {
240
+ addPrototype(protoIndex as DalvikExecutablePrototype);
241
+ }
242
+ }
243
+ }
244
+
245
+ for (const tryBlock of code.tries) {
246
+ for (const handler of tryBlock.handler.handlers) {
247
+ addType(handler.type);
248
+ }
249
+ }
250
+ }
251
+
252
+ function scanMethod(method: DalvikExecutableMethodWithAccess<DalvikBytecode>): void {
253
+ addMethod(method.method);
254
+ scanCode(method.code);
255
+ }
256
+
257
+ function scanClassData(classData: undefined | DalvikExecutableClassData<DalvikBytecode>): void {
258
+ if (!classData) {
259
+ return;
260
+ }
261
+
262
+ for (const field of classData.staticFields) {
263
+ addField(field.field);
264
+ }
265
+
266
+ for (const field of classData.instanceFields) {
267
+ addField(field.field);
268
+ }
269
+
270
+ for (const method of classData.directMethods) {
271
+ scanMethod(method);
272
+ }
273
+
274
+ for (const method of classData.virtualMethods) {
275
+ scanMethod(method);
276
+ }
277
+ }
278
+
279
+ function scanClassDefinition(classDef: DalvikExecutableClassDefinition<DalvikBytecode>): void {
280
+ addType(classDef.class);
281
+ addType(classDef.superclass);
282
+
283
+ for (const iface of classDef.interfaces) {
284
+ addType(iface);
285
+ }
286
+
287
+ addString(classDef.sourceFile);
288
+
289
+ scanAnnotations(classDef.annotations);
290
+
291
+ for (const value of classDef.staticValues) {
292
+ scanEncodedValue(value);
293
+ }
294
+
295
+ scanClassData(classDef.classData);
296
+ }
297
+ }