-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathEnumeration.lua
118 lines (93 loc) · 3.52 KB
/
Enumeration.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
-- Pure-lua implementation of Roblox-style Enums
-- @author Validark
local Resources = require(game:GetService("ReplicatedStorage"):WaitForChild("Resources"))
local Debug = Resources:LoadLibrary("Debug")
local Typer = Resources:LoadLibrary("Typer")
local SortedArray = Resources:LoadLibrary("SortedArray")
local Error__index = {
__index = function(_, i)
Debug.Error(tostring(i) .. " is not a valid EnumerationItem")
end;
}
local Error__index2 = {
__index = function(_, i)
Debug.Error(tostring(i) .. " is not a valid member")
end;
}
local EnumerationsArray = SortedArray.new(nil, function(Left, Right)
return tostring(Left) < tostring(Right)
end)
local Enumerations = setmetatable({}, Error__index)
function Enumerations:GetEnumerations()
return EnumerationsArray:Copy()
end
local function ReadOnlyNewIndex(_, Index, _)
Debug.Error("Cannot write to index [%q]", Index)
end
local function CompareEnumTypes(EnumItem1, EnumItem2)
return EnumItem1.Value < EnumItem2.Value
end
local Casts = {}
local EnumContainerTemplate = {}
EnumContainerTemplate.__index = setmetatable({}, Error__index)
function EnumContainerTemplate.__index:GetEnumerationItems()
local Array = {}
local Count = 0
for _, Item in next, EnumContainerTemplate[self] do
Count = Count + 1
Array[Count] = Item
end
table.sort(Array, CompareEnumTypes)
return Array
end
function EnumContainerTemplate.__index:Cast(Value)
local Castables = Casts[self]
local Cast = Castables[Value]
if Cast then
return Cast
else
return false, "[" .. Debug.Inspect(Value) .. "] is not a valid " .. tostring(self)
end
end
local function ConstructUserdata(__index, __newindex, __tostring)
local Enumeration = newproxy(true)
local EnumerationMetatable = getmetatable(Enumeration)
EnumerationMetatable.__index = __index
EnumerationMetatable.__newindex = __newindex
EnumerationMetatable.__tostring = function() return __tostring end
EnumerationMetatable.__metatable = "[Enumeration] Requested metatable is locked"
return Enumeration
end
local function ConstructEnumerationItem(Name, Value, EnumContainer, LockedEnumContainer, EnumerationStringStub, Castables)
local Item = ConstructUserdata(setmetatable({
Name = Name;
Value = Value;
EnumerationType = LockedEnumContainer
}, Error__index2), ReadOnlyNewIndex, EnumerationStringStub .. Name, Castables)
Castables[Name] = Item
Castables[Value] = Item
Castables[Item] = Item
EnumContainer[Name] = Item
end
local MakeEnumeration = Typer.AssignSignature(2, Typer.String, Typer.ArrayOfStringsOrDictionaryOfNumbers, function(_, EnumType, EnumTypes)
if rawget(Enumerations, EnumType) then Debug.Error("Enumeration of EnumType " .. EnumType .. " already exists") end
local Castables = {}
local EnumContainer = setmetatable({}, EnumContainerTemplate)
local LockedEnumContainer = ConstructUserdata(EnumContainer, ReadOnlyNewIndex, EnumType)
local EnumerationStringStub = "Enumeration." .. EnumType .. "."
local NumEnumTypes = #EnumTypes
if NumEnumTypes > 0 then
for i = 1, NumEnumTypes do
ConstructEnumerationItem(EnumTypes[i], i - 1, EnumContainer, LockedEnumContainer, EnumerationStringStub, Castables)
end
else
for Name, Value in next, EnumTypes do
ConstructEnumerationItem(Name, Value, EnumContainer, LockedEnumContainer, EnumerationStringStub, Castables)
end
end
Casts[LockedEnumContainer] = Castables
EnumContainerTemplate[LockedEnumContainer] = EnumContainer
EnumerationsArray:Insert(LockedEnumContainer)
Enumerations[EnumType] = LockedEnumContainer
end)
return ConstructUserdata(Enumerations, MakeEnumeration, "Enumerations")