@futpib/parser 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/build/allSettledStream.js +32 -14
  2. package/build/allSettledStream.test.js +32 -0
  3. package/build/androidPackage.d.ts +39 -0
  4. package/build/androidPackageParser.d.ts +17 -0
  5. package/build/androidPackageParser.js +183 -0
  6. package/build/{apkParser.test.js → androidPackageParser.test.js} +6 -6
  7. package/build/androidPackageUnparser.d.ts +4 -0
  8. package/build/{apkUnparser.js → androidPackageUnparser.js} +23 -23
  9. package/build/androidPackageUnparser.test.js +26 -0
  10. package/build/arbitrarilySlicedAsyncInterable.d.ts +3 -1
  11. package/build/arbitrarilySlicedAsyncInterable.js +3 -3
  12. package/build/arrayParser.test.js +3 -3
  13. package/build/backsmali.d.ts +1 -0
  14. package/build/backsmali.js +22 -0
  15. package/build/bsonParser.js +6 -2
  16. package/build/customInvariant.d.ts +1 -1
  17. package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
  18. package/build/dalvikBytecodeParser/formatParsers.js +169 -0
  19. package/build/dalvikBytecodeParser.d.ts +107 -0
  20. package/build/dalvikBytecodeParser.js +836 -0
  21. package/build/dalvikExecutable.d.ts +158 -0
  22. package/build/dalvikExecutable.js +20 -0
  23. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
  24. package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
  25. package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
  26. package/build/dalvikExecutableParser/typeParsers.js +34 -0
  27. package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
  28. package/build/dalvikExecutableParser/typedNumbers.js +19 -0
  29. package/build/dalvikExecutableParser.d.ts +5 -0
  30. package/build/dalvikExecutableParser.js +1439 -0
  31. package/build/dalvikExecutableParser.test.js +70 -0
  32. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
  33. package/build/debugLogInputParser.d.ts +4 -0
  34. package/build/debugLogInputParser.js +16 -0
  35. package/build/debugLogParser.js +14 -3
  36. package/build/disjunctionParser.d.ts +2 -1
  37. package/build/disjunctionParser.js +4 -2
  38. package/build/elementTerminatedArrayParser.d.ts +3 -0
  39. package/build/elementTerminatedArrayParser.js +18 -0
  40. package/build/elementTerminatedArrayParser.test.js +52 -0
  41. package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
  42. package/build/elementTerminatedSequenceArrayParser.js +32 -0
  43. package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
  44. package/build/elementTerminatedSequenceParser.d.ts +3 -0
  45. package/build/elementTerminatedSequenceParser.js +27 -0
  46. package/build/elementTerminatedSequenceParser.test.js +34 -0
  47. package/build/exactElementParser.js +10 -5
  48. package/build/exactSequenceParser.d.ts +2 -1
  49. package/build/exactSequenceParser.js +12 -2
  50. package/build/fetchCid.d.ts +1 -0
  51. package/build/fetchCid.js +107 -0
  52. package/build/fixedLengthSequenceParser.d.ts +1 -0
  53. package/build/fixedLengthSequenceParser.js +18 -1
  54. package/build/fixedLengthSequenceParser.test.js +41 -0
  55. package/build/hasExecutable.d.ts +1 -0
  56. package/build/hasExecutable.js +8 -0
  57. package/build/highResolutionTimer.d.ts +16 -0
  58. package/build/highResolutionTimer.js +42 -0
  59. package/build/inputReader.d.ts +11 -0
  60. package/build/inputReader.js +37 -0
  61. package/build/inputReader.test.js +165 -0
  62. package/build/inputReaderState.d.ts +10 -0
  63. package/build/inputReaderState.js +16 -0
  64. package/build/inspect.d.ts +1 -0
  65. package/build/inspect.js +7 -0
  66. package/build/javaKeyStoreParser.test.js +2 -2
  67. package/build/jsonParser.d.ts +2 -0
  68. package/build/jsonParser.js +11 -14
  69. package/build/leb128Parser.d.ts +7 -0
  70. package/build/leb128Parser.js +82 -0
  71. package/build/leb128Parser.test.js +107 -0
  72. package/build/lookaheadParser.d.ts +2 -0
  73. package/build/lookaheadParser.js +14 -0
  74. package/build/negativeLookaheadParser.js +21 -15
  75. package/build/negativeLookaheadParser.test.js +30 -0
  76. package/build/nonEmptyArrayParser.d.ts +2 -0
  77. package/build/nonEmptyArrayParser.js +32 -0
  78. package/build/nonEmptyArrayParser.test.js +16 -0
  79. package/build/parser.d.ts +10 -1
  80. package/build/parser.js +66 -31
  81. package/build/parser.test.js +79 -12
  82. package/build/parserAccessorParser.js +9 -1
  83. package/build/parserConsumedSequenceParser.js +20 -15
  84. package/build/parserContext.d.ts +14 -0
  85. package/build/parserContext.js +56 -27
  86. package/build/parserContext.test.js +27 -0
  87. package/build/parserCreatorCompose.d.ts +1 -0
  88. package/build/parserCreatorCompose.js +8 -2
  89. package/build/parserError.d.ts +6 -0
  90. package/build/parserError.js +6 -6
  91. package/build/parserInputCompanion.d.ts +15 -0
  92. package/build/parserInputCompanion.js +38 -0
  93. package/build/promiseCompose.d.ts +1 -1
  94. package/build/promiseCompose.js +12 -1
  95. package/build/promiseSettled.d.ts +1 -0
  96. package/build/promiseSettled.js +4 -0
  97. package/build/separatedArrayParser.d.ts +2 -0
  98. package/build/separatedArrayParser.js +39 -0
  99. package/build/separatedArrayParser.test.d.ts +1 -0
  100. package/build/separatedArrayParser.test.js +21 -0
  101. package/build/sequenceBuffer.d.ts +10 -0
  102. package/build/sequenceBuffer.js +54 -2
  103. package/build/sequenceBuffer.test.js +57 -0
  104. package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
  105. package/build/sequenceTerminatedSequenceParser.js +32 -0
  106. package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
  107. package/build/sequenceTerminatedSequenceParser.test.js +37 -0
  108. package/build/skipParser.d.ts +1 -1
  109. package/build/skipParser.js +4 -2
  110. package/build/skipToParser.d.ts +2 -0
  111. package/build/skipToParser.js +11 -0
  112. package/build/sliceBoundedParser.d.ts +1 -1
  113. package/build/sliceBoundedParser.js +7 -2
  114. package/build/sliceBoundedParser.test.js +35 -1
  115. package/build/smali.d.ts +1 -0
  116. package/build/smali.js +17 -0
  117. package/build/smaliParser.d.ts +12 -0
  118. package/build/smaliParser.js +656 -0
  119. package/build/smaliParser.test.d.ts +1 -0
  120. package/build/smaliParser.test.js +115 -0
  121. package/build/terminatedArrayParser.d.ts +3 -1
  122. package/build/terminatedArrayParser.js +79 -2
  123. package/build/terminatedArrayParser.test.d.ts +1 -0
  124. package/build/terminatedArrayParser.test.js +131 -0
  125. package/build/toAsyncIterable.d.ts +1 -0
  126. package/build/toAsyncIterable.js +7 -0
  127. package/build/toAsyncIterator.d.ts +1 -0
  128. package/build/toAsyncIterator.js +33 -0
  129. package/build/tupleParser.d.ts +4 -0
  130. package/build/tupleParser.js +1 -5
  131. package/build/unionParser.d.ts +2 -1
  132. package/build/unionParser.js +27 -12
  133. package/build/unionParser.test.d.ts +1 -0
  134. package/build/unionParser.test.js +60 -0
  135. package/build/zipParser.d.ts +7 -2
  136. package/build/zipParser.js +36 -12
  137. package/build/zipUnparser.d.ts +4 -1
  138. package/build/zipUnparser.js +55 -26
  139. package/build/zipUnparser.test.js +14 -14
  140. package/package.json +23 -7
  141. package/src/allSettledStream.test.ts +40 -0
  142. package/src/allSettledStream.ts +47 -15
  143. package/src/androidPackage.ts +48 -0
  144. package/src/{apkParser.test.ts → androidPackageParser.test.ts} +6 -7
  145. package/src/{apkParser.test.ts.md → androidPackageParser.test.ts.md} +4 -4
  146. package/src/androidPackageParser.test.ts.snap +0 -0
  147. package/src/androidPackageParser.ts +440 -0
  148. package/src/androidPackageUnparser.test.ts +36 -0
  149. package/src/androidPackageUnparser.ts +120 -0
  150. package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
  151. package/src/arrayParser.test.ts +3 -3
  152. package/src/backsmali.ts +30 -0
  153. package/src/bsonParser.ts +13 -2
  154. package/src/customInvariant.ts +1 -1
  155. package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
  156. package/src/dalvikBytecodeParser.ts +2074 -0
  157. package/src/dalvikExecutable.ts +220 -0
  158. package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
  159. package/src/dalvikExecutableParser/typeParsers.ts +65 -0
  160. package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
  161. package/src/dalvikExecutableParser.test.ts +89 -0
  162. package/src/dalvikExecutableParser.test.ts.md +634 -0
  163. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  164. package/src/dalvikExecutableParser.ts +2768 -0
  165. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
  166. package/src/debugLogInputParser.ts +28 -0
  167. package/src/debugLogParser.ts +19 -3
  168. package/src/disjunctionParser.ts +10 -5
  169. package/src/elementTerminatedArrayParser.test.ts +99 -0
  170. package/src/elementTerminatedArrayParser.ts +31 -0
  171. package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
  172. package/src/elementTerminatedSequenceArrayParser.ts +52 -0
  173. package/src/elementTerminatedSequenceParser.test.ts +54 -0
  174. package/src/elementTerminatedSequenceParser.ts +43 -0
  175. package/src/exactElementParser.ts +17 -11
  176. package/src/exactSequenceParser.ts +23 -2
  177. package/src/fetchCid.ts +125 -0
  178. package/src/fixedLengthSequenceParser.test.ts +77 -0
  179. package/src/fixedLengthSequenceParser.ts +28 -1
  180. package/src/hasExecutable.ts +11 -0
  181. package/src/highResolutionTimer.ts +49 -0
  182. package/src/inputReader.test.ts +209 -0
  183. package/src/inputReader.ts +75 -0
  184. package/src/inputReaderState.ts +33 -0
  185. package/src/inspect.ts +9 -0
  186. package/src/javaKeyStoreParser.test.ts +2 -3
  187. package/src/jsonParser.ts +13 -25
  188. package/src/leb128Parser.test.ts +171 -0
  189. package/src/leb128Parser.ts +125 -0
  190. package/src/lookaheadParser.ts +19 -0
  191. package/src/negativeLookaheadParser.test.ts +53 -0
  192. package/src/negativeLookaheadParser.ts +26 -14
  193. package/src/nonEmptyArrayParser.test.ts +20 -0
  194. package/src/nonEmptyArrayParser.ts +44 -0
  195. package/src/optionalParser.ts +1 -0
  196. package/src/parser.test.ts +131 -12
  197. package/src/parser.test.ts.md +21 -21
  198. package/src/parser.test.ts.snap +0 -0
  199. package/src/parser.ts +149 -45
  200. package/src/parserAccessorParser.ts +12 -2
  201. package/src/parserConsumedSequenceParser.ts +25 -16
  202. package/src/parserContext.test.ts +31 -0
  203. package/src/parserContext.ts +109 -37
  204. package/src/parserCreatorCompose.ts +20 -2
  205. package/src/parserError.ts +9 -6
  206. package/src/parserInputCompanion.ts +55 -0
  207. package/src/promiseCompose.ts +17 -3
  208. package/src/promiseSettled.ts +6 -0
  209. package/src/separatedArrayParser.test.ts +34 -0
  210. package/src/separatedArrayParser.ts +55 -0
  211. package/src/sequenceBuffer.test.ts +70 -0
  212. package/src/sequenceBuffer.ts +88 -2
  213. package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
  214. package/src/sequenceTerminatedSequenceParser.ts +62 -0
  215. package/src/skipParser.ts +7 -5
  216. package/src/skipToParser.ts +16 -0
  217. package/src/sliceBoundedParser.test.ts +43 -1
  218. package/src/sliceBoundedParser.ts +19 -1
  219. package/src/smali.ts +24 -0
  220. package/src/smaliParser.test.ts +132 -0
  221. package/src/smaliParser.test.ts.md +2320 -0
  222. package/src/smaliParser.test.ts.snap +0 -0
  223. package/src/smaliParser.ts +1166 -0
  224. package/src/terminatedArrayParser.test.ts +258 -0
  225. package/src/terminatedArrayParser.ts +108 -3
  226. package/src/toAsyncIterable.ts +7 -0
  227. package/src/toAsyncIterator.ts +48 -0
  228. package/src/tupleParser.ts +8 -5
  229. package/src/unionParser.test.ts +79 -0
  230. package/src/unionParser.ts +44 -16
  231. package/src/zipParser.ts +77 -18
  232. package/src/zipUnparser.test.ts +18 -18
  233. package/src/zipUnparser.ts +88 -27
  234. package/build/apk.d.ts +0 -39
  235. package/build/apkParser.d.ts +0 -16
  236. package/build/apkParser.js +0 -164
  237. package/build/apkUnparser.d.ts +0 -4
  238. package/build/apkUnparser.test.js +0 -26
  239. package/build/arbitraryDosDate.d.ts +0 -2
  240. package/build/arbitraryDosDate.js +0 -8
  241. package/build/arbitraryZipEntry.d.ts +0 -3
  242. package/build/arbitraryZipEntry.js +0 -26
  243. package/build/createDisjunctionParser.d.ts +0 -2
  244. package/build/createDisjunctionParser.js +0 -47
  245. package/build/createExactParser.d.ts +0 -2
  246. package/build/createExactParser.js +0 -12
  247. package/build/createSequentialUnionParser.d.ts +0 -2
  248. package/build/createSequentialUnionParser.js +0 -69
  249. package/build/fixedLengthChunkParser.d.ts +0 -2
  250. package/build/fixedLengthChunkParser.js +0 -12
  251. package/build/fixedLengthParser.d.ts +0 -2
  252. package/build/fixedLengthParser.js +0 -12
  253. package/build/inputChunkBuffer.d.ts +0 -15
  254. package/build/inputChunkBuffer.js +0 -40
  255. package/build/inputChunkBuffer.test.js +0 -34
  256. package/build/inputCompanion.d.ts +0 -18
  257. package/build/inputCompanion.js +0 -28
  258. package/build/invariantDefined.d.ts +0 -1
  259. package/build/invariantDefined.js +0 -5
  260. package/build/invariantIdentity.d.ts +0 -3
  261. package/build/invariantIdentity.js +0 -5
  262. package/build/javaKeystoreParser.d.ts +0 -2
  263. package/build/javaKeystoreParser.js +0 -7
  264. package/build/jsonParser2.d.ts +0 -3
  265. package/build/jsonParser2.js +0 -52
  266. package/build/jsonParser2.test.js +0 -22
  267. package/build/negativeLookahead.d.ts +0 -2
  268. package/build/negativeLookahead.js +0 -18
  269. package/build/parserCompose.d.ts +0 -3
  270. package/build/parserCompose.js +0 -7
  271. package/build/parserImplementationInvariantInvariant.d.ts +0 -3
  272. package/build/parserImplementationInvariantInvariant.js +0 -15
  273. package/build/parserInvariant.d.ts +0 -4
  274. package/build/parserInvariant.js +0 -11
  275. package/build/promiseFish.d.ts +0 -1
  276. package/build/promiseFish.js +0 -3
  277. package/build/sequenceParser.d.ts +0 -3
  278. package/build/sequenceParser.js +0 -10
  279. package/build/terminatedSequenceParser.d.ts +0 -2
  280. package/build/terminatedSequenceParser.js +0 -24
  281. package/build/unparserInputCompanion.d.ts +0 -15
  282. package/build/unparserInputCompanion.js +0 -13
  283. package/build/zipEntry.d.ts +0 -28
  284. package/build/zipFile.d.ts +0 -32
  285. package/build/zipFileEntry.d.ts +0 -6
  286. package/src/apk.ts +0 -48
  287. package/src/apkParser.test.ts.snap +0 -0
  288. package/src/apkParser.ts +0 -392
  289. package/src/apkUnparser.test.ts +0 -37
  290. package/src/apkUnparser.ts +0 -120
  291. package/src/invariantDefined.ts +0 -6
  292. package/src/invariantIdentity.ts +0 -8
  293. /package/build/{apk.js → androidPackage.js} +0 -0
  294. /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
  295. /package/build/{apkUnparser.test.d.ts → androidPackageUnparser.test.d.ts} +0 -0
  296. /package/build/{arbitraryDosPermissions.d.ts → dalvikExecutableParser.test.d.ts} +0 -0
  297. /package/build/{arbitraryDosPermissions.js → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
  298. /package/build/{inputChunkBuffer.test.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
  299. /package/build/{jsonParser2.test.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
  300. /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceParser.test.d.ts} +0 -0
  301. /package/build/{parserParsingInvariant.js → fixedLengthSequenceParser.test.d.ts} +0 -0
  302. /package/build/{zipEntry.js → leb128Parser.test.d.ts} +0 -0
  303. /package/build/{zipFile.js → negativeLookaheadParser.test.d.ts} +0 -0
  304. /package/build/{zipFileEntry.js → nonEmptyArrayParser.test.d.ts} +0 -0
@@ -11,6 +11,8 @@ import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js'
11
11
  import { createOptionalParser } from './optionalParser.js';
12
12
  import { parserCreatorCompose } from './parserCreatorCompose.js';
13
13
  import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
14
+ import { createNegativeLookaheadParser } from './negativeLookaheadParser.js';
15
+ import { createSequenceTerminatedSequenceParser } from './sequenceTerminatedSequenceParser.js';
14
16
  // https://pkwaredownloads.blob.core.windows.net/pem/APPNOTE.txt
15
17
  const uint16LEParser = promiseCompose(createFixedLengthSequenceParser(2), array => Buffer.from(array).readUInt16LE());
16
18
  setParserName(uint16LEParser, 'uint16LEParser');
@@ -29,8 +31,9 @@ const zipCompressionMethodParser = promiseCompose(uint16LEParser, compressionMet
29
31
  }
30
32
  invariant(false, 'Unsupported compression method %s', compressionMethod);
31
33
  });
34
+ const zipLocalFileHeaderSignatureParser = createExactSequenceParser(Buffer.from('504b0304', 'hex'));
32
35
  const zipLocalFileHeaderParser_ = createTupleParser([
33
- createExactSequenceParser(Buffer.from('504b0304', 'hex')),
36
+ zipLocalFileHeaderSignatureParser,
34
37
  uint16LEParser,
35
38
  uint16LEParser,
36
39
  zipCompressionMethodParser,
@@ -61,20 +64,40 @@ const zipLocalFileHeaderParser = promiseCompose(zipLocalFileHeaderParser_, ([_zi
61
64
  const zipEncryptionHeaderParser = async (parserContext) => {
62
65
  parserContext.invariant(false, 'Not implemented');
63
66
  };
64
- const zipDataDescriptorParser = createTupleParser([
67
+ const zipDataDescriptorSignature = Buffer.from('504b0708', 'hex');
68
+ const zipDataDescriptorSignatureParser = createExactSequenceParser(zipDataDescriptorSignature);
69
+ const zipDataDescriptorParser = promiseCompose(createTupleParser([
70
+ createNegativeLookaheadParser(zipLocalFileHeaderSignatureParser),
65
71
  // FIXME: optional in spec
66
- // createOptionalParser(createExactSequenceParser<Uint8Array>(Buffer.from('504b0708', 'hex'))),
67
- createExactSequenceParser(Buffer.from('504b0708', 'hex')),
72
+ //createOptionalParser(zipDataDescriptorSignatureParser),
73
+ zipDataDescriptorSignatureParser,
68
74
  uint32LEParser,
69
75
  uint32LEParser,
70
76
  uint32LEParser,
71
- ]);
72
- export const zipLocalFileParser = promiseCompose(parserCreatorCompose(() => zipLocalFileHeaderParser, zipLocalFileHeader => createTupleParser([
73
- async () => zipLocalFileHeader,
74
- createOptionalParser(zipEncryptionHeaderParser),
75
- createFixedLengthSequenceParser(zipLocalFileHeader.compressedSize),
76
- createOptionalParser(zipDataDescriptorParser),
77
- ]))(), ([zipLocalFileHeader, zipEncryptionHeader, compressedData, zipDataDescriptor,]) => ({
77
+ ]), ([_notZipLocalFileHeaderSignature, _zipDataDescriptorSignature, crc32, compressedSize, uncompressedSize,]) => ({
78
+ crc32,
79
+ compressedSize,
80
+ uncompressedSize,
81
+ }));
82
+ setParserName(zipDataDescriptorParser, 'zipDataDescriptorParser');
83
+ export const zipLocalFileParser = promiseCompose(parserCreatorCompose(() => zipLocalFileHeaderParser, zipLocalFileHeader => {
84
+ const sizeInDataDescriptor = Boolean(zipLocalFileHeader.generalPurposeBitFlag & 0b0000_0000_0000_1000
85
+ && zipLocalFileHeader.crc32 === 0
86
+ && zipLocalFileHeader.compressedSize === 0
87
+ && zipLocalFileHeader.uncompressedSize === 0);
88
+ return createTupleParser([
89
+ async () => zipLocalFileHeader,
90
+ createOptionalParser(zipEncryptionHeaderParser),
91
+ (sizeInDataDescriptor
92
+ ? createSequenceTerminatedSequenceParser(zipDataDescriptorSignature, {
93
+ consumeTerminator: false,
94
+ })
95
+ : createFixedLengthSequenceParser(zipLocalFileHeader.compressedSize)),
96
+ (sizeInDataDescriptor
97
+ ? ((parser) => parser)
98
+ : createOptionalParser)(zipDataDescriptorParser),
99
+ ]);
100
+ })(), ([zipLocalFileHeader, zipEncryptionHeader, compressedData, zipDataDescriptor,]) => ({
78
101
  zipLocalFileHeader,
79
102
  zipEncryptionHeader,
80
103
  compressedData,
@@ -163,7 +186,7 @@ const zipEndOfCentralDirectoryRecordParser_ = createTupleParser([
163
186
  uint32LEParser,
164
187
  zipFileCommentParser,
165
188
  ]);
166
- setParserName(zipEndOfCentralDirectoryRecordParser_, 'endOfCentralDirectoryRecordParser_');
189
+ setParserName(zipEndOfCentralDirectoryRecordParser_, 'zipEndOfCentralDirectoryRecordParser_');
167
190
  export const zipEndOfCentralDirectoryRecordParser = promiseCompose(zipEndOfCentralDirectoryRecordParser_, ([_endOfCentralDirectoryRecordSignature, numberOfThisDisk, numberOfTheDiskWithTheStartOfTheCentralDirectory, totalNumberOfEntriesInTheCentralDirectoryOnThisDisk, totalNumberOfEntriesInTheCentralDirectory, sizeOfTheCentralDirectory, offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber, zipFileComment,]) => ({
168
191
  numberOfThisDisk,
169
192
  numberOfTheDiskWithTheStartOfTheCentralDirectory,
@@ -173,6 +196,7 @@ export const zipEndOfCentralDirectoryRecordParser = promiseCompose(zipEndOfCentr
173
196
  offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber,
174
197
  zipFileComment,
175
198
  }));
199
+ setParserName(zipEndOfCentralDirectoryRecordParser, 'zipEndOfCentralDirectoryRecordParser');
176
200
  const zipParser_ = createTupleParser([
177
201
  createArrayParser(zipLocalFileParser),
178
202
  createOptionalParser(zipArchiveDecryptionHeaderParser),
@@ -2,4 +2,7 @@ import { Unparser } from "./unparser.js";
2
2
  import { Zip } from "./zip.js";
3
3
  import { ZipEndOfCentralDirectoryRecord } from './zipParser.js';
4
4
  export declare const zipEndOfCentralDirectoryRecordUnparser: Unparser<ZipEndOfCentralDirectoryRecord, Uint8Array>;
5
- export declare const zipUnparser: Unparser<Zip, Uint8Array>;
5
+ export declare const createZipUnparser: ({ dataDescriptor, }?: {
6
+ dataDescriptor?: boolean;
7
+ }) => Unparser<Zip, Uint8Array>;
8
+ export declare const zipUnparser: Unparser<Zip, Uint8Array<ArrayBufferLike>>;
@@ -45,7 +45,28 @@ export const zipEndOfCentralDirectoryRecordUnparser = async function* (zipEndOfC
45
45
  yield* uint32LEUnparser(zipEndOfCentralDirectoryRecord.offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber, unparserContext);
46
46
  yield* uint16LEPrefixedStringUnparser(zipEndOfCentralDirectoryRecord.zipFileComment, unparserContext);
47
47
  };
48
- export const zipUnparser = async function* (zip, unparserContext) {
48
+ const zipDataDescriptorUnparser = async function* ({ crc32, compressedSize, uncompressedSize, }, unparserContext) {
49
+ yield Buffer.from('504b0708', 'hex');
50
+ yield* uint32LEUnparser(crc32, unparserContext);
51
+ yield* uint32LEUnparser(compressedSize, unparserContext);
52
+ yield* uint32LEUnparser(uncompressedSize, unparserContext);
53
+ };
54
+ const zipLocalFileHeaderUnparser = async function* ({ versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModifiedFile, crc32, compressedSize, uncompressedSize, filePath, extraField, }, unparserContext) {
55
+ yield Buffer.from('504b0304', 'hex');
56
+ yield* uint16LEUnparser(versionNeededToExtract, unparserContext);
57
+ yield* uint16LEUnparser(generalPurposeBitFlag, unparserContext);
58
+ yield* zipCompressionMethodUnparser(compressionMethod, unparserContext);
59
+ yield* dosDateTimeUnparser(lastModifiedFile, unparserContext);
60
+ yield* uint32LEUnparser(crc32, unparserContext);
61
+ yield* uint32LEUnparser(compressedSize, unparserContext);
62
+ yield* uint32LEUnparser(uncompressedSize, unparserContext);
63
+ const filePathBuffer = Buffer.from(filePath, 'utf8');
64
+ yield* uint16LEUnparser(filePathBuffer.length, unparserContext);
65
+ yield* uint16LEUnparser(extraField.length, unparserContext);
66
+ yield filePathBuffer;
67
+ yield extraField;
68
+ };
69
+ export const createZipUnparser = ({ dataDescriptor = false, } = {}) => async function* (zip, unparserContext) {
49
70
  const compressedContentByZipFileEntry = new Map(zip.entries.flatMap(zipEntry => {
50
71
  if (zipEntry.type !== 'file') {
51
72
  return [];
@@ -66,37 +87,44 @@ export const zipUnparser = async function* (zip, unparserContext) {
66
87
  const localHeaderPositionByZipEntry = new Map();
67
88
  for (const zipEntry of zip.entries) {
68
89
  localHeaderPositionByZipEntry.set(zipEntry, unparserContext.position);
69
- yield Buffer.from('504b0304', 'hex');
70
- yield* uint16LEUnparser(10, unparserContext); // version needed to extract
71
- yield* uint16LEUnparser(0, unparserContext); // general purpose bit flag
72
- if (zipEntry.type === 'file') {
73
- yield* zipCompressionMethodUnparser(zipEntry.compression, unparserContext);
74
- }
75
- else {
76
- yield* uint16LEUnparser(0, unparserContext);
77
- }
78
- yield* dosDateTimeUnparser(zipEntry.date, unparserContext);
90
+ const filePath = filePathByZipEntry.get(zipEntry);
91
+ const zipLocalFileHeader = {
92
+ versionNeededToExtract: 20,
93
+ generalPurposeBitFlag: 0,
94
+ compressionMethod: 'store',
95
+ lastModifiedFile: zipEntry.date,
96
+ crc32: 0,
97
+ compressedSize: 0,
98
+ uncompressedSize: 0,
99
+ filePath,
100
+ extraField: Buffer.alloc(0),
101
+ };
102
+ let shouldWriteDataDescriptor = false;
79
103
  if (zipEntry.type === 'file') {
80
104
  const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
81
- yield* uint32LEUnparser(0, unparserContext); // crc32 // TODO
82
- yield* uint32LEUnparser(compressedContent.length, unparserContext);
83
- yield* uint32LEUnparser(zipEntry.content.length, unparserContext);
105
+ zipLocalFileHeader.compressionMethod = zipEntry.compression;
106
+ zipLocalFileHeader.crc32 = 0; // TODO
107
+ zipLocalFileHeader.compressedSize = compressedContent.length;
108
+ zipLocalFileHeader.uncompressedSize = zipEntry.content.length;
109
+ if (dataDescriptor) {
110
+ shouldWriteDataDescriptor = true;
111
+ zipLocalFileHeader.generalPurposeBitFlag |= 0b0000_0000_0000_1000;
112
+ zipLocalFileHeader.crc32 = 0;
113
+ zipLocalFileHeader.compressedSize = 0;
114
+ zipLocalFileHeader.uncompressedSize = 0;
115
+ }
84
116
  }
85
- else {
86
- yield* uint32LEUnparser(0, unparserContext);
87
- yield* uint32LEUnparser(0, unparserContext);
88
- yield* uint32LEUnparser(0, unparserContext);
89
- }
90
- const filePath = filePathByZipEntry.get(zipEntry);
91
- const filePathBuffer = Buffer.from(filePath, 'utf8');
92
- const extraFieldBuffer = Buffer.alloc(0);
93
- yield* uint16LEUnparser(filePathBuffer.length, unparserContext);
94
- yield* uint16LEUnparser(extraFieldBuffer.length, unparserContext);
95
- yield filePathBuffer;
96
- yield extraFieldBuffer;
117
+ yield* zipLocalFileHeaderUnparser(zipLocalFileHeader, unparserContext);
97
118
  if (zipEntry.type === 'file') {
98
119
  const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
99
120
  yield compressedContent;
121
+ if (shouldWriteDataDescriptor) {
122
+ yield* zipDataDescriptorUnparser({
123
+ crc32: zipLocalFileHeader.crc32,
124
+ compressedSize: zipLocalFileHeader.compressedSize,
125
+ uncompressedSize: zipLocalFileHeader.uncompressedSize,
126
+ }, unparserContext);
127
+ }
100
128
  }
101
129
  }
102
130
  const startOfCentralDirectoryPosition = unparserContext.position;
@@ -169,3 +197,4 @@ export const zipUnparser = async function* (zip, unparserContext) {
169
197
  zipFileComment: zip.comment,
170
198
  }, unparserContext);
171
199
  };
200
+ export const zipUnparser = createZipUnparser();
@@ -1,21 +1,15 @@
1
- import { testProp } from '@fast-check/ava';
1
+ import { fc, testProp } from '@fast-check/ava';
2
2
  import { temporaryFile } from 'tempy';
3
3
  import { execa } from 'execa';
4
4
  import fsPromises from 'node:fs/promises';
5
5
  import { runUnparser } from './unparser.js';
6
- import { zipUnparser } from './zipUnparser.js';
6
+ import { createZipUnparser } from './zipUnparser.js';
7
7
  import { uint8ArrayUnparserOutputCompanion } from './unparserOutputCompanion.js';
8
8
  import { runParser } from './parser.js';
9
9
  import { zipParser } from './zipParser.js';
10
10
  import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
11
11
  import { arbitraryZip } from './arbitraryZip.js';
12
- async function hasExecutable(executable) {
13
- const hasExecutable = execa(executable).then(() => true, () => false);
14
- if (!hasExecutable) {
15
- console.warn(`Executable %o not found`, executable);
16
- }
17
- return hasExecutable;
18
- }
12
+ import { hasExecutable } from './hasExecutable.js';
19
13
  const hasZipinfoPromise = hasExecutable('zipinfo');
20
14
  const has7zPromise = hasExecutable('7z');
21
15
  async function zipinfo(zipFilePath) {
@@ -45,16 +39,22 @@ async function _7zList(zipFilePath) {
45
39
  }
46
40
  testProp('zip', [
47
41
  arbitraryZip,
48
- ], async (t, zip) => {
42
+ fc.record({
43
+ dataDescriptor: fc.boolean(),
44
+ }),
45
+ ], async (t, zip, options) => {
46
+ const zipUnparser = createZipUnparser(options);
47
+ {
48
+ const zipStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
49
+ await fsPromises.writeFile('/tmp/zip.zip', zipStream);
50
+ }
49
51
  const actualStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
50
52
  const actual = await runParser(zipParser, actualStream, uint8ArrayParserInputCompanion);
51
- const isDeepEqual = t.deepEqual(actual, zip);
52
- if (!isDeepEqual) {
53
- return;
54
- }
53
+ t.deepEqual(actual, zip);
55
54
  const hasZipinfo = await hasZipinfoPromise;
56
55
  const has7z = await has7zPromise;
57
56
  if (!hasZipinfo && !has7z) {
57
+ t.pass('no zipinfo or 7z, skipping zipfile check');
58
58
  return;
59
59
  }
60
60
  const temporaryFilePath = temporaryFile({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@futpib/parser",
3
- "version": "1.0.1",
3
+ "version": "1.0.2",
4
4
  "main": "build/index.js",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
@@ -24,20 +24,24 @@
24
24
  "@ava/typescript": "^5.0.0",
25
25
  "@fast-check/ava": "^2.0.1",
26
26
  "@types/invariant": "^2.2.37",
27
- "@types/node": "^22.10.1",
27
+ "@types/node": "^22.10.2",
28
28
  "ava": "^6.2.0",
29
- "bson": "^6.10.0",
30
- "c8": "^10.1.2",
29
+ "bson": "^6.10.1",
30
+ "c8": "^10.1.3",
31
31
  "coveralls": "^3.1.1",
32
+ "env-paths": "^3.0.0",
32
33
  "eslint-config-xo-typescript-overrides": "^1.6.1",
33
34
  "execa": "^9.5.2",
34
- "fast-check": "^3.23.1",
35
+ "fast-check": "^3.23.2",
35
36
  "invariant": "^2.2.4",
36
37
  "jszip": "^3.10.1",
38
+ "leb128": "^0.0.5",
39
+ "mutf-8": "^1.1.4",
40
+ "p-memoize": "^7.1.1",
37
41
  "tempy": "^3.1.0",
38
- "type-fest": "^4.29.0",
42
+ "type-fest": "^4.30.1",
39
43
  "typescript": "^5.7.2",
40
- "xo": "^0.59.3"
44
+ "xo": "^0.60.0"
41
45
  },
42
46
  "xo": {
43
47
  "extends": [
@@ -49,6 +53,18 @@
49
53
  },
50
54
  "packageManager": "yarn@4.5.3",
51
55
  "dependencies": {
56
+ "fp-ts": "^2.16.9",
57
+ "mem": "^10.0.0",
58
+ "monocle-ts": "^2.3.13",
59
+ "newtype-ts": "^0.3.5",
52
60
  "p-mutex": "^0.1.0"
61
+ },
62
+ "peerDependencies": {
63
+ "mutf-8": "^1.1.4"
64
+ },
65
+ "peerDependenciesMeta": {
66
+ "mutf-8": {
67
+ "optional": true
68
+ }
53
69
  }
54
70
  }
@@ -57,3 +57,43 @@ test('allSettledStream', async t => {
57
57
  t.snapshot(results);
58
58
  t.is(results.length, 8);
59
59
  });
60
+
61
+ test('allSettledStream reader cancel', async t => {
62
+ const stream = allSettledStream<number, number>([
63
+ 10,
64
+ 20,
65
+ 0,
66
+ 40,
67
+ 30,
68
+ ].map((delay) => ({
69
+ promise: new Promise<number>((resolve) => {
70
+ setTimeout(() => {
71
+ resolve(delay);
72
+ }, delay);
73
+ }),
74
+ context: delay,
75
+ })));
76
+
77
+ const results: any[] = [];
78
+
79
+ for await (const value of stream) {
80
+ results.push(value);
81
+
82
+ if (value.context === 30) {
83
+ break;
84
+ }
85
+ }
86
+
87
+ await new Promise<void>(resolve => {
88
+ setTimeout(resolve, 50);
89
+ });
90
+
91
+ stream.cancel();
92
+
93
+ for await (const value of stream) {
94
+ t.fail();
95
+ results.push(value);
96
+ }
97
+
98
+ t.deepEqual(results.map(({ context }) => context), [ 0, 10, 20, 30 ]);
99
+ });
@@ -1,3 +1,5 @@
1
+ import { promiseSettled } from "./promiseSettled.js";
2
+
1
3
  type AllSettledStreamFulfilledResult<T, Context> = {
2
4
  status: 'fulfilled';
3
5
  value: T;
@@ -18,27 +20,57 @@ type AllSettledStreamTask<T, Context> = {
18
20
  };
19
21
 
20
22
  export function allSettledStream<T, Context>(tasks: Array<AllSettledStreamTask<T, Context>>): ReadableStream<AllSettedStreamResult<T, Context>> {
23
+ let cancelled = false;
24
+
21
25
  return new ReadableStream({
22
- async start(controller) {
23
- let settledCount = 0;
24
- for (const { promise, context } of tasks) {
25
- (async () => {
26
- const [ promiseSettledResult ] = await Promise.allSettled([ promise ]);
26
+ start(controller) {
27
+ const startStack = (
28
+ (new Error('allSettledStream ReadableStream start stack holder').stack ?? '')
29
+ .split('\n')
30
+ .slice(1)
31
+ .join('\n')
32
+ );
33
+
34
+ const allSettledStreamTaskAwaiter = async ({
35
+ promise,
36
+ context,
37
+ }: AllSettledStreamTask<T, Context>) => {
38
+ const promiseSettledResult = await promiseSettled(promise);
39
+
40
+ if (
41
+ promiseSettledResult.status === 'rejected'
42
+ && promiseSettledResult.reason instanceof Error
43
+ && promiseSettledResult.reason.stack
44
+ ) {
45
+ promiseSettledResult.reason.stack += `\n${startStack}`;
46
+ }
27
47
 
28
- settledCount++;
48
+ settledCount++;
29
49
 
30
- const allSettedStreamResult: AllSettedStreamResult<T, Context> = {
31
- ...promiseSettledResult,
32
- context,
33
- };
50
+ if (cancelled) {
51
+ return;
52
+ }
34
53
 
35
- controller.enqueue(allSettedStreamResult);
54
+ const allSettedStreamResult: AllSettedStreamResult<T, Context> = {
55
+ ...promiseSettledResult,
56
+ context,
57
+ };
36
58
 
37
- if (settledCount === tasks.length) {
38
- controller.close();
39
- }
40
- })();
59
+ controller.enqueue(allSettedStreamResult);
60
+
61
+ if (settledCount === tasks.length) {
62
+ controller.close();
63
+ }
64
+ };
65
+
66
+ let settledCount = 0;
67
+ for (const task of tasks) {
68
+ allSettledStreamTaskAwaiter(task);
41
69
  }
42
70
  },
71
+
72
+ cancel() {
73
+ cancelled = true;
74
+ },
43
75
  });
44
76
  }
@@ -0,0 +1,48 @@
1
+ import { type Zip } from './zip.js';
2
+
3
+ export type AndroidPackageSigningBlockPair = {
4
+ id: number;
5
+ value: Uint8Array;
6
+ };
7
+
8
+ export type AndroidPackageSignatureV2Digest = {
9
+ signatureAlgorithmId: number;
10
+ digest: Uint8Array;
11
+ };
12
+
13
+ export type AndroidPackageSignatureV2AdditionalAttribute = {
14
+ id: number;
15
+ value: Uint8Array;
16
+ };
17
+
18
+ export type AndroidPackageSignatureV2SignedData = {
19
+ digests: AndroidPackageSignatureV2Digest[];
20
+ certificates: Uint8Array[];
21
+ additionalAttributes: AndroidPackageSignatureV2AdditionalAttribute[];
22
+ zeroPaddingLength?: number;
23
+ };
24
+
25
+ export type AndroidPackageSignatureV2Signature = {
26
+ signatureAlgorithmId: number;
27
+ signature: Uint8Array;
28
+ };
29
+
30
+ export type AndroidPackageSignatureV2Signer = {
31
+ signedData: AndroidPackageSignatureV2SignedData;
32
+ signatures: AndroidPackageSignatureV2Signature[];
33
+ publicKey: Uint8Array;
34
+ };
35
+
36
+ export type AndroidPackageSignatureV2 = {
37
+ signers: AndroidPackageSignatureV2Signer[];
38
+ };
39
+
40
+ export type AndroidPackageSigningBlock = {
41
+ pairs: AndroidPackageSigningBlockPair[];
42
+ signatureV2?: AndroidPackageSignatureV2;
43
+ zeroPaddingLength?: number;
44
+ };
45
+
46
+ export type AndroidPackage = Zip & {
47
+ signingBlock?: AndroidPackageSigningBlock;
48
+ };
@@ -1,20 +1,19 @@
1
1
  import test from 'ava';
2
2
  import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
3
3
  import { runParser } from './parser.js';
4
- import { apkParser } from './apkParser.js';
4
+ import { androidPackageParser } from './androidPackageParser.js';
5
+ import { fetchCid } from './fetchCid.js';
5
6
 
6
- for (const apkCid of [
7
+ for (const androidPackageCid of [
7
8
  'bafkreicckcmzrdxwoc3w2in3tivpyxrdtcfpct4zwauq3igew3nkpvfapu',
8
9
  'bafkreidqycbgrtp7ywhevsgtm464dqpamxsijpaqfcfz2k3ymc3wrzsb5m',
9
10
  ]) {
10
11
  test(
11
- 'apk ' + apkCid,
12
+ 'androidPackage ' + androidPackageCid,
12
13
  async t => {
13
- const apkResponse = await fetch('https://ipfs.io/ipfs/' + apkCid);
14
+ const androidPackageStream = await fetchCid(androidPackageCid);
14
15
 
15
- const apkStream = apkResponse.body!;
16
-
17
- const actual = await runParser(apkParser, apkStream, uint8ArrayParserInputCompanion, {
16
+ const actual = await runParser(androidPackageParser, androidPackageStream, uint8ArrayParserInputCompanion, {
18
17
  errorJoinMode: 'all',
19
18
  });
20
19
 
@@ -1,10 +1,10 @@
1
- # Snapshot report for `src/apkParser.test.ts`
1
+ # Snapshot report for `src/androidPackageParser.test.ts`
2
2
 
3
- The actual snapshot is saved in `apkParser.test.ts.snap`.
3
+ The actual snapshot is saved in `androidPackageParser.test.ts.snap`.
4
4
 
5
5
  Generated by [AVA](https://avajs.dev).
6
6
 
7
- ## apk bafkreicckcmzrdxwoc3w2in3tivpyxrdtcfpct4zwauq3igew3nkpvfapu
7
+ ## androidPackage bafkreicckcmzrdxwoc3w2in3tivpyxrdtcfpct4zwauq3igew3nkpvfapu
8
8
 
9
9
  > Snapshot 1
10
10
 
@@ -189,7 +189,7 @@ Generated by [AVA](https://avajs.dev).
189
189
  },
190
190
  }
191
191
 
192
- ## apk bafkreidqycbgrtp7ywhevsgtm464dqpamxsijpaqfcfz2k3ymc3wrzsb5m
192
+ ## androidPackage bafkreidqycbgrtp7ywhevsgtm464dqpamxsijpaqfcfz2k3ymc3wrzsb5m
193
193
 
194
194
  > Snapshot 1
195
195