ix
Version:
The Interactive Extensions for JavaScript
108 lines (100 loc) • 3.46 kB
text/typescript
import { BufferLike } from '../interfaces.js';
import { IterableX } from '../iterable/iterablex.js';
import { Readable, ReadableOptions } from 'stream';
const done = (_: any) => null as any;
type SourceIterator<TSource> = Iterator<TSource, any, number | ArrayBufferView | undefined | null>;
/** @ignore */
/** @ignore */
export class IterableReadable<T> extends Readable {
private _pulling = false;
private _objectMode = true;
private _iterator: SourceIterator<T> | undefined;
constructor(source: Iterable<T>, options?: ReadableOptions) {
super(options);
this._iterator = source[Symbol.iterator]();
this._objectMode = !options || !!options.objectMode;
}
public _read(size: number) {
const it = this._iterator;
if (it && !this._pulling && (this._pulling = true)) {
this._pulling = this._pull(it, size);
}
}
public _destroy(err: Error | null, cb: (err: Error | null) => void) {
const it = this._iterator;
this._iterator = undefined;
const fn = (it && (err ? it.throw : it.return)) || done;
fn.call(it, err);
if (cb) {
cb(null);
}
}
// eslint-disable-next-line complexity
_pull(it: SourceIterator<T>, size: number) {
let innerSize = size;
const objectMode = this._objectMode;
let r: IteratorResult<BufferLike | T> | undefined;
while (this.readable && !(r = it.next(innerSize)).done) {
if (innerSize != null) {
if (objectMode) {
innerSize -= 1;
} else {
innerSize -= Buffer.byteLength(<BufferLike>r.value || '');
}
}
if (!this.push(r.value) || innerSize <= 0) {
break;
}
}
if ((r && r.done) || !this.readable) {
this.push(null);
if (it.return) {
it.return();
}
}
return !this.readable;
}
}
export function toNodeStream<TSource>(source: Iterable<TSource>): IterableReadable<TSource>;
export function toNodeStream<TSource>(
source: Iterable<TSource>,
options: ReadableOptions & { objectMode: true }
): IterableReadable<TSource>;
export function toNodeStream<TSource extends BufferLike>(
source: Iterable<TSource>,
options: ReadableOptions & { objectMode: false }
): IterableReadable<TSource>;
export function toNodeStream<TSource>(
source: Iterable<any>,
options?: ReadableOptions
): IterableReadable<TSource> {
return !options || options.objectMode === true
? new IterableReadable<TSource>(source, options)
: new IterableReadable<TSource extends BufferLike ? TSource : any>(source, options);
}
/**
* @ignore
*/
export function toNodeStreamProto<TSource>(this: Iterable<TSource>): IterableReadable<TSource>;
export function toNodeStreamProto<TSource>(
this: Iterable<TSource>,
options: ReadableOptions | { objectMode: true }
): IterableReadable<TSource>;
export function toNodeStreamProto<TSource extends BufferLike>(
this: Iterable<TSource>,
options: ReadableOptions | { objectMode: false }
): IterableReadable<TSource>;
export function toNodeStreamProto<TSource>(
this: Iterable<any>,
options?: ReadableOptions
): IterableReadable<TSource> {
return !options || options.objectMode === true
? new IterableReadable<TSource>(this, options)
: new IterableReadable<TSource extends BufferLike ? TSource : any>(this, options);
}
IterableX.prototype.toNodeStream = toNodeStreamProto;
declare module '../iterable/iterablex' {
interface IterableX<T> {
toNodeStream: typeof toNodeStreamProto;
}
}