Browse Source

move custom operations into options

tags/0.0.3-1^2
parent
commit
338c39436d
4 changed files with 73 additions and 50 deletions
  1. 23
    0
      LICENSE
  2. 33
    21
      logic.lua
  3. 4
    1
      readme.md
  4. 13
    28
      spec/logic_spec.lua

+ 23
- 0
LICENSE View File

@@ -0,0 +1,23 @@
1
+Copyright (c) 2013, James Hurst
2
+All rights reserved.
3
+
4
+Redistribution and use in source and binary forms, with or without modification,
5
+are permitted provided that the following conditions are met:
6
+
7
+  Redistributions of source code must retain the above copyright notice, this
8
+  list of conditions and the following disclaimer.
9
+
10
+  Redistributions in binary form must reproduce the above copyright notice, this
11
+  list of conditions and the following disclaimer in the documentation and/or
12
+  other materials provided with the distribution.
13
+
14
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 33
- 21
logic.lua View File

@@ -13,7 +13,7 @@ local function mark_as_array(tab)
13 13
 end
14 14
 
15 15
 local function array(...)
16
-    return mark_as_array({unpack(arg)})
16
+    return mark_as_array({...})
17 17
 end
18 18
 
19 19
 local function is_array(tab)
@@ -175,6 +175,7 @@ local function js_to_string(a)
175 175
 end
176 176
 
177 177
 local operations = {}
178
+operations.__index = operations
178 179
 
179 180
 operations['!!'] = function(_, a)
180 181
     return js_to_boolean(a)
@@ -1050,16 +1051,16 @@ local function is_sub_operation(op)
1050 1051
         not string_ends(op, '.')
1051 1052
 end
1052 1053
 
1053
-local function get_operation(op_string)
1054
-    if type(operations[op_string]) == 'function' then
1055
-        return operations[op_string]
1054
+local function get_operation(op_string, available_operations)
1055
+    if type(available_operations[op_string]) == 'function' then
1056
+        return available_operations[op_string]
1056 1057
     elseif not is_sub_operation(op_string) then
1057 1058
         return nil
1058 1059
     end
1059 1060
 
1060 1061
     -- op string contain "."
1061 1062
     -- WARN: untested
1062
-    local new_op = operations
1063
+    local new_op = available_operations
1063 1064
     for sub_op_string in op_string:gmatch('([^\\.]+)') do
1064 1065
         new_op = new_op[sub_op_string]
1065 1066
         if new_op == nil then
@@ -1072,10 +1073,17 @@ local function get_operation(op_string)
1072 1073
     return new_op
1073 1074
     --
1074 1075
 end
1075
-local function recurse_others(stack, current, last_child_result)
1076
+
1077
+local function recurse_others(stack, current, last_child_result, options)
1076 1078
     local err = nil
1077 1079
     local op = get_operator(current.logic)
1078
-    local operation = get_operation(op)
1080
+    local available_operations
1081
+    if options ~= nil and type(options.custom_operations) == 'table' then
1082
+        available_operations = setmetatable(options.custom_operations, operations)
1083
+    else
1084
+        available_operations = operations
1085
+    end
1086
+    local operation = get_operation(op, available_operations)
1079 1087
     if operation == nil then
1080 1088
         return table.remove(stack), current.logic, 'invalid operations'
1081 1089
     end
@@ -1104,8 +1112,20 @@ end
1104 1112
 
1105 1113
 local JsonLogic = {}
1106 1114
 
1107
-JsonLogic.apply =
1108
-    function(logic, data, options)
1115
+--- function sum description.
1116
+-- apply the json-logic with the given data
1117
+-- some behavior of json-logic can be influenced by 'options' table
1118
+-- 'options' can include the following attribute:
1119
+--   custom_operations = (table), a table contains custom operations
1120
+--   blacklist = (table), an array contains list of operations to be blacklisted.
1121
+--   whitelist = (table), an array contains list of operations to be whitelisted.
1122
+--   is_array = (function), a function that determine wether a table is an array or not
1123
+-- @tparam table logic description
1124
+-- @tparam table data description
1125
+-- @tparam table options is a table containing keys:
1126
+-- @return value result of the logic.
1127
+-- @author
1128
+function JsonLogic.apply(logic, data, options)
1109 1129
     local stack = {}
1110 1130
     local current = {
1111 1131
         logic = logic,
@@ -1154,9 +1174,9 @@ JsonLogic.apply =
1154 1174
             current.data = current.data or {}
1155 1175
             current.state.normalized = current.state.normalized or {}
1156 1176
             if type(recurser[op]) == 'function' then
1157
-                current, last_child_result, err = recurser[op](stack, current, last_child_result)
1177
+                current, last_child_result, err = recurser[op](stack, current, last_child_result, options)
1158 1178
             else
1159
-                current, last_child_result, err = recurse_others(stack, current, last_child_result)
1179
+                current, last_child_result, err = recurse_others(stack, current, last_child_result, options)
1160 1180
             end
1161 1181
         end
1162 1182
     end
@@ -1164,22 +1184,14 @@ JsonLogic.apply =
1164 1184
     return last_child_result, err
1165 1185
 end
1166 1186
 
1167
-JsonLogic.new_logic = function(operation, ...)
1187
+function JsonLogic.new_logic(operation, ...)
1168 1188
     local lgc = {}
1169 1189
     if operation ~= nil then
1170
-        lgc[operation] = array(unpack(arg))
1190
+        lgc[operation] = array(...)
1171 1191
     end
1172 1192
     return lgc
1173 1193
 end
1174 1194
 
1175
-JsonLogic.add_operation = function(name, code)
1176
-    operations[name] = code
1177
-end
1178
-
1179
-JsonLogic.delete_operation = function(name)
1180
-    operations[name] = nil
1181
-end
1182
-
1183 1195
 JsonLogic.array = array
1184 1196
 JsonLogic.is_array = is_array
1185 1197
 JsonLogic.mark_as_array = mark_as_array

+ 4
- 1
readme.md View File

@@ -2,4 +2,7 @@
2 2
 
3 3
 lua port of <https://github.com/jwadhams/json-logic-js>.
4 4
 
5
-WARNING: empty array is evaluated to true, unlike the original json-logic which evaluate empty array to false
5
+WARNING:
6
+
7
+1. empty array is evaluated to true, unlike the original json-logic which evaluate empty array to false.
8
+1. add_operation is simulated by using third parameter named options in Apply()

+ 13
- 28
spec/logic_spec.lua View File

@@ -1,6 +1,6 @@
1 1
 local array_mt = {}
2 2
 local function array(...)
3
-    return setmetatable({unpack(arg)}, array_mt)
3
+    return setmetatable({...}, array_mt)
4 4
 end
5 5
 local function is_array(tab)
6 6
     return getmetatable(tab) == array_mt
@@ -2146,7 +2146,7 @@ describe("json-logic operation test", function ()
2146 2146
             {logic = {echo = array(1,2,3)}},
2147 2147
             {logic = {first = array(1,2,3)}},
2148 2148
         }
2149
-        it("should return the original logic", function ()   
2149
+        it("should return the original logic", function ()
2150 2150
             for i, t in ipairs(test_table) do
2151 2151
                 local res = logic_apply(t.logic, nil)
2152 2152
                 assert.message('failed at index: ' .. i).are.equal(t.logic, res)
@@ -2157,19 +2157,19 @@ describe("json-logic operation test", function ()
2157 2157
     describe("given new operation to be registered", function ()
2158 2158
         local test_table = {
2159 2159
             {
2160
-                new_op_name = "echo", 
2161
-                new_op = function(_, ...) 
2160
+                new_op_name = "echo",
2161
+                new_op = function(_, ...)
2162 2162
                     arg["n"] = nil
2163
-                    return arg 
2163
+                    return arg
2164 2164
                 end,
2165 2165
                 logic = {echo = array(array(1,2,3,4,5))},
2166 2166
                 expected = array(array(1,2,3,4,5)),
2167 2167
              },
2168 2168
              {
2169
-                new_op_name = "first", 
2169
+                new_op_name = "first",
2170 2170
                 new_op = function(_, ...)
2171
-                    -- return first parameter 
2172
-                    return unpack(arg)
2171
+                    -- return first parameter
2172
+                    return arg[1]
2173 2173
                 end,
2174 2174
                 logic = {first = array(1,2,3,4,5)},
2175 2175
                 expected = 1,
@@ -2178,31 +2178,16 @@ describe("json-logic operation test", function ()
2178 2178
         it("should call the new operation correctly", function ()
2179 2179
             for i, t in ipairs(test_table) do
2180 2180
                 local called = 0
2181
-                local operation = function(data, ...) 
2182
-                    local res =  t.new_op(data, unpack(arg))
2181
+                local operation = function(data, ...)
2182
+                    local res =  t.new_op(data, ...)
2183 2183
                     called = called + 1
2184 2184
                     return res
2185 2185
                 end
2186
-                logic.add_operation(t.new_op_name, operation)
2187
-                local res = logic_apply(t.logic, nil)
2186
+                local options = {custom_operations = {}}
2187
+                options.custom_operations[t.new_op_name] = operation
2188
+                local res = logic_apply(t.logic, nil, options)
2188 2189
                 assert.message("the new operation was not called once").are.equal(1, called)
2189 2190
                 assert.message('failed at index: ' .. i).are.same(t.expected, res)
2190
-                logic.delete_operation(t.new_op_name)
2191
-            end
2192
-        end)
2193
-        it("should not call the operation after it is removed", function ()
2194
-            for i, t in ipairs(test_table) do
2195
-                local called = 0
2196
-                local operation = function(data, ...) 
2197
-                    local res =  t.new_op(data, unpack(arg))
2198
-                    called = called + 1
2199
-                    return res
2200
-                end
2201
-                logic.add_operation(t.new_op_name, operation)
2202
-                logic.delete_operation(t.new_op_name)
2203
-                local res = logic_apply(t.logic, nil)
2204
-                assert.message("the new operation was not called once").are.equal(0, called)
2205
-                assert.message('failed at index: ' .. i).are.equal(t.logic, res)
2206 2191
             end
2207 2192
         end)
2208 2193
     end)

Loading…
Cancel
Save