Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- *******************************************
- * libtypecheck.lua 2.0.0 *
- * Library that implements type checking *
- * Licensed under WTFPL version 2 license *
- * by annelion, 2019 *
- *******************************************
- *******************************************
- ** methods ********************************
- *******************************************
- validate(variable, typeobj) => result(boolean), variable_with_expected_type, error_code, error_reason
- ERROR CODES:
- 1: `variable` passed to `validate()` is different with indicated in `typeobj`
- 2: `variable` passed to `validate()` out of bounds that indicated in `typeobj`
- 255: invalid `type` passed to `validate()` function
- *******************************************
- ** howto **********************************
- *******************************************
- just call validate method and pass variable that you want to check and type object that you expect.
- type object consists of type and additional options, such as bounds and default value.
- type constructor syntax: ` t.type[bounds_min][bounds_max](default_value) ` .
- bounds and default value are optional. null default means that variable *may be* empty. one bounds value specifies maximal variable length/value.
- available types:
- - int (integer/float numbers)
- - char (string)
- - uchar (unicode string — only matters when using bounds)
- - bool (true or false represented by boolean or string)
- - array (table in lua)
- examples:
- int or int[...] -- (mandatory) number with no bounds
- int() or int[...]() -- (optional) number number with no bounds
- int[10] -- (mandatory) number (lesser or equal than 10)
- int[0][10] -- (mandatory) number (between 0 and 10)
- char or char[...] -- (mandatory) string with no bounds
- char() or char[...]() -- (optional) string with no bounds
- char[128] -- (mandatory) string no longer than 128 bytes
- uchar("default value") -- (mandatory) string with default value "default value")
- uchar[10]("defaultstr") -- (mandatory) string no longer than 10 characters and with default value "defaultstr"
- *******************************************
- ** usage examples ************************
- *******************************************
- local t = require 'libtypecheck'
- print(t.validate(1, t.int)) -- true 1 nil nil
- print(t.validate(nil, t.int(100))) -- true 100 nil nil
- print(t.validate("100", t.int)) -- true 100 nil nil
- print(t.validate("100s", t.int)) -- false nil 1 string
- print(t.validate(128, t.int[0][127] )) -- false nil 2 128
- print(t.validate(nil, t.char )) -- false nil 1 nil
- print(t.validate(nil, t.char() )) -- true nil nil nil
- print(t.validate("test", t.char)) -- true "test" nil nil
- print(t.validate("some long string that will fail", t.char[10])) -- false nil 2 31
- print(t.validate(true, t.char)) -- true "true" nil nil
- print(t.validate(false, t.bool)) -- true false nil nil
- print(t.validate("true", t.bool)) -- true true nil nil
- print(t.validate("what a fuck?", t.bool)) -- false nil 1 string
- print(t.validate({1,2,3}, t.array[3])) -- true [table: 0x...] nil nil
- print(t.validate({1,2,3}, t.array[10][math.huge])) -- false nil 2 3
- print(t.validate("invalid type", t.no_such_type))
- ]]--
- local t = {}
- local ERR_UNKNOWN_TYPE, ERR_INVALID_TYPE, ERR_OUT_OF_BOUNDS = 0xFF, 0x01, 0x02 -- error codes
- local types_mt = { __index = function(this, max) this.min = rawget(this, 'max'); this.max = max; return this; end, __call = function(this,value) this.default = value; this.mandatory = false; return this; end, } -- types generator
- local types = {} -- available types. must be functions that accepts (arg,min,max) and returns (arg) or (nil,error_reason)
- -----------------------------------
- -- TYPES --------------------------
- -----------------------------------
- -- type: bool (boolean in lua) --
- types.bool = function(arg)
- if arg ~= true and arg ~= 'true' and arg ~= false and arg ~= 'false' then return nil, type(arg); end
- arg = (arg == true or arg == 'true') and true or false
- return arg
- end
- -- type: int (number in lua) --
- types.int = function(arg,min,max)
- local s = tostring(arg); local n = tonumber(s)
- if not (n) or (n and s ~= tostring(n) and not string.match(s, '%.(%d*)0+$') ) then return nil, type(arg); end
- if (min and n < min) or (max and n > max) then return nil, n; end
- return n
- end
- -- type: char (string in lua) --
- types.char = function(arg,min,max)
- if not arg then return nil, type(nil) else arg = tostring(arg); end
- if min or max then local len = string.len(arg); if (min and len < min) or (max and len > max) then return nil, len; end; end
- return arg
- end
- -- type: uchar (string in lua) (unicode counter -- works a bit slower) - -
- types.uchar = function(arg,min,max) -- string with unicode counter (works slightly slower) --
- if not arg then return nil, type(nil) else arg = tostring(arg); end
- if min or max then local _,len = string.gsub(arg, "[^\128-\193]", ""); if (min and len < min) or (max and len > max) then return nil, len; end; end
- return arg
- end
- -- type: array (table in lua) --
- types.array = function(arg,min,max)
- if type(arg) ~= 'table' then return nil, type(arg); end
- if min or max then local len = 0; for _ in pairs(arg) do len = len+1; end; if (min and len < min) or (max and len > max) then return nil, len; end; end
- return arg
- end
- -----------------------------------
- -- EXPORTS ------------------------
- -----------------------------------
- -- validating function, returns: RESULT (true/false), VARIABLE WITH EXPECTED TYPE, ERROR CODE (if result == false), ERROR REASON (wrong type or out-of-bounds variable size) --
- t.validate = function(var_, expect_)
- -- set runtime variables --
- local expect = (expect_) and {id=rawget(expect_, 'id'), mandatory=rawget(expect_, 'mandatory'), default=rawget(expect_, 'default'), min=rawget(expect_, 'min'), max=rawget(expect_, 'max')} or {}
- local var = (var_ == nil) and expect.default or var_ -- apply default value --
- -- check is type valid --
- if not expect.id or not types[expect.id] then return false, nil, ERR_UNKNOWN_TYPE, nil end -- unknown type --
- -- validate --
- if not var and not expect.mandatory then return true, nil end -- optional value is null -- it's ok, return nil asap --
- local res, err = types[expect.id](var, expect.min, expect.max) -- check our variable --
- -- push result --
- if not err then return true, res, nil, nil end -- ok --
- if err and type(err) == 'number' then return false, nil, ERR_OUT_OF_BOUNDS, err end -- out of bounds error --
- if err and type(err) == 'string' then return false, nil, ERR_INVALID_TYPE, err end -- type error --
- end
- -- export available types --
- for export in pairs(types) do t[export] = setmetatable({id=export,mandatory=true,default=nil}, types_mt) end
- return t
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement