Advertisement
InTesting

Obj wrapper (mainly for roblox)

Oct 9th, 2021
1,059
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.52 KB | None | 0 0
  1. local wrapper = {}
  2.  
  3. --[[
  4.     gonna be fun lol
  5.    
  6.          - CHL
  7.          
  8.     Notes:
  9.          - Too lazy to add descriptive errors, refer to the line number from the output.
  10.          * When __index is invoked on the obj, and there are multiple indexes in properties,
  11.            functions and events, then the script will check properties, function and events
  12.            in that order.
  13.  
  14. Descriptions:
  15.      * wrapper:createConstructor()
  16.          Legend:
  17.             Indexes:
  18.                 [A] = Argument (based on index?)
  19.                 [M] = Mandatory? (T or F)
  20.                     [ ] = same as last
  21.        ,________________________________________________________________________________________________.
  22.        |A|Type              |M|Description                                                              |
  23.        |1|table (dictionary)|F|Represents as the properties of the object. In this dictionary, the index|
  24.        | |                  | |is the property name and the value represents as an optional table       |
  25.        | |                  | |(ITEM_1). See more charts below about this.                              |
  26.        |2|table (dictionary)| |Represents as the functions of the object. In this dictionary, each index|
  27.        | |                  | |represents the function name while the value represents the function     |
  28.        | |                  | |(ITEM_2). See more charts below about this.                              |
  29.        |3|table (dictionary)| |Represents as the events of the object. In this dictionary, the index is |
  30.        | |                  | |the event name and the value represents as a non-falsy value, typically  |
  31.        | |                  | |true                                                                     |
  32.        '------------------------------------------------------------------------------------------------'
  33.     This function returns a function, representing as the constructor function, as well as a dictionary,
  34.         where the index is the event name and the value is the function, where when called with any
  35.         arguments, it will call the functions from an internal dictionary.
  36.    
  37.      * ITEM_1
  38.         Legend:
  39.             Indexes:
  40.                 [M] = Mandatory? (T or F)
  41.                     [ ] = same as last
  42.        ,________________________________________________________________________________________________.
  43.        |Index           |M|value type        |value description                                         |
  44.        |strictValueType |F|table (dictionary)|Represents how many values can the new value has to be.   |
  45.        |                | |                  |Index being the type of value and the value being a       |
  46.        |                | |                  |boolean-ish value.                                        |
  47.        |                | |string            |Same as last but this string represents as the index and  |
  48.        |                | |                  |the value is true.                                        |
  49.        |newIndexCallback| |function          |Function which is called when the object has __newindex   |
  50.        |                | |                  |invoked. The value returned is the value that is stored   |
  51.        |                | |                  |internally. Refer to ITEM_1.1 for parameter info.         |
  52.        |indexCallback   | |function          |Function which is called when the object has __index      |
  53.        |                | |                  |invoked. The returned value of that function is also the  |
  54.        |                | |                  |returned value for the __index invoke. Refer to ITEM_1.2  |
  55.        |                | |                  |for parameter info.                                       |
  56.        |default         | |variant           |default value of the property.                            |
  57.        '------------------------------------------------------------------------------------------------'
  58.    
  59.      * ITEM_1.1
  60.         Legend:
  61.             Indexes:
  62.                 [P] = Expected parameters
  63.        ,________________________________________________________________________________________________.
  64.        |P|Type    |Description                                                                          |
  65.        |1|Variant |The new value                                                                        |
  66.        |2|table   |The object                                                                           |
  67.        |3|table   |The object's internal storage                                                        |
  68.        '------------------------------------------------------------------------------------------------'
  69.    
  70.      * ITEM_1.2
  71.         Legend:
  72.             Indexes:
  73.                 [P] = Expected parameters
  74.        ,________________________________________________________________________________________________.
  75.        |P|Type    |Description                                                                          |
  76.        |1|Variant |The index                                                                            |
  77.        |2|table   |The object                                                                           |
  78.        |3|table   |The object's internal storage                                                        |
  79.        '------------------------------------------------------------------------------------------------'
  80.    
  81.      * ITEM_2
  82.         Legend:
  83.             Indexes:
  84.                 [Par] = Expected parameters
  85.                     [T] = tuple arguments
  86.        ,________________________________________________________________________________________________.
  87.        |P|Type              |Description                                                                |
  88.        |1|table             |Object                                                                     |
  89.        |2|table (dictionary)|Object's internal storage                                                  |
  90.        |3|Variant           |The value  when there's at least one argument and when the object was      |
  91.        | |                  |indexed with a period.                                                     |
  92.        | |table             |Representing as the object if the function was indexed with a colon,       |
  93.        | |                  |however since this object is the same as argument 1, you can use the ==    |
  94.        | |                  |operator to determine if the function was index with a colon or period     |
  95.        |T|                  |Tuple arguments                                                            |
  96.        '------------------------------------------------------------------------------------------------'
  97. ]]
  98.  
  99. function wrapper:createConstructor(properties, functions, events)
  100.     -- precondtions
  101.     properties = properties or {}
  102.     functions = functions or {}
  103.     events = events or {}
  104.  
  105.     assert(
  106.         type(properties) == 'table' and
  107.             type(functions) == 'table'and
  108.             type(events) == 'table'
  109.     )
  110.    
  111.     local currentlyUsedEvents = {}
  112.     local fireableEvents = {}
  113.    
  114.     -- set up functions
  115.     local function getFireableEvent(name)
  116.         return function(...)
  117.             for _, set in next, currentlyUsedEvents[name]do
  118.                 local func = set['function']
  119.  
  120.                 if set.newThread then
  121.                     func = coroutine.wrap(func)
  122.                 end
  123.  
  124.                 func(...)
  125.             end
  126.         end
  127.     end
  128.    
  129.    
  130.     -- check properties
  131.     for propertyName, set in next, properties do
  132.         assert(
  133.             type(propertyName) == 'string' and
  134.                 type(set) == 'table'
  135.         )
  136.  
  137.         if set.strictValueType then
  138.             assert(
  139.                 type(set.strictValueType) == 'string' or
  140.                 type(set.strictValueType) == 'table'
  141.             )
  142.         end
  143.        
  144.         if set.newIndexCallback then
  145.             assert(type(set.newIndexCallback) == 'function')
  146.         end
  147.        
  148.         if set.indexCallback then
  149.             assert(type(set.indexCallback) == 'function')
  150.         end
  151.     end
  152.    
  153.     -- check functions
  154.     for functionName, func in next, functions do
  155.         assert(
  156.             type(functionName) == 'string' and
  157.             type(func) == 'function'
  158.         )
  159.     end
  160.    
  161.     -- check events
  162.     for eventName, bool in next, events do
  163.         assert(type(eventName) == 'string')
  164.        
  165.         if bool then
  166.             currentlyUsedEvents[eventName] = {}
  167.            
  168.             fireableEvents[eventName] = getFireableEvent(eventName)
  169.         end
  170.     end
  171.    
  172.     -- return constructor + listeners
  173.     return function()
  174.         local objPropertiesInternal = {}
  175.        
  176.        
  177.         local obj = {}
  178.        
  179.         -- set up obj
  180.         setmetatable(obj, {
  181.             __index = function(_, index)
  182.                 -- index invoked, can be properties, functions or events
  183.                 local propertiesSet = properties[index]
  184.                 local functionsSet = functions[index]
  185.                 local eventSet = events[index]
  186.                
  187.                 local returnedValue
  188.                
  189.                 if propertiesSet then
  190.                     -- properties
  191.                    
  192.                     returnedValue = objPropertiesInternal[index]
  193.                    
  194.                     -- use callback if there is so,
  195.                     if propertiesSet.indexCallback then
  196.                         returnedValue = propertiesSet.indexCallback(index, obj, objPropertiesInternal)
  197.                     end
  198.                 elseif functionsSet then
  199.                     -- functions
  200.                    
  201.                     returnedValue = function(...)
  202.                         return functionsSet(obj, objPropertiesInternal, ...)
  203.                     end
  204.                 elseif eventSet then
  205.                     local eventName = index
  206.                     local timeStamp = "" .. os.time()
  207.                    
  208.                     returnedValue = {
  209.                         Connect = function(obj2, func)
  210.                             assert(type(obj2) == 'table', 'Attempting to index event with a period.')
  211.                            
  212.                             currentlyUsedEvents[eventName][timeStamp] = {
  213.                                 ['function'] = func;
  214.                                 newThread = true
  215.                             }
  216.                            
  217.                             return {
  218.                                 Disconnect = function()
  219.                                     currentlyUsedEvents[eventName][timeStamp] = nil
  220.                                 end
  221.                             }
  222.                         end;
  223.                         Wait = function()
  224.                             local thread = coroutine.running()
  225.                            
  226.                             currentlyUsedEvents[eventName][timeStamp] = {
  227.                                 ['function'] = function(...)
  228.                                     coroutine.resume(thread, ...)
  229.                                    
  230.                                     currentlyUsedEvents[eventName][timeStamp] = nil
  231.                                 end;
  232.                             }
  233.                            
  234.                             return coroutine.yield()
  235.                         end,
  236.                     }
  237.                 else
  238.                     error('Attempting to use index, ' .. index .. ' but the object has none.')
  239.                 end
  240.                
  241.                 return returnedValue
  242.             end;
  243.            
  244.             __newindex = function(_, index, newValue)
  245.                 -- assume it's a property
  246.                 local set = assert(properties[index])
  247.  
  248.                 -- check value type if we have to
  249.                 if set.strictValueType then
  250.                     checkType(newValue, set.strictValueType)
  251.                 end
  252.                
  253.                 -- change newvalue from callback if we have to
  254.                 if set.newIndexCallback then
  255.                     newValue = set.newIndexCallback(newValue, obj, objPropertiesInternal)
  256.                 end
  257.                
  258.                 -- set internal table
  259.                 objPropertiesInternal[index] = newValue
  260.             end
  261.         })
  262.        
  263.         -- set defaults
  264.         for propertyName, set in next, properties do
  265.             obj[propertyName] = set.default
  266.         end
  267.        
  268.         -- return
  269.         return obj
  270.     end, fireableEvents
  271. end
  272.  
  273. function checkType(value, types)
  274.     if type(types) == 'string'then
  275.         types = {
  276.             [types] = true
  277.         }
  278.     end
  279.  
  280.     assert(types[typeof(value)], 'Non-valid type of value')
  281. end
  282.  
  283. return wrapper
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement