-- Trim empty datastores and scopes from an entire datastore type:

local function prepareDataStoresForExport(origin)
	local dataPrepared = {}

	for name, scopes in pairs(origin) do
		local exportScopes = {}
		for scope, data in pairs(scopes) do
			local exportData = {}
			for key, value in pairs(data) do
				exportData[key] = value
			end
			if next(exportData) ~= nil then -- Only export datastore when non-empty
				exportScopes[scope] = exportData
			end
		end
		if next(exportScopes) ~= nil then -- Only export scope list when non-empty
			dataPrepared[name] = exportScopes
		end
	end

	if next(dataPrepared) ~= nil then -- Only return datastore type when non-empty
		return dataPrepared
	end
end

local function preprocessKey(key)
	if type(key) == "number" then
		if key ~= key then
			return "NAN"
		elseif key >= math.huge then
			return "INF"
		elseif key <= -math.huge then
			return "-INF"
		end
		return tostring(key)
	end
	return key
end

local function simulateYield()
	if Constants.YIELD_TIME_MAX > 0 then
		task.wait(rand:NextNumber(Constants.YIELD_TIME_MIN, Constants.YIELD_TIME_MAX))
	end
end

local function simulateErrorCheck(method)
	if Constants.SIMULATE_ERROR_RATE > 0 and rand:NextNumber() <= Constants.SIMULATE_ERROR_RATE then
		simulateYield()
		error(method .. " rejected with error (simulated error)", 3)
	end
end
