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 @@
Copyright (c) 2013, James Hurst
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
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)
end

local function array(...)
return mark_as_array({unpack(arg)})
return mark_as_array({...})
end

local function is_array(tab)
@@ -175,6 +175,7 @@ local function js_to_string(a)
end

local operations = {}
operations.__index = operations

operations['!!'] = function(_, a)
return js_to_boolean(a)
@@ -1050,16 +1051,16 @@ local function is_sub_operation(op)
not string_ends(op, '.')
end

local function get_operation(op_string)
if type(operations[op_string]) == 'function' then
return operations[op_string]
local function get_operation(op_string, available_operations)
if type(available_operations[op_string]) == 'function' then
return available_operations[op_string]
elseif not is_sub_operation(op_string) then
return nil
end

-- op string contain "."
-- WARN: untested
local new_op = operations
local new_op = available_operations
for sub_op_string in op_string:gmatch('([^\\.]+)') do
new_op = new_op[sub_op_string]
if new_op == nil then
@@ -1072,10 +1073,17 @@ local function get_operation(op_string)
return new_op
--
end
local function recurse_others(stack, current, last_child_result)

local function recurse_others(stack, current, last_child_result, options)
local err = nil
local op = get_operator(current.logic)
local operation = get_operation(op)
local available_operations
if options ~= nil and type(options.custom_operations) == 'table' then
available_operations = setmetatable(options.custom_operations, operations)
else
available_operations = operations
end
local operation = get_operation(op, available_operations)
if operation == nil then
return table.remove(stack), current.logic, 'invalid operations'
end
@@ -1104,8 +1112,20 @@ end

local JsonLogic = {}

JsonLogic.apply =
function(logic, data, options)
--- function sum description.
-- apply the json-logic with the given data
-- some behavior of json-logic can be influenced by 'options' table
-- 'options' can include the following attribute:
-- custom_operations = (table), a table contains custom operations
-- blacklist = (table), an array contains list of operations to be blacklisted.
-- whitelist = (table), an array contains list of operations to be whitelisted.
-- is_array = (function), a function that determine wether a table is an array or not
-- @tparam table logic description
-- @tparam table data description
-- @tparam table options is a table containing keys:
-- @return value result of the logic.
-- @author
function JsonLogic.apply(logic, data, options)
local stack = {}
local current = {
logic = logic,
@@ -1154,9 +1174,9 @@ JsonLogic.apply =
current.data = current.data or {}
current.state.normalized = current.state.normalized or {}
if type(recurser[op]) == 'function' then
current, last_child_result, err = recurser[op](stack, current, last_child_result)
current, last_child_result, err = recurser[op](stack, current, last_child_result, options)
else
current, last_child_result, err = recurse_others(stack, current, last_child_result)
current, last_child_result, err = recurse_others(stack, current, last_child_result, options)
end
end
end
@@ -1164,22 +1184,14 @@ JsonLogic.apply =
return last_child_result, err
end

JsonLogic.new_logic = function(operation, ...)
function JsonLogic.new_logic(operation, ...)
local lgc = {}
if operation ~= nil then
lgc[operation] = array(unpack(arg))
lgc[operation] = array(...)
end
return lgc
end

JsonLogic.add_operation = function(name, code)
operations[name] = code
end

JsonLogic.delete_operation = function(name)
operations[name] = nil
end

JsonLogic.array = array
JsonLogic.is_array = is_array
JsonLogic.mark_as_array = mark_as_array

+ 4
- 1
readme.md View File

@@ -2,4 +2,7 @@

lua port of <https://github.com/jwadhams/json-logic-js>.

WARNING: empty array is evaluated to true, unlike the original json-logic which evaluate empty array to false
WARNING:

1. empty array is evaluated to true, unlike the original json-logic which evaluate empty array to false.
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 @@
local array_mt = {}
local function array(...)
return setmetatable({unpack(arg)}, array_mt)
return setmetatable({...}, array_mt)
end
local function is_array(tab)
return getmetatable(tab) == array_mt
@@ -2146,7 +2146,7 @@ describe("json-logic operation test", function ()
{logic = {echo = array(1,2,3)}},
{logic = {first = array(1,2,3)}},
}
it("should return the original logic", function ()
it("should return the original logic", function ()
for i, t in ipairs(test_table) do
local res = logic_apply(t.logic, nil)
assert.message('failed at index: ' .. i).are.equal(t.logic, res)
@@ -2157,19 +2157,19 @@ describe("json-logic operation test", function ()
describe("given new operation to be registered", function ()
local test_table = {
{
new_op_name = "echo",
new_op = function(_, ...)
new_op_name = "echo",
new_op = function(_, ...)
arg["n"] = nil
return arg
return arg
end,
logic = {echo = array(array(1,2,3,4,5))},
expected = array(array(1,2,3,4,5)),
},
{
new_op_name = "first",
new_op_name = "first",
new_op = function(_, ...)
-- return first parameter
return unpack(arg)
-- return first parameter
return arg[1]
end,
logic = {first = array(1,2,3,4,5)},
expected = 1,
@@ -2178,31 +2178,16 @@ describe("json-logic operation test", function ()
it("should call the new operation correctly", function ()
for i, t in ipairs(test_table) do
local called = 0
local operation = function(data, ...)
local res = t.new_op(data, unpack(arg))
local operation = function(data, ...)
local res = t.new_op(data, ...)
called = called + 1
return res
end
logic.add_operation(t.new_op_name, operation)
local res = logic_apply(t.logic, nil)
local options = {custom_operations = {}}
options.custom_operations[t.new_op_name] = operation
local res = logic_apply(t.logic, nil, options)
assert.message("the new operation was not called once").are.equal(1, called)
assert.message('failed at index: ' .. i).are.same(t.expected, res)
logic.delete_operation(t.new_op_name)
end
end)
it("should not call the operation after it is removed", function ()
for i, t in ipairs(test_table) do
local called = 0
local operation = function(data, ...)
local res = t.new_op(data, unpack(arg))
called = called + 1
return res
end
logic.add_operation(t.new_op_name, operation)
logic.delete_operation(t.new_op_name)
local res = logic_apply(t.logic, nil)
assert.message("the new operation was not called once").are.equal(0, called)
assert.message('failed at index: ' .. i).are.equal(t.logic, res)
end
end)
end)

Loading…
Cancel
Save