function RxAttributeUtils.observeAttributeBrio(s,Q,w)assert(typeof(s)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")assert(type(Q)=="\115\116\114\105\110\103","\066\097\100 \097\116\116\114\105\098\117\116\101\078\097\109\101")return Observable.new(function(t)local A=Maid.new()local x=UNSET_VALUE local function M()local M=s:GetAttribute(Q)if x~=M then x=M if not w or w(M)then local s=Brio.new(M)A._lastBrio=s if A._lastBrio==s then t:Fire(s)end else A._lastBrio=nil end end end A:GiveTask((s:GetAttributeChangedSignal(Q)):Connect(M))M()return A end)end return RxAttributeUtils

function RxAttributeUtils.observeAttributeBrio(instance, attributeName, condition)
	assert(typeof(instance) == "Instance", "Bad instance")
	assert(type(attributeName) == "string", "Bad attributeName")

	return Observable.new(function(sub)
		local maid = Maid.new()
		local lastValue = UNSET_VALUE

		local function handleAttributeChanged()
			local attributeValue = instance:GetAttribute(attributeName)

			-- Deferred events can cause multiple values to be queued at once
			-- but we operate at this post-deferred layer, so lets only output
			-- reflected values.
			if lastValue ~= attributeValue then
				lastValue = attributeValue

				if not condition or condition(attributeValue) then
					local brio = Brio.new(attributeValue)
					maid._lastBrio = brio

					-- The above line can cause us to be overwritten so make sure before firing.
					if maid._lastBrio == brio then
						sub:Fire(brio)
					end
				else
					maid._lastBrio = nil
				end
			end
		end

		maid:GiveTask(instance:GetAttributeChangedSignal(attributeName):Connect(handleAttributeChanged))
		handleAttributeChanged()

		return maid
	end)
end

return RxAttributeUtils
