local a=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local C=require(a:WaitForChild("\078\101\118\101\114\109\111\114\101"))local P=C("\116")local B=C(script.Parent.Functions)local Z=C(script.Parent.Tables)local L={}local y=table.insert local G=table.concat function L.camelCase(a)assert(P.string(a))return((a:gsub("\040\037\097\041\040\091\037\119\093\042\041",function(a,C)return a:upper()..C:lower()end)):gsub("\037\065","")):gsub("\094\037\117",string.lower)end function L.kebabCase(a)assert(P.string(a))return((((a:gsub("\040\037\108\041\040\037\117\041",function(a,C)return a..("-"..C)end)):gsub("\037\065","-")):gsub("\094\037-\043","")):gsub("\037-\043\036","")):lower()end function L.snakeCase(a)assert(P.string(a))return((((a:gsub("\040\037\108\041\040\037\117\041",function(a,C)return a..("\095"..C)end)):gsub("\037\065","\095")):gsub("\094\095\043","")):gsub("\095\043\036","")):upper()end function L.titleCase(a)assert(P.string(a))return a:gsub("\040\037\097\041\040\091\037\119\095\037-\'\226\128\153\093\042\041",function(a,C)return a:upper()..C end)end function L.capitalize(a)assert(P.string(a))return a:gsub("\094\037\108",string.upper)end function L.encodeHtml(a)assert(P.string(a))local C={["\060"]="\108\116",["\062"]="\103\116";["\038"]="\097\109\112";["\""]="\113\117\111\116",["\'"]="\097\112\111\115"}return a:gsub("\046",function(a)return C[a]and"\038"..(C[a].."\059")or a end)end function L.decodeHtml(a)assert(P.string(a))local C={lt="\060";gt="\062",amp="\038";quot="\"";apos="\'"}return a:gsub("\040\038\040\035\063\120\063\041\040\091\037\100\037\097\093\043\041\059\041",function(a,P,B)return P==""and C[B]or(P=="\035\120"and tonumber(B,16))and utf8.char(tonumber(B,16))or(P=="\035"and tonumber(B))and utf8.char(B)or a end)end function L.splitByPattern(a,C)assert(P.string(a))assert((P.optional(P.string))(C))local B={}local Z=1 if not C then for C=1,#a,1 do y(B,a:sub(C,C))end return B end local L,G=a:find(C,Z)while L do y(B,a:sub(Z,L-1))Z=G+1 L,G=a:find(C,Z)end y(B,a:sub(Z))return B end function L.trim(a)assert(P.string(a))return a:match("\094\037\115\042\040\046-\041\037\115\042\036")end function L.startsWith(a,C)assert(P.string(a))return a:sub(1,C:len())==C end function L.endsWith(a,C)assert(P.string(a))assert(P.string(C))return a:sub(-C:len())==C end function L.leftPad(a,C,B)assert(P.string(a))assert(P.number(C))assert((P.optional(P.string))(B))B=B or" "local Z=C-#a local L=Z%#B local y=(Z-L)/#B return string.rep(B or" ",y)..(B:sub(1,L)..a)end function L.rightPad(a,C,B)assert(P.string(a))assert(P.number(C))assert((P.optional(P.string))(B))B=B or" "local Z=C-#a local L=Z%#B local y=(Z-L)/#B return a..(string.rep(B or" ",y)..B:sub(1,L))end function L.format(a,...) end function L.pretty(a,C) end function L.debug(a,...)if L.debugTarget==nil then return end L.debugTarget(L.format(...))end function L.setDebug(a)L.debugTarget=a end function L.charToHex(a,C,B)assert(P.string(a))assert(utf8.len(a)==1)local R={}if B then for a,C in utf8.codes(a)do y(R,C)end else for C=1,a:len(),1 do y(R,a:byte(C))end end return G(Z.map(R,function(a)return C and L.format(C,string.format("\037\088",a))end,""))end function L.hexToChar(a)assert(P.string(a))if a:sub(0,1)=="\037"or a:sub(0,1)=="\035"then a=a:sub(1)elseif a:sub(0,2)=="\048\120"then a=a:sub(2)end return utf8.char(tonumber(a,16))or error("\077\097\108\102\111\114\109\101\100\073\110\112\117\116")end function L.encodeUrl(a)assert(P.string(a))return a:gsub("\091\094\037\059\037\044\037\047\037\063\037\058\037\064\037\038\037\061\037\043\037\036\037\119\037-\037\095\037\046\037\033\037~\037\042\037\'\037\040\037\041\037\035\093",B.bindTail(L.charToHex,"\037\123\125",true))end function L.encodeUrlComponent(a)assert(P.string(a))return a:gsub("\091\094\037\119\037-\095\037\046\037\033\037~\037\042\037\'\037\040\037\041\093",B.bindTail(L.charToHex,"\037\123\125",true))end local R=B.once(function()local a={}for C in("\035\036\038\043\044\047\058\059\061\063\064"):gmatch("\046")do a[string.byte(C)]=true end return a end)function L.decodeUrl(a)assert(P.string(a))local C=R()return a:gsub("\037\037\040\037\120\037\120\041",function(a)local P=tonumber(a,16)if not C[P]then return utf8.char(P)end end)end function L.decodeUrlComponent(a)assert(P.string(a))return a:gsub("\037\037\040\037\120\037\120\041",L.hexToChar)end function L.encodeQueryString(a)assert(P.table(a))local C=Z.mapValues(a,function(a,C)return L.encodeUrlComponent(tostring(C))..("\061"..L.encodeUrlComponent(tostring(a)))end)return"\063"..G(C,"\038")end return L
--[[
	Useful functions to manipulate strings, based on similar implementations in other standard libraries.
]]
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local require = require(ReplicatedStorage:WaitForChild("Nevermore"))
local t = require("t")

local Functions = require(script.Parent.Functions)
local Tables = require(script.Parent.Tables)
local Strings = {}
local append = table.insert
local concat = table.concat

--[[
	Convert `str` to camel-case.
	@example _.camelCase('Pepperoni Pizza') --> 'pepperoniPizza'
	@example _.camelCase('--pepperoni-pizza--') --> 'pepperoniPizza'
	@example _.camelCase('__PEPPERONI_PIZZA') --> 'pepperoniPizza'
	@trait Chainable
]]
--: string -> string
function Strings.camelCase(str)
	assert(t.string(str))
	return str:gsub(
		"(%a)([%w]*)",
		function(head, tail)
			return head:upper() .. tail:lower()
		end
	):gsub("%A", ""):gsub("^%u", string.lower)
end

--[[
	Convert `str` to kebab-case, making all letters lowercase.
	@example _.kebabCase('strongStilton') --> 'strong-stilton'
	@example _.kebabCase(' Strong Stilton ') --> 'strong-stilton'
	@example _.kebabCase('__STRONG_STILTON__') --> 'strong-stilton'
	@usage Chain with `:upper()` if you need an upper kebab-case string.
	@trait Chainable
]]
--: string -> string
function Strings.kebabCase(str)
	assert(t.string(str))
	return str:gsub(
		"(%l)(%u)",
		function(a, b)
			return a .. "-" .. b
		end
	):gsub("%A", "-"):gsub("^%-+", ""):gsub("%-+$", ""):lower()
end

--[[
	Convert `str` to snake-case, making all letters uppercase.
	@example _.snakeCase('sweetChickenCurry') --> 'SWEET_CHICKEN_CURRY'
	@example _.snakeCase(' Sweet Chicken  Curry ') --> 'SWEET_CHICKEN__CURRY'
	@example _.snakeCase('--sweet-chicken--curry--') --> 'SWEET_CHICKEN__CURRY'
	@usage Chain with `:lower()` if you need a lower snake-case string.
	@trait Chainable
]]
function Strings.snakeCase(str)
	assert(t.string(str))
	return str:gsub(
		"(%l)(%u)",
		function(a, b)
			return a .. "_" .. b
		end
	):gsub("%A", "_"):gsub("^_+", ""):gsub("_+$", ""):upper()
end

--[[
	Convert `str` to title-case, where the first letter of each word is capitalized.
	@example _.titleCase("jello world") --> "Jello World"
	@example _.titleCase("yellow-jello with_sprinkles") --> "Yellow-jello With_sprinkles"
	@example _.titleCase("yellow jello's don’t mellow") --> "Yellow Jello's Dont’t Mellow"
	@usage Dashes, underscores and apostraphes don't break words.
	@trait Chainable
]]
function Strings.titleCase(str)
	assert(t.string(str))
	return str:gsub(
		"(%a)([%w_%-'’]*)",
		function(head, tail)
			return head:upper() .. tail
		end
	)
end

--[[
	Capitalize the first letter of `str`.
	@example _.capitalize("hello mould") --> "Hello mould"
	@trait Chainable
]]
function Strings.capitalize(str)
	assert(t.string(str))
	return str:gsub("^%l", string.upper)
end

--[==[
	Converts the characters `&<>"'` in `str` to their corresponding HTML entities.
	@example _.encodeHtml([[Pease < Bacon > "Fish" & 'Chips']]) --> "Peas &lt; Bacon &gt; &quot;Fish&quot; &amp; &apos;Chips&apos;"
	@trait Chainable
]==]
function Strings.encodeHtml(str)
	assert(t.string(str))
	local entities = {["<"] = "lt", [">"] = "gt", ["&"] = "amp", ['"'] = "quot", ["'"] = "apos"}
	return str:gsub(
		".",
		function(char)
			return entities[char] and ("&" .. entities[char] .. ";") or char
		end
	)
end

--[==[
	The inverse of `_.encodeHtml`.
	Converts any HTML entities in `str` to their corresponding characters.
	@example _.decodeHtml("&lt;b&gt;&#34;Smashed&quot;&lt;/b&gt; &apos;Avocado&#39; &#x1F60F;") --> [[<b>"Smashed"</b> 'Avocado' 😏]]
	@trait Chainable
]==]
function Strings.decodeHtml(str)
	assert(t.string(str))
	local entities = {lt = "<", gt = ">", amp = "&", quot = '"', apos = "'"}
	return str:gsub(
		"(&(#?x?)([%d%a]+);)",
		function(original, hashPrefix, code)
			return (hashPrefix == "" and entities[code]) or
				(hashPrefix == "#x" and tonumber(code, 16)) and utf8.char(tonumber(code, 16)) or
				(hashPrefix == "#" and tonumber(code)) and utf8.char(code) or
				original
		end
	)
end

--[[
	Splits `str` into parts based on a pattern delimiter and returns a table of the parts.
	@example _.splitByPattern("rice") --> {"r", "i", "c", "e"}
	@example _.splitByPattern("one.two::flour", "[.:]") --> {"one", "two", "", "flour"}
	@usage This method is useful only when you need a _pattern_ as a delimiter.
	@usage Use the Roblox native `string.split` if you are splitting on a simple string.
	@param delimiter (default = "")
	@trait Chainable
]]
--: string, pattern -> string[]
function Strings.splitByPattern(str, delimiter)
	assert(t.string(str))
	assert(t.optional(t.string)(delimiter))
	local result = {}
	local from = 1
	if (not delimiter) then
		for i = 1, #str do
			append(result, str:sub(i, i))
		end
		return result
	end
	local delim_from, delim_to = str:find(delimiter, from)
	while delim_from do
		append(result, str:sub(from, delim_from - 1))
		from = delim_to + 1
		delim_from, delim_to = str:find(delimiter, from)
	end
	append(result, str:sub(from))
	return result
end

--[[
	Removes any spaces from the start and end of `str`.
	@example _.trim("  roast veg  ") --> "roast veg"
	@trait Chainable
]]
--: string -> string
function Strings.trim(str)
	assert(t.string(str))
	return str:match("^%s*(.-)%s*$")
end

--[[
	Checks if `str` starts with the string `start`.
	@example _.startsWith("Fun Roblox Games", "Fun") --> true
	@example _.startsWith("Chess", "Fun") --> false
	@trait Chainable
]]
--: string, string -> bool
function Strings.startsWith(str, prefix)
	assert(t.string(str))
	return str:sub(1, prefix:len()) == prefix
end

--[[
	Checks if `str` ends with the string `suffix`.
	@example _.endsWith("Fun Roblox Games", "Games") --> true
	@example _.endsWith("Bad Roblox Memes", "Games") --> false
	@trait Chainable
]]
--: string, string -> bool
function Strings.endsWith(str, suffix)
	assert(t.string(str))
	assert(t.string(suffix))
	return str:sub(-suffix:len()) == suffix
end

--[[
	Makes a string of `length` from `str` by repeating characters from `prefix` at the start of the string.
	@example _.leftPad("toast", 6) --> " toast"
	@example _.leftPad("2", 2, "0") --> "02"
	@example _.leftPad("toast", 10, ":)") --> ":):):toast"
	@param prefix (default = `" "`)
	@trait Chainable
]]
--: string, number, string -> string
function Strings.leftPad(str, length, prefix)
	assert(t.string(str))
	assert(t.number(length))
	assert(t.optional(t.string)(prefix))
	prefix = prefix or " "
	local padLength = length - #str
	local remainder = padLength % #prefix
	local repetitions = (padLength - remainder) / #prefix
	return string.rep(prefix or " ", repetitions) .. prefix:sub(1, remainder) .. str
end

--[[
	Makes a string of `length` from `str` by repeating characters from `suffix` at the end of the string.
	@example _.rightPad("toast", 6) --> "toast "
	@example _.rightPad("2", 2, "!") --> "2!"
	@example _.rightPad("toast", 10, ":)") --> "toast:):):"
	@param suffix (default = `" "`)
	@trait Chainable
]]
--: string, number, string -> string
function Strings.rightPad(str, length, suffix)
	assert(t.string(str))
	assert(t.number(length))
	assert(t.optional(t.string)(suffix))
	suffix = suffix or " "
	local padLength = length - #str
	local remainder = padLength % #suffix
	local repetitions = (padLength - remainder) / #suffix
	return str .. string.rep(suffix or " ", repetitions) .. suffix:sub(1, remainder)
end

--[[
This function is a simpler & more powerful version of `string.format`, inspired by `format!` in Rust.
	If an instance has a `:format()` method, this is used instead, passing the format arguments.
	
		* `{}` prints the next variable using or `tostring`.
		* `{:?}` prints using `_.serializeDeep`.
		* `{:#?}` prints using `_.pretty`.

	@param subject the format match string
]]
function Strings.format(subject, ...)
end

--[[
	Pretty-prints the _subject_ and its associated metatable if _withMetatable_ is true
	@param withMetatable (default = false)
]]
--: any, bool? -> string
function Strings.pretty(subject, withMetatable)
end

--[[
	This function first calls `_.format` on the arguments provided and then outputs the response
	to the debug target, set using `_.setDebug`. By default, this function does nothing, allowing
	developers to leave the calls in the source code if that is beneficial.
	@param subject the format match string
	@usage A common pattern would be to `_.setDebug()` to alias to `print` during local development,
		and call e.g. `_.setDebug(_.bind(HttpService.PostAsync, "https://example.com/log"))`
		on a production build to allow remote debugging.
]]
function Strings.debug(subject, ...)
	if Strings.debugTarget == nil then
		return
	end
	Strings.debugTarget(Strings.format(...))
end

--[[
	Hooks up any debug methods to invoke _fn_. By default, `_.debug` does nothing.
	@param fn (default = `print`)
	@usage Calling `_.setDebug()` will simply print all calls to `_.debug` with formatted arguments.
]]
function Strings.setDebug(fn)
	Strings.debugTarget = fn
end

--[[
	Converts _char_ into a hex representation
	@param format (optional) a string passed to `_.format` which formats the hex value of each of the character's code points.
	@param useBytes (default = false) whether to use the character's bytes, rather than UTF-8 code points.
	@example _.charToHex("<") --> "3C"
	@example _.charToHex("<", "&#{};") --> "&#3C;"
	@example _.charToHex("😏") --> "1F60F"
	@example _.charToHex("😏", "0x{}") --> "0x1F60F"
	@example _.charToHex("🤷🏼‍♀️", "&#x{};") --> "&#x1F937;&#x1F3FC;&#x200D;&#x2640;&#xFE0F;"
	@example _.charToHex("🤷🏼‍♀️", "%{}", true) --> "%F0%9F%A4%B7%F0%9F%8F%BC%E2%80%8D%E2%99%80%EF%B8%8F"
]]
--: char -> str, str?, boolean?
function Strings.charToHex(char, format, useBytes)
	assert(t.string(char))
	assert(utf8.len(char) == 1)
	local values = {}
	if useBytes then
		for position, codePoint in utf8.codes(char) do
			append(values, codePoint)
		end
	else
		for i = 1, char:len() do
			append(values, char:byte(i))
		end
	end
	return concat(
		Tables.map(
			values,
			function(value)
				return format and Strings.format(format, string.format("%X", value))
			end,
			""
		)
	)
end

--[[
	Generates a character from its _hex_ representation.
	@example _.hexToChar("1F60F") --> "😏"
	@example _.hexToChar("%1F60F") --> "😏"
	@example _.hexToChar("#1F60F") --> "😏"
	@example _.hexToChar("0x1F60F") --> "😏"
	@throws _MalformedInput_ if _char_ is not a valid encoding.
]]
--: str -> char
function Strings.hexToChar(hex)
	assert(t.string(hex))
	if hex:sub(0, 1) == "%" or hex:sub(0, 1) == "#" then
		hex = hex:sub(1)
	elseif hex:sub(0, 2) == "0x" then
		hex = hex:sub(2)
	end
	return utf8.char(tonumber(hex, 16)) or error("MalformedInput")
end

--[[
	Encodes _str_ for use as a URL, for example as an entire URL.
	@trait Chainable
	@example
		_.encodeUrl("https://example.com/Egg+Fried Rice!?🤷🏼‍♀️")
		--> "https://example.com/Egg+Fried%20Rice!?%1F937%1F3FC%200D%2640%FE0F"
	@usage
		This method is designed to act like `encodeURI` in JavaScript.
]]
--: string -> string
function Strings.encodeUrl(str)
	assert(t.string(str))
	return str:gsub("[^%;%,%/%?%:%@%&%=%+%$%w%-%_%.%!%~%*%'%(%)%#]", Functions.bindTail(Strings.charToHex, "%{}", true))
end

--[[
	Encodes _str_ for use in a URL, for example as a query parameter of a URL.
	@trait Chainable
	@example
		_.encodeUrlComponent("https://example.com/Egg+Fried Rice!?🤷🏼‍♀️")
		--> "https%3A%2F%2Fexample.com%2FEgg%2BFried%20Rice!%3F%1F937%1F3FC%200D%2640%FE0F"
	@usage
		This method is designed to act like `encodeURIComponent` in JavaScript.
	@usage
		This is very similar to `HttpService.EncodeUrl`, but is included for parity and conforms closer to the standard (e.g. EncodeUrl unnecessarily encodes `!`).
]]
--: string -> string
function Strings.encodeUrlComponent(str)
	assert(t.string(str))
	return str:gsub("[^%w%-_%.%!%~%*%'%(%)]", Functions.bindTail(Strings.charToHex, "%{}", true))
end

local calculateDecodeUrlExceptions =
	Functions.once(
	function()
		local exceptions = {}
		for char in ("#$&+,/:;=?@"):gmatch(".") do
			exceptions[string.byte(char)] = true
		end
		return exceptions
	end
)

--[[
	The inverse of `_.encodeUrl`.
	@trait Chainable
	@example
		_.decodeUrl("https://Egg+Fried%20Rice!?")
		--> "https://Egg+Fried Rice!?"
	@usage
		This method is designed to act like `decodeURI` in JavaScript.
]]
--: string -> string
function Strings.decodeUrl(str)
	assert(t.string(str))
	local exceptions = calculateDecodeUrlExceptions()
	return str:gsub(
		"%%(%x%x)",
		function(term)
			local charId = tonumber(term, 16)
			if not exceptions[charId] then
				return utf8.char(charId)
			end
		end
	)
end

--[[
	The inverse of `_.encodeUrlComponent`.
	@trait Chainable
	@example
		_.decodeUrlComponent("https%3A%2F%2FEgg%2BFried%20Rice!%3F")
		--> "https://Egg+Fried Rice!?"
	@usage This method is designed to act like `decodeURIComponent` in JavaScript.
	@throws _MalformedInput_ if _str_ contains characters encoded incorrectly.
]]
--: string -> string
function Strings.decodeUrlComponent(str)
	assert(t.string(str))
	return str:gsub("%%(%x%x)", Strings.hexToChar)
end

--[[
	Takes a _query_ dictionary of key-value pairs and builds a query string that can be concatenated
	to the end of a url.
	
	@example
		_.encodeQueryString({
			time = 11,
			biscuits = "hob nobs",
			chocolatey = true
		})) --> "?biscuits=hob+nobs&time=11&chocolatey=true"

	@usage A query string which contains duplicate keys with different values is technically valid, but this function doesn't provide a way to produce them.
]]
--: <K,V>(Iterable<K,V> -> string)
function Strings.encodeQueryString(query)
	assert(t.table(query))
	local fields =
		Tables.mapValues(
		query,
		function(value, key)
			return Strings.encodeUrlComponent(tostring(key)) .. "=" .. Strings.encodeUrlComponent(tostring(value))
		end
	)
	return ("?" .. concat(fields, "&"))
end

return Strings