@futpib/parser 1.0.0 → 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.
- 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 +183 -0
- package/build/{apkParser.test.js → androidPackageParser.test.js} +7 -7
- package/build/androidPackageUnparser.d.ts +4 -0
- package/build/androidPackageUnparser.js +90 -0
- package/build/androidPackageUnparser.test.js +26 -0
- package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
- package/build/arbitrarilySlicedAsyncInterable.js +3 -3
- package/build/arbitraryFileSystemEntry.js +1 -1
- package/build/arbitraryZip.d.ts +1 -1
- package/build/arbitraryZip.js +13 -19
- package/build/arbitraryZipPermissions.d.ts +1 -8
- package/build/arbitraryZipPermissions.js +1 -16
- package/build/arbitraryZipStream.d.ts +1 -1
- package/build/arbitraryZipStream.js +3 -3
- package/build/arrayParser.d.ts +1 -1
- package/build/arrayParser.js +2 -2
- package/build/arrayParser.test.js +4 -4
- package/build/arrayUnparser.d.ts +2 -0
- package/build/arrayUnparser.js +8 -0
- package/build/backsmali.d.ts +1 -0
- package/build/backsmali.js +22 -0
- package/build/bsonParser.js +6 -2
- package/build/bsonParser.test.js +2 -2
- package/build/{parserInvariant.d.ts → customInvariant.d.ts} +1 -1
- package/build/{parserInvariant.js → customInvariant.js} +1 -1
- package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
- package/build/dalvikBytecodeParser/formatParsers.js +169 -0
- package/build/dalvikBytecodeParser.d.ts +107 -0
- package/build/dalvikBytecodeParser.js +836 -0
- package/build/dalvikExecutable.d.ts +158 -0
- package/build/dalvikExecutable.js +20 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
- package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
- package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
- package/build/dalvikExecutableParser/typeParsers.js +34 -0
- package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
- package/build/dalvikExecutableParser/typedNumbers.js +19 -0
- package/build/dalvikExecutableParser.d.ts +5 -0
- package/build/dalvikExecutableParser.js +1439 -0
- package/build/dalvikExecutableParser.test.js +70 -0
- package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
- package/build/debugLogInputParser.d.ts +4 -0
- package/build/debugLogInputParser.js +16 -0
- package/build/debugLogParser.d.ts +1 -1
- package/build/debugLogParser.js +15 -4
- package/build/disjunctionParser.d.ts +2 -1
- package/build/disjunctionParser.js +4 -2
- package/build/elementParser.d.ts +2 -2
- package/build/elementParser.js +1 -1
- 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 +2 -2
- package/build/exactElementParser.d.ts +1 -1
- package/build/exactElementParser.js +10 -5
- package/build/exactSequenceParser.d.ts +2 -1
- package/build/exactSequenceParser.js +12 -2
- package/build/fetchCid.d.ts +1 -0
- package/build/fetchCid.js +107 -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/index.d.ts +5 -2
- package/build/index.js +3 -0
- package/build/inputReader.d.ts +14 -3
- package/build/inputReader.js +43 -6
- package/build/inputReader.test.js +172 -7
- 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.d.ts +2 -0
- package/build/javaKeyStoreParser.js +67 -0
- package/build/javaKeyStoreParser.test.d.ts +1 -0
- package/build/javaKeyStoreParser.test.js +16 -0
- package/build/jsonParser.d.ts +2 -0
- package/build/jsonParser.js +13 -15
- package/build/jsonParser.test.js +2 -2
- 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/listParser.d.ts +1 -1
- package/build/listParser.js +5 -5
- package/build/lookaheadParser.d.ts +2 -0
- package/build/lookaheadParser.js +14 -0
- package/build/{negativeLookahead.d.ts → negativeLookaheadParser.d.ts} +1 -1
- package/build/negativeLookaheadParser.js +24 -0
- package/build/negativeLookaheadParser.test.d.ts +1 -0
- package/build/negativeLookaheadParser.test.js +30 -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 +16 -0
- package/build/optionalParser.d.ts +1 -1
- package/build/optionalParser.js +2 -2
- package/build/parser.d.ts +13 -4
- package/build/parser.js +67 -32
- package/build/parser.test.js +94 -27
- package/build/parserAccessorParser.d.ts +1 -1
- package/build/parserAccessorParser.js +9 -1
- package/build/parserConsumedSequenceParser.d.ts +2 -0
- package/build/parserConsumedSequenceParser.js +22 -0
- package/build/parserContext.d.ts +20 -6
- package/build/parserContext.js +70 -40
- package/build/parserContext.test.js +34 -7
- package/build/parserCreatorCompose.d.ts +4 -3
- package/build/parserCreatorCompose.js +9 -3
- package/build/parserError.d.ts +6 -0
- package/build/parserError.js +6 -6
- package/build/parserImplementationInvariant.d.ts +1 -1
- package/build/parserImplementationInvariant.js +2 -2
- package/build/parserInputCompanion.d.ts +35 -0
- package/build/parserInputCompanion.js +68 -0
- package/build/promiseCompose.d.ts +1 -1
- package/build/promiseCompose.js +12 -1
- package/build/promiseSettled.d.ts +1 -0
- package/build/promiseSettled.js +4 -0
- package/build/quantifierParser.d.ts +2 -0
- package/build/quantifierParser.js +17 -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/sequenceBuffer.d.ts +13 -3
- package/build/sequenceBuffer.js +60 -8
- package/build/sequenceBuffer.test.js +59 -2
- 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 +2 -0
- package/build/sequenceUnparser.js +6 -0
- 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 +2 -2
- package/build/sliceBoundedParser.js +8 -3
- package/build/sliceBoundedParser.test.js +37 -3
- package/build/smali.d.ts +1 -0
- package/build/smali.js +17 -0
- package/build/smaliParser.d.ts +12 -0
- package/build/smaliParser.js +656 -0
- package/build/smaliParser.test.d.ts +1 -0
- package/build/smaliParser.test.js +115 -0
- package/build/terminatedArrayParser.d.ts +4 -2
- package/build/terminatedArrayParser.js +82 -5
- 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/uint8Array.d.ts +1 -0
- package/build/uint8Array.js +7 -0
- package/build/unionParser.d.ts +2 -1
- package/build/unionParser.js +27 -12
- package/build/unionParser.test.d.ts +1 -0
- package/build/unionParser.test.js +60 -0
- package/build/unparser.d.ts +8 -0
- package/build/unparser.js +104 -0
- package/build/unparser.test.d.ts +1 -0
- package/build/unparser.test.js +150 -0
- package/build/unparserContext.d.ts +31 -0
- package/build/unparserContext.js +74 -0
- package/build/unparserError.d.ts +9 -0
- package/build/unparserError.js +9 -0
- package/build/unparserImplementationInvariant.d.ts +2 -0
- package/build/unparserImplementationInvariant.js +5 -0
- package/build/unparserOutputCompanion.d.ts +15 -0
- package/build/unparserOutputCompanion.js +13 -0
- package/build/zip.d.ts +9 -17
- package/build/zipParser.d.ts +20 -12
- package/build/zipParser.js +83 -71
- package/build/zipParser.test.js +2 -7
- package/build/zipUnparser.d.ts +8 -0
- package/build/zipUnparser.js +200 -0
- package/build/zipUnparser.test.d.ts +1 -0
- package/build/zipUnparser.test.js +80 -0
- package/package.json +26 -8
- package/src/allSettledStream.test.ts +40 -0
- package/src/allSettledStream.ts +47 -15
- package/src/androidPackage.ts +48 -0
- package/src/{apkParser.test.ts → androidPackageParser.test.ts} +7 -8
- package/src/androidPackageParser.test.ts.md +271 -0
- package/src/androidPackageParser.test.ts.snap +0 -0
- package/src/androidPackageParser.ts +440 -0
- package/src/androidPackageUnparser.test.ts +36 -0
- package/src/androidPackageUnparser.ts +120 -0
- package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
- package/src/arbitraryFileSystemEntry.ts +2 -4
- package/src/arbitraryZip.ts +20 -27
- package/src/arbitraryZipPermissions.ts +0 -25
- package/src/arbitraryZipStream.ts +4 -4
- package/src/arrayParser.test.ts +4 -4
- package/src/arrayParser.ts +3 -2
- package/src/arrayUnparser.ts +13 -0
- package/src/backsmali.ts +30 -0
- package/src/bsonParser.test.ts +2 -2
- package/src/bsonParser.ts +16 -5
- package/src/{parserInvariant.ts → customInvariant.ts} +2 -2
- package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
- package/src/dalvikBytecodeParser.ts +2074 -0
- package/src/dalvikExecutable.ts +220 -0
- package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
- package/src/dalvikExecutableParser/typeParsers.ts +65 -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 +2768 -0
- package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
- package/src/debugLogInputParser.ts +28 -0
- package/src/debugLogParser.ts +20 -4
- package/src/disjunctionParser.ts +10 -5
- package/src/elementParser.ts +3 -3
- package/src/elementTerminatedArrayParser.test.ts +99 -0
- package/src/elementTerminatedArrayParser.ts +31 -0
- package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
- package/src/elementTerminatedSequenceArrayParser.ts +52 -0
- package/src/elementTerminatedSequenceParser.test.ts +54 -0
- package/src/elementTerminatedSequenceParser.ts +43 -0
- package/src/endOfInputParser.ts +4 -4
- package/src/exactElementParser.ts +18 -12
- package/src/exactSequenceParser.ts +24 -3
- package/src/fetchCid.ts +125 -0
- package/src/fixedLengthSequenceParser.test.ts +77 -0
- package/src/fixedLengthSequenceParser.ts +28 -1
- package/src/hasExecutable.ts +11 -0
- package/src/highResolutionTimer.ts +49 -0
- package/src/index.ts +15 -2
- package/src/inputReader.test.ts +216 -7
- package/src/inputReader.ts +80 -5
- package/src/inputReaderState.ts +33 -0
- package/src/inspect.ts +9 -0
- package/src/javaKeyStore.ts +0 -0
- package/src/javaKeyStoreParser.test.ts +22 -0
- package/src/javaKeyStoreParser.test.ts.md +103 -0
- package/src/javaKeyStoreParser.test.ts.snap +0 -0
- package/src/javaKeyStoreParser.ts +136 -0
- package/src/jsonParser.test.ts +2 -2
- package/src/jsonParser.ts +23 -34
- package/src/leb128Parser.test.ts +171 -0
- package/src/leb128Parser.ts +125 -0
- package/src/listParser.ts +6 -6
- package/src/lookaheadParser.ts +19 -0
- package/src/negativeLookaheadParser.test.ts +53 -0
- package/src/negativeLookaheadParser.ts +36 -0
- package/src/nonEmptyArrayParser.test.ts +20 -0
- package/src/nonEmptyArrayParser.ts +44 -0
- package/src/optionalParser.ts +4 -3
- package/src/parser.test.ts +148 -27
- package/src/parser.test.ts.md +21 -21
- package/src/parser.test.ts.snap +0 -0
- package/src/parser.ts +153 -49
- package/src/parserAccessorParser.ts +12 -2
- package/src/parserConsumedSequenceParser.ts +29 -0
- package/src/parserContext.test.ts +38 -7
- package/src/parserContext.ts +127 -51
- package/src/parserCreatorCompose.ts +25 -7
- package/src/parserError.ts +9 -6
- package/src/parserImplementationInvariant.ts +2 -2
- package/src/parserInputCompanion.ts +102 -0
- package/src/promiseCompose.ts +17 -3
- package/src/promiseSettled.ts +6 -0
- package/src/quantifierParser.ts +25 -0
- package/src/separatedArrayParser.test.ts +34 -0
- package/src/separatedArrayParser.ts +55 -0
- package/src/sequenceBuffer.test.ts +72 -2
- package/src/sequenceBuffer.ts +93 -7
- package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
- package/src/sequenceTerminatedSequenceParser.ts +62 -0
- package/src/sequenceUnparser.ts +9 -0
- package/src/skipParser.ts +7 -5
- package/src/skipToParser.ts +16 -0
- package/src/sliceBoundedParser.test.ts +45 -3
- package/src/sliceBoundedParser.ts +21 -3
- package/src/smali.ts +24 -0
- package/src/smaliParser.test.ts +132 -0
- package/src/smaliParser.test.ts.md +2320 -0
- package/src/smaliParser.test.ts.snap +0 -0
- package/src/smaliParser.ts +1166 -0
- package/src/terminatedArrayParser.test.ts +258 -0
- package/src/terminatedArrayParser.ts +111 -6
- package/src/toAsyncIterable.ts +7 -0
- package/src/toAsyncIterator.ts +48 -0
- package/src/tupleParser.ts +8 -5
- package/src/uint8Array.ts +10 -0
- package/src/unionParser.test.ts +79 -0
- package/src/unionParser.ts +44 -16
- package/src/unparser.test.ts +221 -0
- package/src/unparser.ts +209 -0
- package/src/unparserContext.ts +127 -0
- package/src/unparserError.ts +12 -0
- package/src/unparserImplementationInvariant.ts +6 -0
- package/src/unparserOutputCompanion.ts +24 -0
- package/src/zip.ts +10 -22
- package/src/zipParser.test.ts +2 -8
- package/src/zipParser.ts +223 -146
- package/src/zipUnparser.test.ts +119 -0
- package/src/zipUnparser.ts +300 -0
- package/build/apk.d.ts +0 -13
- package/build/apkParser.d.ts +0 -3
- package/build/apkParser.js +0 -135
- 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/jsonParser2.d.ts +0 -3
- package/build/jsonParser2.js +0 -52
- package/build/jsonParser2.test.js +0 -22
- package/build/negativeLookahead.js +0 -20
- 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/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/zipEntry.d.ts +0 -28
- package/build/zipFile.d.ts +0 -32
- package/build/zipFileEntry.d.ts +0 -6
- package/src/apk.ts +0 -16
- package/src/apkParser.test.ts.md +0 -268
- package/src/apkParser.test.ts.snap +0 -0
- package/src/apkParser.ts +0 -327
- package/src/inputCompanion.ts +0 -43
- package/src/invariantDefined.ts +0 -6
- package/src/invariantIdentity.ts +0 -8
- package/src/negativeLookahead.ts +0 -26
- /package/build/{apk.js → androidPackage.js} +0 -0
- /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
- /package/build/{arbitraryDosPermissions.d.ts → androidPackageUnparser.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 → elementTerminatedArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
- /package/build/{parserParsingInvariant.js → elementTerminatedSequenceParser.test.d.ts} +0 -0
- /package/build/{zipEntry.js → fixedLengthSequenceParser.test.d.ts} +0 -0
- /package/build/{zipFile.js → javaKeyStore.d.ts} +0 -0
- /package/build/{zipFileEntry.js → javaKeyStore.js} +0 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { runParser } from './parser.js';
|
|
3
|
+
import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
4
|
+
import { dalvikExecutableParser, dalvikExecutableWithRawInstructionsParser } from './dalvikExecutableParser.js';
|
|
5
|
+
import { fetchCid } from './fetchCid.js';
|
|
6
|
+
for (const [dexCid, shouldSnapshot] of [
|
|
7
|
+
['bafkreibb4gsprc3fvmnyqx6obswvm7e7wngnfj64gz65ey72r7xgyzymt4', true],
|
|
8
|
+
['bafybeiebe27ylo53trgitu6fqfbmba43c4ivxj3nt4kumsilkucpbdxtqq', false],
|
|
9
|
+
['bafybeibbupm7uzhuq4pa674rb2amxsenbdaoijigmaf4onaodaql4mh7yy', false],
|
|
10
|
+
['bafybeicb3qajmwy6li7hche2nkucvytaxcyxhwhphmi73tgydjzmyoqoda', false],
|
|
11
|
+
]) {
|
|
12
|
+
test.serial('dex (with instructions as bytes) ' + dexCid, async (t) => {
|
|
13
|
+
const dexStream = await fetchCid(dexCid);
|
|
14
|
+
const actual = await runParser(dalvikExecutableWithRawInstructionsParser, dexStream, uint8ArrayParserInputCompanion, {
|
|
15
|
+
errorJoinMode: 'all',
|
|
16
|
+
});
|
|
17
|
+
if (shouldSnapshot) {
|
|
18
|
+
t.snapshot(actual);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
//console.dir(actual, { depth: null });
|
|
22
|
+
t.pass();
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
function objectWalk(object, f, initialPath = []) {
|
|
27
|
+
f(initialPath, object);
|
|
28
|
+
if (!object
|
|
29
|
+
|| typeof object !== 'object') {
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (Array.isArray(object)) {
|
|
33
|
+
for (const [index, value] of object.entries()) {
|
|
34
|
+
objectWalk(value, f, [...initialPath, index]);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
for (const [key, value] of Object.entries(object)) {
|
|
39
|
+
objectWalk(value, f, [...initialPath, key]);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
for (const [dexCid, shouldSnapshot] of [
|
|
44
|
+
['bafkreibb4gsprc3fvmnyqx6obswvm7e7wngnfj64gz65ey72r7xgyzymt4', true],
|
|
45
|
+
// [ 'bafybeiebe27ylo53trgitu6fqfbmba43c4ivxj3nt4kumsilkucpbdxtqq', false ],
|
|
46
|
+
// [ 'bafybeibbupm7uzhuq4pa674rb2amxsenbdaoijigmaf4onaodaql4mh7yy', false ],
|
|
47
|
+
// [ 'bafybeicb3qajmwy6li7hche2nkucvytaxcyxhwhphmi73tgydjzmyoqoda', false ],
|
|
48
|
+
]) {
|
|
49
|
+
test.serial('dex (with parsed instructions) ' + dexCid, async (t) => {
|
|
50
|
+
const dexStream = await fetchCid(dexCid);
|
|
51
|
+
const actual = await runParser(dalvikExecutableParser, dexStream, uint8ArrayParserInputCompanion, {
|
|
52
|
+
errorJoinMode: 'all',
|
|
53
|
+
});
|
|
54
|
+
objectWalk(actual, (path) => {
|
|
55
|
+
const key = path.at(-1);
|
|
56
|
+
if (typeof key !== 'string') {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
t.false(key.endsWith('Offset'), 'All offsets should be resolved: ' + path.join('.'));
|
|
60
|
+
t.false(key.endsWith('Index'), 'All indexes should be resolved: ' + path.join('.'));
|
|
61
|
+
});
|
|
62
|
+
if (shouldSnapshot) {
|
|
63
|
+
t.snapshot(actual);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
//console.dir(actual, { depth: null });
|
|
67
|
+
t.pass();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { runParser } from './parser.js';
|
|
3
|
+
import { stringParserInputCompanion, uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
|
|
4
|
+
import { dalvikExecutableParser } from './dalvikExecutableParser.js';
|
|
5
|
+
import { fetchCid } from './fetchCid.js';
|
|
6
|
+
import { hasExecutable } from './hasExecutable.js';
|
|
7
|
+
import { baksmaliClass } from './backsmali.js';
|
|
8
|
+
import { smaliParser } from './smaliParser.js';
|
|
9
|
+
import { smaliClass } from './smali.js';
|
|
10
|
+
const hasBaksmaliPromise = hasExecutable('baksmali');
|
|
11
|
+
const hasSmaliPromise = hasExecutable('smali');
|
|
12
|
+
function objectWalk(object, f, initialPath = []) {
|
|
13
|
+
f(initialPath, object);
|
|
14
|
+
if (!object
|
|
15
|
+
|| typeof object !== 'object') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (Array.isArray(object)) {
|
|
19
|
+
for (const [index, value] of object.entries()) {
|
|
20
|
+
objectWalk(value, f, [...initialPath, index]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
for (const [key, value] of Object.entries(object)) {
|
|
25
|
+
objectWalk(value, f, [...initialPath, key]);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
for (const [dexCid, smaliFilePaths] of [
|
|
30
|
+
[
|
|
31
|
+
'bafkreibb4gsprc3fvmnyqx6obswvm7e7wngnfj64gz65ey72r7xgyzymt4',
|
|
32
|
+
[
|
|
33
|
+
'pl/czak/minimal/MainActivity',
|
|
34
|
+
],
|
|
35
|
+
],
|
|
36
|
+
// [
|
|
37
|
+
// 'bafybeiebe27ylo53trgitu6fqfbmba43c4ivxj3nt4kumsilkucpbdxtqq',
|
|
38
|
+
// [
|
|
39
|
+
// 'd/m',
|
|
40
|
+
// ],
|
|
41
|
+
// ],
|
|
42
|
+
// [ 'bafybeiebe27ylo53trgitu6fqfbmba43c4ivxj3nt4kumsilkucpbdxtqq' ],
|
|
43
|
+
// [
|
|
44
|
+
// 'bafybeibbupm7uzhuq4pa674rb2amxsenbdaoijigmaf4onaodaql4mh7yy',
|
|
45
|
+
// [
|
|
46
|
+
// 'com/journeyapps/barcodescanner/CaptureActivity',
|
|
47
|
+
// ],
|
|
48
|
+
// ],
|
|
49
|
+
// [ 'bafybeicb3qajmwy6li7hche2nkucvytaxcyxhwhphmi73tgydjzmyoqoda' ],
|
|
50
|
+
]) {
|
|
51
|
+
for (const smaliFilePath of smaliFilePaths) {
|
|
52
|
+
test.serial('parse(dex) against parse(smali(dex))' + dexCid + ' ' + smaliFilePath, async (t) => {
|
|
53
|
+
const hasBaksmali = await hasBaksmaliPromise;
|
|
54
|
+
if (!hasBaksmali) {
|
|
55
|
+
t.pass('skipping test because baksmali is not available');
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const dexStream = await fetchCid(dexCid);
|
|
59
|
+
const smali = await baksmaliClass(dexStream, smaliFilePath);
|
|
60
|
+
const classDefinitionFromSmali = await runParser(smaliParser, smali, stringParserInputCompanion, {
|
|
61
|
+
errorJoinMode: 'all',
|
|
62
|
+
});
|
|
63
|
+
const dexStream2 = await fetchCid(dexCid);
|
|
64
|
+
const executableFromDex = await runParser(dalvikExecutableParser, dexStream2, uint8ArrayParserInputCompanion, {
|
|
65
|
+
errorJoinMode: 'all',
|
|
66
|
+
});
|
|
67
|
+
const classDefinitionFromDex = executableFromDex.classDefinitions.find(classDefinition => classDefinition.class === classDefinitionFromSmali.class);
|
|
68
|
+
// console.log(smali);
|
|
69
|
+
// console.dir({
|
|
70
|
+
// classDefinitionFromDex,
|
|
71
|
+
// classDefinitionFromSmali,
|
|
72
|
+
// }, {
|
|
73
|
+
// depth: null,
|
|
74
|
+
// });
|
|
75
|
+
objectWalk(classDefinitionFromDex, (_path, value) => {
|
|
76
|
+
if (value
|
|
77
|
+
&& typeof value === 'object'
|
|
78
|
+
&& 'debugInfo' in value) {
|
|
79
|
+
value.debugInfo = undefined;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
t.deepEqual(classDefinitionFromDex, classDefinitionFromSmali);
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const smali = `
|
|
87
|
+
.class public Lcom/journeyapps/barcodescanner/CaptureActivity;
|
|
88
|
+
.super Landroid/app/Activity;
|
|
89
|
+
.source "CaptureActivity.java"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
# instance fields
|
|
93
|
+
.field private barcodeScannerView:Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
94
|
+
|
|
95
|
+
.field private capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# direct methods
|
|
99
|
+
.method public constructor <init>()V
|
|
100
|
+
.registers 1
|
|
101
|
+
|
|
102
|
+
.line 13
|
|
103
|
+
invoke-direct {p0}, Landroid/app/Activity;-><init>()V
|
|
104
|
+
|
|
105
|
+
return-void
|
|
106
|
+
.end method
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
# virtual methods
|
|
110
|
+
.method protected initializeContent()Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
111
|
+
.registers 2
|
|
112
|
+
|
|
113
|
+
sget v0, Lcom/google/zxing/client/android/R$layout;->zxing_capture:I
|
|
114
|
+
|
|
115
|
+
.line 34
|
|
116
|
+
invoke-virtual {p0, v0}, Landroid/app/Activity;->setContentView(I)V
|
|
117
|
+
|
|
118
|
+
sget v0, Lcom/google/zxing/client/android/R$id;->zxing_barcode_scanner:I
|
|
119
|
+
|
|
120
|
+
.line 35
|
|
121
|
+
invoke-virtual {p0, v0}, Landroid/app/Activity;->findViewById(I)Landroid/view/View;
|
|
122
|
+
|
|
123
|
+
move-result-object v0
|
|
124
|
+
|
|
125
|
+
check-cast v0, Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
126
|
+
|
|
127
|
+
return-object v0
|
|
128
|
+
.end method
|
|
129
|
+
|
|
130
|
+
.method protected onCreate(Landroid/os/Bundle;)V
|
|
131
|
+
.registers 4
|
|
132
|
+
|
|
133
|
+
.line 19
|
|
134
|
+
invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V
|
|
135
|
+
|
|
136
|
+
.line 21
|
|
137
|
+
invoke-virtual {p0}, Lcom/journeyapps/barcodescanner/CaptureActivity;->initializeContent()Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
138
|
+
|
|
139
|
+
move-result-object v0
|
|
140
|
+
|
|
141
|
+
iput-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->barcodeScannerView:Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
142
|
+
|
|
143
|
+
.line 23
|
|
144
|
+
new-instance v0, Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
145
|
+
|
|
146
|
+
iget-object v1, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->barcodeScannerView:Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
147
|
+
|
|
148
|
+
invoke-direct {v0, p0, v1}, Lcom/journeyapps/barcodescanner/CaptureManager;-><init>(Landroid/app/Activity;Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;)V
|
|
149
|
+
|
|
150
|
+
iput-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
151
|
+
|
|
152
|
+
.line 24
|
|
153
|
+
invoke-virtual {p0}, Landroid/app/Activity;->getIntent()Landroid/content/Intent;
|
|
154
|
+
|
|
155
|
+
move-result-object v1
|
|
156
|
+
|
|
157
|
+
invoke-virtual {v0, v1, p1}, Lcom/journeyapps/barcodescanner/CaptureManager;->initializeFromIntent(Landroid/content/Intent;Landroid/os/Bundle;)V
|
|
158
|
+
|
|
159
|
+
iget-object p1, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
160
|
+
|
|
161
|
+
.line 25
|
|
162
|
+
invoke-virtual {p1}, Lcom/journeyapps/barcodescanner/CaptureManager;->decode()V
|
|
163
|
+
|
|
164
|
+
return-void
|
|
165
|
+
.end method
|
|
166
|
+
|
|
167
|
+
.method protected onDestroy()V
|
|
168
|
+
.registers 2
|
|
169
|
+
|
|
170
|
+
.line 52
|
|
171
|
+
invoke-super {p0}, Landroid/app/Activity;->onDestroy()V
|
|
172
|
+
|
|
173
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
174
|
+
|
|
175
|
+
.line 53
|
|
176
|
+
invoke-virtual {v0}, Lcom/journeyapps/barcodescanner/CaptureManager;->onDestroy()V
|
|
177
|
+
|
|
178
|
+
return-void
|
|
179
|
+
.end method
|
|
180
|
+
|
|
181
|
+
.method public onKeyDown(ILandroid/view/KeyEvent;)Z
|
|
182
|
+
.registers 4
|
|
183
|
+
|
|
184
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->barcodeScannerView:Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;
|
|
185
|
+
|
|
186
|
+
.line 69
|
|
187
|
+
invoke-virtual {v0, p1, p2}, Lcom/journeyapps/barcodescanner/DecoratedBarcodeView;->onKeyDown(ILandroid/view/KeyEvent;)Z
|
|
188
|
+
|
|
189
|
+
move-result v0
|
|
190
|
+
|
|
191
|
+
if-nez v0, :cond_11
|
|
192
|
+
|
|
193
|
+
invoke-super {p0, p1, p2}, Landroid/app/Activity;->onKeyDown(ILandroid/view/KeyEvent;)Z
|
|
194
|
+
|
|
195
|
+
move-result p1
|
|
196
|
+
|
|
197
|
+
if-eqz p1, :cond_f
|
|
198
|
+
|
|
199
|
+
goto :goto_11
|
|
200
|
+
|
|
201
|
+
:cond_f
|
|
202
|
+
const/4 p1, 0x0
|
|
203
|
+
|
|
204
|
+
goto :goto_12
|
|
205
|
+
|
|
206
|
+
:cond_11
|
|
207
|
+
:goto_11
|
|
208
|
+
const/4 p1, 0x1
|
|
209
|
+
|
|
210
|
+
:goto_12
|
|
211
|
+
return p1
|
|
212
|
+
.end method
|
|
213
|
+
|
|
214
|
+
.method protected onPause()V
|
|
215
|
+
.registers 2
|
|
216
|
+
|
|
217
|
+
.line 46
|
|
218
|
+
invoke-super {p0}, Landroid/app/Activity;->onPause()V
|
|
219
|
+
|
|
220
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
221
|
+
|
|
222
|
+
.line 47
|
|
223
|
+
invoke-virtual {v0}, Lcom/journeyapps/barcodescanner/CaptureManager;->onPause()V
|
|
224
|
+
|
|
225
|
+
return-void
|
|
226
|
+
.end method
|
|
227
|
+
|
|
228
|
+
.method public onRequestPermissionsResult(I[Ljava/lang/String;[I)V
|
|
229
|
+
.registers 5
|
|
230
|
+
|
|
231
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
232
|
+
|
|
233
|
+
.line 64
|
|
234
|
+
invoke-virtual {v0, p1, p2, p3}, Lcom/journeyapps/barcodescanner/CaptureManager;->onRequestPermissionsResult(I[Ljava/lang/String;[I)V
|
|
235
|
+
|
|
236
|
+
return-void
|
|
237
|
+
.end method
|
|
238
|
+
|
|
239
|
+
.method protected onResume()V
|
|
240
|
+
.registers 2
|
|
241
|
+
|
|
242
|
+
.line 40
|
|
243
|
+
invoke-super {p0}, Landroid/app/Activity;->onResume()V
|
|
244
|
+
|
|
245
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
246
|
+
|
|
247
|
+
.line 41
|
|
248
|
+
invoke-virtual {v0}, Lcom/journeyapps/barcodescanner/CaptureManager;->onResume()V
|
|
249
|
+
|
|
250
|
+
return-void
|
|
251
|
+
.end method
|
|
252
|
+
|
|
253
|
+
.method protected onSaveInstanceState(Landroid/os/Bundle;)V
|
|
254
|
+
.registers 3
|
|
255
|
+
|
|
256
|
+
.line 58
|
|
257
|
+
invoke-super {p0, p1}, Landroid/app/Activity;->onSaveInstanceState(Landroid/os/Bundle;)V
|
|
258
|
+
|
|
259
|
+
iget-object v0, p0, Lcom/journeyapps/barcodescanner/CaptureActivity;->capture:Lcom/journeyapps/barcodescanner/CaptureManager;
|
|
260
|
+
|
|
261
|
+
.line 59
|
|
262
|
+
invoke-virtual {v0, p1}, Lcom/journeyapps/barcodescanner/CaptureManager;->onSaveInstanceState(Landroid/os/Bundle;)V
|
|
263
|
+
|
|
264
|
+
return-void
|
|
265
|
+
.end method
|
|
266
|
+
`;
|
|
267
|
+
test.serial.skip('parse(dex(smali)) againts parse(smali)', async (t) => {
|
|
268
|
+
const hasSmali = await hasSmaliPromise;
|
|
269
|
+
if (!hasSmali) {
|
|
270
|
+
t.pass('skipping test because smali is not available');
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
const dexBuffer = await smaliClass(async function* () {
|
|
274
|
+
yield smali;
|
|
275
|
+
}());
|
|
276
|
+
const classDefinitionFromSmali = await runParser(smaliParser, smali, stringParserInputCompanion, {
|
|
277
|
+
errorJoinMode: 'all',
|
|
278
|
+
});
|
|
279
|
+
const executableFromDex = await runParser(dalvikExecutableParser, dexBuffer, uint8ArrayParserInputCompanion, {
|
|
280
|
+
errorJoinMode: 'all',
|
|
281
|
+
});
|
|
282
|
+
const classDefinitionFromDex = executableFromDex.classDefinitions.find(classDefinition => classDefinition.class === classDefinitionFromSmali.class);
|
|
283
|
+
// console.log(smali);
|
|
284
|
+
console.dir({
|
|
285
|
+
classDefinitionFromDex,
|
|
286
|
+
classDefinitionFromSmali,
|
|
287
|
+
}, {
|
|
288
|
+
depth: null,
|
|
289
|
+
});
|
|
290
|
+
objectWalk(classDefinitionFromDex, (_path, value) => {
|
|
291
|
+
if (value
|
|
292
|
+
&& typeof value === 'object'
|
|
293
|
+
&& 'debugInfo' in value) {
|
|
294
|
+
value.debugInfo = undefined;
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
t.deepEqual(classDefinitionFromDex, classDefinitionFromSmali);
|
|
298
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export const createDebugLogInputParser = ({ maxLookahead = 8, } = {}) => async (parserContext) => {
|
|
2
|
+
let lookahead = maxLookahead;
|
|
3
|
+
while (lookahead > 0) {
|
|
4
|
+
const sequence = await parserContext.peekSequence(0, lookahead);
|
|
5
|
+
if (!sequence) {
|
|
6
|
+
lookahead = lookahead - 1;
|
|
7
|
+
continue;
|
|
8
|
+
}
|
|
9
|
+
let prettySequence = sequence;
|
|
10
|
+
if (prettySequence instanceof Uint8Array) {
|
|
11
|
+
prettySequence = Buffer.from(prettySequence).toString('hex');
|
|
12
|
+
}
|
|
13
|
+
console.log('debugLogInput (position: %s): %s', parserContext.position, prettySequence);
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Parser } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
2
|
export declare const createDebugLogParser: <Output, Sequence>(childParser: Parser<Output, Sequence>) => Parser<Output, Sequence>;
|
package/build/debugLogParser.js
CHANGED
|
@@ -1,17 +1,28 @@
|
|
|
1
|
-
import { getParserName, setParserName } from
|
|
1
|
+
import { getParserName, setParserName } from './parser.js';
|
|
2
2
|
export const createDebugLogParser = (childParser) => {
|
|
3
3
|
let idCounter = 0;
|
|
4
|
+
function getLogParserName() {
|
|
5
|
+
const childParserName = getParserName(childParser);
|
|
6
|
+
if (childParserName !== 'anonymous') {
|
|
7
|
+
return childParserName;
|
|
8
|
+
}
|
|
9
|
+
const debugLogParserName = getParserName(debugLogParser);
|
|
10
|
+
if (!debugLogParserName.startsWith('debugLog(')) {
|
|
11
|
+
return debugLogParserName;
|
|
12
|
+
}
|
|
13
|
+
return 'anonymousDebugLogChild';
|
|
14
|
+
}
|
|
4
15
|
const debugLogParser = async (parserContext) => {
|
|
5
16
|
const id = idCounter++;
|
|
6
17
|
const initialPosition = parserContext.position;
|
|
7
|
-
console.debug('%s %s: started (position: %s)',
|
|
18
|
+
console.debug('%s %s: started (position: %s)', getLogParserName(), id, initialPosition);
|
|
8
19
|
try {
|
|
9
20
|
const result = await childParser(parserContext);
|
|
10
|
-
console.debug('%s %s: finished (position: %s, consumed: %s): %o',
|
|
21
|
+
console.debug('%s %s: finished (position: %s, consumed: %s): %o', getLogParserName(), id, parserContext.position, parserContext.position - initialPosition, result);
|
|
11
22
|
return result;
|
|
12
23
|
}
|
|
13
24
|
catch (error) {
|
|
14
|
-
console.debug('%s %s: failed (position: %s, consumed: %s): %o',
|
|
25
|
+
console.debug('%s %s: failed (position: %s, consumed: %s): %o', getLogParserName(), id, parserContext.position, parserContext.position - initialPosition, error);
|
|
15
26
|
throw error;
|
|
16
27
|
}
|
|
17
28
|
};
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { type Parser } from './parser.js';
|
|
2
|
-
|
|
2
|
+
import { DeriveSequenceElement } from './sequence.js';
|
|
3
|
+
export declare const createDisjunctionParser: <Output, Sequence, Element = DeriveSequenceElement<Sequence>>(childParsers: Array<Parser<any, Sequence, Element>>) => Parser<Output, Sequence, Element>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getParserName, setParserName } from './parser.js';
|
|
2
2
|
import { ParserParsingFailedError } from './parserError.js';
|
|
3
3
|
import { parserImplementationInvariant } from './parserImplementationInvariant.js';
|
|
4
|
+
import { promiseSettled } from './promiseSettled.js';
|
|
4
5
|
export const createDisjunctionParser = (childParsers) => {
|
|
5
6
|
parserImplementationInvariant(childParsers.length > 0, 'Disjunction parser must have at least one child parser.');
|
|
6
7
|
const disjunctionParser = async (parserContext) => {
|
|
@@ -9,13 +10,14 @@ export const createDisjunctionParser = (childParsers) => {
|
|
|
9
10
|
const childParserContext = parserContext.lookahead({
|
|
10
11
|
debugName: getParserName(childParser, 'anonymousDisjunctionChild'),
|
|
11
12
|
});
|
|
12
|
-
const
|
|
13
|
+
const childParserResult = await promiseSettled(childParser(childParserContext));
|
|
13
14
|
if (childParserResult.status === 'fulfilled') {
|
|
14
15
|
const successfulParserOutput = childParserResult.value;
|
|
15
16
|
childParserContext.unlookahead();
|
|
16
17
|
childParserContext.dispose();
|
|
17
18
|
return successfulParserOutput;
|
|
18
19
|
}
|
|
20
|
+
childParserContext.dispose();
|
|
19
21
|
const error = childParserResult.reason;
|
|
20
22
|
if (error instanceof ParserParsingFailedError) {
|
|
21
23
|
parserParsingFailedErrors.push(error);
|
|
@@ -24,7 +26,7 @@ export const createDisjunctionParser = (childParsers) => {
|
|
|
24
26
|
throw error;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
parserContext.invariantJoin(false, parserParsingFailedErrors, 'No disjunction child parser succeeded.');
|
|
29
|
+
return parserContext.invariantJoin(false, parserParsingFailedErrors, 'No disjunction child parser succeeded.');
|
|
28
30
|
};
|
|
29
31
|
const name = [
|
|
30
32
|
'(',
|
package/build/elementParser.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { Parser } from
|
|
2
|
-
import { DeriveSequenceElement } from
|
|
1
|
+
import { type Parser } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
3
|
export declare const createElementParser: <Sequence, Element = DeriveSequenceElement<Sequence>>() => Parser<Element, Sequence, Element>;
|
package/build/elementParser.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const createElementParser = () => parserContext => parserContext.read(0);
|
|
1
|
+
export const createElementParser = () => async (parserContext) => parserContext.read(0);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Parser } from "./parser.js";
|
|
2
|
+
import { DeriveSequenceElement } from "./sequence.js";
|
|
3
|
+
export declare const createElementTerminatedArrayParserUnsafe: <ElementOutput, Sequence, Element = DeriveSequenceElement<Sequence>>(elementParser: Parser<ElementOutput, Sequence>, terminatorElement: Element) => Parser<ElementOutput[], Sequence>;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { getParserName, setParserName } from "./parser.js";
|
|
2
|
+
export const createElementTerminatedArrayParserUnsafe = (elementParser, terminatorElement) => {
|
|
3
|
+
const elementTerminatedArrayParserUnsafe = async (parserContext) => {
|
|
4
|
+
const elements = [];
|
|
5
|
+
while (true) {
|
|
6
|
+
const inputElement = await parserContext.peek(0);
|
|
7
|
+
if (inputElement === terminatorElement) {
|
|
8
|
+
parserContext.skip(1);
|
|
9
|
+
break;
|
|
10
|
+
}
|
|
11
|
+
const element = await elementParser(parserContext);
|
|
12
|
+
elements.push(element);
|
|
13
|
+
}
|
|
14
|
+
return elements;
|
|
15
|
+
};
|
|
16
|
+
setParserName(elementTerminatedArrayParserUnsafe, `${getParserName(elementParser, 'anonymousElement')}*?${JSON.stringify(terminatorElement)}`);
|
|
17
|
+
return elementTerminatedArrayParserUnsafe;
|
|
18
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import * as fc from 'fast-check';
|
|
3
|
+
import { testProp } from '@fast-check/ava';
|
|
4
|
+
import { createTerminatedArrayParserNaive } from './terminatedArrayParser.js';
|
|
5
|
+
import { runParser } from './parser.js';
|
|
6
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
7
|
+
import { HighResolutionTotalTimer } from './highResolutionTimer.js';
|
|
8
|
+
import { createElementParser } from './elementParser.js';
|
|
9
|
+
import { createExactSequenceParser } from './exactSequenceParser.js';
|
|
10
|
+
import { createTupleParser } from './tupleParser.js';
|
|
11
|
+
import { createNegativeLookaheadParser } from './negativeLookaheadParser.js';
|
|
12
|
+
import { promiseCompose } from './promiseCompose.js';
|
|
13
|
+
import { createElementTerminatedArrayParserUnsafe } from './elementTerminatedArrayParser.js';
|
|
14
|
+
const naiveTotalTimer = new HighResolutionTotalTimer();
|
|
15
|
+
const elementTotalTimer = new HighResolutionTotalTimer();
|
|
16
|
+
testProp.serial('elementTerminatedArrayParserUnsafe', [
|
|
17
|
+
fc
|
|
18
|
+
.string({
|
|
19
|
+
minLength: 1,
|
|
20
|
+
})
|
|
21
|
+
.map(string => ({
|
|
22
|
+
string,
|
|
23
|
+
terminator: string.slice(-1)
|
|
24
|
+
}))
|
|
25
|
+
.filter(({ string, terminator }) => string.split(terminator).length === 2)
|
|
26
|
+
], async (t, { string, terminator }) => {
|
|
27
|
+
const terminatedArrayParserNaive = promiseCompose(createTerminatedArrayParserNaive(promiseCompose(createTupleParser([
|
|
28
|
+
createNegativeLookaheadParser(createExactSequenceParser(terminator)),
|
|
29
|
+
createElementParser(),
|
|
30
|
+
]), ([_, element]) => element), createExactSequenceParser(terminator)), ([characters]) => characters);
|
|
31
|
+
const elementTerminatedArrayParserUnsafe = createElementTerminatedArrayParserUnsafe(promiseCompose(createTupleParser([
|
|
32
|
+
createNegativeLookaheadParser(createExactSequenceParser(terminator)),
|
|
33
|
+
createElementParser(),
|
|
34
|
+
]), ([_, element]) => element), terminator);
|
|
35
|
+
const createTestWrapperParser = (innerParser) => async (parserContext) => {
|
|
36
|
+
const characters = await innerParser(parserContext);
|
|
37
|
+
return {
|
|
38
|
+
string: characters.join(''),
|
|
39
|
+
nextPeek: await parserContext.peek(0),
|
|
40
|
+
position: parserContext.position,
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
const actualNaive = await naiveTotalTimer.measureAsync(() => runParser(createTestWrapperParser(terminatedArrayParserNaive), string, stringParserInputCompanion));
|
|
44
|
+
t.is(actualNaive.string.length, string.split(terminator)[0].length);
|
|
45
|
+
const actual = await elementTotalTimer.measureAsync(() => runParser(createTestWrapperParser(elementTerminatedArrayParserUnsafe), string, stringParserInputCompanion));
|
|
46
|
+
t.deepEqual(actual, actualNaive);
|
|
47
|
+
}, {
|
|
48
|
+
verbose: true,
|
|
49
|
+
});
|
|
50
|
+
test.serial('elementTerminatedArrayParserUnsafe performance', t => {
|
|
51
|
+
t.true(elementTotalTimer.time * 4n < naiveTotalTimer.time, `Naive: ${naiveTotalTimer.time / 1000000n}ms, Unsafe: ${elementTotalTimer.time / 1000000n}ms`);
|
|
52
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Parser } from "./parser.js";
|
|
2
|
+
import { DeriveSequenceElement } from "./sequence.js";
|
|
3
|
+
export declare const createElementTerminatedSequenceArrayParser: <Sequence, Element = DeriveSequenceElement<Sequence>>(terminatorElement: Element) => Parser<Sequence[], Sequence, Element>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { setParserName } from "./parser.js";
|
|
2
|
+
export const createElementTerminatedSequenceArrayParser = (terminatorElement) => {
|
|
3
|
+
const elementTerminatedSequenceArrayParser = async (parserContext) => {
|
|
4
|
+
const sequences = [];
|
|
5
|
+
let start = 0;
|
|
6
|
+
let window = 1;
|
|
7
|
+
while (true) {
|
|
8
|
+
const sequence = await parserContext.peekSequence(start, start + window);
|
|
9
|
+
if (sequence === undefined) {
|
|
10
|
+
window = Math.floor(window / 2);
|
|
11
|
+
if (start === 0 && window === 0) {
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
parserContext.invariant(window > 0, 'Unexpected end of input without terminator');
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
const terminatorIndex = parserContext.indexOf(sequence, terminatorElement);
|
|
18
|
+
if (terminatorIndex === -1) {
|
|
19
|
+
start += window;
|
|
20
|
+
window *= 2;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
const sequence_ = await parserContext.readSequence(0, start + terminatorIndex);
|
|
24
|
+
parserContext.skip(1);
|
|
25
|
+
sequences.push(sequence_);
|
|
26
|
+
start = 0;
|
|
27
|
+
}
|
|
28
|
+
return sequences;
|
|
29
|
+
};
|
|
30
|
+
setParserName(elementTerminatedSequenceArrayParser, `(.*?${JSON.stringify(terminatorElement)})*`);
|
|
31
|
+
return elementTerminatedSequenceArrayParser;
|
|
32
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import { testProp } from '@fast-check/ava';
|
|
3
|
+
import { runParser } from './parser.js';
|
|
4
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
5
|
+
import { createElementTerminatedSequenceArrayParser } from './elementTerminatedSequenceArrayParser.js';
|
|
6
|
+
testProp.serial('elementTerminatedSequenceArrayParser', [
|
|
7
|
+
fc
|
|
8
|
+
.string({
|
|
9
|
+
minLength: 1,
|
|
10
|
+
})
|
|
11
|
+
.map(string => ({
|
|
12
|
+
string,
|
|
13
|
+
terminator: string.slice(-1)
|
|
14
|
+
}))
|
|
15
|
+
.filter(({ string, terminator }) => string.split(terminator).length === 2)
|
|
16
|
+
], async (t, { string, terminator }) => {
|
|
17
|
+
const elementTerminatedSequenceArrayParser = createElementTerminatedSequenceArrayParser(terminator);
|
|
18
|
+
const createTestWrapperParser = (innerParser) => async (parserContext) => {
|
|
19
|
+
const strings = await innerParser(parserContext);
|
|
20
|
+
return {
|
|
21
|
+
strings,
|
|
22
|
+
nextPeek: await parserContext.peek(0),
|
|
23
|
+
position: parserContext.position,
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const actual = await runParser(createTestWrapperParser(elementTerminatedSequenceArrayParser), string, stringParserInputCompanion);
|
|
27
|
+
t.deepEqual(actual, {
|
|
28
|
+
strings: [string.split(terminator)[0]],
|
|
29
|
+
nextPeek: undefined,
|
|
30
|
+
position: string.length,
|
|
31
|
+
});
|
|
32
|
+
}, {
|
|
33
|
+
verbose: true,
|
|
34
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { Parser } from "./parser.js";
|
|
2
|
+
import { DeriveSequenceElement } from "./sequence.js";
|
|
3
|
+
export declare const createElementTerminatedSequenceParser: <Sequence, Element = DeriveSequenceElement<Sequence>>(terminatorElement: Element) => Parser<Sequence, Sequence, Element>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { setParserName } from "./parser.js";
|
|
2
|
+
export const createElementTerminatedSequenceParser = (terminatorElement) => {
|
|
3
|
+
const elementTerminatedSequenceParser = async (parserContext) => {
|
|
4
|
+
let start = 0;
|
|
5
|
+
let window = 1;
|
|
6
|
+
while (true) {
|
|
7
|
+
const sequence = await parserContext.peekSequence(start, start + window);
|
|
8
|
+
if (sequence === undefined) {
|
|
9
|
+
window = Math.floor(window / 2);
|
|
10
|
+
parserContext.invariant(!(start === 0 && window === 0), 'Unexpected end of input without terminated sequence');
|
|
11
|
+
parserContext.invariant(window > 0, 'Unexpected end of input without terminator');
|
|
12
|
+
continue;
|
|
13
|
+
}
|
|
14
|
+
const terminatorIndex = parserContext.indexOf(sequence, terminatorElement);
|
|
15
|
+
if (terminatorIndex === -1) {
|
|
16
|
+
start += window;
|
|
17
|
+
window *= 2;
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const sequence_ = await parserContext.readSequence(0, start + terminatorIndex);
|
|
21
|
+
parserContext.skip(1);
|
|
22
|
+
return sequence_;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
setParserName(elementTerminatedSequenceParser, `.*?${JSON.stringify(terminatorElement)}`);
|
|
26
|
+
return elementTerminatedSequenceParser;
|
|
27
|
+
};
|