--[[
	luadata by CapsAdmin (fuck copyright, do what you want with this)

	-- encodes table to string
		string 	luadata.Encode(tbl)

	-- decodes string to table
	-- it will throw an error if there's a syntax error in the table
		table 	luadata.Decode(str)

	-- writes the table to file ( it's just "file.Write(path, luadata.Encode(str))" )
		nil 	luadata.WriteFile(path, tbl)
		table 	luadata.ReadFile(path)

	-- returns a string of how the variable is typically initialized
		string  luadata.ToString(var)

	-- will let you add your own tostring function for a custom type
	-- if you have made a custom data object, you can do this "mymatrix.LuaDataType = "Matrix33""
	-- and it will make luadata.Type return that instead
		nil		luadata.SetModifier(type, callback)

]]
luadata = luadata or {} local s = luadata

luadata.EscapeSequences = {
	[("\a"):byte()] = [[\a]],
	[("\b"):byte()] = [[\b]],
	[("\f"):byte()] = [[\f]],
	[("\t"):byte()] = [[\t]],
	[("\r"):byte()] = [[\r]],
	[("\v"):byte()] = [[\v]],
}

local tab = 0

luadata.Types = {
	["number"] = function(var)
		return ("%s"):format(var)
	end,
	["string"] = function(var)

		local str = ""

		for char in var:gmatch(".") do
			str = str  .. (s.EscapeSequences[str:byte()] or char)
		end

		if str:find('"', nil, true) then
			str = "'" .. str .. "'"
		else
			str = '"' .. str .. '"'
		end

		return str
	end,
	["boolean"] = function(var)
		return ("%s"):format(var and "true" or "false")
	end,

--[[ 	-- comment these out if you don't want shit like this to be storeable
	["Entity"] = function(var)
		if var:IsPlayer() then
			return ("player.GetByUniqueID(%q)"):format(var:UniqueID())
		end

		return ("Entity(%i)"):format(var:EntIndex())
	end,
	["Panel"] = function(var)
		return "NULL"
	end,
	["NULL"] = function(var)
		return "NULL"
	end, ]]

	["table"] = function(var)

		tab = tab + 1
		local str = luadata.Encode(var, true)
		tab = tab - 1
		return str
	end,
}

function luadata.SetModifier(type, callback)
	luadata.Types[type] = callback
end

function luadata.Type(var)
	local t=type(var)


	if t == "table" then
		if var.LuaDataType then
			t = var.LuaDataType
		end
	end

	return t
end

function luadata.ToString(var)
	local func = s.Types[s.Type(var)]
	return func and func(var)
end

function luadata.Encode(tbl, __brackets)
	if luadata.Hushed then return end

	local str = __brackets and "{\n" or ""

	for key, value in pairs(tbl) do
		value = s.ToString(value)
		key = s.ToString(key)

		if key and value and key ~= "__index" then
			str = str .. ("\t"):rep(tab) ..  ("[%s] = %s,\n"):format(key, value)
		end
	end

	str = str .. ("\t"):rep(math.max(tab-1,0)) .. (__brackets and "}" or "")

	return str
end

function luadata.Decode(str)
	return loadstring("return {\n" .. str .. "\n}")()
end