function RxAttributeUtils.observeAttributeBrio(q,w,M)assert(typeof(q)=="\073\110\115\116\097\110\099\101","\066\097\100 \105\110\115\116\097\110\099\101")assert(type(w)=="\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(Q)local z=Maid.new()local b=UNSET_VALUE local function g()local g=q:GetAttribute(w)if b~=g then b=g if not M or M(g)then local q=Brio.new(g)z._lastBrio=q if z._lastBrio==q then Q:Fire(q)end else z._lastBrio=nil end end end z:GiveTask((q:GetAttributeChangedSignal(w)):Connect(g))g()return z end)end return RxAttributeUtils
--[=[
	Observes an attribute on an instance with a conditional statement.
	@param instance Instance
	@param attributeName string
	@param condition function | nil
	@return Observable<Brio<any>>
]=]
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
