@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.
Files changed (380) 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} +7 -7
  7. package/build/androidPackageUnparser.d.ts +4 -0
  8. package/build/androidPackageUnparser.js +90 -0
  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/arbitraryFileSystemEntry.js +1 -1
  13. package/build/arbitraryZip.d.ts +1 -1
  14. package/build/arbitraryZip.js +13 -19
  15. package/build/arbitraryZipPermissions.d.ts +1 -8
  16. package/build/arbitraryZipPermissions.js +1 -16
  17. package/build/arbitraryZipStream.d.ts +1 -1
  18. package/build/arbitraryZipStream.js +3 -3
  19. package/build/arrayParser.d.ts +1 -1
  20. package/build/arrayParser.js +2 -2
  21. package/build/arrayParser.test.js +4 -4
  22. package/build/arrayUnparser.d.ts +2 -0
  23. package/build/arrayUnparser.js +8 -0
  24. package/build/backsmali.d.ts +1 -0
  25. package/build/backsmali.js +22 -0
  26. package/build/bsonParser.js +6 -2
  27. package/build/bsonParser.test.js +2 -2
  28. package/build/{parserInvariant.d.ts → customInvariant.d.ts} +1 -1
  29. package/build/{parserInvariant.js → customInvariant.js} +1 -1
  30. package/build/dalvikBytecodeParser/formatParsers.d.ts +97 -0
  31. package/build/dalvikBytecodeParser/formatParsers.js +169 -0
  32. package/build/dalvikBytecodeParser.d.ts +107 -0
  33. package/build/dalvikBytecodeParser.js +836 -0
  34. package/build/dalvikExecutable.d.ts +158 -0
  35. package/build/dalvikExecutable.js +20 -0
  36. package/build/dalvikExecutableParser/stringSyntaxParser.d.ts +4 -0
  37. package/build/dalvikExecutableParser/stringSyntaxParser.js +76 -0
  38. package/build/dalvikExecutableParser/typeParsers.d.ts +10 -0
  39. package/build/dalvikExecutableParser/typeParsers.js +34 -0
  40. package/build/dalvikExecutableParser/typedNumbers.d.ts +90 -0
  41. package/build/dalvikExecutableParser/typedNumbers.js +19 -0
  42. package/build/dalvikExecutableParser.d.ts +5 -0
  43. package/build/dalvikExecutableParser.js +1439 -0
  44. package/build/dalvikExecutableParser.test.js +70 -0
  45. package/build/dalvikExecutableParserAgainstSmaliParser.test.js +298 -0
  46. package/build/debugLogInputParser.d.ts +4 -0
  47. package/build/debugLogInputParser.js +16 -0
  48. package/build/debugLogParser.d.ts +1 -1
  49. package/build/debugLogParser.js +15 -4
  50. package/build/disjunctionParser.d.ts +2 -1
  51. package/build/disjunctionParser.js +4 -2
  52. package/build/elementParser.d.ts +2 -2
  53. package/build/elementParser.js +1 -1
  54. package/build/elementTerminatedArrayParser.d.ts +3 -0
  55. package/build/elementTerminatedArrayParser.js +18 -0
  56. package/build/elementTerminatedArrayParser.test.js +52 -0
  57. package/build/elementTerminatedSequenceArrayParser.d.ts +3 -0
  58. package/build/elementTerminatedSequenceArrayParser.js +32 -0
  59. package/build/elementTerminatedSequenceArrayParser.test.js +34 -0
  60. package/build/elementTerminatedSequenceParser.d.ts +3 -0
  61. package/build/elementTerminatedSequenceParser.js +27 -0
  62. package/build/elementTerminatedSequenceParser.test.js +34 -0
  63. package/build/endOfInputParser.d.ts +2 -2
  64. package/build/exactElementParser.d.ts +1 -1
  65. package/build/exactElementParser.js +10 -5
  66. package/build/exactSequenceParser.d.ts +2 -1
  67. package/build/exactSequenceParser.js +12 -2
  68. package/build/fetchCid.d.ts +1 -0
  69. package/build/fetchCid.js +107 -0
  70. package/build/fixedLengthSequenceParser.d.ts +1 -0
  71. package/build/fixedLengthSequenceParser.js +18 -1
  72. package/build/fixedLengthSequenceParser.test.js +41 -0
  73. package/build/hasExecutable.d.ts +1 -0
  74. package/build/hasExecutable.js +8 -0
  75. package/build/highResolutionTimer.d.ts +16 -0
  76. package/build/highResolutionTimer.js +42 -0
  77. package/build/index.d.ts +5 -2
  78. package/build/index.js +3 -0
  79. package/build/inputReader.d.ts +14 -3
  80. package/build/inputReader.js +43 -6
  81. package/build/inputReader.test.js +172 -7
  82. package/build/inputReaderState.d.ts +10 -0
  83. package/build/inputReaderState.js +16 -0
  84. package/build/inspect.d.ts +1 -0
  85. package/build/inspect.js +7 -0
  86. package/build/javaKeyStoreParser.d.ts +2 -0
  87. package/build/javaKeyStoreParser.js +67 -0
  88. package/build/javaKeyStoreParser.test.d.ts +1 -0
  89. package/build/javaKeyStoreParser.test.js +16 -0
  90. package/build/jsonParser.d.ts +2 -0
  91. package/build/jsonParser.js +13 -15
  92. package/build/jsonParser.test.js +2 -2
  93. package/build/leb128Parser.d.ts +7 -0
  94. package/build/leb128Parser.js +82 -0
  95. package/build/leb128Parser.test.d.ts +1 -0
  96. package/build/leb128Parser.test.js +107 -0
  97. package/build/listParser.d.ts +1 -1
  98. package/build/listParser.js +5 -5
  99. package/build/lookaheadParser.d.ts +2 -0
  100. package/build/lookaheadParser.js +14 -0
  101. package/build/{negativeLookahead.d.ts → negativeLookaheadParser.d.ts} +1 -1
  102. package/build/negativeLookaheadParser.js +24 -0
  103. package/build/negativeLookaheadParser.test.d.ts +1 -0
  104. package/build/negativeLookaheadParser.test.js +30 -0
  105. package/build/nonEmptyArrayParser.d.ts +2 -0
  106. package/build/nonEmptyArrayParser.js +32 -0
  107. package/build/nonEmptyArrayParser.test.d.ts +1 -0
  108. package/build/nonEmptyArrayParser.test.js +16 -0
  109. package/build/optionalParser.d.ts +1 -1
  110. package/build/optionalParser.js +2 -2
  111. package/build/parser.d.ts +13 -4
  112. package/build/parser.js +67 -32
  113. package/build/parser.test.js +94 -27
  114. package/build/parserAccessorParser.d.ts +1 -1
  115. package/build/parserAccessorParser.js +9 -1
  116. package/build/parserConsumedSequenceParser.d.ts +2 -0
  117. package/build/parserConsumedSequenceParser.js +22 -0
  118. package/build/parserContext.d.ts +20 -6
  119. package/build/parserContext.js +70 -40
  120. package/build/parserContext.test.js +34 -7
  121. package/build/parserCreatorCompose.d.ts +4 -3
  122. package/build/parserCreatorCompose.js +9 -3
  123. package/build/parserError.d.ts +6 -0
  124. package/build/parserError.js +6 -6
  125. package/build/parserImplementationInvariant.d.ts +1 -1
  126. package/build/parserImplementationInvariant.js +2 -2
  127. package/build/parserInputCompanion.d.ts +35 -0
  128. package/build/parserInputCompanion.js +68 -0
  129. package/build/promiseCompose.d.ts +1 -1
  130. package/build/promiseCompose.js +12 -1
  131. package/build/promiseSettled.d.ts +1 -0
  132. package/build/promiseSettled.js +4 -0
  133. package/build/quantifierParser.d.ts +2 -0
  134. package/build/quantifierParser.js +17 -0
  135. package/build/separatedArrayParser.d.ts +2 -0
  136. package/build/separatedArrayParser.js +39 -0
  137. package/build/separatedArrayParser.test.d.ts +1 -0
  138. package/build/separatedArrayParser.test.js +21 -0
  139. package/build/sequenceBuffer.d.ts +13 -3
  140. package/build/sequenceBuffer.js +60 -8
  141. package/build/sequenceBuffer.test.js +59 -2
  142. package/build/sequenceTerminatedSequenceParser.d.ts +5 -0
  143. package/build/sequenceTerminatedSequenceParser.js +32 -0
  144. package/build/sequenceTerminatedSequenceParser.test.d.ts +1 -0
  145. package/build/sequenceTerminatedSequenceParser.test.js +37 -0
  146. package/build/sequenceUnparser.d.ts +2 -0
  147. package/build/sequenceUnparser.js +6 -0
  148. package/build/skipParser.d.ts +1 -1
  149. package/build/skipParser.js +4 -2
  150. package/build/skipToParser.d.ts +2 -0
  151. package/build/skipToParser.js +11 -0
  152. package/build/sliceBoundedParser.d.ts +2 -2
  153. package/build/sliceBoundedParser.js +8 -3
  154. package/build/sliceBoundedParser.test.js +37 -3
  155. package/build/smali.d.ts +1 -0
  156. package/build/smali.js +17 -0
  157. package/build/smaliParser.d.ts +12 -0
  158. package/build/smaliParser.js +656 -0
  159. package/build/smaliParser.test.d.ts +1 -0
  160. package/build/smaliParser.test.js +115 -0
  161. package/build/terminatedArrayParser.d.ts +4 -2
  162. package/build/terminatedArrayParser.js +82 -5
  163. package/build/terminatedArrayParser.test.d.ts +1 -0
  164. package/build/terminatedArrayParser.test.js +131 -0
  165. package/build/toAsyncIterable.d.ts +1 -0
  166. package/build/toAsyncIterable.js +7 -0
  167. package/build/toAsyncIterator.d.ts +1 -0
  168. package/build/toAsyncIterator.js +33 -0
  169. package/build/tupleParser.d.ts +4 -0
  170. package/build/tupleParser.js +1 -5
  171. package/build/uint8Array.d.ts +1 -0
  172. package/build/uint8Array.js +7 -0
  173. package/build/unionParser.d.ts +2 -1
  174. package/build/unionParser.js +27 -12
  175. package/build/unionParser.test.d.ts +1 -0
  176. package/build/unionParser.test.js +60 -0
  177. package/build/unparser.d.ts +8 -0
  178. package/build/unparser.js +104 -0
  179. package/build/unparser.test.d.ts +1 -0
  180. package/build/unparser.test.js +150 -0
  181. package/build/unparserContext.d.ts +31 -0
  182. package/build/unparserContext.js +74 -0
  183. package/build/unparserError.d.ts +9 -0
  184. package/build/unparserError.js +9 -0
  185. package/build/unparserImplementationInvariant.d.ts +2 -0
  186. package/build/unparserImplementationInvariant.js +5 -0
  187. package/build/unparserOutputCompanion.d.ts +15 -0
  188. package/build/unparserOutputCompanion.js +13 -0
  189. package/build/zip.d.ts +9 -17
  190. package/build/zipParser.d.ts +20 -12
  191. package/build/zipParser.js +83 -71
  192. package/build/zipParser.test.js +2 -7
  193. package/build/zipUnparser.d.ts +8 -0
  194. package/build/zipUnparser.js +200 -0
  195. package/build/zipUnparser.test.d.ts +1 -0
  196. package/build/zipUnparser.test.js +80 -0
  197. package/package.json +26 -8
  198. package/src/allSettledStream.test.ts +40 -0
  199. package/src/allSettledStream.ts +47 -15
  200. package/src/androidPackage.ts +48 -0
  201. package/src/{apkParser.test.ts → androidPackageParser.test.ts} +7 -8
  202. package/src/androidPackageParser.test.ts.md +271 -0
  203. package/src/androidPackageParser.test.ts.snap +0 -0
  204. package/src/androidPackageParser.ts +440 -0
  205. package/src/androidPackageUnparser.test.ts +36 -0
  206. package/src/androidPackageUnparser.ts +120 -0
  207. package/src/arbitrarilySlicedAsyncInterable.ts +7 -2
  208. package/src/arbitraryFileSystemEntry.ts +2 -4
  209. package/src/arbitraryZip.ts +20 -27
  210. package/src/arbitraryZipPermissions.ts +0 -25
  211. package/src/arbitraryZipStream.ts +4 -4
  212. package/src/arrayParser.test.ts +4 -4
  213. package/src/arrayParser.ts +3 -2
  214. package/src/arrayUnparser.ts +13 -0
  215. package/src/backsmali.ts +30 -0
  216. package/src/bsonParser.test.ts +2 -2
  217. package/src/bsonParser.ts +16 -5
  218. package/src/{parserInvariant.ts → customInvariant.ts} +2 -2
  219. package/src/dalvikBytecodeParser/formatParsers.ts +421 -0
  220. package/src/dalvikBytecodeParser.ts +2074 -0
  221. package/src/dalvikExecutable.ts +220 -0
  222. package/src/dalvikExecutableParser/stringSyntaxParser.ts +145 -0
  223. package/src/dalvikExecutableParser/typeParsers.ts +65 -0
  224. package/src/dalvikExecutableParser/typedNumbers.ts +57 -0
  225. package/src/dalvikExecutableParser.test.ts +89 -0
  226. package/src/dalvikExecutableParser.test.ts.md +634 -0
  227. package/src/dalvikExecutableParser.test.ts.snap +0 -0
  228. package/src/dalvikExecutableParser.ts +2768 -0
  229. package/src/dalvikExecutableParserAgainstSmaliParser.test.ts +346 -0
  230. package/src/debugLogInputParser.ts +28 -0
  231. package/src/debugLogParser.ts +20 -4
  232. package/src/disjunctionParser.ts +10 -5
  233. package/src/elementParser.ts +3 -3
  234. package/src/elementTerminatedArrayParser.test.ts +99 -0
  235. package/src/elementTerminatedArrayParser.ts +31 -0
  236. package/src/elementTerminatedSequenceArrayParser.test.ts +54 -0
  237. package/src/elementTerminatedSequenceArrayParser.ts +52 -0
  238. package/src/elementTerminatedSequenceParser.test.ts +54 -0
  239. package/src/elementTerminatedSequenceParser.ts +43 -0
  240. package/src/endOfInputParser.ts +4 -4
  241. package/src/exactElementParser.ts +18 -12
  242. package/src/exactSequenceParser.ts +24 -3
  243. package/src/fetchCid.ts +125 -0
  244. package/src/fixedLengthSequenceParser.test.ts +77 -0
  245. package/src/fixedLengthSequenceParser.ts +28 -1
  246. package/src/hasExecutable.ts +11 -0
  247. package/src/highResolutionTimer.ts +49 -0
  248. package/src/index.ts +15 -2
  249. package/src/inputReader.test.ts +216 -7
  250. package/src/inputReader.ts +80 -5
  251. package/src/inputReaderState.ts +33 -0
  252. package/src/inspect.ts +9 -0
  253. package/src/javaKeyStore.ts +0 -0
  254. package/src/javaKeyStoreParser.test.ts +22 -0
  255. package/src/javaKeyStoreParser.test.ts.md +103 -0
  256. package/src/javaKeyStoreParser.test.ts.snap +0 -0
  257. package/src/javaKeyStoreParser.ts +136 -0
  258. package/src/jsonParser.test.ts +2 -2
  259. package/src/jsonParser.ts +23 -34
  260. package/src/leb128Parser.test.ts +171 -0
  261. package/src/leb128Parser.ts +125 -0
  262. package/src/listParser.ts +6 -6
  263. package/src/lookaheadParser.ts +19 -0
  264. package/src/negativeLookaheadParser.test.ts +53 -0
  265. package/src/negativeLookaheadParser.ts +36 -0
  266. package/src/nonEmptyArrayParser.test.ts +20 -0
  267. package/src/nonEmptyArrayParser.ts +44 -0
  268. package/src/optionalParser.ts +4 -3
  269. package/src/parser.test.ts +148 -27
  270. package/src/parser.test.ts.md +21 -21
  271. package/src/parser.test.ts.snap +0 -0
  272. package/src/parser.ts +153 -49
  273. package/src/parserAccessorParser.ts +12 -2
  274. package/src/parserConsumedSequenceParser.ts +29 -0
  275. package/src/parserContext.test.ts +38 -7
  276. package/src/parserContext.ts +127 -51
  277. package/src/parserCreatorCompose.ts +25 -7
  278. package/src/parserError.ts +9 -6
  279. package/src/parserImplementationInvariant.ts +2 -2
  280. package/src/parserInputCompanion.ts +102 -0
  281. package/src/promiseCompose.ts +17 -3
  282. package/src/promiseSettled.ts +6 -0
  283. package/src/quantifierParser.ts +25 -0
  284. package/src/separatedArrayParser.test.ts +34 -0
  285. package/src/separatedArrayParser.ts +55 -0
  286. package/src/sequenceBuffer.test.ts +72 -2
  287. package/src/sequenceBuffer.ts +93 -7
  288. package/src/sequenceTerminatedSequenceParser.test.ts +60 -0
  289. package/src/sequenceTerminatedSequenceParser.ts +62 -0
  290. package/src/sequenceUnparser.ts +9 -0
  291. package/src/skipParser.ts +7 -5
  292. package/src/skipToParser.ts +16 -0
  293. package/src/sliceBoundedParser.test.ts +45 -3
  294. package/src/sliceBoundedParser.ts +21 -3
  295. package/src/smali.ts +24 -0
  296. package/src/smaliParser.test.ts +132 -0
  297. package/src/smaliParser.test.ts.md +2320 -0
  298. package/src/smaliParser.test.ts.snap +0 -0
  299. package/src/smaliParser.ts +1166 -0
  300. package/src/terminatedArrayParser.test.ts +258 -0
  301. package/src/terminatedArrayParser.ts +111 -6
  302. package/src/toAsyncIterable.ts +7 -0
  303. package/src/toAsyncIterator.ts +48 -0
  304. package/src/tupleParser.ts +8 -5
  305. package/src/uint8Array.ts +10 -0
  306. package/src/unionParser.test.ts +79 -0
  307. package/src/unionParser.ts +44 -16
  308. package/src/unparser.test.ts +221 -0
  309. package/src/unparser.ts +209 -0
  310. package/src/unparserContext.ts +127 -0
  311. package/src/unparserError.ts +12 -0
  312. package/src/unparserImplementationInvariant.ts +6 -0
  313. package/src/unparserOutputCompanion.ts +24 -0
  314. package/src/zip.ts +10 -22
  315. package/src/zipParser.test.ts +2 -8
  316. package/src/zipParser.ts +223 -146
  317. package/src/zipUnparser.test.ts +119 -0
  318. package/src/zipUnparser.ts +300 -0
  319. package/build/apk.d.ts +0 -13
  320. package/build/apkParser.d.ts +0 -3
  321. package/build/apkParser.js +0 -135
  322. package/build/arbitraryDosDate.d.ts +0 -2
  323. package/build/arbitraryDosDate.js +0 -8
  324. package/build/arbitraryZipEntry.d.ts +0 -3
  325. package/build/arbitraryZipEntry.js +0 -26
  326. package/build/createDisjunctionParser.d.ts +0 -2
  327. package/build/createDisjunctionParser.js +0 -47
  328. package/build/createExactParser.d.ts +0 -2
  329. package/build/createExactParser.js +0 -12
  330. package/build/createSequentialUnionParser.d.ts +0 -2
  331. package/build/createSequentialUnionParser.js +0 -69
  332. package/build/fixedLengthChunkParser.d.ts +0 -2
  333. package/build/fixedLengthChunkParser.js +0 -12
  334. package/build/fixedLengthParser.d.ts +0 -2
  335. package/build/fixedLengthParser.js +0 -12
  336. package/build/inputChunkBuffer.d.ts +0 -15
  337. package/build/inputChunkBuffer.js +0 -40
  338. package/build/inputChunkBuffer.test.js +0 -34
  339. package/build/inputCompanion.d.ts +0 -18
  340. package/build/inputCompanion.js +0 -28
  341. package/build/invariantDefined.d.ts +0 -1
  342. package/build/invariantDefined.js +0 -5
  343. package/build/invariantIdentity.d.ts +0 -3
  344. package/build/invariantIdentity.js +0 -5
  345. package/build/jsonParser2.d.ts +0 -3
  346. package/build/jsonParser2.js +0 -52
  347. package/build/jsonParser2.test.js +0 -22
  348. package/build/negativeLookahead.js +0 -20
  349. package/build/parserCompose.d.ts +0 -3
  350. package/build/parserCompose.js +0 -7
  351. package/build/parserImplementationInvariantInvariant.d.ts +0 -3
  352. package/build/parserImplementationInvariantInvariant.js +0 -15
  353. package/build/promiseFish.d.ts +0 -1
  354. package/build/promiseFish.js +0 -3
  355. package/build/sequenceParser.d.ts +0 -3
  356. package/build/sequenceParser.js +0 -10
  357. package/build/terminatedSequenceParser.d.ts +0 -2
  358. package/build/terminatedSequenceParser.js +0 -24
  359. package/build/zipEntry.d.ts +0 -28
  360. package/build/zipFile.d.ts +0 -32
  361. package/build/zipFileEntry.d.ts +0 -6
  362. package/src/apk.ts +0 -16
  363. package/src/apkParser.test.ts.md +0 -268
  364. package/src/apkParser.test.ts.snap +0 -0
  365. package/src/apkParser.ts +0 -327
  366. package/src/inputCompanion.ts +0 -43
  367. package/src/invariantDefined.ts +0 -6
  368. package/src/invariantIdentity.ts +0 -8
  369. package/src/negativeLookahead.ts +0 -26
  370. /package/build/{apk.js → androidPackage.js} +0 -0
  371. /package/build/{apkParser.test.d.ts → androidPackageParser.test.d.ts} +0 -0
  372. /package/build/{arbitraryDosPermissions.d.ts → androidPackageUnparser.test.d.ts} +0 -0
  373. /package/build/{arbitraryDosPermissions.js → dalvikExecutableParser.test.d.ts} +0 -0
  374. /package/build/{inputChunkBuffer.test.d.ts → dalvikExecutableParserAgainstSmaliParser.test.d.ts} +0 -0
  375. /package/build/{jsonParser2.test.d.ts → elementTerminatedArrayParser.test.d.ts} +0 -0
  376. /package/build/{parserParsingInvariant.d.ts → elementTerminatedSequenceArrayParser.test.d.ts} +0 -0
  377. /package/build/{parserParsingInvariant.js → elementTerminatedSequenceParser.test.d.ts} +0 -0
  378. /package/build/{zipEntry.js → fixedLengthSequenceParser.test.d.ts} +0 -0
  379. /package/build/{zipFile.js → javaKeyStore.d.ts} +0 -0
  380. /package/build/{zipFileEntry.js → javaKeyStore.js} +0 -0
@@ -1,15 +1,18 @@
1
- import invariant from "invariant";
2
- import zlib from "node:zlib";
3
- import { createArrayParser } from "./arrayParser.js";
4
- import { createExactSequenceParser } from "./exactSequenceParser.js";
5
- import { setParserName } from "./parser.js";
6
- import { createTupleParser } from "./tupleParser.js";
7
- import { promiseCompose } from "./promiseCompose.js";
8
- import { createFixedLengthSequenceParser } from "./fixedLengthSequenceParser.js";
9
- import { createOptionalParser } from "./optionalParser.js";
10
- import { parserCreatorCompose } from "./parserCreatorCompose.js";
11
- import { Readable } from "node:stream";
12
- import { pipeline } from "node:stream/promises";
1
+ import zlib from 'node:zlib';
2
+ import { Readable } from 'node:stream';
3
+ import { pipeline } from 'node:stream/promises';
4
+ import invariant from 'invariant';
5
+ import { createArrayParser } from './arrayParser.js';
6
+ import { createExactSequenceParser } from './exactSequenceParser.js';
7
+ import { setParserName } from './parser.js';
8
+ import { createTupleParser } from './tupleParser.js';
9
+ import { promiseCompose } from './promiseCompose.js';
10
+ import { createFixedLengthSequenceParser } from './fixedLengthSequenceParser.js';
11
+ import { createOptionalParser } from './optionalParser.js';
12
+ import { parserCreatorCompose } from './parserCreatorCompose.js';
13
+ import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
14
+ import { createNegativeLookaheadParser } from './negativeLookaheadParser.js';
15
+ import { createSequenceTerminatedSequenceParser } from './sequenceTerminatedSequenceParser.js';
13
16
  // https://pkwaredownloads.blob.core.windows.net/pem/APPNOTE.txt
14
17
  const uint16LEParser = promiseCompose(createFixedLengthSequenceParser(2), array => Buffer.from(array).readUInt16LE());
15
18
  setParserName(uint16LEParser, 'uint16LEParser');
@@ -18,7 +21,7 @@ setParserName(uint32LEParser, 'uint32LEParser');
18
21
  const dosDateTimeParser = promiseCompose(createTupleParser([
19
22
  uint16LEParser,
20
23
  uint16LEParser,
21
- ]), ([time, date]) => new Date(Date.UTC(1980 + ((date >> 9) & 0x7f), ((date >> 5) & 0xf) - 1, date & 0x1f, (time >> 11) & 0x1f, (time >> 5) & 0x3f, (time & 0x1f) * 2)));
24
+ ]), ([time, date]) => new Date(Date.UTC(1980 + ((date >> 9) & 0x7F), ((date >> 5) & 0xF) - 1, date & 0x1F, (time >> 11) & 0x1F, (time >> 5) & 0x3F, (time & 0x1F) * 2)));
22
25
  const zipCompressionMethodParser = promiseCompose(uint16LEParser, compressionMethod => {
23
26
  if (compressionMethod === 0) {
24
27
  return 'store';
@@ -28,8 +31,9 @@ const zipCompressionMethodParser = promiseCompose(uint16LEParser, compressionMet
28
31
  }
29
32
  invariant(false, 'Unsupported compression method %s', compressionMethod);
30
33
  });
34
+ const zipLocalFileHeaderSignatureParser = createExactSequenceParser(Buffer.from('504b0304', 'hex'));
31
35
  const zipLocalFileHeaderParser_ = createTupleParser([
32
- createExactSequenceParser(Buffer.from('504b0304', 'hex')),
36
+ zipLocalFileHeaderSignatureParser,
33
37
  uint16LEParser,
34
38
  uint16LEParser,
35
39
  zipCompressionMethodParser,
@@ -40,40 +44,60 @@ const zipLocalFileHeaderParser_ = createTupleParser([
40
44
  parserCreatorCompose(() => createTupleParser([
41
45
  uint16LEParser,
42
46
  uint16LEParser,
43
- ]), ([fileNameLength, extraFieldLength,]) => createTupleParser([
44
- createFixedLengthSequenceParser(fileNameLength),
47
+ ]), ([filePathLength, extraFieldLength,]) => createTupleParser([
48
+ createFixedLengthSequenceParser(filePathLength),
45
49
  createFixedLengthSequenceParser(extraFieldLength),
46
50
  ]))(),
47
51
  ]);
48
52
  setParserName(zipLocalFileHeaderParser_, 'zipLocalFileHeaderParser_');
49
- const zipLocalFileHeaderParser = promiseCompose(zipLocalFileHeaderParser_, ([_zipLocalFileHeaderSignature, versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModFile, crc32, compressedSize, uncompressedSize, [fileName, extraField],]) => ({
53
+ const zipLocalFileHeaderParser = promiseCompose(zipLocalFileHeaderParser_, ([_zipLocalFileHeaderSignature, versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModifiedFile, crc32, compressedSize, uncompressedSize, [filePath, extraField],]) => ({
50
54
  versionNeededToExtract,
51
55
  generalPurposeBitFlag,
52
56
  compressionMethod,
53
- lastModFile,
57
+ lastModifiedFile,
54
58
  crc32,
55
59
  compressedSize,
56
60
  uncompressedSize,
57
- fileName: Buffer.from(fileName).toString('utf8'),
61
+ filePath: Buffer.from(filePath).toString('utf8'),
58
62
  extraField,
59
63
  }));
60
64
  const zipEncryptionHeaderParser = async (parserContext) => {
61
65
  parserContext.invariant(false, 'Not implemented');
62
66
  };
63
- const zipDataDescriptorParser = createTupleParser([
67
+ const zipDataDescriptorSignature = Buffer.from('504b0708', 'hex');
68
+ const zipDataDescriptorSignatureParser = createExactSequenceParser(zipDataDescriptorSignature);
69
+ const zipDataDescriptorParser = promiseCompose(createTupleParser([
70
+ createNegativeLookaheadParser(zipLocalFileHeaderSignatureParser),
64
71
  // FIXME: optional in spec
65
- // createOptionalParser(createExactSequenceParser<Uint8Array>(Buffer.from('504b0708', 'hex'))),
66
- createExactSequenceParser(Buffer.from('504b0708', 'hex')),
72
+ //createOptionalParser(zipDataDescriptorSignatureParser),
73
+ zipDataDescriptorSignatureParser,
67
74
  uint32LEParser,
68
75
  uint32LEParser,
69
76
  uint32LEParser,
70
- ]);
71
- export const zipLocalFileParser = promiseCompose(parserCreatorCompose(() => zipLocalFileHeaderParser, (zipLocalFileHeader) => createTupleParser([
72
- async () => zipLocalFileHeader,
73
- createOptionalParser(zipEncryptionHeaderParser),
74
- createFixedLengthSequenceParser(zipLocalFileHeader.compressedSize),
75
- createOptionalParser(zipDataDescriptorParser),
76
- ]))(), ([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,]) => ({
77
101
  zipLocalFileHeader,
78
102
  zipEncryptionHeader,
79
103
  compressedData,
@@ -90,9 +114,18 @@ const zipVersionMadeByParser = promiseCompose(createFixedLengthSequenceParser(2)
90
114
  hostSystem,
91
115
  zipSpecificationVersion,
92
116
  }));
93
- const zipCentralDirectoryHeaderParser_ = createTupleParser([
117
+ const dosExternalFileAttributesParser = promiseCompose(uint32LEParser, externalFileAttributes => ({
118
+ directory: (externalFileAttributes & 0b0001_0000) !== 0,
119
+ }));
120
+ const unixExternalFileAttributesParser = promiseCompose(uint32LEParser, externalFileAttributes => ({
121
+ directory: (externalFileAttributes & (0b0100_0000_0000_0000 << 16)) !== 0,
122
+ }));
123
+ const createExternalFileAttributesParser = (hostSystem) => promiseCompose(hostSystem === 0 ? dosExternalFileAttributesParser : unixExternalFileAttributesParser, externalFileAttributes => externalFileAttributes);
124
+ const zipCentralDirectoryHeaderParser_ = parserCreatorCompose(() => createTupleParser([
94
125
  createExactSequenceParser(Buffer.from('504b0102', 'hex')),
95
126
  zipVersionMadeByParser,
127
+ ]), ([_centralDirectoryHeaderSignature, versionMadeBy,]) => createTupleParser([
128
+ async () => versionMadeBy,
96
129
  uint16LEParser,
97
130
  uint16LEParser,
98
131
  zipCompressionMethodParser,
@@ -106,10 +139,10 @@ const zipCentralDirectoryHeaderParser_ = createTupleParser([
106
139
  uint16LEParser,
107
140
  uint16LEParser,
108
141
  uint16LEParser,
142
+ createExternalFileAttributesParser(versionMadeBy.hostSystem),
109
143
  uint32LEParser,
110
- uint32LEParser,
111
- ]), ([fileNameLength, extraFieldLength, fileCommentLength, diskNumberStart, internalFileAttributes, externalFileAttributes, relativeOffsetOfLocalHeader,]) => createTupleParser([
112
- createFixedLengthSequenceParser(fileNameLength),
144
+ ]), ([filePathLength, extraFieldLength, fileCommentLength, diskNumberStart, internalFileAttributes, externalFileAttributes, relativeOffsetOfLocalHeader,]) => createTupleParser([
145
+ createFixedLengthSequenceParser(filePathLength),
113
146
  createFixedLengthSequenceParser(extraFieldLength),
114
147
  createFixedLengthSequenceParser(fileCommentLength),
115
148
  async () => diskNumberStart,
@@ -117,14 +150,14 @@ const zipCentralDirectoryHeaderParser_ = createTupleParser([
117
150
  async () => externalFileAttributes,
118
151
  async () => relativeOffsetOfLocalHeader,
119
152
  ]))(),
120
- ]);
153
+ ]))();
121
154
  setParserName(zipCentralDirectoryHeaderParser_, 'centralDirectoryHeaderParser_');
122
- export const zipCentralDirectoryHeaderParser = promiseCompose(zipCentralDirectoryHeaderParser_, ([_centralDirectoryHeaderSignature, versionMadeBy, versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModFile, crc32, compressedSize, uncompressedSize, [fileName, extraField, fileComment, diskNumberStart, internalFileAttributes, externalFileAttributes, relativeOffsetOfLocalHeader,],]) => ({
155
+ export const zipCentralDirectoryHeaderParser = promiseCompose(zipCentralDirectoryHeaderParser_, ([versionMadeBy, versionNeededToExtract, generalPurposeBitFlag, compressionMethod, lastModifiedFile, crc32, compressedSize, uncompressedSize, [filePath, extraField, fileComment, diskNumberStart, internalFileAttributes, externalFileAttributes, relativeOffsetOfLocalHeader,],]) => ({
123
156
  versionMadeBy,
124
157
  versionNeededToExtract,
125
158
  generalPurposeBitFlag,
126
159
  compressionMethod,
127
- lastModFile,
160
+ lastModifiedFile,
128
161
  crc32,
129
162
  compressedSize,
130
163
  uncompressedSize,
@@ -132,7 +165,7 @@ export const zipCentralDirectoryHeaderParser = promiseCompose(zipCentralDirector
132
165
  internalFileAttributes,
133
166
  externalFileAttributes,
134
167
  relativeOffsetOfLocalHeader,
135
- fileName: Buffer.from(fileName).toString('utf8'),
168
+ filePath: Buffer.from(filePath).toString('utf8'),
136
169
  extraField,
137
170
  fileComment: Buffer.from(fileComment).toString('utf8'),
138
171
  }));
@@ -153,7 +186,7 @@ const zipEndOfCentralDirectoryRecordParser_ = createTupleParser([
153
186
  uint32LEParser,
154
187
  zipFileCommentParser,
155
188
  ]);
156
- setParserName(zipEndOfCentralDirectoryRecordParser_, 'endOfCentralDirectoryRecordParser_');
189
+ setParserName(zipEndOfCentralDirectoryRecordParser_, 'zipEndOfCentralDirectoryRecordParser_');
157
190
  export const zipEndOfCentralDirectoryRecordParser = promiseCompose(zipEndOfCentralDirectoryRecordParser_, ([_endOfCentralDirectoryRecordSignature, numberOfThisDisk, numberOfTheDiskWithTheStartOfTheCentralDirectory, totalNumberOfEntriesInTheCentralDirectoryOnThisDisk, totalNumberOfEntriesInTheCentralDirectory, sizeOfTheCentralDirectory, offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber, zipFileComment,]) => ({
158
191
  numberOfThisDisk,
159
192
  numberOfTheDiskWithTheStartOfTheCentralDirectory,
@@ -163,6 +196,7 @@ export const zipEndOfCentralDirectoryRecordParser = promiseCompose(zipEndOfCentr
163
196
  offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber,
164
197
  zipFileComment,
165
198
  }));
199
+ setParserName(zipEndOfCentralDirectoryRecordParser, 'zipEndOfCentralDirectoryRecordParser');
166
200
  const zipParser_ = createTupleParser([
167
201
  createArrayParser(zipLocalFileParser),
168
202
  createOptionalParser(zipArchiveDecryptionHeaderParser),
@@ -179,36 +213,20 @@ export async function zipEntriesFromZipSegments({ zipLocalFiles, zipCentralDirec
179
213
  const { zipLocalFileHeader, compressedData, zipDataDescriptor, zipEncryptionHeader, } = zipLocalFile;
180
214
  const centralDirectoryHeader = zipCentralDirectoryHeaders.at(index);
181
215
  invariant(centralDirectoryHeader, 'Central directory header not found for local file %s', index);
182
- let isDosDirectory = false;
183
- let permissions = {
184
- type: 'unix',
185
- unixPermissions: 0,
186
- };
187
- if (centralDirectoryHeader.versionMadeBy.hostSystem === 0) {
188
- isDosDirectory = (centralDirectoryHeader.externalFileAttributes & 0b00010000) !== 0;
189
- permissions = {
190
- type: 'dos',
191
- dosPermissions: centralDirectoryHeader.externalFileAttributes & 0b00111111,
192
- };
193
- }
194
- if (centralDirectoryHeader.versionMadeBy.hostSystem === 3) {
195
- permissions = {
196
- type: 'unix',
197
- unixPermissions: (centralDirectoryHeader.externalFileAttributes >> 16) & 0b111111111,
198
- };
199
- }
200
216
  const commonFields = {
201
- path: zipLocalFileHeader.fileName,
217
+ path: zipLocalFileHeader.filePath,
202
218
  comment: centralDirectoryHeader.fileComment,
203
- date: zipLocalFileHeader.lastModFile,
204
- permissions,
219
+ date: zipLocalFileHeader.lastModifiedFile,
220
+ hostSystem: centralDirectoryHeader.versionMadeBy.hostSystem === 0 ? 'dos' : 'unix',
221
+ attributes: centralDirectoryHeader.externalFileAttributes,
205
222
  };
206
- const isDirectory = isDosDirectory || commonFields.path.endsWith('/');
223
+ const isDirectory = (centralDirectoryHeader.externalFileAttributes.directory
224
+ || commonFields.path.endsWith('/'));
207
225
  if (isDirectory) {
208
226
  return {
209
227
  ...commonFields,
210
228
  type: 'directory',
211
- path: commonFields.path.slice(0, -1),
229
+ path: commonFields.path.replace(/\/$/, ''),
212
230
  };
213
231
  }
214
232
  const fileEntry = {
@@ -217,18 +235,12 @@ export async function zipEntriesFromZipSegments({ zipLocalFiles, zipCentralDirec
217
235
  content: compressedData,
218
236
  compression: zipLocalFileHeader.compressionMethod,
219
237
  };
220
- if (fileEntry.content.length && fileEntry.compression === 'deflate') {
221
- const deflate = zlib.createInflateRaw();
238
+ if (fileEntry.content.length > 0 && fileEntry.compression === 'deflate') {
239
+ const inflate = zlib.createInflateRaw();
222
240
  const input = Readable.from(Buffer.from(compressedData));
223
241
  const [_, buffer] = await Promise.all([
224
- pipeline(input, deflate),
225
- (async () => {
226
- const chunks = [];
227
- for await (const chunk of deflate) {
228
- chunks.push(chunk);
229
- }
230
- return Buffer.concat(chunks);
231
- })(),
242
+ pipeline(input, inflate),
243
+ uint8ArrayAsyncIterableToUint8Array(inflate),
232
244
  ]);
233
245
  fileEntry.content = Uint8Array.from(buffer);
234
246
  }
@@ -1,17 +1,12 @@
1
1
  import { testProp } from '@fast-check/ava';
2
2
  import { arbitraryZipStream } from './arbitraryZipStream.js';
3
3
  import { zipParser } from './zipParser.js';
4
- import { uint8ArrayInputCompanion } from './inputCompanion.js';
4
+ import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
5
5
  import { runParser } from './parser.js';
6
- async function* readableStreamToUint8ArrayAsyncIterator(stream) {
7
- for await (const chunk of stream) {
8
- yield chunk;
9
- }
10
- }
11
6
  testProp('zip', [
12
7
  arbitraryZipStream,
13
8
  ], async (t, [zip, zipStream]) => {
14
- const actual = await runParser(zipParser, readableStreamToUint8ArrayAsyncIterator(zipStream), uint8ArrayInputCompanion, {
9
+ const actual = await runParser(zipParser, zipStream, uint8ArrayParserInputCompanion, {
15
10
  errorJoinMode: 'all',
16
11
  });
17
12
  actual.entries.sort((a, b) => a.path.localeCompare(b.path));
@@ -0,0 +1,8 @@
1
+ import { Unparser } from "./unparser.js";
2
+ import { Zip } from "./zip.js";
3
+ import { ZipEndOfCentralDirectoryRecord } from './zipParser.js';
4
+ export declare const zipEndOfCentralDirectoryRecordUnparser: Unparser<ZipEndOfCentralDirectoryRecord, Uint8Array>;
5
+ export declare const createZipUnparser: ({ dataDescriptor, }?: {
6
+ dataDescriptor?: boolean;
7
+ }) => Unparser<Zip, Uint8Array>;
8
+ export declare const zipUnparser: Unparser<Zip, Uint8Array<ArrayBufferLike>>;
@@ -0,0 +1,200 @@
1
+ import zlib from 'node:zlib';
2
+ import { Readable } from 'node:stream';
3
+ import { pipeline } from 'node:stream/promises';
4
+ import { uint8ArrayAsyncIterableToUint8Array } from './uint8Array.js';
5
+ const uint16LEUnparser = async function* (uint16LE) {
6
+ const buffer = Buffer.alloc(2);
7
+ buffer.writeUInt16LE(uint16LE);
8
+ yield buffer;
9
+ };
10
+ const uint32LEUnparser = async function* (uint32LE) {
11
+ const buffer = Buffer.alloc(4);
12
+ buffer.writeUInt32LE(uint32LE);
13
+ yield buffer;
14
+ };
15
+ const uint16LEPrefixedUint8ArrayUnparser = async function* (uint8Array, unparserContext) {
16
+ yield* uint16LEUnparser(uint8Array.length, unparserContext);
17
+ yield uint8Array;
18
+ };
19
+ const uint16LEPrefixedStringUnparser = async function* (string, unparserContext) {
20
+ yield* uint16LEPrefixedUint8ArrayUnparser(Buffer.from(string, 'utf8'), unparserContext);
21
+ };
22
+ const dosDateTimeUnparser = async function* (date, unparserContext) {
23
+ yield* uint16LEUnparser((date.getUTCSeconds() / 2
24
+ | date.getUTCMinutes() << 5
25
+ | date.getUTCHours() << 11), unparserContext);
26
+ yield* uint16LEUnparser((date.getUTCDate()
27
+ | (date.getUTCMonth() + 1) << 5
28
+ | (date.getUTCFullYear() - 1980) << 9), unparserContext);
29
+ };
30
+ const zipCompressionMethodUnparser = async function* (compressionMethod, unparserContext) {
31
+ if (compressionMethod === 'store') {
32
+ yield* uint16LEUnparser(0, unparserContext);
33
+ }
34
+ else {
35
+ yield* uint16LEUnparser(8, unparserContext);
36
+ }
37
+ };
38
+ export const zipEndOfCentralDirectoryRecordUnparser = async function* (zipEndOfCentralDirectoryRecord, unparserContext) {
39
+ yield Buffer.from('504b0506', 'hex');
40
+ yield* uint16LEUnparser(zipEndOfCentralDirectoryRecord.numberOfThisDisk, unparserContext);
41
+ yield* uint16LEUnparser(zipEndOfCentralDirectoryRecord.numberOfTheDiskWithTheStartOfTheCentralDirectory, unparserContext);
42
+ yield* uint16LEUnparser(zipEndOfCentralDirectoryRecord.totalNumberOfEntriesInTheCentralDirectoryOnThisDisk, unparserContext);
43
+ yield* uint16LEUnparser(zipEndOfCentralDirectoryRecord.totalNumberOfEntriesInTheCentralDirectory, unparserContext);
44
+ yield* uint32LEUnparser(zipEndOfCentralDirectoryRecord.sizeOfTheCentralDirectory, unparserContext);
45
+ yield* uint32LEUnparser(zipEndOfCentralDirectoryRecord.offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber, unparserContext);
46
+ yield* uint16LEPrefixedStringUnparser(zipEndOfCentralDirectoryRecord.zipFileComment, unparserContext);
47
+ };
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) {
70
+ const compressedContentByZipFileEntry = new Map(zip.entries.flatMap(zipEntry => {
71
+ if (zipEntry.type !== 'file') {
72
+ return [];
73
+ }
74
+ if (zipEntry.compression === 'store') {
75
+ return [[zipEntry, Promise.resolve(zipEntry.content)]];
76
+ }
77
+ const uncompressedContent = zipEntry.content;
78
+ const deflate = zlib.createDeflateRaw();
79
+ const input = Readable.from(Buffer.from(uncompressedContent));
80
+ const promise = Promise.all([
81
+ pipeline(input, deflate),
82
+ uint8ArrayAsyncIterableToUint8Array(deflate),
83
+ ]);
84
+ return [[zipEntry, promise.then(([, compressedContent]) => compressedContent)]];
85
+ }));
86
+ const filePathByZipEntry = new Map(zip.entries.map(zipEntry => [zipEntry, zipEntry.type === 'file' ? zipEntry.path : zipEntry.path + '/']));
87
+ const localHeaderPositionByZipEntry = new Map();
88
+ for (const zipEntry of zip.entries) {
89
+ localHeaderPositionByZipEntry.set(zipEntry, unparserContext.position);
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;
103
+ if (zipEntry.type === 'file') {
104
+ const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
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
+ }
116
+ }
117
+ yield* zipLocalFileHeaderUnparser(zipLocalFileHeader, unparserContext);
118
+ if (zipEntry.type === 'file') {
119
+ const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
120
+ yield compressedContent;
121
+ if (shouldWriteDataDescriptor) {
122
+ yield* zipDataDescriptorUnparser({
123
+ crc32: zipLocalFileHeader.crc32,
124
+ compressedSize: zipLocalFileHeader.compressedSize,
125
+ uncompressedSize: zipLocalFileHeader.uncompressedSize,
126
+ }, unparserContext);
127
+ }
128
+ }
129
+ }
130
+ const startOfCentralDirectoryPosition = unparserContext.position;
131
+ for (const zipEntry of zip.entries) {
132
+ yield Buffer.from('504b0102', 'hex');
133
+ if (zipEntry.hostSystem === 'unix') {
134
+ yield 0; // zip specification version
135
+ yield 3; // host system
136
+ }
137
+ else {
138
+ yield 0;
139
+ yield 0;
140
+ }
141
+ yield* uint16LEUnparser(0, unparserContext); // version needed to extract
142
+ yield* uint16LEUnparser(0, unparserContext); // general purpose bit flag
143
+ if (zipEntry.type === 'file') {
144
+ yield* zipCompressionMethodUnparser(zipEntry.compression, unparserContext);
145
+ }
146
+ else {
147
+ yield* uint16LEUnparser(0, unparserContext);
148
+ }
149
+ yield* dosDateTimeUnparser(zipEntry.date, unparserContext);
150
+ if (zipEntry.type === 'file') {
151
+ const compressedContent = await compressedContentByZipFileEntry.get(zipEntry);
152
+ yield* uint32LEUnparser(0, unparserContext); // crc32 // TODO
153
+ yield* uint32LEUnparser(compressedContent.length, unparserContext);
154
+ yield* uint32LEUnparser(zipEntry.content.length, unparserContext);
155
+ }
156
+ else {
157
+ yield* uint32LEUnparser(0, unparserContext);
158
+ yield* uint32LEUnparser(0, unparserContext);
159
+ yield* uint32LEUnparser(0, unparserContext);
160
+ }
161
+ const filePath = filePathByZipEntry.get(zipEntry);
162
+ const filePathBuffer = Buffer.from(filePath, 'utf8');
163
+ yield* uint16LEUnparser(filePathBuffer.length, unparserContext);
164
+ const extraFieldBuffer = Buffer.alloc(0);
165
+ yield* uint16LEUnparser(extraFieldBuffer.length, unparserContext);
166
+ const fileCommentBuffer = Buffer.from(zipEntry.comment, 'utf8');
167
+ yield* uint16LEUnparser(fileCommentBuffer.length, unparserContext);
168
+ yield* uint16LEUnparser(0, unparserContext); // disk number start
169
+ yield* uint16LEUnparser(0, unparserContext); // internal file attributes
170
+ if (zipEntry.hostSystem === 'unix') {
171
+ yield* uint32LEUnparser((0
172
+ | (zipEntry.type === 'directory'
173
+ ? (0b0100_0000_0000_0000 << 16)
174
+ : (0b1000_0000_0000_0000 << 16))) >>> 0, unparserContext);
175
+ }
176
+ else {
177
+ yield* uint32LEUnparser((0
178
+ | (zipEntry.type === 'directory'
179
+ ? 0b0001_0000
180
+ : 0)), unparserContext);
181
+ }
182
+ const localHeaderPosition = localHeaderPositionByZipEntry.get(zipEntry);
183
+ yield* uint32LEUnparser(localHeaderPosition, unparserContext);
184
+ yield filePathBuffer;
185
+ yield extraFieldBuffer;
186
+ yield fileCommentBuffer;
187
+ }
188
+ const endOfCentralDirectoryPosition = unparserContext.position;
189
+ const sizeOfTheCentralDirectory = endOfCentralDirectoryPosition - startOfCentralDirectoryPosition;
190
+ yield* zipEndOfCentralDirectoryRecordUnparser({
191
+ numberOfThisDisk: 0,
192
+ numberOfTheDiskWithTheStartOfTheCentralDirectory: 0,
193
+ totalNumberOfEntriesInTheCentralDirectoryOnThisDisk: zip.entries.length,
194
+ totalNumberOfEntriesInTheCentralDirectory: zip.entries.length,
195
+ sizeOfTheCentralDirectory,
196
+ offsetOfStartOfCentralDirectoryWithRespectToTheStartingDiskNumber: startOfCentralDirectoryPosition,
197
+ zipFileComment: zip.comment,
198
+ }, unparserContext);
199
+ };
200
+ export const zipUnparser = createZipUnparser();
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,80 @@
1
+ import { fc, testProp } from '@fast-check/ava';
2
+ import { temporaryFile } from 'tempy';
3
+ import { execa } from 'execa';
4
+ import fsPromises from 'node:fs/promises';
5
+ import { runUnparser } from './unparser.js';
6
+ import { createZipUnparser } from './zipUnparser.js';
7
+ import { uint8ArrayUnparserOutputCompanion } from './unparserOutputCompanion.js';
8
+ import { runParser } from './parser.js';
9
+ import { zipParser } from './zipParser.js';
10
+ import { uint8ArrayParserInputCompanion } from './parserInputCompanion.js';
11
+ import { arbitraryZip } from './arbitraryZip.js';
12
+ import { hasExecutable } from './hasExecutable.js';
13
+ const hasZipinfoPromise = hasExecutable('zipinfo');
14
+ const has7zPromise = hasExecutable('7z');
15
+ async function zipinfo(zipFilePath) {
16
+ const { stdout } = await execa('zipinfo', [
17
+ '-v',
18
+ zipFilePath,
19
+ ], {
20
+ reject: false,
21
+ });
22
+ return {
23
+ isEmptyZipfile: stdout.endsWith('Empty zipfile.'),
24
+ };
25
+ }
26
+ async function _7zList(zipFilePath) {
27
+ const { stdout } = await execa('7z', [
28
+ 'l',
29
+ zipFilePath,
30
+ ], {
31
+ reject: false,
32
+ });
33
+ if (/Errors: \d+$/.test(stdout)) {
34
+ throw new Error(`7z reports errors: ${stdout}`);
35
+ }
36
+ return {
37
+ isEmptyZipfile: false, // TODO
38
+ };
39
+ }
40
+ testProp('zip', [
41
+ arbitraryZip,
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
+ }
51
+ const actualStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
52
+ const actual = await runParser(zipParser, actualStream, uint8ArrayParserInputCompanion);
53
+ t.deepEqual(actual, zip);
54
+ const hasZipinfo = await hasZipinfoPromise;
55
+ const has7z = await has7zPromise;
56
+ if (!hasZipinfo && !has7z) {
57
+ t.pass('no zipinfo or 7z, skipping zipfile check');
58
+ return;
59
+ }
60
+ const temporaryFilePath = temporaryFile({
61
+ extension: 'zip',
62
+ });
63
+ const zipStream = runUnparser(zipUnparser, zip, uint8ArrayUnparserOutputCompanion);
64
+ await fsPromises.writeFile(temporaryFilePath, zipStream);
65
+ if (has7z) {
66
+ const { isEmptyZipfile, } = await _7zList(temporaryFilePath);
67
+ if (isEmptyZipfile) {
68
+ t.deepEqual(actual.entries, [], '7z reports the zipfile as empty, but it has entries');
69
+ }
70
+ }
71
+ if (hasZipinfo) {
72
+ const { isEmptyZipfile, } = await zipinfo(temporaryFilePath);
73
+ if (isEmptyZipfile) {
74
+ t.deepEqual(actual.entries.filter(entry => entry.type === 'file'), [], 'zipinfo reports the zipfile as empty, but it has file entries');
75
+ }
76
+ }
77
+ await fsPromises.unlink(temporaryFilePath);
78
+ }, {
79
+ verbose: true,
80
+ });
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@futpib/parser",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "build/index.js",
5
5
  "license": "GPL-3.0-only",
6
6
  "type": "module",
7
7
  "scripts": {
8
8
  "dev": "tsc --watch",
9
9
  "build": "tsc",
10
- "test": "xo && c8 ava",
10
+ "test": "c8 ava",
11
11
  "prepack": "yarn build"
12
12
  },
13
13
  "homepage": "https://github.com/futpib/parser",
@@ -24,18 +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
- "fast-check": "^3.23.1",
34
+ "execa": "^9.5.2",
35
+ "fast-check": "^3.23.2",
34
36
  "invariant": "^2.2.4",
35
37
  "jszip": "^3.10.1",
36
- "type-fest": "^4.29.0",
38
+ "leb128": "^0.0.5",
39
+ "mutf-8": "^1.1.4",
40
+ "p-memoize": "^7.1.1",
41
+ "tempy": "^3.1.0",
42
+ "type-fest": "^4.30.1",
37
43
  "typescript": "^5.7.2",
38
- "xo": "^0.59.3"
44
+ "xo": "^0.60.0"
39
45
  },
40
46
  "xo": {
41
47
  "extends": [
@@ -47,6 +53,18 @@
47
53
  },
48
54
  "packageManager": "yarn@4.5.3",
49
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",
50
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
+ }
51
69
  }
52
70
  }