Skip to content

Commit 22d91ba

Browse files
committed
Support json.Number.
1 parent 0f8eb41 commit 22d91ba

6 files changed

Lines changed: 223 additions & 149 deletions

File tree

attrexp.go

Lines changed: 64 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package filter
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"github.com/di-wu/parser"
67
"github.com/di-wu/parser/ast"
@@ -10,55 +11,17 @@ import (
1011
"strings"
1112
)
1213

13-
func parseNumber(node *ast.Node) (interface{}, error) {
14-
var frac, exp bool
15-
var nStr string
16-
for _, node := range node.Children() {
17-
switch t := node.Type; t {
18-
case typ.Minus:
19-
nStr = "-"
20-
case typ.Int:
21-
nStr += node.Value
22-
case typ.Frac:
23-
frac = true
24-
children := node.Children()
25-
if l := len(children); l != 1 {
26-
return AttributeExpression{}, invalidLengthError(typ.Frac, 1, l)
27-
}
28-
nStr += fmt.Sprintf(".%s", children[0].Value)
29-
case typ.Exp:
30-
exp = true
31-
nStr += "e"
32-
for _, node := range node.Children() {
33-
switch t := node.Type; t {
34-
case typ.Sign, typ.Digits:
35-
nStr += node.Value
36-
default:
37-
return AttributeExpression{}, invalidChildTypeError(typ.Number, node.Type)
38-
39-
}
40-
}
41-
default:
42-
return AttributeExpression{}, invalidChildTypeError(typ.Number, node.Type)
43-
}
44-
}
45-
f, err := strconv.ParseFloat(nStr, 64)
46-
if err != nil {
47-
return AttributeExpression{}, &internalError{
48-
Message: err.Error(),
49-
}
50-
}
14+
// ParseAttrExp parses the given raw data as an AttributeExpression.
15+
func ParseAttrExp(raw []byte) (AttributeExpression, error) {
16+
return parseAttrExp(raw, config{})
17+
}
5118

52-
// Integers can not contain fractional or exponent parts.
53-
// More info: https://tools.ietf.org/html/rfc7643#section-2.3.4
54-
if !frac && !exp {
55-
return int(f), nil
56-
}
57-
return f, err
19+
// ParseAttrExpNumber parses the given raw data as an AttributeExpression with json.Number.
20+
func ParseAttrExpNumber(raw []byte) (AttributeExpression, error) {
21+
return parseAttrExp(raw, config{useNumber: true})
5822
}
5923

60-
// ParseAttrExp parses the given raw data as an AttributeExpression.
61-
func ParseAttrExp(raw []byte) (AttributeExpression, error) {
24+
func parseAttrExp(raw []byte, c config) (AttributeExpression, error) {
6225
p, err := ast.New(raw)
6326
if err != nil {
6427
return AttributeExpression{}, err
@@ -70,10 +33,10 @@ func ParseAttrExp(raw []byte) (AttributeExpression, error) {
7033
if _, err := p.Expect(parser.EOD); err != nil {
7134
return AttributeExpression{}, err
7235
}
73-
return parseAttrExp(node)
36+
return c.parseAttrExp(node)
7437
}
7538

76-
func parseAttrExp(node *ast.Node) (AttributeExpression, error) {
39+
func (p config) parseAttrExp(node *ast.Node) (AttributeExpression, error) {
7740
if node.Type != typ.AttrExp {
7841
return AttributeExpression{}, invalidTypeError(typ.AttrExp, node.Type)
7942
}
@@ -112,7 +75,7 @@ func parseAttrExp(node *ast.Node) (AttributeExpression, error) {
11275
case typ.True:
11376
compareValue = true
11477
case typ.Number:
115-
value, err := parseNumber(node)
78+
value, err := p.parseNumber(node)
11679
if err != nil {
11780
return AttributeExpression{}, err
11881
}
@@ -132,3 +95,55 @@ func parseAttrExp(node *ast.Node) (AttributeExpression, error) {
13295
CompareValue: compareValue,
13396
}, nil
13497
}
98+
99+
func (p config) parseNumber(node *ast.Node) (interface{}, error) {
100+
var frac, exp bool
101+
var nStr string
102+
for _, node := range node.Children() {
103+
switch t := node.Type; t {
104+
case typ.Minus:
105+
nStr = "-"
106+
case typ.Int:
107+
nStr += node.Value
108+
case typ.Frac:
109+
frac = true
110+
children := node.Children()
111+
if l := len(children); l != 1 {
112+
return AttributeExpression{}, invalidLengthError(typ.Frac, 1, l)
113+
}
114+
nStr += fmt.Sprintf(".%s", children[0].Value)
115+
case typ.Exp:
116+
exp = true
117+
nStr += "e"
118+
for _, node := range node.Children() {
119+
switch t := node.Type; t {
120+
case typ.Sign, typ.Digits:
121+
nStr += node.Value
122+
default:
123+
return AttributeExpression{}, invalidChildTypeError(typ.Number, node.Type)
124+
125+
}
126+
}
127+
default:
128+
return AttributeExpression{}, invalidChildTypeError(typ.Number, node.Type)
129+
}
130+
}
131+
132+
if p.useNumber {
133+
return json.Number(nStr), nil
134+
}
135+
136+
f, err := strconv.ParseFloat(nStr, 64)
137+
if err != nil {
138+
return AttributeExpression{}, &internalError{
139+
Message: err.Error(),
140+
}
141+
}
142+
143+
// Integers can not contain fractional or exponent parts.
144+
// More info: https://tools.ietf.org/html/rfc7643#section-2.3.4
145+
if !frac && !exp {
146+
return int(f), nil
147+
}
148+
return f, err
149+
}

attrexp_test.go

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package filter
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"github.com/di-wu/parser/ast"
67
"github.com/scim2/filter-parser/v2/internal/grammar"
8+
"strings"
79
"testing"
810
)
911

@@ -41,16 +43,39 @@ func TestParseNumber(t *testing.T) {
4143
p, _ := ast.New([]byte(test.nStr))
4244
n, err := grammar.Number(p)
4345
if err != nil {
44-
t.Error(err)
45-
return
46+
t.Fatal(err)
4647
}
47-
i, err := parseNumber(n)
48-
if err != nil {
49-
t.Error(err)
50-
return
48+
{ // Empty config.
49+
i, err := config{}.parseNumber(n)
50+
if err != nil {
51+
t.Fatal(err)
52+
}
53+
if i != test.expected {
54+
t.Error(test.expected, i)
55+
}
5156
}
52-
if i != test.expected {
53-
t.Error(test.expected, i)
57+
{ // Config with useNumber = true.
58+
d := json.NewDecoder(strings.NewReader(test.nStr))
59+
d.UseNumber()
60+
var number json.Number
61+
if err := d.Decode(&number); err != nil {
62+
t.Error(err)
63+
}
64+
65+
i, err := config{
66+
useNumber: true,
67+
}.parseNumber(n)
68+
if err != nil {
69+
t.Fatal(err)
70+
}
71+
if i != json.Number(test.nStr) {
72+
t.Error(test.nStr, i)
73+
}
74+
75+
// Check if equal to json.Decode.
76+
if i != number {
77+
t.Error(number, i)
78+
}
5479
}
5580
})
5681
}

config.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
package filter
2+
3+
// config represents the internal config of the parser functions.
4+
type config struct {
5+
// useNumber indicates that json.Number needs to be returned instead of int/float64 values.
6+
useNumber bool
7+
}

filter.go

Lines changed: 51 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,15 @@ import (
99

1010
// ParseFilter parses the given raw data as an Expression.
1111
func ParseFilter(raw []byte) (Expression, error) {
12+
return parseFilter(raw, config{})
13+
}
14+
15+
// ParseFilterNumber parses the given raw data as an Expression with json.Number.
16+
func ParseFilterNumber(raw []byte) (Expression, error) {
17+
return parseFilter(raw, config{useNumber: true})
18+
}
19+
20+
func parseFilter(raw []byte, c config) (Expression, error) {
1221
p, err := ast.New(raw)
1322
if err != nil {
1423
return nil, err
@@ -20,101 +29,101 @@ func ParseFilter(raw []byte) (Expression, error) {
2029
if _, err := p.Expect(parser.EOD); err != nil {
2130
return nil, err
2231
}
23-
return parseFilterOr(node)
32+
return c.parseFilterOr(node)
2433
}
2534

26-
func parseFilterAnd(node *ast.Node) (Expression, error) {
27-
if node.Type != typ.FilterAnd {
28-
return nil, invalidTypeError(typ.FilterAnd, node.Type)
35+
func (p config) parseFilterOr(node *ast.Node) (Expression, error) {
36+
if node.Type != typ.FilterOr {
37+
return nil, invalidTypeError(typ.FilterOr, node.Type)
2938
}
3039

3140
children := node.Children()
3241
if len(children) == 0 {
33-
return nil, invalidLengthError(typ.FilterAnd, 1, 0)
42+
return nil, invalidLengthError(typ.FilterOr, 1, 0)
3443
}
3544

3645
if len(children) == 1 {
37-
return parseFilterValue(children[0])
46+
return p.parseFilterAnd(children[0])
3847
}
3948

40-
var and LogicalExpression
49+
var or LogicalExpression
4150
for _, node := range children {
42-
exp, err := parseFilterValue(node)
51+
exp, err := p.parseFilterAnd(node)
4352
if err != nil {
4453
return nil, err
4554
}
4655
switch {
47-
case and.Left == nil:
48-
and.Left = exp
49-
case and.Right == nil:
50-
and.Right = exp
51-
and.Operator = AND
56+
case or.Left == nil:
57+
or.Left = exp
58+
case or.Right == nil:
59+
or.Right = exp
60+
or.Operator = OR
5261
default:
53-
and = LogicalExpression{
62+
or = LogicalExpression{
5463
Left: &LogicalExpression{
55-
Left: and.Left,
56-
Right: and.Right,
57-
Operator: AND,
64+
Left: or.Left,
65+
Right: or.Right,
66+
Operator: OR,
5867
},
5968
Right: exp,
60-
Operator: AND,
69+
Operator: OR,
6170
}
6271
}
6372
}
64-
return &and, nil
73+
return &or, nil
6574
}
6675

67-
func parseFilterOr(node *ast.Node) (Expression, error) {
68-
if node.Type != typ.FilterOr {
69-
return nil, invalidTypeError(typ.FilterOr, node.Type)
76+
func (p config) parseFilterAnd(node *ast.Node) (Expression, error) {
77+
if node.Type != typ.FilterAnd {
78+
return nil, invalidTypeError(typ.FilterAnd, node.Type)
7079
}
7180

7281
children := node.Children()
7382
if len(children) == 0 {
74-
return nil, invalidLengthError(typ.FilterOr, 1, 0)
83+
return nil, invalidLengthError(typ.FilterAnd, 1, 0)
7584
}
7685

7786
if len(children) == 1 {
78-
return parseFilterAnd(children[0])
87+
return p.parseFilterValue(children[0])
7988
}
8089

81-
var or LogicalExpression
90+
var and LogicalExpression
8291
for _, node := range children {
83-
exp, err := parseFilterAnd(node)
92+
exp, err := p.parseFilterValue(node)
8493
if err != nil {
8594
return nil, err
8695
}
8796
switch {
88-
case or.Left == nil:
89-
or.Left = exp
90-
case or.Right == nil:
91-
or.Right = exp
92-
or.Operator = OR
97+
case and.Left == nil:
98+
and.Left = exp
99+
case and.Right == nil:
100+
and.Right = exp
101+
and.Operator = AND
93102
default:
94-
or = LogicalExpression{
103+
and = LogicalExpression{
95104
Left: &LogicalExpression{
96-
Left: or.Left,
97-
Right: or.Right,
98-
Operator: OR,
105+
Left: and.Left,
106+
Right: and.Right,
107+
Operator: AND,
99108
},
100109
Right: exp,
101-
Operator: OR,
110+
Operator: AND,
102111
}
103112
}
104113
}
105-
return &or, nil
114+
return &and, nil
106115
}
107116

108-
func parseFilterValue(node *ast.Node) (Expression, error) {
117+
func (p config) parseFilterValue(node *ast.Node) (Expression, error) {
109118
switch t := node.Type; t {
110119
case typ.ValuePath:
111-
valuePath, err := parseValuePath(node)
120+
valuePath, err := p.parseValuePath(node)
112121
if err != nil {
113122
return nil, err
114123
}
115124
return &valuePath, nil
116125
case typ.AttrExp:
117-
attrExp, err := parseAttrExp(node)
126+
attrExp, err := p.parseAttrExp(node)
118127
if err != nil {
119128
return nil, err
120129
}
@@ -125,15 +134,15 @@ func parseFilterValue(node *ast.Node) (Expression, error) {
125134
return nil, invalidLengthError(typ.FilterNot, 1, l)
126135
}
127136

128-
exp, err := parseFilterOr(children[0])
137+
exp, err := p.parseFilterOr(children[0])
129138
if err != nil {
130139
return nil, err
131140
}
132141
return &NotExpression{
133142
Expression: exp,
134143
}, nil
135144
case typ.FilterOr:
136-
return parseFilterOr(node)
145+
return p.parseFilterOr(node)
137146
default:
138147
return nil, invalidChildTypeError(typ.FilterAnd, t)
139148
}

0 commit comments

Comments
 (0)