Skip to content

Commit

Permalink
Merge pull request #3 from howmanysmall/V2.0.0
Browse files Browse the repository at this point in the history
V2.0.0
  • Loading branch information
howmanysmall authored Apr 9, 2021
2 parents a7772e2 + 12ea28d commit 4424a9d
Show file tree
Hide file tree
Showing 7 changed files with 236 additions and 71 deletions.
1 change: 1 addition & 0 deletions .styluaignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"Lua.runtime.version": "Luau"
"Lua.runtime.version": "Luau",
"rojo.buildOutputPath": "enumerator"
}
28 changes: 28 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Changelog
All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [2.1.0] - 2021-04-09
### Added
- **[BREAKING]** Added `Enumerator.cast` to the enumerator function list, replacing `castToEnumerator`.
- Added all the missing tests for the module.
- Added `EnumeratorItem.type` and `EnumeratorItem.rawType()`, which return the `Enumerator` they belong to.
- Added this CHANGELOG.

### Changed
- Minor formatting updates.

### Removed
- Removed `castToEnumerator`, please use `Enumerator.cast` instead.

## [1.1.0] - 2021-03-18
### Added
- Added `EnumeratorItem.name` and `EnumeratorItem.rawName()`, which simply return the string version of the EnumeratorItem.

## [1.0.0] - ????-??-??
### Added
- All the code.

[1.0.0]: https://github.com/howmanysmall/enumerator/releases/tag/1.0.0
4 changes: 2 additions & 2 deletions rotriever.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[package]
name = "howmanysmall/enumerator"
version = "1.0.0"
version = "2.0.0"
author = "howmanysmall"
dependencies_root="./src/enumerator/"
dependencies_root = "./src/enumerator/"
content_root = "./src/enumerator"
license = "MIT"

Expand Down
79 changes: 41 additions & 38 deletions src/enumerator/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,13 @@ end
--[[**
Creates a new enumeration.
@param [t:string] enumName The unique name of the enumeration.
@param [t:union(t:array<t:string>, t:keys<t:string>)] enumValues The values of the enumeration.
@param [t:union<t:array<t:string>, t:keys<t:string>>] enumValues The values of the enumeration.
@returns [t:userdata] a new enumeration
**--]]
local function enumerator(enumName, enumValues)
assert(enumeratorTuple(enumName, enumValues))

local enum = newproxy(true)
local internal = {}
local rawValues = {}

Expand All @@ -65,28 +66,57 @@ local function enumerator(enumName, enumValues)
return false
end

--[[**
This function will cast values to the appropriate enumerator. This behaves like a type checker from t, except it returns the value if it was found.
@param [t:any] value The value you want to cast.
@returns [t:tuple<t:union<t:literal<false>, enumerator>, t:optional<t:string>>] Either returns the appropriate enumeration if found or false and an error message if it couldn't find it.
**--]]
function internal.cast(value)
if internal.isEnumValue(value) then
return value
end

local foundEnumerator = rawValues[value]
if foundEnumerator ~= nil then
return foundEnumerator
else
return false, string.format(
INVALID_VALUE_ERROR,
tostring(value),
typeof(value),
tostring(enum)
)
end
end

if enumValues[1] then
for _, valueName in ipairs(enumValues) do
assert(valueName ~= "fromRawValue", "Cannot use 'fromRawValue' as a value")
assert(valueName ~= "isEnumValue", "Cannot use 'isEnumValue' as a value")
assert(valueName ~= "cast", "Cannot use 'cast' as a value")
assert(internal[valueName] == nil, string.format(ALREADY_USED_NAME_ERROR, valueName, enumName))
assert(rawValues[valueName] == nil, string.format(ALREADY_USED_VALUE_ERROR, valueName, enumName))

local value = newproxy(true)
local metatable = getmetatable(value)
local valueString = string.format("%s.%s", enumName, valueName)

function metatable.__tostring()
function metatable:__tostring()
return valueString
end

metatable.__index = lockTable({
name = valueName,
type = enum,
value = valueName,
rawName = function()
return valueName
end,

rawType = function()
return enum
end,

rawValue = function()
return valueName
end,
Expand All @@ -99,24 +129,30 @@ local function enumerator(enumName, enumValues)
for valueName, rawValue in pairs(enumValues) do
assert(valueName ~= "fromRawValue", "Cannot use 'fromRawValue' as a value")
assert(valueName ~= "isEnumValue", "Cannot use 'isEnumValue' as a value")
assert(valueName ~= "cast", "Cannot use 'cast' as a value")
assert(internal[valueName] == nil, string.format(ALREADY_USED_NAME_ERROR, valueName, enumName))
assert(rawValues[valueName] == nil, string.format(ALREADY_USED_VALUE_ERROR, valueName, enumName))

local value = newproxy(true)
local metatable = getmetatable(value)
local valueString = string.format("%s.%s", enumName, valueName)

function metatable.__tostring()
function metatable:__tostring()
return valueString
end

metatable.__index = lockTable({
name = valueName,
type = enum,
value = rawValue,
rawName = function()
return valueName
end,

rawType = function()
return enum
end,

rawValue = function()
return rawValue
end,
Expand All @@ -127,47 +163,14 @@ local function enumerator(enumName, enumValues)
end
end

local enum = newproxy(true)
local metatable = getmetatable(enum)
metatable.__index = lockTable(internal, enumName)

function metatable.__tostring()
function metatable:__tostring()
return enumName
end

return enum
end

--[[**
Creates a function for the passed enumerator that will cast values to the appropriate enumerator. This behaves like a type checker from t, except it returns the value if it was found.
@param [enumerator] castFromEnumerator The enumerator you are casting from.
@returns [t:callback] castingFunction This is a function that takes a value and returns the appropriate enumeration if found or false and an error message if it couldn't find it.
**--]]
local function castEnumerator(castFromEnumerator)
return function(value)
if castFromEnumerator.isEnumValue(value) then
return value
end

local foundEnumerator = castFromEnumerator.fromRawValue(value)
if foundEnumerator ~= nil then
return foundEnumerator
else
return false, string.format(
INVALID_VALUE_ERROR,
tostring(value),
typeof(value),
tostring(castFromEnumerator)
)
end
end
end

return setmetatable({
castEnumerator = castEnumerator,
enumerator = enumerator,
}, {
__call = function(_, enumName, enumValues)
return enumerator(enumName, enumValues)
end,
})
return enumerator
Loading

0 comments on commit 4424a9d

Please sign in to comment.