123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- import {getAsyncIterable} from './stream.js';
- export const getStreamContents = async (stream, {init, convertChunk, getSize, truncateChunk, addChunk, getFinalChunk, finalize}, {maxBuffer = Number.POSITIVE_INFINITY} = {}) => {
- const asyncIterable = getAsyncIterable(stream);
- const state = init();
- state.length = 0;
- try {
- for await (const chunk of asyncIterable) {
- const chunkType = getChunkType(chunk);
- const convertedChunk = convertChunk[chunkType](chunk, state);
- appendChunk({
- convertedChunk,
- state,
- getSize,
- truncateChunk,
- addChunk,
- maxBuffer,
- });
- }
- appendFinalChunk({
- state,
- convertChunk,
- getSize,
- truncateChunk,
- addChunk,
- getFinalChunk,
- maxBuffer,
- });
- return finalize(state);
- } catch (error) {
- const normalizedError = typeof error === 'object' && error !== null ? error : new Error(error);
- normalizedError.bufferedData = finalize(state);
- throw normalizedError;
- }
- };
- const appendFinalChunk = ({state, getSize, truncateChunk, addChunk, getFinalChunk, maxBuffer}) => {
- const convertedChunk = getFinalChunk(state);
- if (convertedChunk !== undefined) {
- appendChunk({
- convertedChunk,
- state,
- getSize,
- truncateChunk,
- addChunk,
- maxBuffer,
- });
- }
- };
- const appendChunk = ({convertedChunk, state, getSize, truncateChunk, addChunk, maxBuffer}) => {
- const chunkSize = getSize(convertedChunk);
- const newLength = state.length + chunkSize;
- if (newLength <= maxBuffer) {
- addNewChunk(convertedChunk, state, addChunk, newLength);
- return;
- }
- const truncatedChunk = truncateChunk(convertedChunk, maxBuffer - state.length);
- if (truncatedChunk !== undefined) {
- addNewChunk(truncatedChunk, state, addChunk, maxBuffer);
- }
- throw new MaxBufferError();
- };
- const addNewChunk = (convertedChunk, state, addChunk, newLength) => {
- state.contents = addChunk(convertedChunk, state, newLength);
- state.length = newLength;
- };
- const getChunkType = chunk => {
- const typeOfChunk = typeof chunk;
- if (typeOfChunk === 'string') {
- return 'string';
- }
- if (typeOfChunk !== 'object' || chunk === null) {
- return 'others';
- }
- if (globalThis.Buffer?.isBuffer(chunk)) {
- return 'buffer';
- }
- const prototypeName = objectToString.call(chunk);
- if (prototypeName === '[object ArrayBuffer]') {
- return 'arrayBuffer';
- }
- if (prototypeName === '[object DataView]') {
- return 'dataView';
- }
- if (
- Number.isInteger(chunk.byteLength)
- && Number.isInteger(chunk.byteOffset)
- && objectToString.call(chunk.buffer) === '[object ArrayBuffer]'
- ) {
- return 'typedArray';
- }
- return 'others';
- };
- const {toString: objectToString} = Object.prototype;
- export class MaxBufferError extends Error {
- name = 'MaxBufferError';
- constructor() {
- super('maxBuffer exceeded');
- }
- }
|