Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: (ast) support casting V_STRING to number #262

Merged
merged 1 commit into from Jul 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
18 changes: 14 additions & 4 deletions ast/node.go
Expand Up @@ -187,13 +187,14 @@ func (self *Node) Bool() (bool, error) {
}
}

// Int64 casts the node to int64 value, including V_NUMBER, V_TRUE, V_FALSE, V_ANY
// Int64 casts the node to int64 value, including V_NUMBER, V_TRUE, V_FALSE, V_ANY,
// V_STRING of invalid digits
func (self *Node) Int64() (int64, error) {
if err := self.checkRaw(); err != nil {
return 0, err
}
switch self.t {
case _V_NUMBER : return numberToInt64(self)
case _V_NUMBER, types.V_STRING : return numberToInt64(self)
case types.V_TRUE : return 1, nil
case types.V_FALSE : return 0, nil
case _V_ANY :
Expand Down Expand Up @@ -241,13 +242,22 @@ func (self *Node) StrictInt64() (int64, error) {
}
}

// Number casts node to float64, including V_NUMBER, V_TRUE, V_FALSE, V_ANY of json.Number
// Number casts node to float64, including V_NUMBER, V_TRUE, V_FALSE, V_ANY of json.Number,
// V_STRING of invalid digits
func (self *Node) Number() (json.Number, error) {
if err := self.checkRaw(); err != nil {
return json.Number(""), err
}
switch self.t {
case _V_NUMBER : return toNumber(self) , nil
case types.V_STRING :
if _, err := numberToInt64(self); err == nil {
return toNumber(self), nil
} else if _, err := numberToFloat64(self); err == nil {
return toNumber(self), nil
} else {
return json.Number(""), err
}
case types.V_TRUE : return json.Number("1"), nil
case types.V_FALSE : return json.Number("0"), nil
case _V_ANY :
Expand Down Expand Up @@ -329,7 +339,7 @@ func (self *Node) Float64() (float64, error) {
return 0.0, err
}
switch self.t {
case _V_NUMBER : return numberToFloat64(self)
case _V_NUMBER, types.V_STRING : return numberToFloat64(self)
case types.V_TRUE : return 1.0, nil
case types.V_FALSE : return 0.0, nil
case _V_ANY :
Expand Down
42 changes: 28 additions & 14 deletions ast/node_test.go
Expand Up @@ -17,18 +17,19 @@
package ast

import (
`encoding/json`
`fmt`
`reflect`
`runtime`
`runtime/debug`
`strconv`
`testing`

`github.com/bytedance/sonic/encoder`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
`github.com/stretchr/testify/assert`
`encoding/json`
`errors`
`fmt`
`reflect`
`runtime`
`runtime/debug`
`strconv`
`testing`

`github.com/bytedance/sonic/encoder`
`github.com/bytedance/sonic/internal/native/types`
`github.com/bytedance/sonic/internal/rt`
`github.com/stretchr/testify/assert`
)


Expand Down Expand Up @@ -232,6 +233,7 @@ func TestTypeCast(t *testing.T) {
exp interface{}
err error
}
var nonEmptyErr error = errors.New("")
a1 := NewAny(1)
lazyArray, _ := NewParser("[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]").Parse()
lazyObject, _ := NewParser(`{"0":0,"1":1,"2":2,"3":3,"4":4,"5":5,"6":6,"7":7,"8":8,"9":9,"10":10,"11":11,"12":12,"13":13,"14":14,"15":15,"16":16}`).Parse()
Expand Down Expand Up @@ -282,6 +284,8 @@ func TestTypeCast(t *testing.T) {
{"Bool", NewRaw("false"), false, nil},
{"Int64", NewRaw("true"), int64(1), nil},
{"Int64", NewRaw("false"), int64(0), nil},
{"Int64", NewRaw("\"1\""), int64(1), nil},
{"Int64", NewRaw("\"1.0\""), int64(0), nonEmptyErr},
{"Int64", NewAny(int(0)), int64(0), nil},
{"Int64", NewAny(int8(0)), int64(0), nil},
{"Int64", NewAny(int16(0)), int64(0), nil},
Expand All @@ -308,6 +312,8 @@ func TestTypeCast(t *testing.T) {
{"StrictInt64", NewRaw("0"), int64(0), nil},
{"Float64", NewRaw("true"), float64(1), nil},
{"Float64", NewRaw("false"), float64(0), nil},
{"Float64", NewRaw("\"1.0\""), float64(1.0), nil},
{"Float64", NewRaw("\"xx\""), float64(0), nonEmptyErr},
{"Float64", Node{}, float64(0), ErrUnsupportType},
{"Float64", NewAny(float32(0)), float64(0), nil},
{"Float64", NewAny(float64(0)), float64(0), nil},
Expand All @@ -321,6 +327,9 @@ func TestTypeCast(t *testing.T) {
{"Number", Node{}, json.Number(""), ErrUnsupportType},
{"Number", NewAny(json.Number("0")), json.Number("0"), nil},
{"Number", NewRaw("0.0"), json.Number("0.0"), nil},
{"Number", NewRaw("\"1\""), json.Number("1"), nil},
{"Number", NewRaw("\"1.1\""), json.Number("1.1"), nil},
{"Number", NewRaw("\"0.x0\""), json.Number(""), nonEmptyErr},
{"Number", NewRaw("true"), json.Number("1"), nil},
{"Number", NewRaw("false"), json.Number("0"), nil},
{"StrictNumber", NewRaw("true"), json.Number(""), ErrUnsupportType},
Expand Down Expand Up @@ -380,8 +389,13 @@ func TestTypeCast(t *testing.T) {
if !reflect.DeepEqual(rets[0].Interface(), c.exp) {
t.Fatal(i, rets[0].Interface(), c.exp)
}
if rets[1].Interface() != c.err {
t.Fatal(i, rets[1].Interface())
v := rets[1].Interface();
if c.err == nonEmptyErr {
if reflect.ValueOf(v).IsNil() {
t.Fatal(i, v)
}
} else if v != c.err {
t.Fatal(i, v)
}
}
}
Expand Down