react-native-fast-io
Version:
Modern IO for React Native, built on top of Nitro and Web standards
84 lines (82 loc) • 2.05 kB
JavaScript
import { ReadableStream } from "./streams.js";
import { TextDecoder } from "./text.js";
export class Blob {
get size() {
return this._size;
}
constructor(parts = [], options = {}) {
this.parts = parts;
this.type = options?.type?.toLowerCase() || '';
this._size = calculateSize(parts);
}
slice() {
throw new Error('Not implemented');
}
stream() {
const streams = this.parts.map(part => {
if (part instanceof Blob) {
return part.stream();
}
return new ReadableStream({
start(controller) {
// tbd: handle all types and convert to Uint8Array
// @ts-ignore
controller.enqueue(part);
controller.close();
}
});
});
return new ReadableStream({
async start(controller) {
try {
for (const stream of streams) {
for await (const chunk of stream) {
controller.enqueue(chunk);
}
}
controller.close();
} catch (error) {
controller.error(error);
}
}
});
}
async arrayBuffer() {
const view = await this.bytes();
return view.buffer;
}
async bytes() {
const result = new ArrayBuffer(this.size);
const view = new Uint8Array(result);
let offset = 0;
for await (const chunk of this.stream()) {
view.set(chunk, offset);
offset += chunk.length;
}
return view;
}
async text() {
const buffer = await this.bytes();
return new TextDecoder().decode(buffer);
}
get [Symbol.toStringTag]() {
return 'Blob';
}
}
// tbd: verify this
function calculateSize(parts) {
return parts.reduce((acc, part) => {
if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
return acc + part.byteLength;
}
if (part instanceof Blob) {
return acc + part.size;
}
if (typeof part === 'string') {
return acc + new TextEncoder().encode(part).length;
}
return acc;
}, 0);
}
//# sourceMappingURL=blob.js.map
;