streaming 7-Zip archive extractor
0

Configure Feed

Select the types of activity you want to include in your feed.

pkg-7zip / lib / reader / node.ts
2.2 kB 82 lines
1/** 2 * @module 3 * 4 * {@link Reader} factories that wrap Node.js runtime APIs. 5 */ 6 7import type { FileHandle } from 'node:fs/promises'; 8 9import type { Reader } from './types.ts'; 10 11/** 12 * creates a reader from a Node.js' FileHandle 13 * @param handle the file handle to read from 14 * @returns a reader for the file 15 */ 16export const fromFileHandle = async (handle: FileHandle): Promise<Reader> => { 17 const totalLength = (await handle.stat()).size; 18 19 return { 20 length: totalLength, 21 // deno-lint-ignore require-await 22 async read(offset: number, length?: number): Promise<ReadableStream<Uint8Array<ArrayBuffer>>> { 23 let remaining = length !== undefined ? length : totalLength - offset; 24 25 return new ReadableStream<Uint8Array<ArrayBuffer>>({ 26 type: 'bytes', 27 async pull(rawController) { 28 const controller = rawController as ReadableByteStreamController; 29 30 const byob = controller.byobRequest; 31 // loose `!= null`: Bun yields `undefined` for an absent 32 // byobRequest, not the spec's `null`. 33 if (byob != null) { 34 const view = byob.view as Uint8Array<ArrayBuffer>; 35 const cap = view.byteLength <= remaining ? view.byteLength : remaining; 36 const target = cap === view.byteLength ? view : new Uint8Array(view.buffer, view.byteOffset, cap); 37 const { bytesRead } = await handle.read(target, 0, cap, offset); 38 39 if (bytesRead === 0) { 40 byob.respond(0); 41 controller.close(); 42 return; 43 } 44 45 remaining -= bytesRead; 46 offset += bytesRead; 47 byob.respond(bytesRead); 48 49 if (remaining <= 0) { 50 controller.close(); 51 } 52 return; 53 } 54 55 const size = Math.min(controller.desiredSize!, remaining); 56 57 const buffer = new Uint8Array(size); 58 const { bytesRead } = await handle.read(buffer, 0, size, offset); 59 60 if (bytesRead === 0) { 61 controller.close(); 62 return; 63 } 64 65 if (bytesRead < size) { 66 controller.enqueue(buffer.subarray(0, bytesRead)); 67 } else { 68 controller.enqueue(buffer); 69 } 70 71 remaining -= bytesRead; 72 offset += bytesRead; 73 74 if (remaining <= 0) { 75 controller.close(); 76 return; 77 } 78 }, 79 }, { highWaterMark: 64 * 1024 }); 80 }, 81 }; 82};