function Util.MakeSequenceType(X)X=X or{}assert(X.Parse~=nil or X.Constructor~=nil,"\077\097\107\101\083\101\113\117\101\110\099\101\084\121\112\101\058 \077\117\115\116 \112\114\111\118\105\100\101 \111\110\101 \111\102\058 \067\111\110\115\116\114\117\099\116\111\114\044 \080\097\114\115\101")X.TransformEach=X.TransformEach or function(...)return...end X.ValidateEach=X.ValidateEach or function()return true end return{Transform=function(G)return Util.Map(Util.SplitPrioritizedDelimeter(G,{"\044";"\037\115"}),function(G)return X.TransformEach(G)end)end,Validate=function(G)if X.Length and#G>X.Length then return false,("\077\097\120\105\109\117\109 \111\102 \037\100 \118\097\108\117\101\115 \097\108\108\111\119\101\100 \105\110 \115\101\113\117\101\110\099\101"):format(X.Length)end for A=1,X.Length or#G,1 do local l,T=X.ValidateEach(G[A],A)if not l then return false,T end end return true end;Parse=X.Parse or function(G)return X.Constructor(unpack(G))end}end

function Util.MakeSequenceType(options)
	options = options or {}

	assert(options.Parse ~= nil or options.Constructor ~= nil, "MakeSequenceType: Must provide one of: Constructor, Parse")

	options.TransformEach = options.TransformEach or function(...)
		return ...
	end

	options.ValidateEach = options.ValidateEach or function()
		return true
	end

	return {
		Transform = function (text)
			return Util.Map(Util.SplitPrioritizedDelimeter(text, {",", "%s"}), function(value)
				return options.TransformEach(value)
			end)
		end;

		Validate = function (components)
			if options.Length and #components > options.Length then
				return false, ("Maximum of %d values allowed in sequence"):format(options.Length)
			end

			for i = 1, options.Length or #components do
				local valid, reason = options.ValidateEach(components[i], i)

				if not valid then
					return false, reason
				end
			end

			return true
		end;

		Parse = options.Parse or function(components)
			return options.Constructor(unpack(components))
		end
	}
end
