UNPKG

@zkochan/pnpm

Version:

Fast, disk space efficient package manager

131 lines (108 loc) 3.3 kB
/** @license MIT License (c) copyright 2010-2016 original author or authors */ /** @author Brian Cavalier */ /** @author John Hann */ import Stream from '../Stream' import * as transform from './transform' import * as core from '../source/core' import Pipe from '../sink/Pipe' import IndexSink from '../sink/IndexSink' import * as dispose from '../disposable/dispose' import * as base from '@most/prelude' import invoke from '../invoke' import Queue from '../Queue' var map = base.map var tail = base.tail /** * Combine streams pairwise (or tuple-wise) by index by applying f to values * at corresponding indices. The returned stream ends when any of the input * streams ends. * @param {function} f function to combine values * @returns {Stream} new stream with items at corresponding indices combined * using f */ export function zip (f /*, ...streams */) { return zipArray(f, tail(arguments)) } /** * Combine streams pairwise (or tuple-wise) by index by applying f to values * at corresponding indices. The returned stream ends when any of the input * streams ends. * @param {function} f function to combine values * @param {[Stream]} streams streams to zip using f * @returns {Stream} new stream with items at corresponding indices combined * using f */ export function zipArray (f, streams) { return streams.length === 0 ? core.empty() : streams.length === 1 ? transform.map(f, streams[0]) : new Stream(new Zip(f, map(getSource, streams))) } function getSource (stream) { return stream.source } function Zip (f, sources) { this.f = f this.sources = sources } Zip.prototype.run = function (sink, scheduler) { var l = this.sources.length var disposables = new Array(l) var sinks = new Array(l) var buffers = new Array(l) var zipSink = new ZipSink(this.f, buffers, sinks, sink) for (var indexSink, i = 0; i < l; ++i) { buffers[i] = new Queue() indexSink = sinks[i] = new IndexSink(i, zipSink) disposables[i] = this.sources[i].run(indexSink, scheduler) } return dispose.all(disposables) } function ZipSink (f, buffers, sinks, sink) { this.f = f this.sinks = sinks this.sink = sink this.buffers = buffers } ZipSink.prototype.event = function (t, indexedValue) { // eslint-disable-line complexity var buffers = this.buffers var buffer = buffers[indexedValue.index] buffer.push(indexedValue.value) if (buffer.length() === 1) { if (!ready(this.buffers)) { return } emitZipped(this.f, t, buffers, this.sink) if (ended(this.buffers, this.sinks)) { this.sink.end(t, void 0) } } } ZipSink.prototype.end = function (t, indexedValue) { var buffer = this.buffers[indexedValue.index] if (buffer.isEmpty()) { this.sink.end(t, indexedValue.value) } } ZipSink.prototype.error = Pipe.prototype.error function emitZipped (f, t, buffers, sink) { sink.event(t, invoke(f, map(head, buffers))) } function head (buffer) { return buffer.shift() } function ended (buffers, sinks) { for (var i = 0, l = buffers.length; i < l; ++i) { if (buffers[i].isEmpty() && !sinks[i].active) { return true } } return false } function ready (buffers) { for (var i = 0, l = buffers.length; i < l; ++i) { if (buffers[i].isEmpty()) { return false } } return true }