Advertisement
Guest User

Untitled

a guest
Mar 7th, 2019
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.89 KB | None | 0 0
  1. --[[
  2.  
  3. *******************************************
  4. * libtypecheck.lua 2.0.0 *
  5. * Library that implements type checking *
  6.  
  7. * Licensed under WTFPL version 2 license *
  8. * by annelion, 2019 *
  9. *******************************************
  10.  
  11. *******************************************
  12. ** methods ********************************
  13. *******************************************
  14.  
  15. validate(variable, typeobj) => result(boolean), variable_with_expected_type, error_code, error_reason
  16.  
  17. ERROR CODES:
  18.  
  19.       1: `variable` passed to `validate()` is different with indicated in `typeobj`
  20.       2: `variable` passed to `validate()` out of bounds that indicated in `typeobj`
  21.       255: invalid `type` passed to `validate()` function
  22.  
  23. *******************************************
  24. ** howto **********************************
  25. *******************************************
  26.  
  27. just call validate method and pass variable that you want to check and type object that you expect.
  28. type object consists of type and additional options, such as bounds and default value.
  29.  
  30. type constructor syntax: ` t.type[bounds_min][bounds_max](default_value) ` .
  31. bounds and default value are optional. null default means that variable *may be* empty. one bounds value specifies maximal variable length/value.
  32.  
  33. available types:
  34.  
  35.  - int (integer/float numbers)
  36.  - char (string)
  37.  - uchar (unicode string — only matters when using bounds)
  38.  - bool (true or false represented by boolean or string)
  39.  - array (table in lua)
  40.  
  41. examples:
  42.  
  43. int or int[...] -- (mandatory) number with no bounds
  44. int() or int[...]() -- (optional) number number with no bounds
  45. int[10] -- (mandatory) number (lesser or equal than 10)
  46. int[0][10] -- (mandatory) number (between 0 and 10)
  47. char or char[...] -- (mandatory) string with no bounds
  48. char() or char[...]() -- (optional) string with no bounds
  49. char[128] -- (mandatory) string no longer than 128 bytes
  50. uchar("default value") -- (mandatory) string with default value "default value")
  51. uchar[10]("defaultstr") -- (mandatory) string no longer than 10 characters and with default value "defaultstr"
  52.  
  53. *******************************************
  54. ** usage examples ************************
  55. *******************************************
  56.  
  57. local t = require 'libtypecheck'
  58. print(t.validate(1, t.int)) -- true  1  nil  nil
  59. print(t.validate(nil, t.int(100))) -- true  100  nil  nil
  60. print(t.validate("100", t.int)) -- true  100  nil  nil
  61. print(t.validate("100s", t.int)) -- false nil  1  string
  62. print(t.validate(128, t.int[0][127] )) -- false nil  2  128
  63. print(t.validate(nil, t.char )) -- false  nil  1  nil
  64. print(t.validate(nil, t.char() )) -- true  nil  nil  nil
  65. print(t.validate("test", t.char)) -- true  "test"  nil  nil
  66. print(t.validate("some long string that will fail", t.char[10])) -- false  nil  2  31
  67. print(t.validate(true, t.char))  -- true  "true"  nil  nil
  68. print(t.validate(false, t.bool)) -- true  false  nil  nil
  69. print(t.validate("true", t.bool)) -- true  true  nil  nil
  70. print(t.validate("what a fuck?", t.bool)) -- false  nil  1  string
  71. print(t.validate({1,2,3}, t.array[3]))  -- true  [table: 0x...]  nil  nil  
  72. print(t.validate({1,2,3}, t.array[10][math.huge]))  -- false  nil  2  3
  73. print(t.validate("invalid type", t.no_such_type))
  74.  
  75.  
  76. ]]--
  77.  
  78. local t = {}
  79.  
  80. local ERR_UNKNOWN_TYPE, ERR_INVALID_TYPE, ERR_OUT_OF_BOUNDS = 0xFF, 0x01, 0x02  -- error codes
  81. 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
  82. local types = {}  -- available types. must be functions that accepts (arg,min,max) and returns (arg) or (nil,error_reason)
  83.  
  84. -----------------------------------
  85. -- TYPES --------------------------
  86. -----------------------------------
  87.  
  88. -- type: bool (boolean in lua) --
  89. types.bool = function(arg)
  90.       if arg ~= true and arg ~= 'true' and arg ~= false and arg ~= 'false' then return nil, type(arg); end
  91.       arg = (arg == true or arg == 'true') and true or false
  92.       return arg
  93. end
  94. -- type: int (number in lua) --
  95. types.int = function(arg,min,max)
  96.       local s = tostring(arg); local n = tonumber(s)
  97.       if not (n) or (n and s ~= tostring(n) and not string.match(s, '%.(%d*)0+$') ) then return nil, type(arg); end
  98.       if (min and n < min) or (max and n > max) then return nil, n; end
  99.       return n
  100. end
  101. -- type: char (string in lua) --
  102. types.char = function(arg,min,max)
  103.       if not arg then return nil, type(nil) else arg = tostring(arg); end
  104.       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
  105.       return arg
  106. end
  107. -- type: uchar (string in lua) (unicode counter -- works a bit slower) - -
  108. types.uchar = function(arg,min,max) -- string with unicode counter (works slightly slower) --
  109.       if not arg then return nil, type(nil) else arg = tostring(arg); end
  110.       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
  111.       return arg
  112. end
  113. -- type: array (table in lua) --
  114. types.array = function(arg,min,max)
  115.       if type(arg) ~= 'table' then return nil, type(arg); end
  116.       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
  117.       return arg
  118. end
  119.  
  120. -----------------------------------
  121. -- EXPORTS ------------------------
  122. -----------------------------------
  123.  
  124. -- 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) --
  125. t.validate = function(var_, expect_)
  126.       -- set runtime variables --
  127.       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 {}
  128.       local var = (var_ == nil) and expect.default or var_ -- apply default value --
  129.  
  130.       -- check is type valid --
  131.       if not expect.id or not types[expect.id] then return false, nil, ERR_UNKNOWN_TYPE, nil end -- unknown type --
  132.  
  133.       -- validate --
  134.       if not var and not expect.mandatory then return true, nil end -- optional value is null -- it's ok, return nil asap --
  135.       local res, err = types[expect.id](var, expect.min, expect.max) -- check our variable --      
  136.  
  137.       -- push result --
  138.       if not err then return true, res, nil, nil end -- ok --
  139.       if err and type(err) == 'number' then return false, nil, ERR_OUT_OF_BOUNDS, err end -- out of bounds error --  
  140.       if err and type(err) == 'string' then return false, nil, ERR_INVALID_TYPE, err end -- type error --
  141. end
  142.  
  143. -- export available types --
  144. for export in pairs(types) do t[export] = setmetatable({id=export,mandatory=true,default=nil}, types_mt) end
  145.  
  146. return t
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement