function Rx.switchAll()return function(M)assert(Observable.isObservable(M),"\066\097\100 \111\098\115\101\114\118\097\098\108\101")return Observable.new(function(c)local Z=Maid.new()local N=false local z=false local C=nil Z:GiveTask(function()Z._innerSub=nil Z._outerSuber=nil end)Z._outerSuber=M:Subscribe(function(M)assert(Observable.isObservable(M),"\066\097\100 \111\098\115\101\114\118\097\098\108\101")z=false C=M Z._innerSub=nil Z._innerSub=M:Subscribe(function(...)c:Fire(...)end,function(...)if C==M then c:Fail(...)end end,function()if C==M then z=true if z and N then c:Complete()Z:DoCleaning()end end end)end,function(...)c:Fail(...)Z:DoCleaning()end,function()N=true if z and N then c:Complete()Z:DoCleaning()end end)return Z end)end end

function Rx.switchAll()
	return function(source)
		assert(Observable.isObservable(source), "Bad observable")

		return Observable.new(function(sub)
			local outerMaid = Maid.new()
			local topComplete = false
			local insideComplete = false
			local currentInside = nil

			outerMaid:GiveTask(function()
				-- Ensure inner subscription is disconnected first. This prevents
				-- the inner sub from firing while the outer is subscribed,
				-- throwing a warning.
				outerMaid._innerSub = nil
				outerMaid._outerSuber = nil
			end)

			outerMaid._outerSuber = source:Subscribe(
				function(observable)
					assert(Observable.isObservable(observable), "Bad observable")

					insideComplete = false
					currentInside = observable
					outerMaid._innerSub = nil

					outerMaid._innerSub = observable:Subscribe(
						function(...)
							sub:Fire(...)
						end, -- Merge each inner observable
						function(...)
							if currentInside == observable then
								sub:Fail(...)
							end
						end, -- Emit failure automatically
						function()
							if currentInside == observable then
								insideComplete = true
								if insideComplete and topComplete then
									sub:Complete()
									outerMaid:DoCleaning() -- Paranoid ensure cleanup.
								end
							end
						end)
				end,
				function(...)
					sub:Fail(...) -- Also reflect failures up to the top!
					outerMaid:DoCleaning()
				end,
				function()
					topComplete = true
					if insideComplete and topComplete then
						sub:Complete()
						outerMaid:DoCleaning() -- Paranoid ensure cleanup
					end
				end)

			return outerMaid
		end)
	end
end
