Skip to content

Commit f27e8bb

Browse files
committed
(feat)Add extension operator "range"
1 parent c70fb5f commit f27e8bb

File tree

2 files changed

+121
-0
lines changed

2 files changed

+121
-0
lines changed

ext/ext.go

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package ext
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/huangjunwen/jsonlogic-go"
7+
)
8+
9+
// AddOpRange adds "range" operation to the JSONLogic instance. The op accept 1 to 3 numeric params and
10+
// generate a range of numbers, examples:
11+
// - {"range":null} -> []
12+
// - {"range":0} -> []
13+
// - {"range":2} -> [0,1]
14+
// - {"range":-2} -> [0,-1]
15+
// - {"range":[3,6]} -> [3,4,5]
16+
// - {"range":[6,3]} -> [6,5,4]
17+
// - {"range":[3,6,2]} -> [3,5]
18+
// - {"range":[6,3,-2]} -> [6,4]
19+
func AddOpRange(jl *jsonlogic.JSONLogic) {
20+
jl.AddOperation("range", opRange)
21+
}
22+
23+
func opRange(apply jsonlogic.Applier, params []interface{}, data interface{}) (result interface{}, err error) {
24+
if len(params) < 1 {
25+
return nil, fmt.Errorf("range: expect at least one param")
26+
}
27+
28+
params, err = jsonlogic.ApplyParams(apply, params, data)
29+
if err != nil {
30+
return
31+
}
32+
var b, e, s interface{}
33+
switch len(params) {
34+
default:
35+
fallthrough
36+
case 3:
37+
b = params[0]
38+
e = params[1]
39+
s = params[2]
40+
case 2:
41+
b = params[0]
42+
e = params[1]
43+
case 1:
44+
b = float64(0)
45+
e = params[0]
46+
}
47+
48+
bf64, err := jsonlogic.ToNumeric(b)
49+
if err != nil {
50+
return nil, fmt.Errorf("range: get begin error %s", err.Error())
51+
}
52+
ef64, err := jsonlogic.ToNumeric(e)
53+
if err != nil {
54+
return nil, fmt.Errorf("range: get end error %s", err.Error())
55+
}
56+
sf64, err := jsonlogic.ToNumeric(s)
57+
if err != nil {
58+
return nil, fmt.Errorf("range: get step error %s", err.Error())
59+
}
60+
61+
var (
62+
begin = int(bf64)
63+
end = int(ef64)
64+
step = int(sf64)
65+
)
66+
if end == begin {
67+
return []interface{}{}, nil
68+
}
69+
if end > begin {
70+
if step == 0 {
71+
step = 1
72+
}
73+
if step < 0 {
74+
return nil, fmt.Errorf("range: end > begin but got negative step")
75+
}
76+
ret := []interface{}{}
77+
for i := begin; i < end; i += step {
78+
ret = append(ret, float64(i))
79+
}
80+
return ret, nil
81+
}
82+
83+
if step == 0 {
84+
step = -1
85+
}
86+
if step > 0 {
87+
return nil, fmt.Errorf("range: end < begin but got postive step")
88+
}
89+
ret := []interface{}{}
90+
for i := begin; i > end; i += step {
91+
ret = append(ret, float64(i))
92+
}
93+
return ret, nil
94+
}

ext/ext_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package ext
2+
3+
import (
4+
"testing"
5+
6+
"github.com/stretchr/testify/assert"
7+
8+
"github.com/huangjunwen/jsonlogic-go"
9+
)
10+
11+
func TestOpRange(t *testing.T) {
12+
assert := assert.New(t)
13+
jl := jsonlogic.NewEmpty()
14+
AddOpRange(jl)
15+
jsonlogic.TestCases{
16+
{Logic: `{"range":null}`, Data: `null`, Result: []interface{}{}},
17+
{Logic: `{"range":0}`, Data: `null`, Result: []interface{}{}},
18+
{Logic: `{"range":2}`, Data: `null`, Result: []interface{}{float64(0), float64(1)}},
19+
{Logic: `{"range":-2}`, Data: `null`, Result: []interface{}{float64(0), float64(-1)}},
20+
{Logic: `{"range":[3,6]}`, Data: `null`, Result: []interface{}{float64(3), float64(4), float64(5)}},
21+
{Logic: `{"range":[6,3]}`, Data: `null`, Result: []interface{}{float64(6), float64(5), float64(4)}},
22+
{Logic: `{"range":[3,6,2]}`, Data: `null`, Result: []interface{}{float64(3), float64(5)}},
23+
{Logic: `{"range":[6,3,-2]}`, Data: `null`, Result: []interface{}{float64(6), float64(4)}},
24+
{Logic: `{"range":[3,6,-1]}`, Data: `null`, Err: true},
25+
{Logic: `{"range":[6,3,2]}`, Data: `null`, Err: true},
26+
}.Run(assert, jl)
27+
}

0 commit comments

Comments
 (0)