local function b(b,...)for E,p in ipairs({...})do for E,p in pairs(p)do b[E]=p end end return b end local function E(b,E)for E,p in pairs(E)do b[E]=p end end local function p(b,E,p)assert(type(b)=="\116\097\098\108\101","\070\105\114\115\116 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \116\097\098\108\101")assert(E==nil or type(E)=="\115\116\114\105\110\103","\083\101\099\111\110\100 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103 \111\114 \110\105\108")E=E or"\084\065\066\076\069"local l={}local m=" - "local function M(b,E)l[#l+1]=m:rep(E)..(b.."\n")end local function D(b,E)return tostring(b.k)<tostring(E.k)end local function z(b,E,l)M(l.."\058",E-1)local m={}local F={}local k=0 for b,E in pairs(b)do if type(E)=="\116\097\098\108\101"then table.insert(F,{k=b;v=E})else table.insert(m,{k=b;v="\091"..(typeof(E)..("\093 "..tostring(E)))})end local p=#tostring(b)+1 if p>k then k=p end end table.sort(m,D)table.sort(F,D)for b,p in ipairs(m)do M(tostring(p.k)..("\058"..((" "):rep(k-#tostring(p.k))..p.v)),E)end if p then for b,p in ipairs(F)do z(p.v,E+1,tostring(p.k)..((" "):rep(k-#tostring(p.k)).." \091\084\097\098\108\101\093"))end else for b,p in ipairs(F)do M(tostring(p.k)..("\058"..((" "):rep(k-#tostring(p.k)).."\091\084\097\098\108\101\093")),E)end end end z(b,1,E)print(table.concat(l,""))end local function l(b)local E=#b local p=table.create(E)for l=1,E,1 do p[l]=b[(E-l)+1]end return p end local function m(b)assert(type(b)=="\116\097\098\108\101","\070\105\114\115\116 \097\114\103\117\109\101\110\116 \109\117\115\116 \098\101 \097 \116\097\098\108\101")local E=Random.new()for p=#b,2,-1 do local l=E:NextInteger(1,p)b[p],b[l]=b[l],b[p]end end local function M(b)return next(b)==nil end local function D(b)return http:JSONEncode(b)end local function z(b)return http:JSONDecode(b)end local function F(b,E)local p=IndexOf(b,E)if p then FastRemove(b,p)return true,p end return false,nil end TableUtil.Copy=CopyTable TableUtil.CopyShallow=CopyTableShallow TableUtil.Sync=Sync TableUtil.FastRemove=FastRemove TableUtil.FastRemoveFirstValue=F TableUtil.Print=p TableUtil.Map=Map TableUtil.Filter=Filter TableUtil.Reduce=Reduce TableUtil.Assign=b TableUtil.Extend=E TableUtil.IndexOf=IndexOf TableUtil.Reverse=l TableUtil.Shuffle=m TableUtil.IsEmpty=M TableUtil.EncodeJSON=D TableUtil.DecodeJSON=z return TableUtil
-- tableUtil.Assign(Table target, ...Table sources)
local function Assign(target, ...)
	for _, src in ipairs({ ... }) do
		for k, v in pairs(src) do
			target[k] = v
		end
	end
	return target
end

local function Extend(tbl, extension)
	for k, v in pairs(extension) do
		tbl[k] = v
	end
end

local function Print(tbl, label, deepPrint)
	assert(type(tbl) == "table", "First argument must be a table")
	assert(label == nil or type(label) == "string", "Second argument must be a string or nil")

	label = (label or "TABLE")

	local strTbl = {}
	local indent = " - "

	-- Insert(string, indentLevel)
	local function Insert(s, l)
		strTbl[#strTbl + 1] = (indent:rep(l) .. s .. "\n")
	end

	local function AlphaKeySort(a, b)
		return (tostring(a.k) < tostring(b.k))
	end

	local function PrintTable(t, lvl, lbl)
		Insert(lbl .. ":", lvl - 1)
		local nonTbls = {}
		local tbls = {}
		local keySpaces = 0
		for k, v in pairs(t) do
			if type(v) == "table" then
				table.insert(tbls, { k = k, v = v })
			else
				table.insert(nonTbls, { k = k, v = "[" .. typeof(v) .. "] " .. tostring(v) })
			end
			local spaces = #tostring(k) + 1
			if spaces > keySpaces then
				keySpaces = spaces
			end
		end
		table.sort(nonTbls, AlphaKeySort)
		table.sort(tbls, AlphaKeySort)
		for _, v in ipairs(nonTbls) do
			Insert(tostring(v.k) .. ":" .. (" "):rep(keySpaces - #tostring(v.k)) .. v.v, lvl)
		end
		if deepPrint then
			for _, v in ipairs(tbls) do
				PrintTable(v.v, lvl + 1, tostring(v.k) .. (" "):rep(keySpaces - #tostring(v.k)) .. " [Table]")
			end
		else
			for _, v in ipairs(tbls) do
				Insert(tostring(v.k) .. ":" .. (" "):rep(keySpaces - #tostring(v.k)) .. "[Table]", lvl)
			end
		end
	end

	PrintTable(tbl, 1, label)

	print(table.concat(strTbl, ""))
end

local function Reverse(tbl)
	local n = #tbl
	local tblRev = table.create(n)
	for i = 1, n do
		tblRev[i] = tbl[n - i + 1]
	end
	return tblRev
end

local function Shuffle(tbl)
	assert(type(tbl) == "table", "First argument must be a table")
	local rng = Random.new()
	for i = #tbl, 2, -1 do
		local j = rng:NextInteger(1, i)
		tbl[i], tbl[j] = tbl[j], tbl[i]
	end
end

local function IsEmpty(tbl)
	return (next(tbl) == nil)
end

local function EncodeJSON(tbl)
	return http:JSONEncode(tbl)
end

local function DecodeJSON(str)
	return http:JSONDecode(str)
end

local function FastRemoveFirstValue(t, v)
	local index = IndexOf(t, v)
	if index then
		FastRemove(t, index)
		return true, index
	end
	return false, nil
end

TableUtil.Copy = CopyTable
TableUtil.CopyShallow = CopyTableShallow
TableUtil.Sync = Sync
TableUtil.FastRemove = FastRemove
TableUtil.FastRemoveFirstValue = FastRemoveFirstValue
TableUtil.Print = Print
TableUtil.Map = Map
TableUtil.Filter = Filter
TableUtil.Reduce = Reduce
TableUtil.Assign = Assign
TableUtil.Extend = Extend
TableUtil.IndexOf = IndexOf
TableUtil.Reverse = Reverse
TableUtil.Shuffle = Shuffle
TableUtil.IsEmpty = IsEmpty
TableUtil.EncodeJSON = EncodeJSON
TableUtil.DecodeJSON = DecodeJSON

return TableUtil
