UNPKG

@khoohaoyit/image-size

Version:

A stream based image size extractor in Node

131 lines (130 loc) 6.19 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var _StreamReader_instances, _StreamReader_pruneImmediate, _StreamReader_handleRead; Object.defineProperty(exports, "__esModule", { value: true }); exports.StreamReader = void 0; const stream_1 = require("stream"); class StreamReader extends stream_1.Transform { constructor(...args) { super(...args); _StreamReader_instances.add(this); this.pendingRead = []; this.bufferOffset = 0; this.bufferSize = 0; this.buffers = []; _StreamReader_pruneImmediate.set(this, void 0); } peek(options, afterWrite) { const [offset, size] = 'offset' in options ? [options.offset, options.size] : [options.start, options.end - options.start]; if (this.bufferOffset > offset) return Promise.reject(new Error('Unable to read after it has processed')); return new Promise((rs, rj) => __classPrivateFieldGet(this, _StreamReader_instances, "m", _StreamReader_handleRead).call(this, { offset, size, resolveCallback: rs, rejectCallback: rj, blocking: false, afterWrite, })); } readRange(options) { const [offset, size] = 'offset' in options ? [options.offset, options.size] : [options.start, options.end - options.start]; if (this.bufferOffset > offset) return Promise.reject(new Error('Unable to read after it has processed')); return new Promise((rs, rj) => __classPrivateFieldGet(this, _StreamReader_instances, "m", _StreamReader_handleRead).call(this, { offset, size, resolveCallback: rs, rejectCallback: rj, blocking: true, })); } _transform(chunk, encoding, callback) { this.buffers.push(chunk); this.bufferSize += chunk.length; __classPrivateFieldGet(this, _StreamReader_instances, "m", _StreamReader_handleRead).call(this, undefined, true); callback(null, chunk); } _final(callback) { var _a; const error = (_a = this.errored) !== null && _a !== void 0 ? _a : new Error('No more data to read'); for (const { rejectCallback: rjCb } of this.pendingRead.splice(0)) rjCb(error); setImmediate(callback); } } exports.StreamReader = StreamReader; _StreamReader_pruneImmediate = new WeakMap(), _StreamReader_instances = new WeakSet(), _StreamReader_handleRead = function _StreamReader_handleRead(newEntry, isOnWrite) { if (newEntry) this.pendingRead.push(newEntry); const doneRead = []; for (const entry of newEntry ? [newEntry] : this.pendingRead) { const { offset, size, blocking, afterWrite, resolveCallback: callback, } = entry; if (afterWrite && !isOnWrite) continue; if (blocking) { if (offset + size > this.bufferOffset + this.bufferSize) continue; // range not fully buffered } else if (offset >= this.bufferOffset + this.bufferSize) continue; // range not arrived yet const currentBuffers = []; let targetSize = size; let skip = offset - this.bufferOffset; for (const chunk of this.buffers) { if (skip >= chunk.length) { skip -= chunk.length; continue; } const trimmedChunk = chunk.subarray(Math.max(skip, 0)); skip -= chunk.length; if (targetSize >= trimmedChunk.length) { targetSize -= trimmedChunk.length; currentBuffers.push(trimmedChunk); continue; } currentBuffers.push(trimmedChunk.subarray(0, targetSize)); break; } callback(Buffer.concat(currentBuffers)); doneRead.push(entry); } for (const entry of doneRead) this.pendingRead.splice(this.pendingRead.indexOf(entry), 1); if (!__classPrivateFieldGet(this, _StreamReader_pruneImmediate, "f")) __classPrivateFieldSet(this, _StreamReader_pruneImmediate, setImmediate(() => { let extraOffset = this.pendingRead.reduce((minimum, { offset }) => Math.min(minimum, offset), Infinity) - this.bufferOffset; let removeCount = 0; let append = null; for (const chunk of this.buffers) { ++removeCount; if (extraOffset >= chunk.length) { extraOffset -= chunk.length; this.bufferSize -= chunk.length; this.bufferOffset += chunk.length; continue; } const remain = chunk.subarray(extraOffset); this.bufferSize -= extraOffset; this.bufferOffset += extraOffset; append = remain; break; } this.buffers.splice(0, removeCount); if (append) this.buffers.unshift(append); __classPrivateFieldSet(this, _StreamReader_pruneImmediate, undefined, "f"); }), "f"); };