local Observable = require "rx.observable" local Subscription = require "rx.subscription" local util = require "rx.util" --- Returns an Observable that merges the values produced by the source Observables by grouping them -- by their index. The first onNext event contains the first value of all of the sources, the -- second onNext event contains the second value of all of the sources, and so on. onNext is called -- a number of times equal to the number of values produced by the Observable that produces the -- fewest number of values. -- @arg {Observable...} sources - The Observables to zip. -- @returns {Observable} function Observable.zip(...) local sources = util.pack(...) local count = #sources return Observable.create(function(observer) local values = {} local active = {} local subscriptions = {} for i = 1, count do values[i] = { n = 0, } active[i] = true end local function onNext(i) return function(value) table.insert(values[i], value) values[i].n = values[i].n + 1 -- luacheck: ignore i local ready = true for i = 1, count do if values[i].n == 0 then ready = false break end end if ready then local payload = {} for i = 1, count do payload[i] = table.remove(values[i], 1) values[i].n = values[i].n - 1 end observer:onNext(util.unpack(payload)) end end end local function onError(message) return observer:onError(message) end local function onCompleted(i) return function() active[i] = nil if not next(active) or values[i].n == 0 then return observer:onCompleted() end end end for i = 1, count do subscriptions[i] = sources[i]:subscribe(onNext(i), onError, onCompleted(i)) end return Subscription.create(function() for i = 1, count do if subscriptions[i] then subscriptions[i]:unsubscribe() end end end) end) end