@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
package/src/disjunctionParser.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { getParserName, setParserName, type Parser } from './parser.js';
|
|
2
|
-
import { ParserParsingFailedError } from './parserError.js';
|
|
2
|
+
import { isParserParsingFailedError, ParserParsingFailedError } from './parserError.js';
|
|
3
3
|
import { parserImplementationInvariant } from './parserImplementationInvariant.js';
|
|
4
|
+
import { promiseSettled } from './promiseSettled.js';
|
|
5
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
4
6
|
|
|
5
7
|
export const createDisjunctionParser = <
|
|
6
8
|
Output,
|
|
7
9
|
Sequence,
|
|
10
|
+
Element = DeriveSequenceElement<Sequence>,
|
|
8
11
|
>(
|
|
9
|
-
childParsers: Array<Parser<
|
|
10
|
-
): Parser<Output, Sequence,
|
|
12
|
+
childParsers: Array<Parser<unknown, Sequence, Element>>,
|
|
13
|
+
): Parser<Output, Sequence, Element> => {
|
|
11
14
|
parserImplementationInvariant(childParsers.length > 0, 'Disjunction parser must have at least one child parser.');
|
|
12
15
|
|
|
13
|
-
const disjunctionParser: Parser<Output, Sequence,
|
|
16
|
+
const disjunctionParser: Parser<Output, Sequence, Element> = async parserContext => {
|
|
14
17
|
const parserParsingFailedErrors: ParserParsingFailedError[] = [];
|
|
15
18
|
|
|
16
19
|
for (const childParser of childParsers) {
|
|
@@ -18,7 +21,7 @@ export const createDisjunctionParser = <
|
|
|
18
21
|
debugName: getParserName(childParser, 'anonymousDisjunctionChild'),
|
|
19
22
|
});
|
|
20
23
|
|
|
21
|
-
const
|
|
24
|
+
const childParserResult = await promiseSettled<Output>(childParser(childParserContext) as Promise<Output>);
|
|
22
25
|
|
|
23
26
|
if (childParserResult.status === 'fulfilled') {
|
|
24
27
|
const successfulParserOutput = childParserResult.value;
|
|
@@ -29,16 +32,18 @@ export const createDisjunctionParser = <
|
|
|
29
32
|
return successfulParserOutput;
|
|
30
33
|
}
|
|
31
34
|
|
|
35
|
+
childParserContext.dispose();
|
|
36
|
+
|
|
32
37
|
const error = childParserResult.reason;
|
|
33
38
|
|
|
34
|
-
if (error
|
|
39
|
+
if (isParserParsingFailedError(error)) {
|
|
35
40
|
parserParsingFailedErrors.push(error);
|
|
36
41
|
} else {
|
|
37
42
|
throw error;
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
parserContext.invariantJoin(
|
|
46
|
+
return parserContext.invariantJoin(
|
|
42
47
|
false,
|
|
43
48
|
parserParsingFailedErrors,
|
|
44
49
|
'No disjunction child parser succeeded.',
|
|
@@ -0,0 +1,99 @@
|
|
|
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 { type Parser, 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
|
+
|
|
15
|
+
const naiveTotalTimer = new HighResolutionTotalTimer();
|
|
16
|
+
const elementTotalTimer = new HighResolutionTotalTimer();
|
|
17
|
+
|
|
18
|
+
testProp.serial(
|
|
19
|
+
'elementTerminatedArrayParserUnsafe',
|
|
20
|
+
[
|
|
21
|
+
fc
|
|
22
|
+
.string({
|
|
23
|
+
minLength: 1,
|
|
24
|
+
})
|
|
25
|
+
.map(string => ({
|
|
26
|
+
string,
|
|
27
|
+
terminator: string.slice(-1),
|
|
28
|
+
}))
|
|
29
|
+
.filter(({ string, terminator }) => string.split(terminator).length === 2),
|
|
30
|
+
],
|
|
31
|
+
async (t, { string, terminator }) => {
|
|
32
|
+
const terminatedArrayParserNaive = promiseCompose(
|
|
33
|
+
createTerminatedArrayParserNaive(
|
|
34
|
+
promiseCompose(
|
|
35
|
+
createTupleParser([
|
|
36
|
+
createNegativeLookaheadParser(createExactSequenceParser(terminator)),
|
|
37
|
+
createElementParser<string>(),
|
|
38
|
+
]),
|
|
39
|
+
([ _, element ]) => element,
|
|
40
|
+
),
|
|
41
|
+
createExactSequenceParser(terminator),
|
|
42
|
+
),
|
|
43
|
+
([ characters ]) => characters,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const elementTerminatedArrayParserUnsafe = createElementTerminatedArrayParserUnsafe(
|
|
47
|
+
promiseCompose(
|
|
48
|
+
createTupleParser([
|
|
49
|
+
createNegativeLookaheadParser(createExactSequenceParser(terminator)),
|
|
50
|
+
createElementParser<string>(),
|
|
51
|
+
]),
|
|
52
|
+
([ _, element ]) => element,
|
|
53
|
+
),
|
|
54
|
+
terminator,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const createTestWrapperParser = (innerParser: typeof elementTerminatedArrayParserUnsafe): Parser<{
|
|
58
|
+
string: string;
|
|
59
|
+
position: number;
|
|
60
|
+
}, string> => async parserContext => {
|
|
61
|
+
const characters = await innerParser(parserContext);
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
string: characters.join(''),
|
|
65
|
+
nextPeek: await parserContext.peek(0),
|
|
66
|
+
position: parserContext.position,
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const actualNaive = await naiveTotalTimer.measureAsync(async () => runParser(
|
|
71
|
+
createTestWrapperParser(terminatedArrayParserNaive),
|
|
72
|
+
string,
|
|
73
|
+
stringParserInputCompanion,
|
|
74
|
+
));
|
|
75
|
+
|
|
76
|
+
t.is(actualNaive.string.length, string.split(terminator)[0].length);
|
|
77
|
+
|
|
78
|
+
const actual = await elementTotalTimer.measureAsync(async () => runParser(
|
|
79
|
+
createTestWrapperParser(elementTerminatedArrayParserUnsafe),
|
|
80
|
+
string,
|
|
81
|
+
stringParserInputCompanion,
|
|
82
|
+
));
|
|
83
|
+
|
|
84
|
+
t.deepEqual(actual, actualNaive);
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
verbose: true,
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
test.serial(
|
|
92
|
+
'elementTerminatedArrayParserUnsafe performance',
|
|
93
|
+
t => {
|
|
94
|
+
t.true(
|
|
95
|
+
elementTotalTimer.time * 2n < naiveTotalTimer.time,
|
|
96
|
+
`Naive: ${naiveTotalTimer.time / 1_000_000n}ms, Unsafe: ${elementTotalTimer.time / 1_000_000n}ms`,
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getParserName, type Parser, setParserName } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
|
+
|
|
4
|
+
export const createElementTerminatedArrayParserUnsafe = <ElementOutput, Sequence, Element = DeriveSequenceElement<Sequence>>(
|
|
5
|
+
elementParser: Parser<ElementOutput, Sequence>,
|
|
6
|
+
terminatorElement: Element,
|
|
7
|
+
): Parser<ElementOutput[], Sequence> => {
|
|
8
|
+
const elementTerminatedArrayParserUnsafe: Parser<ElementOutput[], Sequence> = async parserContext => {
|
|
9
|
+
const elements: ElementOutput[] = [];
|
|
10
|
+
|
|
11
|
+
while (true) {
|
|
12
|
+
const inputElement = await parserContext.peek(0);
|
|
13
|
+
|
|
14
|
+
if (inputElement === terminatorElement) {
|
|
15
|
+
parserContext.skip(1);
|
|
16
|
+
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const element = await elementParser(parserContext);
|
|
21
|
+
|
|
22
|
+
elements.push(element);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return elements;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
setParserName(elementTerminatedArrayParserUnsafe, `${getParserName(elementParser, 'anonymousElement')}*?${JSON.stringify(terminatorElement)}`);
|
|
29
|
+
|
|
30
|
+
return elementTerminatedArrayParserUnsafe;
|
|
31
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import { testProp } from '@fast-check/ava';
|
|
3
|
+
import { type Parser, runParser } from './parser.js';
|
|
4
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
5
|
+
import { createElementTerminatedSequenceArrayParser } from './elementTerminatedSequenceArrayParser.js';
|
|
6
|
+
|
|
7
|
+
testProp.serial(
|
|
8
|
+
'elementTerminatedSequenceArrayParser',
|
|
9
|
+
[
|
|
10
|
+
fc
|
|
11
|
+
.string({
|
|
12
|
+
minLength: 1,
|
|
13
|
+
})
|
|
14
|
+
.map(string => ({
|
|
15
|
+
string,
|
|
16
|
+
terminator: string.slice(-1),
|
|
17
|
+
}))
|
|
18
|
+
.filter(({ string, terminator }) => string.split(terminator).length === 2),
|
|
19
|
+
],
|
|
20
|
+
async (t, { string, terminator }) => {
|
|
21
|
+
const elementTerminatedSequenceArrayParser = createElementTerminatedSequenceArrayParser<string>(terminator);
|
|
22
|
+
|
|
23
|
+
const createTestWrapperParser = (innerParser: typeof elementTerminatedSequenceArrayParser): Parser<{
|
|
24
|
+
strings: string[];
|
|
25
|
+
nextPeek: string | undefined;
|
|
26
|
+
position: number;
|
|
27
|
+
}, string> => async parserContext => {
|
|
28
|
+
const strings = await innerParser(parserContext);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
strings,
|
|
32
|
+
nextPeek: await parserContext.peek(0),
|
|
33
|
+
position: parserContext.position,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const actual = await runParser(
|
|
38
|
+
createTestWrapperParser(elementTerminatedSequenceArrayParser),
|
|
39
|
+
string,
|
|
40
|
+
stringParserInputCompanion,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
t.deepEqual(actual, {
|
|
44
|
+
strings: [ string.split(terminator)[0] ],
|
|
45
|
+
nextPeek: undefined,
|
|
46
|
+
position: string.length,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
verbose: true,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { type Parser, setParserName } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
|
+
|
|
4
|
+
export const createElementTerminatedSequenceArrayParser = <Sequence, Element = DeriveSequenceElement<Sequence>>(
|
|
5
|
+
terminatorElement: Element,
|
|
6
|
+
): Parser<Sequence[], Sequence, Element> => {
|
|
7
|
+
const elementTerminatedSequenceArrayParser: Parser<Sequence[], Sequence, Element> = async parserContext => {
|
|
8
|
+
const sequences: Sequence[] = [];
|
|
9
|
+
|
|
10
|
+
let start = 0;
|
|
11
|
+
let window = 1;
|
|
12
|
+
|
|
13
|
+
while (true) {
|
|
14
|
+
const sequence = await parserContext.peekSequence(start, start + window);
|
|
15
|
+
|
|
16
|
+
if (sequence === undefined) {
|
|
17
|
+
window = Math.floor(window / 2);
|
|
18
|
+
|
|
19
|
+
if (start === 0 && window === 0) {
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
parserContext.invariant(window > 0, 'Unexpected end of input without terminator');
|
|
24
|
+
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const terminatorIndex = parserContext.indexOf(sequence, terminatorElement);
|
|
29
|
+
|
|
30
|
+
if (terminatorIndex === -1) {
|
|
31
|
+
start += window;
|
|
32
|
+
window *= 2;
|
|
33
|
+
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const sequence_ = await parserContext.readSequence(0, start + terminatorIndex);
|
|
38
|
+
|
|
39
|
+
parserContext.skip(1);
|
|
40
|
+
|
|
41
|
+
sequences.push(sequence_);
|
|
42
|
+
|
|
43
|
+
start = 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return sequences;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
setParserName(elementTerminatedSequenceArrayParser, `(.*?${JSON.stringify(terminatorElement)})*`);
|
|
50
|
+
|
|
51
|
+
return elementTerminatedSequenceArrayParser;
|
|
52
|
+
};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as fc from 'fast-check';
|
|
2
|
+
import { testProp } from '@fast-check/ava';
|
|
3
|
+
import { type Parser, runParser } from './parser.js';
|
|
4
|
+
import { stringParserInputCompanion } from './parserInputCompanion.js';
|
|
5
|
+
import { createElementTerminatedSequenceParser } from './elementTerminatedSequenceParser.js';
|
|
6
|
+
|
|
7
|
+
testProp.serial(
|
|
8
|
+
'elementTerminatedSequenceParser',
|
|
9
|
+
[
|
|
10
|
+
fc
|
|
11
|
+
.string({
|
|
12
|
+
minLength: 1,
|
|
13
|
+
})
|
|
14
|
+
.map(string => ({
|
|
15
|
+
string,
|
|
16
|
+
terminator: string.slice(-1),
|
|
17
|
+
}))
|
|
18
|
+
.filter(({ string, terminator }) => string.split(terminator).length === 2),
|
|
19
|
+
],
|
|
20
|
+
async (t, { string, terminator }) => {
|
|
21
|
+
const elementTerminatedSequenceParser = createElementTerminatedSequenceParser<string>(terminator);
|
|
22
|
+
|
|
23
|
+
const createTestWrapperParser = (innerParser: typeof elementTerminatedSequenceParser): Parser<{
|
|
24
|
+
string: string;
|
|
25
|
+
nextPeek: string | undefined;
|
|
26
|
+
position: number;
|
|
27
|
+
}, string> => async parserContext => {
|
|
28
|
+
const string = await innerParser(parserContext);
|
|
29
|
+
|
|
30
|
+
return {
|
|
31
|
+
string,
|
|
32
|
+
nextPeek: await parserContext.peek(0),
|
|
33
|
+
position: parserContext.position,
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const actual = await runParser(
|
|
38
|
+
createTestWrapperParser(elementTerminatedSequenceParser),
|
|
39
|
+
string,
|
|
40
|
+
stringParserInputCompanion,
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
t.deepEqual(actual, {
|
|
44
|
+
string: string.split(terminator)[0],
|
|
45
|
+
nextPeek: undefined,
|
|
46
|
+
position: string.length,
|
|
47
|
+
});
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
verbose: true,
|
|
51
|
+
},
|
|
52
|
+
);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type Parser, setParserName } from './parser.js';
|
|
2
|
+
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
|
+
|
|
4
|
+
export const createElementTerminatedSequenceParser = <Sequence, Element = DeriveSequenceElement<Sequence>>(
|
|
5
|
+
terminatorElement: Element,
|
|
6
|
+
): Parser<Sequence, Sequence, Element> => {
|
|
7
|
+
const elementTerminatedSequenceParser: Parser<Sequence, Sequence, Element> = async parserContext => {
|
|
8
|
+
let start = 0;
|
|
9
|
+
let window = 1;
|
|
10
|
+
|
|
11
|
+
while (true) {
|
|
12
|
+
const sequence = await parserContext.peekSequence(start, start + window);
|
|
13
|
+
|
|
14
|
+
if (sequence === undefined) {
|
|
15
|
+
window = Math.floor(window / 2);
|
|
16
|
+
|
|
17
|
+
parserContext.invariant(!(start === 0 && window === 0), 'Unexpected end of input without terminated sequence');
|
|
18
|
+
parserContext.invariant(window > 0, 'Unexpected end of input without terminator');
|
|
19
|
+
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const terminatorIndex = parserContext.indexOf(sequence, terminatorElement);
|
|
24
|
+
|
|
25
|
+
if (terminatorIndex === -1) {
|
|
26
|
+
start += window;
|
|
27
|
+
window *= 2;
|
|
28
|
+
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const sequence_ = await parserContext.readSequence(0, start + terminatorIndex);
|
|
33
|
+
|
|
34
|
+
parserContext.skip(1);
|
|
35
|
+
|
|
36
|
+
return sequence_;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
setParserName(elementTerminatedSequenceParser, `.*?${JSON.stringify(terminatorElement)}`);
|
|
41
|
+
|
|
42
|
+
return elementTerminatedSequenceParser;
|
|
43
|
+
};
|
package/src/endOfInputParser.ts
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import { type Parser } from './parser.js';
|
|
1
|
+
import { setParserName, type Parser } from './parser.js';
|
|
2
2
|
import { type DeriveSequenceElement } from './sequence.js';
|
|
3
3
|
|
|
4
4
|
export const createExactElementParser = <
|
|
5
5
|
Sequence,
|
|
6
6
|
Element = DeriveSequenceElement<Sequence>,
|
|
7
|
-
>(element: Element): Parser<Element, Sequence, Element> =>
|
|
8
|
-
const
|
|
7
|
+
>(element: Element): Parser<Element, Sequence, Element> => {
|
|
8
|
+
const exactElementParser: Parser<Element, Sequence, Element> = async parserContext => {
|
|
9
|
+
const actualElement = await parserContext.peek(0);
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
parserContext.invariant(
|
|
12
|
+
actualElement === element,
|
|
13
|
+
'Expected %s, got %s',
|
|
14
|
+
element,
|
|
15
|
+
actualElement,
|
|
16
|
+
);
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
parserContext.skip(1);
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
return element;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
setParserName(exactElementParser, `createExactElementParser(${element})`);
|
|
24
|
+
|
|
25
|
+
return exactElementParser;
|
|
20
26
|
};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
2
|
+
import { getParserName, Parser, setParserName } from "./parser.js";
|
|
3
|
+
import { parserImplementationInvariant } from "./parserImplementationInvariant.js";
|
|
4
|
+
import { DeriveSequenceElement } from "./sequence.js";
|
|
5
|
+
|
|
6
|
+
export const createElementSwitchParser = <
|
|
7
|
+
Output,
|
|
8
|
+
Sequence,
|
|
9
|
+
Element = DeriveSequenceElement<Sequence>,
|
|
10
|
+
>(
|
|
11
|
+
childParsers: Map<Element, Parser<unknown, Sequence, Element>>,
|
|
12
|
+
defaultParser?: Parser<unknown, Sequence, Element>,
|
|
13
|
+
): Parser<Output, Sequence, Element> => {
|
|
14
|
+
parserImplementationInvariant(childParsers.size > 0, 'Element switch parser must have at least one child parser.');
|
|
15
|
+
|
|
16
|
+
const elementSwitchParser: Parser<Output, Sequence, Element> = async parserContext => {
|
|
17
|
+
const currentElement = await parserContext.peek(0);
|
|
18
|
+
|
|
19
|
+
parserContext.invariant(currentElement !== undefined, 'Unexpected end of input.');
|
|
20
|
+
invariant(currentElement !== undefined, 'Unexpected end of input.');
|
|
21
|
+
|
|
22
|
+
const childParser = childParsers.get(currentElement) ?? defaultParser;
|
|
23
|
+
|
|
24
|
+
parserContext.invariant(childParser, `No child parser found for element: ${String(currentElement)}`);
|
|
25
|
+
|
|
26
|
+
const childParserOutput = await childParser!(parserContext) as Output;
|
|
27
|
+
|
|
28
|
+
return childParserOutput;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const name = [
|
|
32
|
+
'elementSwitch(',
|
|
33
|
+
...Array.from(childParsers.entries()).map(
|
|
34
|
+
([ element, childParser ]) => `${String(element)}=>${getParserName(childParser, 'anonymousElementSwitchChild')}`,
|
|
35
|
+
),
|
|
36
|
+
defaultParser ? `|default=>${getParserName(defaultParser, 'anonymousElementSwitchDefaultChild')}` : '',
|
|
37
|
+
')',
|
|
38
|
+
].join('');
|
|
39
|
+
|
|
40
|
+
return setParserName(elementSwitchParser, name);
|
|
41
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { inspect } from 'node:util';
|
|
2
1
|
import { setParserName, type Parser } from './parser.js';
|
|
2
|
+
import { inspect } from './inspect.js';
|
|
3
3
|
|
|
4
|
-
export const
|
|
4
|
+
export const createExactSequenceNaiveParser = <Sequence>(sequence: Sequence) => {
|
|
5
5
|
const exactSequenceParser: Parser<Sequence, Sequence, unknown> = async parserContext => {
|
|
6
6
|
const length = parserContext.length(sequence);
|
|
7
7
|
|
|
@@ -25,3 +25,24 @@ export const createExactSequenceParser = <Sequence>(sequence: Sequence) => {
|
|
|
25
25
|
|
|
26
26
|
return exactSequenceParser;
|
|
27
27
|
};
|
|
28
|
+
|
|
29
|
+
export const createExactSequenceParser = <Sequence>(expectedSequence: Sequence) => {
|
|
30
|
+
const exactSequenceParser: Parser<Sequence, Sequence, unknown> = async parserContext => {
|
|
31
|
+
const length = parserContext.length(expectedSequence);
|
|
32
|
+
|
|
33
|
+
const actualSequence = await parserContext.readSequence(0, length);
|
|
34
|
+
|
|
35
|
+
parserContext.invariant(
|
|
36
|
+
parserContext.equals(actualSequence, expectedSequence),
|
|
37
|
+
'Expected "%s", got "%s"',
|
|
38
|
+
() => inspect(expectedSequence),
|
|
39
|
+
() => inspect(actualSequence),
|
|
40
|
+
);
|
|
41
|
+
|
|
42
|
+
return expectedSequence;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
setParserName(exactSequenceParser, inspect(expectedSequence));
|
|
46
|
+
|
|
47
|
+
return exactSequenceParser;
|
|
48
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import test from 'ava';
|
|
2
|
+
import { fetchCid } from './fetchCid.js';
|
|
3
|
+
|
|
4
|
+
const cid = 'bafybeicb3qajmwy6li7hche2nkucvytaxcyxhwhphmi73tgydjzmyoqoda';
|
|
5
|
+
|
|
6
|
+
test('fetchCid', async t => {
|
|
7
|
+
await Promise.all([
|
|
8
|
+
fetchCid(cid),
|
|
9
|
+
fetchCid(cid),
|
|
10
|
+
fetchCid(cid),
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
await Promise.all([
|
|
14
|
+
fetchCid(cid),
|
|
15
|
+
fetchCid(cid),
|
|
16
|
+
fetchCid(cid),
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
t.pass();
|
|
20
|
+
});
|
package/src/fetchCid.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import fsPromises from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import pMemoize from 'p-memoize';
|
|
4
|
+
import envPaths from 'env-paths';
|
|
5
|
+
|
|
6
|
+
const paths = envPaths('parser.futpib.github.io');
|
|
7
|
+
|
|
8
|
+
function readableWebStreamOnFinish<T>(readableWebStream: ReadableStream<T>, onFinish: () => void): ReadableStream<T> {
|
|
9
|
+
const reader = readableWebStream.getReader();
|
|
10
|
+
|
|
11
|
+
const stream = new ReadableStream<T>({
|
|
12
|
+
async start(controller) {
|
|
13
|
+
try {
|
|
14
|
+
while (true) {
|
|
15
|
+
const { done, value } = await reader.read();
|
|
16
|
+
if (done) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
controller.enqueue(value);
|
|
21
|
+
}
|
|
22
|
+
} finally {
|
|
23
|
+
controller.close();
|
|
24
|
+
reader.releaseLock();
|
|
25
|
+
onFinish();
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
async cancel(reason) {
|
|
29
|
+
await reader.cancel(reason);
|
|
30
|
+
onFinish();
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return stream;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
class FsCache {
|
|
38
|
+
private get _basePath() {
|
|
39
|
+
return path.join(paths.cache, 'fetchCid');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private _getKeyPath(key: string) {
|
|
43
|
+
return path.join(this._basePath, key.replaceAll('/', '_'));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async get(key: string): Promise<[ ReadableStream<Uint8Array>, ReadableStream<Uint8Array> ] | undefined> {
|
|
47
|
+
try {
|
|
48
|
+
const file = await fsPromises.open(this._getKeyPath(key), 'r');
|
|
49
|
+
|
|
50
|
+
const stream = file.readableWebStream() as ReadableStream<Uint8Array>;
|
|
51
|
+
|
|
52
|
+
const streamWithClose = readableWebStreamOnFinish(stream, () => {
|
|
53
|
+
file.close();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return [ streamWithClose, undefined as unknown as ReadableStream<Uint8Array> ];
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async has(key: string) {
|
|
67
|
+
const streams = await this.get(key);
|
|
68
|
+
try {
|
|
69
|
+
return streams !== undefined;
|
|
70
|
+
} finally {
|
|
71
|
+
for (const stream of streams ?? []) {
|
|
72
|
+
await stream?.cancel();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async set(key: string, [ _, value ]: [ ReadableStream<Uint8Array>, ReadableStream<Uint8Array> ]) {
|
|
78
|
+
await fsPromises.mkdir(this._basePath, {
|
|
79
|
+
recursive: true,
|
|
80
|
+
});
|
|
81
|
+
const file = await fsPromises.open(this._getKeyPath(key), 'w');
|
|
82
|
+
try {
|
|
83
|
+
for await (const chunk of value) {
|
|
84
|
+
await file.write(chunk);
|
|
85
|
+
}
|
|
86
|
+
} finally {
|
|
87
|
+
await file.close();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
async delete(key: string) {
|
|
92
|
+
await fsPromises.unlink(this._getKeyPath(key));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function reallyFetchCid(cid: string): Promise<[ ReadableStream<Uint8Array>, ReadableStream<Uint8Array> ]> {
|
|
97
|
+
const response = await fetch('https://ipfs.io/ipfs/' + cid);
|
|
98
|
+
return response.body!.tee();
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const cachedReallyFetchCid = pMemoize(reallyFetchCid, {
|
|
102
|
+
cache: new FsCache(),
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export async function fetchCid(cidOrPath: string): Promise<AsyncIterable<Uint8Array>> {
|
|
106
|
+
if (cidOrPath.includes('/')) {
|
|
107
|
+
const file = await fsPromises.open(cidOrPath, 'r');
|
|
108
|
+
|
|
109
|
+
const stream = file.readableWebStream() as ReadableStream<Uint8Array>;
|
|
110
|
+
|
|
111
|
+
const streamWithClose = readableWebStreamOnFinish(stream, () => {
|
|
112
|
+
file.close();
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
return streamWithClose;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
const [ readable, unused ] = await cachedReallyFetchCid(cidOrPath);
|
|
119
|
+
await unused?.cancel();
|
|
120
|
+
return readable;
|
|
121
|
+
}
|