commit ac278250a8d7a4543bba4f971d66eef067c9c07d
parent 73e818cfa07a20afdd11e26f4abbc3795ec878e4
Author: francoispqt <francois@parquet.ninja>
Date: Sat, 19 May 2018 18:36:04 +0800
refactor tests and error raising
Diffstat:
20 files changed, 652 insertions(+), 225 deletions(-)
diff --git a/benchmarks/decoder/decoder_large_test.go b/benchmarks/decoder/decoder_large_test.go
@@ -1,7 +1,6 @@
package benchmarks
import (
- "log"
"testing"
"github.com/francoispqt/gojay"
@@ -15,7 +14,6 @@ func TestGoJayDecodeObjLarge(t *testing.T) {
assert.Nil(t, err, "err should be nil")
assert.Len(t, result.Users, 32, "Len of users should be 32")
for _, u := range result.Users {
- log.Print(u)
assert.True(t, len(u.Username) > 0, "User should have username")
}
assert.Len(t, result.Topics.Topics, 30, "Len of topics should be 30")
diff --git a/decode_array.go b/decode_array.go
@@ -1,9 +1,5 @@
package gojay
-import (
- "fmt"
-)
-
// DecodeArray reads the next JSON-encoded value from its input and stores it in the value pointed to by v.
//
// v must implement UnmarshalerJSONArray.
@@ -40,7 +36,7 @@ func (dec *Decoder) decodeArray(arr UnmarshalerJSONArray) (int, error) {
}
n++
}
- return 0, InvalidJSONError("Invalid JSON could not find array closing bracket")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
case 'n':
// is null
dec.cursor++
@@ -53,23 +49,17 @@ func (dec *Decoder) decodeArray(arr UnmarshalerJSONArray) (int, error) {
case '{', '"', 'f', 't', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
// can't unmarshall to struct
// we skip array and set Error
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to array, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(arr)
err := dec.skipData()
if err != nil {
return 0, err
}
return dec.cursor, nil
default:
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipArray() (int, error) {
@@ -114,5 +104,5 @@ func (dec *Decoder) skipArray() (int, error) {
continue
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
diff --git a/decode_array_test.go b/decode_array_test.go
@@ -1,7 +1,6 @@
package gojay
import (
- "log"
"strings"
"testing"
@@ -75,7 +74,6 @@ func TestSliceInts(t *testing.T) {
}
continue
}
- log.Print(s)
for k, v := range testCase.expectedResult {
assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
}
@@ -211,7 +209,6 @@ func TestSliceBools(t *testing.T) {
}
return
}
- log.Print(s, testCase.name)
assert.Nil(t, err, "err should be nil")
for k, v := range testCase.expectedResult {
assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
@@ -278,7 +275,6 @@ func TestSliceSlices(t *testing.T) {
}
return
}
- log.Print(s, testCase.name)
assert.Nil(t, err, "err should be nil")
for k, v := range testCase.expectedResult {
assert.Equal(t, v, s[k], "value at given index should be the same as expected results")
@@ -393,7 +389,7 @@ func TestDecodeSliceInvalidType(t *testing.T) {
err := UnmarshalJSONArray([]byte(`{}`), &result)
assert.NotNil(t, err, "err should not be nil")
assert.IsType(t, InvalidUnmarshalError(""), err, "err should be of type InvalidUnmarshalError")
- assert.Equal(t, "Cannot unmarshall to array, wrong char '{' found at pos 0", err.Error(), "err should not be nil")
+ assert.Equal(t, "Cannot unmarshal JSON to type '*gojay.testSliceObjects'", err.Error(), "err should not be nil")
}
func TestDecoderChannelOfObjectsBasic(t *testing.T) {
diff --git a/decode_bool.go b/decode_bool.go
@@ -1,7 +1,5 @@
package gojay
-import "fmt"
-
// DecodeBool reads the next JSON-encoded value from its input and stores it in the boolean pointed to by v.
//
// See the documentation for Unmarshal for details about the conversion of JSON into a Go value.
@@ -44,13 +42,7 @@ func (dec *Decoder) decodeBool(v *bool) error {
dec.cursor++
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to bool, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -67,15 +59,15 @@ func (dec *Decoder) assertTrue() error {
switch i {
case 0:
if dec.data[dec.cursor] != 'r' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 1:
if dec.data[dec.cursor] != 'u' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 2:
if dec.data[dec.cursor] != 'e' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 3:
switch dec.data[dec.cursor] {
@@ -83,7 +75,7 @@ func (dec *Decoder) assertTrue() error {
dec.cursor--
return nil
default:
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
}
i++
@@ -100,15 +92,15 @@ func (dec *Decoder) assertNull() error {
switch i {
case 0:
if dec.data[dec.cursor] != 'u' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 1:
if dec.data[dec.cursor] != 'l' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 2:
if dec.data[dec.cursor] != 'l' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 3:
switch dec.data[dec.cursor] {
@@ -116,7 +108,7 @@ func (dec *Decoder) assertNull() error {
dec.cursor--
return nil
default:
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
}
i++
@@ -133,19 +125,19 @@ func (dec *Decoder) assertFalse() error {
switch i {
case 0:
if dec.data[dec.cursor] != 'a' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 1:
if dec.data[dec.cursor] != 'l' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 2:
if dec.data[dec.cursor] != 's' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 3:
if dec.data[dec.cursor] != 'e' {
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
case 4:
switch dec.data[dec.cursor] {
@@ -153,7 +145,7 @@ func (dec *Decoder) assertFalse() error {
dec.cursor--
return nil
default:
- return InvalidJSONError(fmt.Sprintf(invalidJSONCharErrorMsg, dec.data[dec.cursor], dec.cursor))
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
}
i++
diff --git a/decode_number.go b/decode_number.go
@@ -74,7 +74,7 @@ func (dec *Decoder) skipNumber() (int, error) {
continue
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return end, InvalidJSONError("Invalid JSON while parsing number")
+ return end, dec.raiseInvalidJSONErr(dec.cursor)
}
return end, nil
}
diff --git a/decode_number_float.go b/decode_number_float.go
@@ -1,7 +1,5 @@
package gojay
-import "fmt"
-
// DecodeFloat64 reads the next JSON-encoded value from its input and stores it in the float64 pointed to by v.
//
// See the documentation for Unmarshal for details about the conversion of JSON into a Go value.
@@ -39,13 +37,7 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to float, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -53,7 +45,7 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing float")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getFloat(b byte) (float64, error) {
@@ -114,7 +106,7 @@ func (dec *Decoder) getFloat(b byte) (float64, error) {
return float64(dec.atoi64(start, end)), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return float64(dec.atoi64(start, end)), nil
}
@@ -156,13 +148,7 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to float, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -170,7 +156,7 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing float")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getFloat32(b byte) (float32, error) {
@@ -231,7 +217,7 @@ func (dec *Decoder) getFloat32(b byte) (float32, error) {
return float32(dec.atoi32(start, end)), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return float32(dec.atoi32(start, end)), nil
}
diff --git a/decode_number_float_test.go b/decode_number_float_test.go
@@ -188,6 +188,14 @@ func TestDecoderFloat64(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, 1.25, v, "v must be equal to 1.25")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v float64
+ dec := NewDecoder(strings.NewReader(`1.25`))
+ defer dec.Release()
+ err := dec.DecodeFloat64(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, 1.25, v, "v must be equal to 1.25")
+ })
t.Run("decoder-api-json-error", func(t *testing.T) {
var v float64
dec := NewDecoder(strings.NewReader(``))
@@ -376,6 +384,14 @@ func TestDecoderFloat32(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, float32(1.25), v, "v must be equal to 1.25")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v float32
+ dec := NewDecoder(strings.NewReader(`1.25`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, float32(1.25), v, "v must be equal to 1.25")
+ })
t.Run("decoder-api-json-error", func(t *testing.T) {
var v float32
dec := NewDecoder(strings.NewReader(``))
diff --git a/decode_number_int.go b/decode_number_int.go
@@ -100,13 +100,7 @@ func (dec *Decoder) decodeInt16(v *int16) error {
dec.cursor++
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -114,7 +108,7 @@ func (dec *Decoder) decodeInt16(v *int16) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getInt16(b byte) (int16, error) {
@@ -176,7 +170,7 @@ func (dec *Decoder) getInt16(b byte) (int16, error) {
return dec.atoi16(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoi16(start, end), nil
}
@@ -213,11 +207,10 @@ func (dec *Decoder) getInt16WithExp(init int16, cursor int) (int16, error) {
}
return init * int16(pow10uint64[exp+1]), nil
default:
- dec.err = InvalidJSONError("Invalid JSON")
- return 0, dec.err
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
// DecodeInt8 reads the next JSON-encoded value from its input and stores it in the int8 pointed to by v.
@@ -259,13 +252,7 @@ func (dec *Decoder) decodeInt8(v *int8) error {
dec.cursor++
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -273,7 +260,7 @@ func (dec *Decoder) decodeInt8(v *int8) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getInt8(b byte) (int8, error) {
@@ -335,7 +322,7 @@ func (dec *Decoder) getInt8(b byte) (int8, error) {
return dec.atoi8(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoi8(start, end), nil
}
@@ -372,11 +359,11 @@ func (dec *Decoder) getInt8WithExp(init int8, cursor int) (int8, error) {
}
return init * int8(pow10uint64[exp+1]), nil
default:
- dec.err = InvalidJSONError("Invalid JSON")
+ dec.err = dec.raiseInvalidJSONErr(dec.cursor)
return 0, dec.err
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
// DecodeInt32 reads the next JSON-encoded value from its input and stores it in the int32 pointed to by v.
@@ -416,13 +403,7 @@ func (dec *Decoder) decodeInt32(v *int32) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -430,7 +411,7 @@ func (dec *Decoder) decodeInt32(v *int32) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getInt32(b byte) (int32, error) {
@@ -492,7 +473,7 @@ func (dec *Decoder) getInt32(b byte) (int32, error) {
return dec.atoi32(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoi32(start, end), nil
}
@@ -529,11 +510,11 @@ func (dec *Decoder) getInt32WithExp(init int32, cursor int) (int32, error) {
}
return init * int32(pow10uint64[exp+1]), nil
default:
- dec.err = InvalidJSONError("Invalid JSON")
+ dec.err = dec.raiseInvalidJSONErr(dec.cursor)
return 0, dec.err
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
// DecodeInt64 reads the next JSON-encoded value from its input and stores it in the int64 pointed to by v.
@@ -574,13 +555,7 @@ func (dec *Decoder) decodeInt64(v *int64) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -588,7 +563,7 @@ func (dec *Decoder) decodeInt64(v *int64) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getInt64(b byte) (int64, error) {
@@ -650,7 +625,7 @@ func (dec *Decoder) getInt64(b byte) (int64, error) {
return dec.getInt64WithExp(dec.atoi64(start, end), j+1)
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoi64(start, end), nil
}
@@ -687,11 +662,10 @@ func (dec *Decoder) getInt64WithExp(init int64, cursor int) (int64, error) {
}
return init * int64(pow10uint64[exp+1]), nil
default:
- dec.err = InvalidJSONError("Invalid JSON")
- return 0, dec.err
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
}
- return 0, InvalidJSONError("Invalid JSON")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) atoi64(start, end int) int64 {
@@ -708,18 +682,18 @@ func (dec *Decoder) atoi64(start, end int) int64 {
for i := start + 1; i < end; i++ {
intv := int64(digits[dec.data[i]])
if val > maxInt64toMultiply {
- dec.err = InvalidUnmarshalError("Overflows int64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxInt64-val < intv {
- dec.err = InvalidUnmarshalError("Overflows int64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += intv
}
} else {
- dec.err = InvalidUnmarshalError("Overflows int64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
return val
@@ -739,18 +713,18 @@ func (dec *Decoder) atoi32(start, end int) int32 {
for i := start + 1; i < end; i++ {
intv := int32(digits[dec.data[i]])
if val > maxInt32toMultiply {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxInt32-val < intv {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += intv
}
} else {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
return val
@@ -770,18 +744,18 @@ func (dec *Decoder) atoi16(start, end int) int16 {
for i := start + 1; i < end; i++ {
intv := int16(digits[dec.data[i]])
if val > maxInt16toMultiply {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxInt16-val < intv {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += intv
}
} else {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
return val
@@ -801,18 +775,18 @@ func (dec *Decoder) atoi8(start, end int) int8 {
for i := start + 1; i < end; i++ {
intv := int8(digits[dec.data[i]])
if val > maxInt8toMultiply {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxInt8-val < intv {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += intv
}
} else {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
return val
diff --git a/decode_number_int_test.go b/decode_number_int_test.go
@@ -230,6 +230,14 @@ func TestDecoderInt(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, int(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v int
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, int(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-invalid-json", func(t *testing.T) {
var v int
dec := NewDecoder(strings.NewReader(``))
@@ -287,6 +295,12 @@ func TestDecoderInt64(t *testing.T) {
err: true,
},
{
+ name: "basic-big-overflow",
+ json: " 9223372036854775827",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "basic-big-overflow2",
json: "92233720368547758089",
expectedResult: 0,
@@ -446,6 +460,14 @@ func TestDecoderInt64(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, int64(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v int64
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, int64(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-invalid-json", func(t *testing.T) {
var v int64
dec := NewDecoder(strings.NewReader(``))
@@ -508,6 +530,12 @@ func TestDecoderInt32(t *testing.T) {
err: true,
},
{
+ name: "basic-big-overflow",
+ json: " 2147483657",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "basic-big-overflow2",
json: "21474836483",
expectedResult: 0,
@@ -674,6 +702,14 @@ func TestDecoderInt32(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, int32(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v int32
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, int32(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-invalid-json", func(t *testing.T) {
var v int32
dec := NewDecoder(strings.NewReader(``))
@@ -731,6 +767,18 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-big-overflow",
+ json: "66535",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "32768",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
json: " 2147483648",
expectedResult: 0,
err: true,
@@ -902,6 +950,14 @@ func TestDecoderInt16(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, int16(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v int16
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, int16(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-invalid-json", func(t *testing.T) {
var v int16
dec := NewDecoder(strings.NewReader(``))
@@ -964,6 +1020,18 @@ func TestDecoderInt8(t *testing.T) {
err: true,
},
{
+ name: "basic-big-overflow",
+ json: "137",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "128",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "basic-big-overflow2",
json: "21474836483",
expectedResult: 0,
@@ -1120,6 +1188,14 @@ func TestDecoderInt8(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, int8(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v int8
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, int8(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-invalid-json", func(t *testing.T) {
var v int8
dec := NewDecoder(strings.NewReader(``))
diff --git a/decode_number_uint.go b/decode_number_uint.go
@@ -1,7 +1,6 @@
package gojay
import (
- "fmt"
"math"
)
@@ -44,13 +43,7 @@ func (dec *Decoder) decodeUint8(v *uint8) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -58,7 +51,7 @@ func (dec *Decoder) decodeUint8(v *uint8) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getUint8(b byte) (uint8, error) {
@@ -77,7 +70,7 @@ func (dec *Decoder) getUint8(b byte) (uint8, error) {
return dec.atoui8(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoui8(start, end), nil
}
@@ -121,13 +114,7 @@ func (dec *Decoder) decodeUint16(v *uint16) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -135,7 +122,7 @@ func (dec *Decoder) decodeUint16(v *uint16) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getUint16(b byte) (uint16, error) {
@@ -154,7 +141,7 @@ func (dec *Decoder) getUint16(b byte) (uint16, error) {
return dec.atoui16(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoui16(start, end), nil
}
@@ -198,13 +185,7 @@ func (dec *Decoder) decodeUint32(v *uint32) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -212,7 +193,7 @@ func (dec *Decoder) decodeUint32(v *uint32) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getUint32(b byte) (uint32, error) {
@@ -231,7 +212,7 @@ func (dec *Decoder) getUint32(b byte) (uint32, error) {
return dec.atoui32(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoui32(start, end), nil
}
@@ -274,13 +255,7 @@ func (dec *Decoder) decodeUint64(v *uint64) error {
}
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to int, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -288,7 +263,7 @@ func (dec *Decoder) decodeUint64(v *uint64) error {
return nil
}
}
- return InvalidJSONError("Invalid JSON while parsing int")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) getUint64(b byte) (uint64, error) {
@@ -305,7 +280,7 @@ func (dec *Decoder) getUint64(b byte) (uint64, error) {
return dec.atoui64(start, end), nil
}
// invalid json we expect numbers, dot (single one), comma, or spaces
- return 0, InvalidJSONError("Invalid JSON while parsing number")
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
return dec.atoui64(start, end), nil
}
@@ -323,18 +298,18 @@ func (dec *Decoder) atoui64(start, end int) uint64 {
for i := start + 1; i < end; i++ {
uintv := uint64(digits[dec.data[i]])
if val > maxUint64toMultiply {
- dec.err = InvalidUnmarshalError("Overflows uint64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxUint64-val < uintv {
- dec.err = InvalidUnmarshalError("Overflows uint64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += uintv
}
} else {
- dec.err = InvalidUnmarshalError("Overflows uint64")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
return val
@@ -354,18 +329,18 @@ func (dec *Decoder) atoui32(start, end int) uint32 {
for i := start + 1; i < end; i++ {
uintv := uint32(digits[dec.data[i]])
if val > maxUint32toMultiply {
- dec.err = InvalidUnmarshalError("Overflows uint32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxUint32-val < uintv {
- dec.err = InvalidUnmarshalError("Overflows int32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += uintv
}
} else if ll > maxUint32Length {
- dec.err = InvalidUnmarshalError("Overflows uint32")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
val = 0
}
return val
@@ -385,18 +360,18 @@ func (dec *Decoder) atoui16(start, end int) uint16 {
for i := start + 1; i < end; i++ {
uintv := uint16(digits[dec.data[i]])
if val > maxUint16toMultiply {
- dec.err = InvalidUnmarshalError("Overflows uint16")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxUint16-val < uintv {
- dec.err = InvalidUnmarshalError("Overflows uint16")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += uintv
}
} else if ll > maxUint16Length {
- dec.err = InvalidUnmarshalError("Overflows uint16")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
val = 0
}
return val
@@ -416,18 +391,18 @@ func (dec *Decoder) atoui8(start, end int) uint8 {
for i := start + 1; i < end; i++ {
uintv := uint8(digits[dec.data[i]])
if val > maxUint8toMultiply {
- dec.err = InvalidUnmarshalError("Overflows uint8")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val = (val << 3) + (val << 1)
if math.MaxUint8-val < uintv {
- dec.err = InvalidUnmarshalError("Overflows uint8")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
return 0
}
val += uintv
}
} else if ll > maxUint8Length {
- dec.err = InvalidUnmarshalError("Overflows uint8")
+ dec.err = dec.makeInvalidUnmarshalErr(val)
val = 0
}
return val
diff --git a/decode_number_uint_test.go b/decode_number_uint_test.go
@@ -451,6 +451,14 @@ func TestDecoderUint16(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, uint16(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v uint16
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, uint16(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-json-error", func(t *testing.T) {
var v uint16
dec := NewDecoder(strings.NewReader(``))
@@ -612,6 +620,14 @@ func TestDecoderUint8(t *testing.T) {
assert.Nil(t, err, "Err must be nil")
assert.Equal(t, uint8(33), v, "v must be equal to 33")
})
+ t.Run("decoder-api2", func(t *testing.T) {
+ var v uint8
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.Decode(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, uint8(33), v, "v must be equal to 33")
+ })
t.Run("decoder-api-json-error", func(t *testing.T) {
var v uint8
dec := NewDecoder(strings.NewReader(``))
diff --git a/decode_object.go b/decode_object.go
@@ -1,7 +1,6 @@
package gojay
import (
- "fmt"
"unsafe"
)
@@ -36,6 +35,7 @@ func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
+ dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
@@ -57,6 +57,7 @@ func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
}
err = j.UnmarshalJSONObject(dec, k)
if err != nil {
+ dec.err = err
return 0, err
} else if dec.called&1 == 0 {
err := dec.skipData()
@@ -87,14 +88,8 @@ func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
dec.cursor++
return dec.cursor, nil
default:
- // can't unmarshall to struct
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshal to struct, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ // can't unmarshal to struct
+ dec.err = dec.makeInvalidUnmarshalErr(j)
err := dec.skipData()
if err != nil {
return 0, err
@@ -102,7 +97,7 @@ func (dec *Decoder) decodeObject(j UnmarshalerJSONObject) (int, error) {
return dec.cursor, nil
}
}
- return 0, InvalidJSONError("Invalid JSON while parsing object")
+ return 0, dec.raiseInvalidJSONErr(dec.length - 1)
}
func (dec *Decoder) skipObject() (int, error) {
@@ -173,13 +168,16 @@ func (dec *Decoder) nextKey() (string, bool, error) {
d := dec.data[start : end-1]
return *(*string)(unsafe.Pointer(&d)), false, nil
}
- return "", false, InvalidJSONError("Invalid JSON while parsing object key")
+ return "", false, dec.raiseInvalidJSONErr(dec.cursor)
case '}':
dec.cursor = dec.cursor + 1
return "", true, nil
+ default:
+ // can't unmarshall to struct
+ return "", false, dec.raiseInvalidJSONErr(dec.cursor)
}
}
- return "", false, InvalidJSONError("Invalid JSON while parsing object key")
+ return "", false, dec.raiseInvalidJSONErr(dec.length - 1)
}
func (dec *Decoder) skipData() error {
@@ -235,9 +233,9 @@ func (dec *Decoder) skipData() error {
dec.cursor = end
return err
}
- return InvalidJSONError("Invalid JSON")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
- return InvalidJSONError("Invalid JSON")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
// DecodeObjectFunc is a custom func type implementating UnarshaleObject.
diff --git a/decode_object_test.go b/decode_object_test.go
@@ -2,7 +2,6 @@ package gojay
import (
"io"
- "log"
"strings"
"testing"
@@ -10,16 +9,300 @@ import (
)
func TestDecodeObjectBasic(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult testObject
+ err bool
+ errType interface{}
+ skipCheckResult bool
+ }{
+ {
+ name: "basic",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{
+ testStr: "hello world!",
+ testInt: 4535,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 123.677,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
+ {
+ name: "basic-err",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 453q5,
+ "testBool": trae,
+ "testFloat32": 2q.345,
+ "testFloat64": 12x3.677,
+ "testInt8": 2s3,
+ "testInt16": 1245,
+ "testInt32": 4567q78,
+ "testInt64": 14466e85358,
+ "testUint8": 2s55,
+ "testUint16": 345i5,
+ "testUint32": 343q443,
+ "testUint64": 5456657z57
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err2",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 4567x78,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-float32",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2q.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-float64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 1x23.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err3",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 2q3,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-int16",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1x245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-int64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446q685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint8",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 2x55,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint16",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3x455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint32",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 3x43443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ {
+ name: "basic-err-uint64",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 4535,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 5456x65757
+ }`,
+ expectedResult: testObject{},
+ err: true,
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ s := testObject{}
+ dec := BorrowDecoder(strings.NewReader(testCase.json))
+ defer dec.Release()
+ err := dec.Decode(&s)
+ if testCase.err {
+ t.Log(err)
+ assert.NotNil(t, err, "err should not be nil")
+ if testCase.errType != nil {
+ assert.IsType(t, testCase.errType, err, "err should be of the given type")
+ }
+ return
+ }
+ assert.Nil(t, err, "err should be nil")
+ if !testCase.skipCheckResult {
+ assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
+ }
+ })
+ }
}
func TestDecodeObjectComplex(t *testing.T) {
testCases := []struct {
- name string
- json string
- expectedResult testObjectComplex
- err bool
- errType interface{}
+ name string
+ json string
+ expectedResult testObjectComplex
+ err bool
+ errType interface{}
+ skipCheckResult bool
}{
{
name: "basic",
@@ -47,6 +330,14 @@ func TestDecodeObjectComplex(t *testing.T) {
},
err: false,
},
+ {
+ name: "complex-json-err",
+ json: `{"testSubObject":{"testStr":"some string,"testInt":124465,"testUint16":120, "testUint8":15,"testInt16":-135,"testInt8":-23},"testSubSliceInts":[1,2],"testStr":"some \\n string"}`,
+ expectedResult: testObjectComplex{
+ testSubObject: &testObject{},
+ },
+ err: true,
+ },
}
for _, testCase := range testCases {
@@ -59,15 +350,17 @@ func TestDecodeObjectComplex(t *testing.T) {
defer dec.Release()
err := dec.Decode(&s)
if testCase.err {
+ t.Log(err)
assert.NotNil(t, err, "err should not be nil")
if testCase.errType != nil {
assert.IsType(t, testCase.errType, err, "err should be of the given type")
}
return
}
- log.Print(s, testCase.name)
assert.Nil(t, err, "err should be nil")
- assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
+ if !testCase.skipCheckResult {
+ assert.Equal(t, testCase.expectedResult, s, "value at given index should be the same as expected results")
+ }
})
}
}
@@ -288,7 +581,7 @@ func TestDecodeObjComplex(t *testing.T) {
result := jsonObjectComplex{}
err := UnmarshalJSONObject(jsonComplex, &result)
assert.NotNil(t, err, "err should not be as invalid type as been encountered nil")
- assert.Equal(t, `Cannot unmarshal to struct, wrong char '"' found at pos 639`, err.Error(), "err should not be as invalid type as been encountered nil")
+ assert.Equal(t, `Cannot unmarshal JSON to type '*gojay.jsonObjectComplex'`, err.Error(), "err should not be as invalid type as been encountered nil")
assert.Equal(t, `{"test":"1","test1":2}`, result.Test, "result.Test is not expected value")
assert.Equal(t, "\\\\\\\\\n", result.Test2, "result.Test2 is not expected value")
assert.Equal(t, 1, result.Test3, "result.test3 is not expected value")
diff --git a/decode_stream_test.go b/decode_stream_test.go
@@ -168,7 +168,7 @@ func TestStreamDecodingObjectsParallel(t *testing.T) {
expectations: func(err error, result []*TestObj, t *testing.T) {
assert.NotNil(t, err, "err is not nil as JSON is invalid")
assert.IsType(t, InvalidJSONError(""), err, "err is of type InvalidJSONError")
- assert.Equal(t, "Invalid JSON", err.Error(), "err message is Invalid JSON")
+ assert.Equal(t, "Invalid JSON, wrong char 'i' found at position 6", err.Error(), "err message is Invalid JSON")
},
},
}
@@ -276,7 +276,7 @@ func TestStreamDecodingStringsParallel(t *testing.T) {
assert.NotNil(t, err, "err should not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err is of type InvalidJSONError")
- assert.Equal(t, "Invalid JSON", err.Error(), "err message is Invalid JSON")
+ assert.Equal(t, "Invalid JSON, wrong char 'w' found at position 6", err.Error(), "err message is Invalid JSON")
},
},
}
diff --git a/decode_string.go b/decode_string.go
@@ -1,7 +1,6 @@
package gojay
import (
- "fmt"
"unsafe"
)
@@ -41,13 +40,7 @@ func (dec *Decoder) decodeString(v *string) error {
dec.cursor++
return nil
default:
- dec.err = InvalidUnmarshalError(
- fmt.Sprintf(
- "Cannot unmarshall to string, wrong char '%s' found at pos %d",
- string(dec.data[dec.cursor]),
- dec.cursor,
- ),
- )
+ dec.err = dec.makeInvalidUnmarshalErr(v)
err := dec.skipData()
if err != nil {
return err
@@ -70,7 +63,7 @@ func (dec *Decoder) parseEscapedString() error {
case '"':
// nSlash must be odd
if nSlash&1 != 1 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
diff := (nSlash - 1) >> 1
dec.data = append(dec.data[:start+diff-1], dec.data[dec.cursor-1:]...)
@@ -102,7 +95,7 @@ func (dec *Decoder) parseEscapedString() error {
// divide nSlash - 1 by 2 and leave last one
// else divide nSlash by 2 and leave the letter
if nSlash&1 != 0 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
var diff int
diff = nSlash >> 1
@@ -116,7 +109,7 @@ func (dec *Decoder) parseEscapedString() error {
// divide nSlash - 1 by 2 and leave last one
// else divide nSlash by 2 and leave the letter
if nSlash&1 != 0 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
var diff int
diff = nSlash >> 1
@@ -130,7 +123,7 @@ func (dec *Decoder) parseEscapedString() error {
// divide nSlash - 1 by 2 and leave last one
// else divide nSlash by 2 and leave the letter
if nSlash&1 != 0 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
var diff int
diff = nSlash >> 1
@@ -144,7 +137,7 @@ func (dec *Decoder) parseEscapedString() error {
// divide nSlash - 1 by 2 and leave last one
// else divide nSlash by 2 and leave the letter
if nSlash&1 != 0 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
var diff int
diff = nSlash >> 1
@@ -158,7 +151,7 @@ func (dec *Decoder) parseEscapedString() error {
// divide nSlash - 1 by 2 and leave last one
// else divide nSlash by 2 and leave the letter
if nSlash&1 != 0 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
var diff int
diff = nSlash >> 1
@@ -169,7 +162,7 @@ func (dec *Decoder) parseEscapedString() error {
default:
// nSlash must be even
if nSlash&1 == 1 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
diff := nSlash >> 1
dec.data = append(dec.data[:start+diff-1], dec.data[dec.cursor-1:]...)
@@ -204,7 +197,7 @@ func (dec *Decoder) getString() (int, int, error) {
continue
}
}
- return 0, 0, InvalidJSONError("Invalid JSON while parsing string")
+ return 0, 0, dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipEscapedString() error {
@@ -218,7 +211,7 @@ func (dec *Decoder) skipEscapedString() error {
case '"':
// nSlash must be odd
if nSlash&1 != 1 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
return nil
case 'n', 'r', 't':
@@ -226,13 +219,13 @@ func (dec *Decoder) skipEscapedString() error {
default:
// nSlash must be even
if nSlash&1 == 1 {
- return InvalidJSONError("Invalid JSON unescaped character")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
return nil
}
}
}
- return InvalidJSONError("Invalid JSON")
+ return dec.raiseInvalidJSONErr(dec.cursor)
}
func (dec *Decoder) skipString() error {
@@ -254,5 +247,5 @@ func (dec *Decoder) skipString() error {
continue
}
}
- return InvalidJSONError("Invalid JSON while parsing string")
+ return dec.raiseInvalidJSONErr(len(dec.data) - 1)
}
diff --git a/decode_string_test.go b/decode_string_test.go
@@ -2,7 +2,6 @@ package gojay
import (
"fmt"
- "log"
"strings"
"sync"
"testing"
@@ -151,6 +150,12 @@ func TestDecoderString(t *testing.T) {
err: true,
},
{
+ name: "utf16-surrogate-err3",
+ json: `"\uD834`,
+ expectedResult: ``,
+ err: true,
+ },
+ {
name: "utf16-surrogate-followed-by-control-char",
json: `"\uD834\t"`,
expectedResult: "�\t",
@@ -373,7 +378,6 @@ func TestSkipString(t *testing.T) {
if testCase.errType != nil {
assert.IsType(t, testCase.errType, err, "err should be of expected type")
}
- log.Print(err)
} else {
assert.Nil(t, err, "err should be nil")
}
diff --git a/decode_unsafe.go b/decode_unsafe.go
@@ -57,21 +57,41 @@ func (u decUnsafe) Unmarshal(data []byte, v interface{}) error {
dec.length = len(data)
dec.data = data
err = dec.decodeInt(vt)
- case *int32:
+ case *int8:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
- err = dec.decodeInt32(vt)
- case *uint32:
+ err = dec.decodeInt8(vt)
+ case *int16:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
- err = dec.decodeUint32(vt)
+ err = dec.decodeInt16(vt)
+ case *int32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeInt32(vt)
case *int64:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt64(vt)
+ case *uint8:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint8(vt)
+ case *uint16:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint16(vt)
+ case *uint32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint32(vt)
case *uint64:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
@@ -82,6 +102,11 @@ func (u decUnsafe) Unmarshal(data []byte, v interface{}) error {
dec.length = len(data)
dec.data = data
err = dec.decodeFloat64(vt)
+ case *float32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeFloat32(vt)
case *bool:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
diff --git a/decode_unsafe_test.go b/decode_unsafe_test.go
@@ -46,6 +46,36 @@ func TestUnmarshalUnsafeAllTypes(t *testing.T) {
},
},
{
+ v: new(int8),
+ d: []byte(`1`),
+ name: "test decode int8",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*int8)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, int8(1), *vt, "v must be equal to 1")
+ },
+ },
+ {
+ v: new(int16),
+ d: []byte(`1`),
+ name: "test decode int16",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*int16)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, int16(1), *vt, "v must be equal to 1")
+ },
+ },
+ {
+ v: new(int32),
+ d: []byte(`1`),
+ name: "test decode int32",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*int32)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, int32(1), *vt, "v must be equal to 1")
+ },
+ },
+ {
v: new(int64),
d: []byte(`1`),
name: "test decode int64",
@@ -106,6 +136,26 @@ func TestUnmarshalUnsafeAllTypes(t *testing.T) {
},
},
{
+ v: new(uint8),
+ d: []byte(`1`),
+ name: "test decode int8",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*uint8)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, uint8(1), *vt, "v must be equal to 1")
+ },
+ },
+ {
+ v: new(uint16),
+ d: []byte(`1`),
+ name: "test decode uint16",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*uint16)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, uint16(1), *vt, "v must be equal to 1")
+ },
+ },
+ {
v: new(float64),
d: []byte(`1.15`),
name: "test decode float64",
@@ -126,6 +176,16 @@ func TestUnmarshalUnsafeAllTypes(t *testing.T) {
},
},
{
+ v: new(float32),
+ d: []byte(`1.15`),
+ name: "test decode float64",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*float32)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, float32(1.15), *vt, "v must be equal to 1")
+ },
+ },
+ {
v: new(bool),
d: []byte(`true`),
name: "test decode bool true",
@@ -220,6 +280,15 @@ func TestUnmarshalUnsafeAllTypes(t *testing.T) {
assert.Equal(t, fmt.Sprintf(invalidUnmarshalErrorMsg, reflect.TypeOf(v).String()), err.Error(), "err message should be equal to invalidUnmarshalErrorMsg")
},
},
+ {
+ v: new(int),
+ d: []byte(`1a2`),
+ name: "test decode invalid json",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ assert.NotNil(t, err, "err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err must be of type InvalidJSONError")
+ },
+ },
}
for _, testCase := range testCases {
testCase := testCase
diff --git a/errors.go b/errors.go
@@ -1,6 +1,10 @@
package gojay
-const invalidJSONCharErrorMsg = "Invalid JSON character %c found at position %d"
+import (
+ "fmt"
+)
+
+const invalidJSONCharErrorMsg = "Invalid JSON, wrong char '%c' found at position %d"
// InvalidJSONError is a type representing an error returned when
// Decoding encounters invalid JSON.
@@ -10,7 +14,18 @@ func (err InvalidJSONError) Error() string {
return string(err)
}
-const invalidUnmarshalErrorMsg = "Invalid type %s provided to Unmarshal"
+func (dec *Decoder) raiseInvalidJSONErr(pos int) error {
+ dec.err = InvalidJSONError(
+ fmt.Sprintf(
+ invalidJSONCharErrorMsg,
+ dec.data[pos],
+ pos,
+ ),
+ )
+ return dec.err
+}
+
+const invalidUnmarshalErrorMsg = "Cannot unmarshal JSON to type '%T'"
// InvalidUnmarshalError is a type representing an error returned when
// Decoding cannot unmarshal JSON to the receiver type for various reasons.
@@ -20,6 +35,15 @@ func (err InvalidUnmarshalError) Error() string {
return string(err)
}
+func (dec *Decoder) makeInvalidUnmarshalErr(v interface{}) error {
+ return InvalidUnmarshalError(
+ fmt.Sprintf(
+ invalidUnmarshalErrorMsg,
+ v,
+ ),
+ )
+}
+
const invalidMarshalErrorMsg = "Invalid type %s provided to Marshal"
// InvalidMarshalError is a type representing an error returned when
diff --git a/gojay_test.go b/gojay_test.go
@@ -50,6 +50,8 @@ func (t *testObject) UnmarshalJSONObject(dec *Decoder, k string) error {
return dec.AddInt(&t.testInt)
case "testInt64":
return dec.AddInt64(&t.testInt64)
+ case "testInt32":
+ return dec.AddInt32(&t.testInt32)
case "testInt16":
return dec.AddInt16(&t.testInt16)
case "testInt8":