UNPKG

@zenfs/core

Version:

A filesystem, anywhere

129 lines (128 loc) 3.7 kB
import { Errno, Exception, UV } from 'kerium'; import { warn } from 'kerium/log'; import { Readable, Writable } from 'readable-stream'; /** * A ReadStream implementation that wraps an underlying global ReadableStream. */ export class ReadStream extends Readable { pending = true; _path = '<unknown>'; _bytesRead = 0; reader; ready; constructor(opts = {}, handleOrPromise) { super({ ...opts, encoding: opts.encoding ?? undefined }); this.ready = Promise.resolve(handleOrPromise) .then(handle => { this._path = handle['vfs'].path; const internal = handle.readableWebStream({ start: opts.start, end: opts.end }); this.reader = internal.getReader(); this.pending = false; }) .catch(err => { this.destroy(err); }); } async _read() { try { await this.ready; if (!this.reader) return; const { done, value } = await this.reader.read(); if (done) { this.push(null); return; } this._bytesRead += value.byteLength; this.push(value); } catch (err) { this.destroy(new Exception(Errno.EIO, err.toString())); } } close(callback = () => null) { try { this.destroy(); this.emit('close'); callback(null); } catch (err) { callback(new Exception(Errno.EIO, err.toString())); } } get path() { return this._path; } get bytesRead() { return this._bytesRead; } wrap(oldStream) { super.wrap(oldStream); return this; } } /** * A WriteStream implementation that wraps an underlying global WritableStream. */ export class WriteStream extends Writable { pending = true; _path = '<unknown>'; _bytesWritten = 0; writer; ready; constructor(opts = {}, handleOrPromise) { super(opts); this.ready = Promise.resolve(handleOrPromise) .then(handle => { this._path = handle['vfs'].path; const internal = handle.writableWebStream({ start: opts.start }); this.writer = internal.getWriter(); this.pending = false; }) .catch(err => this.destroy(err)); } async _write(chunk, encoding, callback) { await this.ready; if (!this.writer) return callback(warn(UV('EAGAIN', 'write', this._path))); if (encoding != 'buffer') return callback(warn(UV('ENOTSUP', 'write', this._path))); const data = new Uint8Array(chunk.buffer, chunk.byteOffset, chunk.byteLength); try { await this.writer.write(data); this._bytesWritten += chunk.byteLength; callback(); } catch (error) { callback(new Exception(Errno.EIO, error.toString())); } } async _final(callback) { await this.ready; if (!this.writer) return callback(); try { await this.writer.close(); callback(); } catch (error) { callback(new Exception(Errno.EIO, error.toString())); } } close(callback = () => null) { try { this.destroy(); this.emit('close'); callback(null); } catch (error) { callback(new Exception(Errno.EIO, error.toString())); } } get path() { return this._path; } get bytesWritten() { return this._bytesWritten; } }