♻ Extract waiting for stream to be readable
This commit is contained in:
parent
0122104f4c
commit
ab1280d46c
4 changed files with 29 additions and 34 deletions
|
@ -4,7 +4,7 @@ import * as stream from 'stream';
|
|||
import * as zlib from 'zlib';
|
||||
import { ISsnFileEntry } from '../interfaces/ISsnFileEntry';
|
||||
import decryptStream from './streams/decryptStream';
|
||||
import waitReadableLength from './streams/waitReadableLength';
|
||||
import readBytesFromStream from './streams/readBytesFromStream';
|
||||
|
||||
/** Extracts the file with the given metadata from the stream.
|
||||
* The stream must already start at the .zip's local file header
|
||||
|
@ -18,12 +18,7 @@ export default async function extractFileStream(file: ISsnFileEntry, inputStream
|
|||
const decryptTransform = decryptStream(file.decryptionKeys);
|
||||
curStream = curStream.pipe(decryptTransform);
|
||||
//skip encryption header
|
||||
const encryptionHeader = curStream.read(12);
|
||||
if (encryptionHeader === null) {
|
||||
//need to wait until data is ready for reading
|
||||
await waitReadableLength(curStream, 12);
|
||||
curStream.read(12);
|
||||
}
|
||||
readBytesFromStream(curStream, 12);
|
||||
}
|
||||
|
||||
if (!skipDecompression) {
|
||||
|
|
24
src/ssn/streams/readBytesFromStream.ts
Normal file
24
src/ssn/streams/readBytesFromStream.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import * as stream from 'stream';
|
||||
|
||||
/** Returns a promise that resolves as soon as the given stream has the given number of bytes ready for reading. */
|
||||
function waitReadableLength(inputStream: stream.Readable, minLength: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
if (inputStream.readableLength >= minLength) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
/** Reads the given number of bytes from the stream and returns them as a buffer, optionally waiting until the bytes are ready for reading. */
|
||||
export default async function readBytesFromStream(inputStream: stream.Readable, length: number): Promise<Buffer> {
|
||||
let localFileHeader: Buffer = inputStream.read(length);
|
||||
while (localFileHeader === null) {
|
||||
//need to wait until data is ready for reading
|
||||
await waitReadableLength(inputStream, length);
|
||||
localFileHeader = inputStream.read(length);
|
||||
}
|
||||
return localFileHeader;
|
||||
}
|
|
@ -1,17 +1,12 @@
|
|||
import * as stream from 'stream';
|
||||
import waitReadableLength from './waitReadableLength';
|
||||
import readBytesFromStream from './readBytesFromStream';
|
||||
|
||||
/** Reads the local file header, which is included before
|
||||
* each stored file, and advances the stream accordingly.
|
||||
* Returns length of the local file header.
|
||||
*/
|
||||
export default async function readLocalFileHeader(inputStream: stream.Readable, skipAdditionalLength = false): Promise<number> {
|
||||
let localFileHeader: Buffer = inputStream.read(30);
|
||||
if (localFileHeader === null) {
|
||||
//need to wait until data is ready for reading
|
||||
await waitReadableLength(inputStream, 30);
|
||||
localFileHeader = inputStream.read(30);
|
||||
}
|
||||
const localFileHeader = await readBytesFromStream(inputStream, 30);
|
||||
|
||||
//Local file header signature
|
||||
const magic = localFileHeader.readUInt32LE(0);
|
||||
|
@ -27,13 +22,7 @@ export default async function readLocalFileHeader(inputStream: stream.Readable,
|
|||
//skip local file name and extra field
|
||||
const additionalLength = localFilenameSize + localExtraSize;
|
||||
if (skipAdditionalLength && additionalLength > 0) {
|
||||
await waitReadableLength(inputStream, additionalLength);
|
||||
const tmpChunk = inputStream.read(additionalLength);
|
||||
if (tmpChunk === null) {
|
||||
//need to wait until data is ready for reading
|
||||
await waitReadableLength(inputStream, additionalLength);
|
||||
inputStream.read(additionalLength);
|
||||
}
|
||||
await readBytesFromStream(inputStream, additionalLength);
|
||||
}
|
||||
|
||||
return 30 + additionalLength;
|
||||
|
|
|
@ -1,13 +0,0 @@
|
|||
import * as stream from 'stream';
|
||||
|
||||
/** Returns a promise that resolves as soon as the given stream has the given number of bytes ready for reading. */
|
||||
export default function waitReadableLength(inputStream: stream.Readable, minLength: number): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
const interval = setInterval(() => {
|
||||
if (inputStream.readableLength >= minLength) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue