-- enum.lua --[[提供枚举机制 示例: local enum = require(enum) 用法1: local TEST1 = enum("TEST1", 0, "ONE", "THREE", "TWO") print(TEST1.TWO) 用法2: local TEST2 = enum("TEST2", 1, "ONE", "THREE", "TWO") TEST2.FOUR = TEST2() print(TEST2.TWO, TEST2.FOUR) 用法3: local TEST3 = enum("TEST3", 2) TEST3("ONE") TEST3("TWO") TEST3("FOUR", 4) local five = TEST3("FIVE") print(TEST3.TWO, TEST3.FOUR, TEST3.FIVE, five) --]] local skynet = require "skynet" local ipairs = ipairs local rawget = rawget local rawset = rawset local tconcat = table.concat local sformat = string.format local dgetinfo = debug.getinfo local setmetatable = setmetatable local enum_tpls = {} local function enum_tostring(eo) return sformat("enum:%s(max:%s, elems: {%s})", eo.__name, eo.__vmax, tconcat(eo.__vlist, ",")) end local function enum_new(emobj, field, value) value = value or emobj.__vmax if field then emobj.__vlist[field] = value if value >= emobj.__vmax then emobj.__vmax = value + 1 end end return value end local function enum_index(emobj, field) return emobj.__vlist[field] end local function enum_newindex(emobj, field, value) local vlist = emobj.__vlist if vlist[field] then skynet.error("enum %s redefine field %s!", emobj.__name, field) end vlist[field] = value if value >= emobj.__vmax then emobj.__vmax = value + 1 end end local enumMT = { __call = enum_new, __index = enum_index, __newindex = enum_newindex, __tostring = enum_tostring, } local function enum_init(emobj, base, ...) emobj.__vlist = {} emobj.__vmax = base for _, field in ipairs({...}) do emobj.__vlist[field] = emobj.__vmax emobj.__vmax = emobj.__vmax + 1 end end local function enum_list(ems) local elist = rawget(ems, "__list") if not elist then elist = {} rawset(ems, "__list", elist) end return elist end local function new(ems, name, base, ...) local info = dgetinfo(2, "S") local moudle = info.short_src local lists = enum_list(ems) local eobj = lists[name] if eobj then if eobj.__moudle ~= moudle then skynet.error("enum %s redefined! moudle:%s", name, moudle) end else eobj = { __name = name, __moudle = moudle, } end enum_init(eobj, base, ...) setmetatable(eobj, enumMT) lists[name] = eobj return eobj end local function index(ems, field) local lists = enum_list(ems) return lists[field] end local MT = { __call = new, __index = index, } setmetatable(enum_tpls, MT) function Enum(name, base, ...) if base then return enum_tpls(name, base, ...) end -- 没有传base参数表示查询 return enum_tpls[name] end