|
import {getStreamContents} from './contents.js'; |
|
import {noop, throwObjectStream, getLengthProp} from './utils.js'; |
|
|
|
export async function getStreamAsArrayBuffer(stream, options) { |
|
return getStreamContents(stream, arrayBufferMethods, options); |
|
} |
|
|
|
const initArrayBuffer = () => ({contents: new ArrayBuffer(0)}); |
|
|
|
const useTextEncoder = chunk => textEncoder.encode(chunk); |
|
const textEncoder = new TextEncoder(); |
|
|
|
const useUint8Array = chunk => new Uint8Array(chunk); |
|
|
|
const useUint8ArrayWithOffset = chunk => new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); |
|
|
|
const truncateArrayBufferChunk = (convertedChunk, chunkSize) => convertedChunk.slice(0, chunkSize); |
|
|
|
|
|
const addArrayBufferChunk = (convertedChunk, {contents, length: previousLength}, length) => { |
|
const newContents = hasArrayBufferResize() ? resizeArrayBuffer(contents, length) : resizeArrayBufferSlow(contents, length); |
|
new Uint8Array(newContents).set(convertedChunk, previousLength); |
|
return newContents; |
|
}; |
|
|
|
|
|
|
|
|
|
const resizeArrayBufferSlow = (contents, length) => { |
|
if (length <= contents.byteLength) { |
|
return contents; |
|
} |
|
|
|
const arrayBuffer = new ArrayBuffer(getNewContentsLength(length)); |
|
new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); |
|
return arrayBuffer; |
|
}; |
|
|
|
|
|
|
|
|
|
|
|
const resizeArrayBuffer = (contents, length) => { |
|
if (length <= contents.maxByteLength) { |
|
contents.resize(length); |
|
return contents; |
|
} |
|
|
|
const arrayBuffer = new ArrayBuffer(length, {maxByteLength: getNewContentsLength(length)}); |
|
new Uint8Array(arrayBuffer).set(new Uint8Array(contents), 0); |
|
return arrayBuffer; |
|
}; |
|
|
|
|
|
const getNewContentsLength = length => SCALE_FACTOR ** Math.ceil(Math.log(length) / Math.log(SCALE_FACTOR)); |
|
|
|
const SCALE_FACTOR = 2; |
|
|
|
const finalizeArrayBuffer = ({contents, length}) => hasArrayBufferResize() ? contents : contents.slice(0, length); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const hasArrayBufferResize = () => 'resize' in ArrayBuffer.prototype; |
|
|
|
const arrayBufferMethods = { |
|
init: initArrayBuffer, |
|
convertChunk: { |
|
string: useTextEncoder, |
|
buffer: useUint8Array, |
|
arrayBuffer: useUint8Array, |
|
dataView: useUint8ArrayWithOffset, |
|
typedArray: useUint8ArrayWithOffset, |
|
others: throwObjectStream, |
|
}, |
|
getSize: getLengthProp, |
|
truncateChunk: truncateArrayBufferChunk, |
|
addChunk: addArrayBufferChunk, |
|
getFinalChunk: noop, |
|
finalize: finalizeArrayBuffer, |
|
}; |
|
|