@futpib/parser 1.0.1 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/copilot-instructions.md +149 -0
- package/.github/workflows/copilot-setup-steps.yml +18 -0
- package/.github/workflows/main.yml +29 -8
- package/.yarn/releases/yarn-4.9.4.cjs +942 -0
- package/.yarnrc.yml +1 -1
- package/build/allSettledStream.js +32 -14
- package/build/allSettledStream.test.js +32 -0
- package/build/androidPackage.d.ts +39 -0
- package/build/androidPackageParser.d.ts +17 -0
- package/build/androidPackageParser.js +185 -0
- package/build/androidPackageParser.test.js +22 -0
- package/build/androidPackageUnparser.d.ts +4 -0
- package/build/androidPackageUnparser.js +94 -0
- package/build/androidPackageUnparser.test.js +26 -0
- package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
- package/build/arbitrarilySlicedAsyncInterable.js +3 -3
- package/build/arbitrarilySlicedAsyncInterator.js +2 -1
- package/build/arbitraryDalvikBytecode.d.ts +4 -0
- package/build/arbitraryDalvikBytecode.js +640 -0
- package/build/arbitraryDalvikExecutable.d.ts +3 -0
- package/build/arbitraryDalvikExecutable.js +282 -0
- package/build/arbitraryDosDateTime.js +1 -0
- package/build/arbitraryZipStream.js +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayParser.test.js +3 -3
- package/build/arrayUnparser.d.ts +1 -1
- package/build/backsmali.d.ts +3 -0
- package/build/backsmali.js +50 -0
- package/build/bsonParser.js +6 -2
- package/build/customInvariant.d.ts +2 -1
- package/build/customInvariant.js +4 -6
- package/build/dalvikBytecodeParser/formatParsers.d.ts +171 -0
- package/build/dalvikBytecodeParser/formatParsers.js +304 -0
- package/build/dalvikBytecodeParser/formatSizes.d.ts +34 -0
- package/build/dalvikBytecodeParser/formatSizes.js +34 -0
- package/build/dalvikBytecodeParser/operationFormats.d.ts +225 -0
- package/build/dalvikBytecodeParser/operationFormats.js +225 -0
- package/build/dalvikBytecodeParser.d.ts +1207 -0
- package/build/dalvikBytecodeParser.js +1289 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.d.ts +152 -0
- package/build/dalvikBytecodeUnparser/formatUnparsers.js +225 -0
- package/build/dalvikBytecodeUnparser.d.ts +3 -0
- package/build/dalvikBytecodeUnparser.js +642 -0
- package/build/dalvikBytecodeUnparser.test.js +25 -0
- package/build/dalvikExecutable.d.ts +215 -0
- package/build/dalvikExecutable.js +56 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
- package/build/dalvikExecutableParser/typeParsers.d.ts +11 -0
- package/build/dalvikExecutableParser/typeParsers.js +39 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +106 -0
- package/build/dalvikExecutableParser/typedNumbers.js +18 -0
- package/build/dalvikExecutableParser.d.ts +5 -0
- package/build/dalvikExecutableParser.js +1757 -0
- package/build/dalvikExecutableParser.test.js +72 -0
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +275 -0
- package/build/dalvikExecutableUnparser/annotationUnparsers.d.ts +14 -0
- package/build/dalvikExecutableUnparser/annotationUnparsers.js +97 -0
- package/build/dalvikExecutableUnparser/poolBuilders.d.ts +49 -0
- package/build/dalvikExecutableUnparser/poolBuilders.js +140 -0
- package/build/dalvikExecutableUnparser/poolScanners.d.ts +4 -0
- package/build/dalvikExecutableUnparser/poolScanners.js +220 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.d.ts +25 -0
- package/build/dalvikExecutableUnparser/sectionUnparsers.js +581 -0
- package/build/dalvikExecutableUnparser/utils.d.ts +10 -0
- package/build/dalvikExecutableUnparser/utils.js +108 -0
- package/build/dalvikExecutableUnparser.d.ts +4 -0
- package/build/dalvikExecutableUnparser.js +406 -0
- package/build/dalvikExecutableUnparser.test.js +31 -0
- package/build/debugLogInputParser.d.ts +4 -0
- package/build/debugLogInputParser.js +16 -0
- package/build/debugLogParser.js +14 -3
- package/build/disjunctionParser.d.ts +2 -1
- package/build/disjunctionParser.js +6 -4
- package/build/elementTerminatedArrayParser.d.ts +3 -0
- package/build/elementTerminatedArrayParser.js +18 -0
- package/build/elementTerminatedArrayParser.test.js +52 -0
- package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
- package/build/elementTerminatedSequenceArrayParser.js +32 -0
- package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
- package/build/elementTerminatedSequenceParser.d.ts +3 -0
- package/build/elementTerminatedSequenceParser.js +27 -0
- package/build/elementTerminatedSequenceParser.test.js +34 -0
- package/build/endOfInputParser.d.ts +1 -1
- package/build/exactElementParser.js +10 -5
- package/build/exactElementSwitchParser.d.ts +3 -0
- package/build/exactElementSwitchParser.js +22 -0
- package/build/exactSequenceParser.d.ts +2 -1
- package/build/exactSequenceParser.js +12 -2
- package/build/fetchCid.d.ts +1 -0
- package/build/fetchCid.js +103 -0
- package/build/fetchCid.test.js +16 -0
- package/build/fixedLengthSequenceParser.d.ts +1 -0
- package/build/fixedLengthSequenceParser.js +18 -1
- package/build/fixedLengthSequenceParser.test.js +41 -0
- package/build/hasExecutable.d.ts +1 -0
- package/build/hasExecutable.js +8 -0
- package/build/highResolutionTimer.d.ts +16 -0
- package/build/highResolutionTimer.js +42 -0
- package/build/inputReader.d.ts +11 -0
- package/build/inputReader.js +37 -0
- package/build/inputReader.test.js +161 -8
- package/build/inputReaderState.d.ts +10 -0
- package/build/inputReaderState.js +16 -0
- package/build/inspect.d.ts +1 -0
- package/build/inspect.js +7 -0
- package/build/javaKeyStoreParser.test.js +8 -8
- package/build/jsonParser.d.ts +2 -0
- package/build/jsonParser.js +19 -22
- package/build/lazyMessageError.d.ts +48 -0
- package/build/lazyMessageError.js +53 -0
- package/build/lazyMessageError.test.d.ts +1 -0
- package/build/lazyMessageError.test.js +15 -0
- package/build/leb128Parser.d.ts +7 -0
- package/build/leb128Parser.js +82 -0
- package/build/leb128Parser.test.d.ts +1 -0
- package/build/leb128Parser.test.js +107 -0
- package/build/lookaheadParser.d.ts +2 -0
- package/build/lookaheadParser.js +14 -0
- package/build/negativeLookaheadParser.js +22 -16
- package/build/negativeLookaheadParser.test.d.ts +1 -0
- package/build/negativeLookaheadParser.test.js +30 -0
- package/build/noStackCaptureOverheadError.d.ts +4 -0
- package/build/noStackCaptureOverheadError.js +9 -0
- package/build/noStackCaptureOverheadError.test.d.ts +1 -0
- package/build/noStackCaptureOverheadError.test.js +15 -0
- package/build/nonEmptyArrayParser.d.ts +2 -0
- package/build/nonEmptyArrayParser.js +32 -0
- package/build/nonEmptyArrayParser.test.d.ts +1 -0
- package/build/nonEmptyArrayParser.test.js +17 -0
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +11 -1
- package/build/parser.js +82 -32
- package/build/parser.test.js +141 -25
- package/build/parserAccessorParser.js +9 -1
- package/build/parserConsumedSequenceParser.d.ts +1 -1
- package/build/parserConsumedSequenceParser.js +21 -16
- package/build/parserContext.d.ts +22 -6
- package/build/parserContext.js +113 -57
- package/build/parserContext.test.js +33 -2
- package/build/parserCreatorCompose.d.ts +1 -0
- package/build/parserCreatorCompose.js +8 -2
- package/build/parserError.d.ts +605 -40
- package/build/parserError.js +98 -53
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.d.ts +15 -0
- package/build/parserInputCompanion.js +38 -0
- package/build/promiseCompose.d.ts +1 -1
- package/build/promiseCompose.js +11 -1
- package/build/promiseSettled.d.ts +1 -0
- package/build/promiseSettled.js +4 -0
- package/build/separatedArrayParser.d.ts +2 -0
- package/build/separatedArrayParser.js +39 -0
- package/build/separatedArrayParser.test.d.ts +1 -0
- package/build/separatedArrayParser.test.js +21 -0
- package/build/separatedNonEmptyArrayParser.d.ts +2 -0
- package/build/separatedNonEmptyArrayParser.js +40 -0
- package/build/separatedNonEmptyArrayParser.test.d.ts +1 -0
- package/build/separatedNonEmptyArrayParser.test.js +66 -0
- package/build/sequenceBuffer.d.ts +10 -0
- package/build/sequenceBuffer.js +54 -2
- package/build/sequenceBuffer.test.js +57 -0
- package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
- package/build/sequenceTerminatedSequenceParser.js +32 -0
- package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
- package/build/sequenceTerminatedSequenceParser.test.js +37 -0
- package/build/sequenceUnparser.d.ts +1 -1
- package/build/skipParser.d.ts +1 -1
- package/build/skipParser.js +4 -2
- package/build/skipToParser.d.ts +2 -0
- package/build/skipToParser.js +11 -0
- package/build/sliceBoundedParser.d.ts +1 -1
- package/build/sliceBoundedParser.js +7 -2
- package/build/sliceBoundedParser.test.js +30 -1
- package/build/smali.d.ts +1 -0
- package/build/smali.js +21 -0
- package/build/smaliParser.d.ts +68 -0
- package/build/smaliParser.js +2081 -0
- package/build/smaliParser.test.d.ts +1 -0
- package/build/smaliParser.test.js +410 -0
- package/build/stringFromAsyncIterable.d.ts +1 -0
- package/build/stringFromAsyncIterable.js +7 -0
- package/build/terminatedArrayParser.d.ts +3 -1
- package/build/terminatedArrayParser.js +79 -2
- package/build/terminatedArrayParser.test.d.ts +1 -0
- package/build/terminatedArrayParser.test.js +131 -0
- package/build/toAsyncIterable.d.ts +1 -0
- package/build/toAsyncIterable.js +7 -0
- package/build/toAsyncIterator.d.ts +1 -0
- package/build/toAsyncIterator.js +33 -0
- package/build/tupleParser.d.ts +4 -0
- package/build/tupleParser.js +1 -5
- package/build/unionParser.d.ts +2 -1
- package/build/unionParser.js +29 -14
- package/build/unionParser.test.d.ts +1 -0
- package/build/unionParser.test.js +60 -0
- package/build/unparser.d.ts +3 -3
- package/build/unparser.js +6 -4
- package/build/unparser.test.js +7 -19
- package/build/unparserContext.d.ts +2 -2
- package/build/unparserContext.js +2 -3
- package/build/unparserError.d.ts +2 -1
- package/build/unparserError.js +2 -1
- package/build/unparserImplementationInvariant.d.ts +1 -1
- package/build/unparserOutputCompanion.d.ts +1 -1
- package/build/unparserOutputCompanion.js +1 -1
- package/build/zipParser.d.ts +7 -2
- package/build/zipParser.js +36 -12
- package/build/zipUnparser.d.ts +7 -4
- package/build/zipUnparser.js +64 -45
- package/build/zipUnparser.test.js +15 -15
- package/package.json +33 -24
- package/src/allSettledStream.test.ts +40 -0
- package/src/allSettledStream.ts +47 -15
- package/src/androidPackage.ts +48 -0
- package/src/androidPackageParser.test.ts +27 -0
- package/src/{apkParser.test.ts.md → androidPackageParser.test.ts.md} +4 -4
- package/src/androidPackageParser.test.ts.snap +0 -0
- package/src/androidPackageParser.ts +398 -0
- package/src/androidPackageUnparser.test.ts +34 -0
- package/src/androidPackageUnparser.ts +126 -0
- package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
- package/src/arbitrarilySlicedAsyncInterator.ts +4 -4
- package/src/arbitraryDalvikBytecode.ts +992 -0
- package/src/arbitraryDalvikExecutable.ts +434 -0
- package/src/arbitraryDosDateTime.ts +1 -0
- package/src/arbitraryZipStream.ts +1 -1
- package/src/arrayParser.test.ts +3 -3
- package/src/arrayParser.ts +2 -2
- package/src/arrayUnparser.ts +2 -2
- package/src/backsmali.ts +74 -0
- package/src/bsonParser.test.ts +12 -14
- package/src/bsonParser.ts +13 -2
- package/src/customInvariant.ts +8 -12
- package/src/dalvikBytecodeParser/formatParsers.ts +780 -0
- package/src/dalvikBytecodeParser/formatSizes.ts +35 -0
- package/src/dalvikBytecodeParser/operationFormats.ts +226 -0
- package/src/dalvikBytecodeParser.ts +2873 -0
- package/src/dalvikBytecodeUnparser/formatUnparsers.ts +442 -0
- package/src/dalvikBytecodeUnparser.test.ts +44 -0
- package/src/dalvikBytecodeUnparser.ts +758 -0
- package/src/dalvikExecutable.ts +282 -0
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
- package/src/dalvikExecutableParser/typeParsers.ts +74 -0
- package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
- package/src/dalvikExecutableParser.test.ts +89 -0
- package/src/dalvikExecutableParser.test.ts.md +634 -0
- package/src/dalvikExecutableParser.test.ts.snap +0 -0
- package/src/dalvikExecutableParser.ts +3245 -0
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +363 -0
- package/src/dalvikExecutableUnparser/annotationUnparsers.ts +135 -0
- package/src/dalvikExecutableUnparser/poolBuilders.ts +189 -0
- package/src/dalvikExecutableUnparser/poolScanners.ts +297 -0
- package/src/dalvikExecutableUnparser/sectionUnparsers.ts +683 -0
- package/src/dalvikExecutableUnparser/utils.ts +149 -0
- package/src/dalvikExecutableUnparser.test.ts +57 -0
- package/src/dalvikExecutableUnparser.ts +581 -0
- package/src/debugLogInputParser.ts +28 -0
- package/src/debugLogParser.ts +19 -3
- package/src/disjunctionParser.ts +12 -7
- package/src/elementTerminatedArrayParser.test.ts +99 -0
- package/src/elementTerminatedArrayParser.ts +31 -0
- package/src/elementTerminatedSequenceArrayParser.test.ts +52 -0
- package/src/elementTerminatedSequenceArrayParser.ts +52 -0
- package/src/elementTerminatedSequenceParser.test.ts +52 -0
- package/src/elementTerminatedSequenceParser.ts +43 -0
- package/src/endOfInputParser.ts +1 -1
- package/src/exactElementParser.ts +17 -11
- package/src/exactElementSwitchParser.ts +41 -0
- package/src/exactSequenceParser.ts +23 -2
- package/src/fetchCid.test.ts +20 -0
- package/src/fetchCid.ts +121 -0
- package/src/fixedLengthSequenceParser.test.ts +75 -0
- package/src/fixedLengthSequenceParser.ts +28 -1
- package/src/hasExecutable.ts +11 -0
- package/src/highResolutionTimer.ts +49 -0
- package/src/inputReader.test.ts +204 -8
- package/src/inputReader.ts +76 -3
- package/src/inputReaderState.ts +33 -0
- package/src/inspect.ts +9 -0
- package/src/javaKeyStoreParser.test.ts +12 -15
- package/src/javaKeyStoreParser.ts +2 -6
- package/src/jsonParser.test.ts +2 -4
- package/src/jsonParser.ts +46 -62
- package/src/lazyMessageError.test.ts +21 -0
- package/src/lazyMessageError.ts +88 -0
- package/src/leb128Parser.test.ts +173 -0
- package/src/leb128Parser.ts +125 -0
- package/src/lookaheadParser.ts +19 -0
- package/src/negativeLookaheadParser.test.ts +49 -0
- package/src/negativeLookaheadParser.ts +27 -15
- package/src/noStackCaptureOverheadError.test.ts +17 -0
- package/src/noStackCaptureOverheadError.ts +12 -0
- package/src/nonEmptyArrayParser.test.ts +21 -0
- package/src/nonEmptyArrayParser.ts +44 -0
- package/src/optionalParser.ts +3 -2
- package/src/parser.test.ts +203 -31
- package/src/parser.test.ts.md +34 -27
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +172 -45
- package/src/parserAccessorParser.ts +12 -2
- package/src/parserConsumedSequenceParser.ts +26 -17
- package/src/parserContext.test.ts +37 -2
- package/src/parserContext.ts +185 -79
- package/src/parserCreatorCompose.ts +20 -2
- package/src/parserError.ts +144 -61
- package/src/parserImplementationInvariant.ts +3 -3
- package/src/parserInputCompanion.ts +55 -0
- package/src/promiseCompose.ts +17 -3
- package/src/promiseSettled.ts +6 -0
- package/src/separatedArrayParser.test.ts +34 -0
- package/src/separatedArrayParser.ts +55 -0
- package/src/separatedNonEmptyArrayParser.test.ts +117 -0
- package/src/separatedNonEmptyArrayParser.ts +61 -0
- package/src/sequenceBuffer.test.ts +70 -0
- package/src/sequenceBuffer.ts +88 -2
- package/src/sequenceTerminatedSequenceParser.test.ts +58 -0
- package/src/sequenceTerminatedSequenceParser.ts +62 -0
- package/src/sequenceUnparser.ts +2 -2
- package/src/skipParser.ts +7 -5
- package/src/skipToParser.ts +16 -0
- package/src/sliceBoundedParser.test.ts +35 -1
- package/src/sliceBoundedParser.ts +19 -1
- package/src/smali.ts +29 -0
- package/src/smaliParser.test.ts +443 -0
- package/src/smaliParser.test.ts.md +3907 -0
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +3348 -0
- package/src/stringFromAsyncIterable.ts +9 -0
- package/src/terminatedArrayParser.test.ts +258 -0
- package/src/terminatedArrayParser.ts +109 -6
- package/src/toAsyncIterable.ts +7 -0
- package/src/toAsyncIterator.ts +48 -0
- package/src/tupleParser.ts +8 -5
- package/src/uint8Array.ts +2 -3
- package/src/unionParser.test.ts +78 -0
- package/src/unionParser.ts +47 -21
- package/src/unparser.test.ts +18 -34
- package/src/unparser.ts +13 -9
- package/src/unparserContext.ts +9 -13
- package/src/unparserError.ts +2 -1
- package/src/unparserImplementationInvariant.ts +1 -1
- package/src/unparserOutputCompanion.ts +1 -1
- package/src/zip.ts +2 -6
- package/src/zipParser.ts +71 -20
- package/src/zipUnparser.test.ts +19 -19
- package/src/zipUnparser.ts +139 -90
- package/tsconfig.json +7 -1
- package/xo.config.ts +15 -0
- package/.yarn/releases/yarn-4.5.3.cjs +0 -934
- package/build/apk.d.ts +0 -39
- package/build/apkParser.d.ts +0 -16
- package/build/apkParser.js +0 -164
- package/build/apkParser.test.js +0 -22
- package/build/apkUnparser.d.ts +0 -4
- package/build/apkUnparser.js +0 -90
- package/build/apkUnparser.test.js +0 -26
- package/build/arbitraryDosDate.d.ts +0 -2
- package/build/arbitraryDosDate.js +0 -8
- package/build/arbitraryZipEntry.d.ts +0 -3
- package/build/arbitraryZipEntry.js +0 -26
- package/build/createDisjunctionParser.d.ts +0 -2
- package/build/createDisjunctionParser.js +0 -47
- package/build/createExactParser.d.ts +0 -2
- package/build/createExactParser.js +0 -12
- package/build/createSequentialUnionParser.d.ts +0 -2
- package/build/createSequentialUnionParser.js +0 -69
- package/build/fixedLengthChunkParser.d.ts +0 -2
- package/build/fixedLengthChunkParser.js +0 -12
- package/build/fixedLengthParser.d.ts +0 -2
- package/build/fixedLengthParser.js +0 -12
- package/build/inputChunkBuffer.d.ts +0 -15
- package/build/inputChunkBuffer.js +0 -40
- package/build/inputChunkBuffer.test.js +0 -34
- package/build/inputCompanion.d.ts +0 -18
- package/build/inputCompanion.js +0 -28
- package/build/invariantDefined.d.ts +0 -1
- package/build/invariantDefined.js +0 -5
- package/build/invariantIdentity.d.ts +0 -3
- package/build/invariantIdentity.js +0 -5
- package/build/javaKeystoreParser.d.ts +0 -2
- package/build/javaKeystoreParser.js +0 -7
- package/build/jsonParser2.d.ts +0 -3
- package/build/jsonParser2.js +0 -52
- package/build/jsonParser2.test.js +0 -22
- package/build/negativeLookahead.d.ts +0 -2
- package/build/negativeLookahead.js +0 -18
- package/build/parserCompose.d.ts +0 -3
- package/build/parserCompose.js +0 -7
- package/build/parserImplementationInvariantInvariant.d.ts +0 -3
- package/build/parserImplementationInvariantInvariant.js +0 -15
- package/build/parserInvariant.d.ts +0 -4
- package/build/parserInvariant.js +0 -11
- package/build/promiseFish.d.ts +0 -1
- package/build/promiseFish.js +0 -3
- package/build/sequenceParser.d.ts +0 -3
- package/build/sequenceParser.js +0 -10
- package/build/terminatedSequenceParser.d.ts +0 -2
- package/build/terminatedSequenceParser.js +0 -24
- package/build/unparserInputCompanion.d.ts +0 -15
- package/build/unparserInputCompanion.js +0 -13
- package/build/zipEntry.d.ts +0 -28
- package/build/zipFile.d.ts +0 -32
- package/build/zipFileEntry.d.ts +0 -6
- package/src/apk.ts +0 -48
- package/src/apkParser.test.ts +0 -30
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +0 -392
- package/src/apkUnparser.test.ts +0 -37
- package/src/apkUnparser.ts +0 -120
- package/src/invariantDefined.ts +0 -6
- package/src/invariantIdentity.ts +0 -8
- /package/build/{apk.js → androidPackage.js} +0 -0
- /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
- /package/build/{apkUnparser.test.d.ts → androidPackageUnparser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.d.ts → dalvikBytecodeUnparser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.js → dalvikExecutableParser.test.d.ts} +0 -0
- /package/build/{inputChunkBuffer.test.d.ts → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
- /package/build/{jsonParser2.test.d.ts → dalvikExecutableUnparser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.js → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
- /package/build/{zipEntry.js → elementTerminatedSequenceParser.test.d.ts} +0 -0
- /package/build/{zipFile.js → fetchCid.test.d.ts} +0 -0
- /package/build/{zipFileEntry.js → fixedLengthSequenceParser.test.d.ts} +0 -0
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
import { type Unparser } from './unparser.js';
|
|
2
|
+
import { type DalvikExecutable, type DalvikExecutableClassDefinition, type DalvikExecutableCode, type DalvikExecutableDebugInfo, type DalvikExecutableAnnotation, type DalvikExecutableEncodedValue } from './dalvikExecutable.js';
|
|
3
|
+
import { type DalvikBytecode } from './dalvikBytecodeParser.js';
|
|
4
|
+
import { uintUnparser, ushortUnparser } from './dalvikBytecodeUnparser/formatUnparsers.js';
|
|
5
|
+
import { createPoolBuilders } from './dalvikExecutableUnparser/poolBuilders.js';
|
|
6
|
+
import { scanForPoolReferences } from './dalvikExecutableUnparser/poolScanners.js';
|
|
7
|
+
import { createSectionUnparsers } from './dalvikExecutableUnparser/sectionUnparsers.js';
|
|
8
|
+
import { createAnnotationUnparsers } from './dalvikExecutableUnparser/annotationUnparsers.js';
|
|
9
|
+
import { alignmentUnparser, calculateAdler32, calculateSHA1 } from './dalvikExecutableUnparser/utils.js';
|
|
10
|
+
import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
|
|
11
|
+
import { runUnparser } from './unparser.js';
|
|
12
|
+
import { uint8ArrayUnparserOutputCompanion } from './unparserOutputCompanion.js';
|
|
13
|
+
import { WriteLater } from './unparserContext.js';
|
|
14
|
+
|
|
15
|
+
async function* yieldAndCapture<T>(gen: AsyncIterable<T, T>): AsyncIterable<T, T> {
|
|
16
|
+
let value: T | undefined;
|
|
17
|
+
for await (value of gen) {
|
|
18
|
+
yield value;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return value!;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Helper function to write a pool size and reserve space for its offset.
|
|
26
|
+
* Returns a WriteLater for the offset.
|
|
27
|
+
*/
|
|
28
|
+
async function* writePoolHeader(
|
|
29
|
+
size: number,
|
|
30
|
+
unparserContext: Parameters<Unparser<any, Uint8Array>>[1],
|
|
31
|
+
) {
|
|
32
|
+
yield * uintUnparser(size, unparserContext);
|
|
33
|
+
const offsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
34
|
+
return offsetWriteLater;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Helper function to conditionally write an offset placeholder.
|
|
39
|
+
* Returns WriteLater if condition is true, otherwise writes 0 and returns undefined.
|
|
40
|
+
*/
|
|
41
|
+
async function* writeConditionalOffset(
|
|
42
|
+
condition: boolean,
|
|
43
|
+
unparserContext: Parameters<Unparser<any, Uint8Array>>[1],
|
|
44
|
+
) {
|
|
45
|
+
if (condition) {
|
|
46
|
+
const offsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
47
|
+
return offsetWriteLater;
|
|
48
|
+
} else {
|
|
49
|
+
yield * uintUnparser(0, unparserContext);
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Helper class to track offset and count for a section of items.
|
|
56
|
+
* Records the offset of the first item and counts items as they are written.
|
|
57
|
+
*/
|
|
58
|
+
class SectionTracker {
|
|
59
|
+
private _offset = 0;
|
|
60
|
+
private _count = 0;
|
|
61
|
+
|
|
62
|
+
recordItem(position: number): void {
|
|
63
|
+
if (this._count === 0) {
|
|
64
|
+
this._offset = position;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
this._count++;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
get offset(): number {
|
|
71
|
+
return this._offset;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
get count(): number {
|
|
75
|
+
return this._count;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const dalvikExecutableUnparser: Unparser<DalvikExecutable<DalvikBytecode>, Uint8Array> = async function * (input, unparserContext) {
|
|
80
|
+
const poolBuilders = createPoolBuilders();
|
|
81
|
+
|
|
82
|
+
scanForPoolReferences(input, poolBuilders);
|
|
83
|
+
|
|
84
|
+
const sectionUnparsers = createSectionUnparsers(poolBuilders);
|
|
85
|
+
const annotationUnparsers = createAnnotationUnparsers(
|
|
86
|
+
sectionUnparsers.getStringIndex,
|
|
87
|
+
sectionUnparsers.getTypeIndex,
|
|
88
|
+
sectionUnparsers.getFieldIndex,
|
|
89
|
+
sectionUnparsers.getMethodIndex,
|
|
90
|
+
sectionUnparsers.encodedValueUnparser,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const { stringPool, typePool, protoPool, fieldPool, methodPool } = poolBuilders;
|
|
94
|
+
|
|
95
|
+
const magicBytes = new Uint8Array([ 0x64, 0x65, 0x78, 0x0A ]);
|
|
96
|
+
yield magicBytes;
|
|
97
|
+
|
|
98
|
+
const versionBytes = new Uint8Array([ 0x30, 0x33, 0x35, 0x00 ]);
|
|
99
|
+
yield versionBytes;
|
|
100
|
+
|
|
101
|
+
const checksumWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
102
|
+
const sha1WriteLater = yield * yieldAndCapture(unparserContext.writeLater(20));
|
|
103
|
+
const fileSizeWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
104
|
+
|
|
105
|
+
yield * uintUnparser(0x70, unparserContext);
|
|
106
|
+
|
|
107
|
+
yield * uintUnparser(0x12345678, unparserContext);
|
|
108
|
+
|
|
109
|
+
const linkData = input.link;
|
|
110
|
+
const hasLink = !!(linkData && linkData.length > 0);
|
|
111
|
+
if (hasLink) {
|
|
112
|
+
yield * uintUnparser(linkData.length, unparserContext);
|
|
113
|
+
} else {
|
|
114
|
+
yield * uintUnparser(0, unparserContext);
|
|
115
|
+
}
|
|
116
|
+
const linkOffsetWriteLater = yield * writeConditionalOffset(hasLink, unparserContext);
|
|
117
|
+
|
|
118
|
+
const mapOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
119
|
+
|
|
120
|
+
const stringIdsOffsetWriteLater = yield * writePoolHeader(stringPool.size(), unparserContext);
|
|
121
|
+
const typeIdsOffsetWriteLater = yield * writePoolHeader(typePool.size(), unparserContext);
|
|
122
|
+
const protoIdsOffsetWriteLater = yield * writePoolHeader(protoPool.size(), unparserContext);
|
|
123
|
+
const fieldIdsOffsetWriteLater = yield * writePoolHeader(fieldPool.size(), unparserContext);
|
|
124
|
+
const methodIdsOffsetWriteLater = yield * writePoolHeader(methodPool.size(), unparserContext);
|
|
125
|
+
const classDefsOffsetWriteLater = yield * writePoolHeader(input.classDefinitions.length, unparserContext);
|
|
126
|
+
|
|
127
|
+
const dataOffsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
128
|
+
const dataSizeWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
129
|
+
|
|
130
|
+
const stringIdsOffset = unparserContext.position;
|
|
131
|
+
yield * unparserContext.writeEarlier(stringIdsOffsetWriteLater, uintUnparser, stringIdsOffset);
|
|
132
|
+
|
|
133
|
+
const stringDataOffsetWriteLaters: Array<WriteLater<Uint8Array, number>> = [];
|
|
134
|
+
for (let i = 0; i < stringPool.size(); i++) {
|
|
135
|
+
const offsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
136
|
+
stringDataOffsetWriteLaters.push(offsetWriteLater);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const typeIdsOffset = unparserContext.position;
|
|
140
|
+
yield * unparserContext.writeEarlier(typeIdsOffsetWriteLater, uintUnparser, typeIdsOffset);
|
|
141
|
+
|
|
142
|
+
for (const type of typePool.getTypes()) {
|
|
143
|
+
const stringIndex = sectionUnparsers.getStringIndex(type);
|
|
144
|
+
yield * uintUnparser(stringIndex, unparserContext);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const protoIdsOffset = unparserContext.position;
|
|
148
|
+
yield * unparserContext.writeEarlier(protoIdsOffsetWriteLater, uintUnparser, protoIdsOffset);
|
|
149
|
+
|
|
150
|
+
const protoParameterListOffsetWriteLaters: Array<WriteLater<Uint8Array, number> | null> = [];
|
|
151
|
+
for (const proto of protoPool.getProtos()) {
|
|
152
|
+
const shortyIndex = sectionUnparsers.getStringIndex(proto.shorty);
|
|
153
|
+
const returnTypeIndex = sectionUnparsers.getTypeIndex(proto.returnType);
|
|
154
|
+
|
|
155
|
+
yield * uintUnparser(shortyIndex, unparserContext);
|
|
156
|
+
yield * uintUnparser(returnTypeIndex, unparserContext);
|
|
157
|
+
|
|
158
|
+
if (proto.parameters.length > 0) {
|
|
159
|
+
const offsetWriteLater = yield * yieldAndCapture(unparserContext.writeLater(4));
|
|
160
|
+
protoParameterListOffsetWriteLaters.push(offsetWriteLater);
|
|
161
|
+
} else {
|
|
162
|
+
protoParameterListOffsetWriteLaters.push(null);
|
|
163
|
+
yield * uintUnparser(0, unparserContext);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
const fieldIdsOffset = unparserContext.position;
|
|
168
|
+
yield * unparserContext.writeEarlier(fieldIdsOffsetWriteLater, uintUnparser, fieldIdsOffset);
|
|
169
|
+
|
|
170
|
+
for (const field of fieldPool.getFields()) {
|
|
171
|
+
yield * sectionUnparsers.fieldIdUnparser(field, unparserContext);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const methodIdsOffset = unparserContext.position;
|
|
175
|
+
yield * unparserContext.writeEarlier(methodIdsOffsetWriteLater, uintUnparser, methodIdsOffset);
|
|
176
|
+
|
|
177
|
+
for (const method of methodPool.getMethods()) {
|
|
178
|
+
yield * sectionUnparsers.methodIdUnparser(method, unparserContext);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const classDefsOffset = unparserContext.position;
|
|
182
|
+
yield * unparserContext.writeEarlier(classDefsOffsetWriteLater, uintUnparser, classDefsOffset);
|
|
183
|
+
|
|
184
|
+
const classDefItems: Array<{
|
|
185
|
+
interfacesOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
186
|
+
annotationsOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
187
|
+
classDataOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
188
|
+
staticValuesOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
189
|
+
}> = [];
|
|
190
|
+
|
|
191
|
+
for (const classDef of input.classDefinitions) {
|
|
192
|
+
const classTypeIndex = sectionUnparsers.getTypeIndex(classDef.class);
|
|
193
|
+
const accessFlags = sectionUnparsers.accessFlagsToNumber(classDef.accessFlags);
|
|
194
|
+
const superclassTypeIndex = sectionUnparsers.getTypeIndex(classDef.superclass);
|
|
195
|
+
|
|
196
|
+
yield * uintUnparser(classTypeIndex, unparserContext);
|
|
197
|
+
yield * uintUnparser(accessFlags, unparserContext);
|
|
198
|
+
yield * uintUnparser(superclassTypeIndex, unparserContext);
|
|
199
|
+
|
|
200
|
+
const interfacesOffsetWriteLater = yield * writeConditionalOffset(
|
|
201
|
+
classDef.interfaces.length > 0,
|
|
202
|
+
unparserContext,
|
|
203
|
+
);
|
|
204
|
+
|
|
205
|
+
const sourceFileIndex = classDef.sourceFile ? sectionUnparsers.getStringIndex(classDef.sourceFile) : 0xFFFFFFFF;
|
|
206
|
+
yield * uintUnparser(sourceFileIndex, unparserContext);
|
|
207
|
+
|
|
208
|
+
const annotationsOffsetWriteLater = yield * writeConditionalOffset(
|
|
209
|
+
!!classDef.annotations,
|
|
210
|
+
unparserContext,
|
|
211
|
+
);
|
|
212
|
+
|
|
213
|
+
const hasClassData = !!(classDef.classData && (
|
|
214
|
+
classDef.classData.staticFields.length > 0 ||
|
|
215
|
+
classDef.classData.instanceFields.length > 0 ||
|
|
216
|
+
classDef.classData.directMethods.length > 0 ||
|
|
217
|
+
classDef.classData.virtualMethods.length > 0
|
|
218
|
+
));
|
|
219
|
+
const classDataOffsetWriteLater = yield * writeConditionalOffset(
|
|
220
|
+
hasClassData,
|
|
221
|
+
unparserContext,
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const staticValuesOffsetWriteLater = yield * writeConditionalOffset(
|
|
225
|
+
classDef.staticValues.length > 0,
|
|
226
|
+
unparserContext,
|
|
227
|
+
);
|
|
228
|
+
|
|
229
|
+
classDefItems.push({
|
|
230
|
+
interfacesOffsetWriteLater,
|
|
231
|
+
annotationsOffsetWriteLater,
|
|
232
|
+
classDataOffsetWriteLater,
|
|
233
|
+
staticValuesOffsetWriteLater,
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const dataOffset = unparserContext.position;
|
|
238
|
+
yield * unparserContext.writeEarlier(dataOffsetWriteLater, uintUnparser, dataOffset);
|
|
239
|
+
|
|
240
|
+
for (let i = 0; i < stringPool.size(); i++) {
|
|
241
|
+
const stringDataOffset = unparserContext.position;
|
|
242
|
+
yield * unparserContext.writeEarlier(stringDataOffsetWriteLaters[i], uintUnparser, stringDataOffset);
|
|
243
|
+
yield * sectionUnparsers.stringDataUnparser(stringPool.getStrings()[i], unparserContext);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const typeListItemsTracker = new SectionTracker();
|
|
247
|
+
|
|
248
|
+
for (let i = 0; i < protoPool.size(); i++) {
|
|
249
|
+
const proto = protoPool.getProtos()[i];
|
|
250
|
+
if (proto.parameters.length > 0) {
|
|
251
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
252
|
+
typeListItemsTracker.recordItem(unparserContext.position);
|
|
253
|
+
|
|
254
|
+
const paramListOffset = unparserContext.position;
|
|
255
|
+
const writeLater = protoParameterListOffsetWriteLaters[i];
|
|
256
|
+
if (writeLater) {
|
|
257
|
+
yield * unparserContext.writeEarlier(writeLater, uintUnparser, paramListOffset);
|
|
258
|
+
}
|
|
259
|
+
yield * sectionUnparsers.typeListUnparser(proto.parameters, unparserContext);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Track classDataItem, codeItem, and debugInfoItem for later writing
|
|
264
|
+
// Collect data to write items grouped by type (required by DEX format)
|
|
265
|
+
const classDataToWrite: Array<{
|
|
266
|
+
classDef: DalvikExecutableClassDefinition<DalvikBytecode>;
|
|
267
|
+
classDefItem: {
|
|
268
|
+
interfacesOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
269
|
+
annotationsOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
270
|
+
classDataOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
271
|
+
staticValuesOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
272
|
+
};
|
|
273
|
+
classIdx: number;
|
|
274
|
+
}> = [];
|
|
275
|
+
const codeToWrite: Array<{ code: DalvikExecutableCode<DalvikBytecode> }> = [];
|
|
276
|
+
const debugInfoToWrite: Array<{ debugInfo: DalvikExecutableDebugInfo; offsetWriteLater: WriteLater<Uint8Array, number> }> = [];
|
|
277
|
+
|
|
278
|
+
// First pass: collect type lists, encoded arrays, and classData/code/debugInfo to write
|
|
279
|
+
const encodedArrayItemsTracker = new SectionTracker();
|
|
280
|
+
|
|
281
|
+
type TypeListToWrite = {
|
|
282
|
+
interfaces: string[];
|
|
283
|
+
offsetWriteLater: WriteLater<Uint8Array, number>;
|
|
284
|
+
};
|
|
285
|
+
const typeListsToWrite: TypeListToWrite[] = [];
|
|
286
|
+
|
|
287
|
+
type EncodedArrayToWrite = {
|
|
288
|
+
staticValues: DalvikExecutableEncodedValue[];
|
|
289
|
+
offsetWriteLater: WriteLater<Uint8Array, number>;
|
|
290
|
+
};
|
|
291
|
+
const encodedArraysToWrite: EncodedArrayToWrite[] = [];
|
|
292
|
+
|
|
293
|
+
for (let classIdx = 0; classIdx < input.classDefinitions.length; classIdx++) {
|
|
294
|
+
const classDef = input.classDefinitions[classIdx];
|
|
295
|
+
const classDefItem = classDefItems[classIdx];
|
|
296
|
+
|
|
297
|
+
if (classDef.interfaces.length > 0 && classDefItem.interfacesOffsetWriteLater) {
|
|
298
|
+
typeListsToWrite.push({
|
|
299
|
+
interfaces: classDef.interfaces,
|
|
300
|
+
offsetWriteLater: classDefItem.interfacesOffsetWriteLater,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (classDef.staticValues.length > 0 && classDefItem.staticValuesOffsetWriteLater) {
|
|
305
|
+
encodedArraysToWrite.push({
|
|
306
|
+
staticValues: classDef.staticValues,
|
|
307
|
+
offsetWriteLater: classDefItem.staticValuesOffsetWriteLater,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (classDef.classData && classDefItem.classDataOffsetWriteLater) {
|
|
312
|
+
classDataToWrite.push({ classDef, classDefItem, classIdx });
|
|
313
|
+
// Collect code items from this class
|
|
314
|
+
const allMethods = [ ...classDef.classData.directMethods, ...classDef.classData.virtualMethods ];
|
|
315
|
+
for (const method of allMethods) {
|
|
316
|
+
if (method.code) {
|
|
317
|
+
codeToWrite.push({ code: method.code });
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Second pass: write all type lists (interfaces)
|
|
324
|
+
for (const typeList of typeListsToWrite) {
|
|
325
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
326
|
+
typeListItemsTracker.recordItem(unparserContext.position);
|
|
327
|
+
|
|
328
|
+
const typeListOffset = unparserContext.position;
|
|
329
|
+
yield * unparserContext.writeEarlier(typeList.offsetWriteLater, uintUnparser, typeListOffset);
|
|
330
|
+
yield * sectionUnparsers.typeListUnparser(typeList.interfaces, unparserContext);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Third pass: write all encoded arrays (static values)
|
|
334
|
+
for (const encodedArray of encodedArraysToWrite) {
|
|
335
|
+
encodedArrayItemsTracker.recordItem(unparserContext.position);
|
|
336
|
+
|
|
337
|
+
const encodedArrayOffset = unparserContext.position;
|
|
338
|
+
yield * unparserContext.writeEarlier(encodedArray.offsetWriteLater, uintUnparser, encodedArrayOffset);
|
|
339
|
+
yield * sectionUnparsers.encodedArrayUnparser(encodedArray.staticValues, unparserContext);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Fourth pass: write all code items (grouped) and build offset map
|
|
343
|
+
const codeItemsTracker = new SectionTracker();
|
|
344
|
+
const codeOffsetMap = new Map();
|
|
345
|
+
|
|
346
|
+
for (const { code } of codeToWrite) {
|
|
347
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
348
|
+
codeItemsTracker.recordItem(unparserContext.position);
|
|
349
|
+
|
|
350
|
+
const codeOffset = unparserContext.position;
|
|
351
|
+
codeOffsetMap.set(code, codeOffset);
|
|
352
|
+
|
|
353
|
+
let debugInfoOffsetWriteLater;
|
|
354
|
+
yield * sectionUnparsers.codeItemUnparser(result => {
|
|
355
|
+
debugInfoOffsetWriteLater = result.debugInfoOffsetWriteLater;
|
|
356
|
+
})(code, unparserContext);
|
|
357
|
+
|
|
358
|
+
if (code.debugInfo && debugInfoOffsetWriteLater) {
|
|
359
|
+
debugInfoToWrite.push({ debugInfo: code.debugInfo, offsetWriteLater: debugInfoOffsetWriteLater });
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Fifth pass: write all classData items (grouped) using the offset map
|
|
364
|
+
const classDataItemsTracker = new SectionTracker();
|
|
365
|
+
|
|
366
|
+
for (const { classDef, classDefItem } of classDataToWrite) {
|
|
367
|
+
classDataItemsTracker.recordItem(unparserContext.position);
|
|
368
|
+
|
|
369
|
+
const classDataOffset = unparserContext.position;
|
|
370
|
+
if (classDefItem.classDataOffsetWriteLater && classDef.classData) {
|
|
371
|
+
yield * unparserContext.writeEarlier(classDefItem.classDataOffsetWriteLater, uintUnparser, classDataOffset);
|
|
372
|
+
|
|
373
|
+
yield * sectionUnparsers.classDataUnparser(codeOffsetMap)(classDef.classData, unparserContext);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Sixth pass: write all debugInfo items (grouped)
|
|
378
|
+
const debugInfoItemsTracker = new SectionTracker();
|
|
379
|
+
|
|
380
|
+
for (const { debugInfo, offsetWriteLater } of debugInfoToWrite) {
|
|
381
|
+
debugInfoItemsTracker.recordItem(unparserContext.position);
|
|
382
|
+
|
|
383
|
+
const debugInfoOffset = unparserContext.position;
|
|
384
|
+
yield * unparserContext.writeEarlier(offsetWriteLater, uintUnparser, debugInfoOffset);
|
|
385
|
+
yield * sectionUnparsers.debugInfoUnparser(debugInfo, unparserContext);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Seventh pass: write annotations
|
|
389
|
+
const annotationsDirectoryItemsTracker = new SectionTracker();
|
|
390
|
+
const annotationSetItemsTracker = new SectionTracker();
|
|
391
|
+
const annotationSetRefListItemsTracker = new SectionTracker();
|
|
392
|
+
const annotationItemsTracker = new SectionTracker();
|
|
393
|
+
|
|
394
|
+
// Collect annotation sets and items to write later
|
|
395
|
+
type AnnotationSetToWrite = {
|
|
396
|
+
annotations: DalvikExecutableAnnotation[];
|
|
397
|
+
setOffsetWriteLater: WriteLater<Uint8Array, number>;
|
|
398
|
+
itemOffsetWriteLaters: Array<WriteLater<Uint8Array, number>>;
|
|
399
|
+
};
|
|
400
|
+
const annotationSetsToWrite: AnnotationSetToWrite[] = [];
|
|
401
|
+
|
|
402
|
+
// Collect annotation set ref lists to write later
|
|
403
|
+
type AnnotationSetRefListToWrite = {
|
|
404
|
+
parameterAnnotations: DalvikExecutableAnnotation[][];
|
|
405
|
+
refListOffsetWriteLater: WriteLater<Uint8Array, number>;
|
|
406
|
+
setOffsetWriteLaters: Array<WriteLater<Uint8Array, number> | null>;
|
|
407
|
+
};
|
|
408
|
+
const annotationSetRefListsToWrite: AnnotationSetRefListToWrite[] = [];
|
|
409
|
+
|
|
410
|
+
// First sub-pass: write annotation directories and ref lists, collect sets/items
|
|
411
|
+
for (let classIdx = 0; classIdx < input.classDefinitions.length; classIdx++) {
|
|
412
|
+
const classDef = input.classDefinitions[classIdx];
|
|
413
|
+
const classDefItem = classDefItems[classIdx];
|
|
414
|
+
|
|
415
|
+
if (classDef.annotations && classDefItem.annotationsOffsetWriteLater) {
|
|
416
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
417
|
+
annotationsDirectoryItemsTracker.recordItem(unparserContext.position);
|
|
418
|
+
|
|
419
|
+
const annotationsOffset = unparserContext.position;
|
|
420
|
+
yield * unparserContext.writeEarlier(classDefItem.annotationsOffsetWriteLater, uintUnparser, annotationsOffset);
|
|
421
|
+
|
|
422
|
+
const annotationOffsetWriteLaters: {
|
|
423
|
+
classAnnotationsOffsetWriteLater?: WriteLater<Uint8Array, number>;
|
|
424
|
+
fieldAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number> | null>;
|
|
425
|
+
methodAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number>>;
|
|
426
|
+
parameterAnnotationsOffsetWriteLaters?: Array<WriteLater<Uint8Array, number>>;
|
|
427
|
+
} = {};
|
|
428
|
+
yield * annotationUnparsers.annotationsDirectoryItemUnparser(annotationOffsetWriteLaters)(classDef.annotations, unparserContext);
|
|
429
|
+
|
|
430
|
+
if (classDef.annotations.classAnnotations.length > 0 && annotationOffsetWriteLaters.classAnnotationsOffsetWriteLater) {
|
|
431
|
+
annotationSetsToWrite.push({
|
|
432
|
+
annotations: classDef.annotations.classAnnotations,
|
|
433
|
+
setOffsetWriteLater: annotationOffsetWriteLaters.classAnnotationsOffsetWriteLater,
|
|
434
|
+
itemOffsetWriteLaters: [],
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
for (let i = 0; i < classDef.annotations.fieldAnnotations.length; i++) {
|
|
439
|
+
const fieldAnnotation = classDef.annotations.fieldAnnotations[i];
|
|
440
|
+
const fieldAnnotationsOffsetWriteLater = annotationOffsetWriteLaters.fieldAnnotationsOffsetWriteLaters?.[i];
|
|
441
|
+
if (fieldAnnotation.annotations && fieldAnnotation.annotations.length > 0 && fieldAnnotationsOffsetWriteLater) {
|
|
442
|
+
annotationSetsToWrite.push({
|
|
443
|
+
annotations: fieldAnnotation.annotations,
|
|
444
|
+
setOffsetWriteLater: fieldAnnotationsOffsetWriteLater,
|
|
445
|
+
itemOffsetWriteLaters: [],
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
for (let i = 0; i < classDef.annotations.methodAnnotations.length; i++) {
|
|
451
|
+
const methodAnnotation = classDef.annotations.methodAnnotations[i];
|
|
452
|
+
if (methodAnnotation.annotations.length > 0 && annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters?.[i]) {
|
|
453
|
+
annotationSetsToWrite.push({
|
|
454
|
+
annotations: methodAnnotation.annotations,
|
|
455
|
+
setOffsetWriteLater: annotationOffsetWriteLaters.methodAnnotationsOffsetWriteLaters[i],
|
|
456
|
+
itemOffsetWriteLaters: [],
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
for (let i = 0; i < classDef.annotations.parameterAnnotations.length; i++) {
|
|
462
|
+
const paramAnnotation = classDef.annotations.parameterAnnotations[i];
|
|
463
|
+
if (annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters?.[i]) {
|
|
464
|
+
annotationSetRefListsToWrite.push({
|
|
465
|
+
parameterAnnotations: paramAnnotation.annotations,
|
|
466
|
+
refListOffsetWriteLater: annotationOffsetWriteLaters.parameterAnnotationsOffsetWriteLaters[i],
|
|
467
|
+
setOffsetWriteLaters: [],
|
|
468
|
+
});
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Second sub-pass: write all annotation set ref lists
|
|
475
|
+
for (const refList of annotationSetRefListsToWrite) {
|
|
476
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
477
|
+
annotationSetRefListItemsTracker.recordItem(unparserContext.position);
|
|
478
|
+
|
|
479
|
+
const refListOffset = unparserContext.position;
|
|
480
|
+
yield * unparserContext.writeEarlier(refList.refListOffsetWriteLater, uintUnparser, refListOffset);
|
|
481
|
+
|
|
482
|
+
yield * annotationUnparsers.annotationSetRefListUnparser(refList.setOffsetWriteLaters)(refList.parameterAnnotations, unparserContext);
|
|
483
|
+
|
|
484
|
+
// Collect annotation sets from this ref list
|
|
485
|
+
for (let j = 0; j < refList.parameterAnnotations.length; j++) {
|
|
486
|
+
const paramSet = refList.parameterAnnotations[j];
|
|
487
|
+
const annotationSetOffsetWriteLater = refList.setOffsetWriteLaters[j];
|
|
488
|
+
if (paramSet.length > 0 && annotationSetOffsetWriteLater) {
|
|
489
|
+
annotationSetsToWrite.push({
|
|
490
|
+
annotations: paramSet,
|
|
491
|
+
setOffsetWriteLater: annotationSetOffsetWriteLater,
|
|
492
|
+
itemOffsetWriteLaters: [],
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// Third sub-pass: write all annotation sets
|
|
499
|
+
for (const annotationSet of annotationSetsToWrite) {
|
|
500
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
501
|
+
annotationSetItemsTracker.recordItem(unparserContext.position);
|
|
502
|
+
|
|
503
|
+
const setOffset = unparserContext.position;
|
|
504
|
+
yield * unparserContext.writeEarlier(annotationSet.setOffsetWriteLater, uintUnparser, setOffset);
|
|
505
|
+
|
|
506
|
+
yield * annotationUnparsers.annotationSetItemUnparser(annotationSet.itemOffsetWriteLaters)(annotationSet.annotations, unparserContext);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
// Fourth sub-pass: write all annotation items
|
|
510
|
+
for (const annotationSet of annotationSetsToWrite) {
|
|
511
|
+
for (let i = 0; i < annotationSet.annotations.length; i++) {
|
|
512
|
+
annotationItemsTracker.recordItem(unparserContext.position);
|
|
513
|
+
|
|
514
|
+
const itemOffset = unparserContext.position;
|
|
515
|
+
yield * unparserContext.writeEarlier(annotationSet.itemOffsetWriteLaters[i], uintUnparser, itemOffset);
|
|
516
|
+
yield * annotationUnparsers.annotationItemUnparser(annotationSet.annotations[i], unparserContext);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
if (input.link && linkOffsetWriteLater) {
|
|
521
|
+
const linkOffset = unparserContext.position;
|
|
522
|
+
yield * unparserContext.writeEarlier(linkOffsetWriteLater, uintUnparser, linkOffset);
|
|
523
|
+
yield input.link;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
yield * alignmentUnparser(4)(undefined, unparserContext);
|
|
527
|
+
const mapOffset = unparserContext.position;
|
|
528
|
+
yield * unparserContext.writeEarlier(mapOffsetWriteLater, uintUnparser, mapOffset);
|
|
529
|
+
|
|
530
|
+
// Build map items from section definitions
|
|
531
|
+
const sectionConfigs = [
|
|
532
|
+
{ type: 0x0000, size: 1, offset: 0 },
|
|
533
|
+
{ type: 0x0001, size: stringPool.size(), offset: stringIdsOffset },
|
|
534
|
+
{ type: 0x0002, size: typePool.size(), offset: typeIdsOffset },
|
|
535
|
+
{ type: 0x0003, size: protoPool.size(), offset: protoIdsOffset },
|
|
536
|
+
{ type: 0x0004, size: fieldPool.size(), offset: fieldIdsOffset },
|
|
537
|
+
{ type: 0x0005, size: methodPool.size(), offset: methodIdsOffset },
|
|
538
|
+
{ type: 0x0006, size: input.classDefinitions.length, offset: classDefsOffset },
|
|
539
|
+
{ type: 0x2002, size: stringPool.size(), offset: dataOffset },
|
|
540
|
+
{ type: 0x1001, size: typeListItemsTracker.count, offset: typeListItemsTracker.offset },
|
|
541
|
+
{ type: 0x1002, size: annotationSetRefListItemsTracker.count, offset: annotationSetRefListItemsTracker.offset },
|
|
542
|
+
{ type: 0x1003, size: annotationSetItemsTracker.count, offset: annotationSetItemsTracker.offset },
|
|
543
|
+
{ type: 0x2000, size: classDataItemsTracker.count, offset: classDataItemsTracker.offset },
|
|
544
|
+
{ type: 0x2001, size: codeItemsTracker.count, offset: codeItemsTracker.offset },
|
|
545
|
+
{ type: 0x2003, size: debugInfoItemsTracker.count, offset: debugInfoItemsTracker.offset },
|
|
546
|
+
{ type: 0x2004, size: annotationItemsTracker.count, offset: annotationItemsTracker.offset },
|
|
547
|
+
{ type: 0x2005, size: encodedArrayItemsTracker.count, offset: encodedArrayItemsTracker.offset },
|
|
548
|
+
{ type: 0x2006, size: annotationsDirectoryItemsTracker.count, offset: annotationsDirectoryItemsTracker.offset },
|
|
549
|
+
{ type: 0x1000, size: 1, offset: mapOffset },
|
|
550
|
+
];
|
|
551
|
+
|
|
552
|
+
// Filter out sections with zero size (except header and map which always exist)
|
|
553
|
+
const mapItems = sectionConfigs.filter(
|
|
554
|
+
config => config.type === 0x0000 || config.type === 0x1000 || config.size > 0,
|
|
555
|
+
);
|
|
556
|
+
|
|
557
|
+
// Sort map items by offset (required by DEX format spec)
|
|
558
|
+
mapItems.sort((a, b) => a.offset - b.offset);
|
|
559
|
+
|
|
560
|
+
yield * uintUnparser(mapItems.length, unparserContext);
|
|
561
|
+
|
|
562
|
+
for (const mapItem of mapItems) {
|
|
563
|
+
yield * ushortUnparser(mapItem.type, unparserContext);
|
|
564
|
+
yield * ushortUnparser(0, unparserContext);
|
|
565
|
+
yield * uintUnparser(mapItem.size, unparserContext);
|
|
566
|
+
yield * uintUnparser(mapItem.offset, unparserContext);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
const fileSize = unparserContext.position;
|
|
570
|
+
yield * unparserContext.writeEarlier(fileSizeWriteLater, uintUnparser, fileSize);
|
|
571
|
+
|
|
572
|
+
const dataSize = fileSize - dataOffset;
|
|
573
|
+
yield * unparserContext.writeEarlier(dataSizeWriteLater, uintUnparser, dataSize);
|
|
574
|
+
|
|
575
|
+
yield * unparserContext.writeEarlier(checksumWriteLater, uintUnparser, 0);
|
|
576
|
+
|
|
577
|
+
const zeroSha1 = new Uint8Array(20);
|
|
578
|
+
yield * unparserContext.writeEarlier(sha1WriteLater, async function * (hash) {
|
|
579
|
+
yield hash;
|
|
580
|
+
}, zeroSha1);
|
|
581
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
|
+
|
|
3
|
+
export const createDebugLogInputParser = <Sequence>({
|
|
4
|
+
maxLookahead = 8,
|
|
5
|
+
}: {
|
|
6
|
+
maxLookahead?: number;
|
|
7
|
+
} = {}): Parser<void, Sequence> => async parserContext => {
|
|
8
|
+
let lookahead = maxLookahead;
|
|
9
|
+
|
|
10
|
+
while (lookahead > 0) {
|
|
11
|
+
const sequence = await parserContext.peekSequence(0, lookahead);
|
|
12
|
+
|
|
13
|
+
if (!sequence) {
|
|
14
|
+
lookahead -= 1;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let prettySequence: unknown = sequence;
|
|
19
|
+
|
|
20
|
+
if (prettySequence instanceof Uint8Array) {
|
|
21
|
+
prettySequence = Buffer.from(prettySequence).toString('hex');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
console.log('debugLogInput (position: %s): %s', parserContext.position, prettySequence);
|
|
25
|
+
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
};
|
package/src/debugLogParser.ts
CHANGED
|
@@ -5,13 +5,29 @@ export const createDebugLogParser = <Output, Sequence>(
|
|
|
5
5
|
): Parser<Output, Sequence> => {
|
|
6
6
|
let idCounter = 0;
|
|
7
7
|
|
|
8
|
+
function getLogParserName() {
|
|
9
|
+
const childParserName = getParserName(childParser);
|
|
10
|
+
|
|
11
|
+
if (childParserName !== 'anonymous') {
|
|
12
|
+
return childParserName;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const debugLogParserName = getParserName(debugLogParser);
|
|
16
|
+
|
|
17
|
+
if (!debugLogParserName.startsWith('debugLog(')) {
|
|
18
|
+
return debugLogParserName;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return 'anonymousDebugLogChild';
|
|
22
|
+
}
|
|
23
|
+
|
|
8
24
|
const debugLogParser: typeof childParser = async parserContext => {
|
|
9
25
|
const id = idCounter++;
|
|
10
26
|
const initialPosition = parserContext.position;
|
|
11
27
|
|
|
12
28
|
console.debug(
|
|
13
29
|
'%s %s: started (position: %s)',
|
|
14
|
-
|
|
30
|
+
getLogParserName(),
|
|
15
31
|
id,
|
|
16
32
|
initialPosition,
|
|
17
33
|
);
|
|
@@ -21,7 +37,7 @@ export const createDebugLogParser = <Output, Sequence>(
|
|
|
21
37
|
|
|
22
38
|
console.debug(
|
|
23
39
|
'%s %s: finished (position: %s, consumed: %s): %o',
|
|
24
|
-
|
|
40
|
+
getLogParserName(),
|
|
25
41
|
id,
|
|
26
42
|
parserContext.position,
|
|
27
43
|
parserContext.position - initialPosition,
|
|
@@ -32,7 +48,7 @@ export const createDebugLogParser = <Output, Sequence>(
|
|
|
32
48
|
} catch (error) {
|
|
33
49
|
console.debug(
|
|
34
50
|
'%s %s: failed (position: %s, consumed: %s): %o',
|
|
35
|
-
|
|
51
|
+
getLogParserName(),
|
|
36
52
|
id,
|
|
37
53
|
parserContext.position,
|
|
38
54
|
parserContext.position - initialPosition,
|