function Rx.switchAll()return function(b)assert(Observable.isObservable(b),"\066\097\100 \111\098\115\101\114\118\097\098\108\101")return Observable.new(function(Q)local O=Maid.new()local o=false local w=false local K=nil O:GiveTask(function()O._innerSub=nil O._outerSuber=nil end)O._outerSuber=b:Subscribe(function(b)assert(Observable.isObservable(b),"\066\097\100 \111\098\115\101\114\118\097\098\108\101")w=false K=b O._innerSub=nil O._innerSub=b:Subscribe(function(...)Q:Fire(...)end,function(...)if K==b then Q:Fail(...)end end,function()if K==b then w=true if w and o then Q:Complete()O:DoCleaning()end end end)end,function(...)Q:Fail(...)O:DoCleaning()end,function()o=true if w and o then Q:Complete()O:DoCleaning()end end)return O end)end end
--[=[
	Merges higher order observables together

	https://rxjs.dev/api/operators/switchAll

	Works like mergeAll, where you subscribe to an observable which is
	emitting observables. However, when another observable is emitted it
	disconnects from the other observable and subscribes to that one.

	@return (source: Observable<Observable<T>>) -> Observable<T>
]=]
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
