commit 491f8af345159c2f188f718fd05bef53aa3ef734
parent 1f3d8b54c1fd186494c8f1fe59f24e1f26a9cf18
Author: Francois Parquet <francois.parquet@gmail.com>
Date: Sun, 26 Aug 2018 22:29:17 +0800
Merge pull request #66 from francoispqt/feature/add-decode-null
Feature/add decode null
Diffstat:
16 files changed, 5061 insertions(+), 665 deletions(-)
diff --git a/decode.go b/decode.go
@@ -78,66 +78,131 @@ func Unmarshal(data []byte, v interface{}) error {
dec.length = len(data)
dec.data = data
err = dec.decodeString(vt)
+ case **string:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeStringNull(vt)
case *int:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt(vt)
+ case **int:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeIntNull(vt)
case *int8:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt8(vt)
+ case **int8:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeInt8Null(vt)
case *int16:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt16(vt)
+ case **int16:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeInt16Null(vt)
case *int32:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt32(vt)
+ case **int32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeInt32Null(vt)
case *int64:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeInt64(vt)
+ case **int64:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeInt64Null(vt)
case *uint8:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeUint8(vt)
+ case **uint8:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint8Null(vt)
case *uint16:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeUint16(vt)
+ case **uint16:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint16Null(vt)
case *uint32:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeUint32(vt)
+ case **uint32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint32Null(vt)
case *uint64:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeUint64(vt)
+ case **uint64:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeUint64Null(vt)
case *float64:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeFloat64(vt)
+ case **float64:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeFloat64Null(vt)
case *float32:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeFloat32(vt)
+ case **float32:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeFloat32Null(vt)
case *bool:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
dec.data = data
err = dec.decodeBool(vt)
+ case **bool:
+ dec = borrowDecoder(nil, 0)
+ dec.length = len(data)
+ dec.data = data
+ err = dec.decodeBoolNull(vt)
case UnmarshalerJSONObject:
dec = borrowDecoder(nil, 0)
dec.length = len(data)
@@ -197,30 +262,56 @@ func (dec *Decoder) Decode(v interface{}) error {
switch vt := v.(type) {
case *string:
err = dec.decodeString(vt)
+ case **string:
+ err = dec.decodeStringNull(vt)
case *int:
err = dec.decodeInt(vt)
+ case **int:
+ err = dec.decodeIntNull(vt)
case *int8:
err = dec.decodeInt8(vt)
+ case **int8:
+ err = dec.decodeInt8Null(vt)
case *int16:
err = dec.decodeInt16(vt)
+ case **int16:
+ err = dec.decodeInt16Null(vt)
case *int32:
err = dec.decodeInt32(vt)
+ case **int32:
+ err = dec.decodeInt32Null(vt)
case *int64:
err = dec.decodeInt64(vt)
+ case **int64:
+ err = dec.decodeInt64Null(vt)
case *uint8:
err = dec.decodeUint8(vt)
+ case **uint8:
+ err = dec.decodeUint8Null(vt)
case *uint16:
err = dec.decodeUint16(vt)
+ case **uint16:
+ err = dec.decodeUint16Null(vt)
case *uint32:
err = dec.decodeUint32(vt)
+ case **uint32:
+ err = dec.decodeUint32Null(vt)
case *uint64:
err = dec.decodeUint64(vt)
+ case **uint64:
+ err = dec.decodeUint64Null(vt)
case *float64:
err = dec.decodeFloat64(vt)
+ case **float64:
+ err = dec.decodeFloat64Null(vt)
case *float32:
err = dec.decodeFloat32(vt)
+ case **float32:
+ err = dec.decodeFloat32Null(vt)
case *bool:
err = dec.decodeBool(vt)
+ case **bool:
+ err = dec.decodeBoolNull(vt)
case UnmarshalerJSONObject:
_, err = dec.decodeObject(vt)
case UnmarshalerJSONArray:
@@ -244,72 +335,156 @@ func (dec *Decoder) AddInt(v *int) error {
return dec.Int(v)
}
+// AddIntNull decodes the next key to an *int.
+// If next key value overflows int, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddIntNull(v **int) error {
+ return dec.IntNull(v)
+}
+
// AddInt8 decodes the next key to an *int.
// If next key value overflows int8, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddInt8(v *int8) error {
return dec.Int8(v)
}
+// AddInt8Null decodes the next key to an *int.
+// If next key value overflows int8, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddInt8Null(v **int8) error {
+ return dec.Int8Null(v)
+}
+
// AddInt16 decodes the next key to an *int.
// If next key value overflows int16, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddInt16(v *int16) error {
return dec.Int16(v)
}
+// AddInt16Null decodes the next key to an *int.
+// If next key value overflows int16, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddInt16Null(v **int16) error {
+ return dec.Int16Null(v)
+}
+
// AddInt32 decodes the next key to an *int.
// If next key value overflows int32, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddInt32(v *int32) error {
return dec.Int32(v)
}
+// AddInt32Null decodes the next key to an *int.
+// If next key value overflows int32, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddInt32Null(v **int32) error {
+ return dec.Int32Null(v)
+}
+
// AddInt64 decodes the next key to an *int.
// If next key value overflows int64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddInt64(v *int64) error {
return dec.Int64(v)
}
+// AddInt64Null decodes the next key to an *int.
+// If next key value overflows int64, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddInt64Null(v **int64) error {
+ return dec.Int64Null(v)
+}
+
// AddUint8 decodes the next key to an *int.
// If next key value overflows uint8, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddUint8(v *uint8) error {
return dec.Uint8(v)
}
+// AddUint8Null decodes the next key to an *int.
+// If next key value overflows uint8, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddUint8Null(v **uint8) error {
+ return dec.Uint8Null(v)
+}
+
// AddUint16 decodes the next key to an *int.
// If next key value overflows uint16, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddUint16(v *uint16) error {
return dec.Uint16(v)
}
+// AddUint16Null decodes the next key to an *int.
+// If next key value overflows uint16, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddUint16Null(v **uint16) error {
+ return dec.Uint16Null(v)
+}
+
// AddUint32 decodes the next key to an *int.
// If next key value overflows uint32, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddUint32(v *uint32) error {
return dec.Uint32(v)
}
+// AddUint32Null decodes the next key to an *int.
+// If next key value overflows uint32, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddUint32Null(v **uint32) error {
+ return dec.Uint32Null(v)
+}
+
// AddUint64 decodes the next key to an *int.
// If next key value overflows uint64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddUint64(v *uint64) error {
return dec.Uint64(v)
}
+// AddUint64Null decodes the next key to an *int.
+// If next key value overflows uint64, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddUint64Null(v **uint64) error {
+ return dec.Uint64Null(v)
+}
+
// AddFloat decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddFloat(v *float64) error {
return dec.Float64(v)
}
+// AddFloatNull decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddFloatNull(v **float64) error {
+ return dec.Float64Null(v)
+}
+
// AddFloat64 decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddFloat64(v *float64) error {
return dec.Float64(v)
}
+// AddFloat64Null decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddFloat64Null(v **float64) error {
+ return dec.Float64Null(v)
+}
+
// AddFloat32 decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) AddFloat32(v *float32) error {
return dec.Float32(v)
}
+// AddFloat32Null decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddFloat32Null(v **float32) error {
+ return dec.Float32Null(v)
+}
+
// AddBool decodes the next key to a *bool.
// If next key is neither null nor a JSON boolean, an InvalidUnmarshalError will be returned.
// If next key is null, bool will be false.
@@ -317,12 +492,27 @@ func (dec *Decoder) AddBool(v *bool) error {
return dec.Bool(v)
}
+// AddBoolNull decodes the next key to a *bool.
+// If next key is neither null nor a JSON boolean, an InvalidUnmarshalError will be returned.
+// If next key is null, bool will be false.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddBoolNull(v **bool) error {
+ return dec.BoolNull(v)
+}
+
// AddString decodes the next key to a *string.
// If next key is not a JSON string nor null, InvalidUnmarshalError will be returned.
func (dec *Decoder) AddString(v *string) error {
return dec.String(v)
}
+// AddStringNull decodes the next key to a *string.
+// If next key is not a JSON string nor null, InvalidUnmarshalError will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) AddStringNull(v **string) error {
+ return dec.StringNull(v)
+}
+
// AddObject decodes the next key to a UnmarshalerJSONObject.
func (dec *Decoder) AddObject(v UnmarshalerJSONObject) error {
return dec.Object(v)
@@ -344,6 +534,17 @@ func (dec *Decoder) Int(v *int) error {
return nil
}
+// IntNull decodes the next key to an *int.
+// If next key value overflows int, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) IntNull(v **int) error {
+ err := dec.decodeIntNull(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Int8 decodes the next key to an *int.
// If next key value overflows int8, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Int8(v *int8) error {
@@ -355,6 +556,17 @@ func (dec *Decoder) Int8(v *int8) error {
return nil
}
+// Int8Null decodes the next key to an *int.
+// If next key value overflows int8, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Int8Null(v **int8) error {
+ err := dec.decodeInt8Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Int16 decodes the next key to an *int.
// If next key value overflows int16, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Int16(v *int16) error {
@@ -366,6 +578,17 @@ func (dec *Decoder) Int16(v *int16) error {
return nil
}
+// Int16Null decodes the next key to an *int.
+// If next key value overflows int16, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Int16Null(v **int16) error {
+ err := dec.decodeInt16Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Int32 decodes the next key to an *int.
// If next key value overflows int32, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Int32(v *int32) error {
@@ -377,6 +600,17 @@ func (dec *Decoder) Int32(v *int32) error {
return nil
}
+// Int32Null decodes the next key to an *int.
+// If next key value overflows int32, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Int32Null(v **int32) error {
+ err := dec.decodeInt32Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Int64 decodes the next key to an *int.
// If next key value overflows int64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Int64(v *int64) error {
@@ -388,6 +622,17 @@ func (dec *Decoder) Int64(v *int64) error {
return nil
}
+// Int64Null decodes the next key to an *int.
+// If next key value overflows int64, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Int64Null(v **int64) error {
+ err := dec.decodeInt64Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Uint8 decodes the next key to an *int.
// If next key value overflows uint8, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Uint8(v *uint8) error {
@@ -399,6 +644,17 @@ func (dec *Decoder) Uint8(v *uint8) error {
return nil
}
+// Uint8Null decodes the next key to an *int.
+// If next key value overflows uint8, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Uint8Null(v **uint8) error {
+ err := dec.decodeUint8Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Uint16 decodes the next key to an *int.
// If next key value overflows uint16, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Uint16(v *uint16) error {
@@ -410,6 +666,17 @@ func (dec *Decoder) Uint16(v *uint16) error {
return nil
}
+// Uint16Null decodes the next key to an *int.
+// If next key value overflows uint16, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Uint16Null(v **uint16) error {
+ err := dec.decodeUint16Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Uint32 decodes the next key to an *int.
// If next key value overflows uint32, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Uint32(v *uint32) error {
@@ -421,6 +688,17 @@ func (dec *Decoder) Uint32(v *uint32) error {
return nil
}
+// Uint32Null decodes the next key to an *int.
+// If next key value overflows uint32, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Uint32Null(v **uint32) error {
+ err := dec.decodeUint32Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Uint64 decodes the next key to an *int.
// If next key value overflows uint64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Uint64(v *uint64) error {
@@ -432,12 +710,29 @@ func (dec *Decoder) Uint64(v *uint64) error {
return nil
}
+// Uint64Null decodes the next key to an *int.
+// If next key value overflows uint64, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Uint64Null(v **uint64) error {
+ err := dec.decodeUint64Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Float decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Float(v *float64) error {
return dec.Float64(v)
}
+// FloatNull decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) FloatNull(v **float64) error {
+ return dec.Float64Null(v)
+}
+
// Float64 decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Float64(v *float64) error {
@@ -449,6 +744,17 @@ func (dec *Decoder) Float64(v *float64) error {
return nil
}
+// Float64Null decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Float64Null(v **float64) error {
+ err := dec.decodeFloat64Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Float32 decodes the next key to a *float64.
// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
func (dec *Decoder) Float32(v *float32) error {
@@ -460,6 +766,17 @@ func (dec *Decoder) Float32(v *float32) error {
return nil
}
+// Float32Null decodes the next key to a *float64.
+// If next key value overflows float64, an InvalidUnmarshalError error will be returned.
+func (dec *Decoder) Float32Null(v **float32) error {
+ err := dec.decodeFloat32Null(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// Bool decodes the next key to a *bool.
// If next key is neither null nor a JSON boolean, an InvalidUnmarshalError will be returned.
// If next key is null, bool will be false.
@@ -472,6 +789,18 @@ func (dec *Decoder) Bool(v *bool) error {
return nil
}
+// BoolNull decodes the next key to a *bool.
+// If next key is neither null nor a JSON boolean, an InvalidUnmarshalError will be returned.
+// If next key is null, bool will be false.
+func (dec *Decoder) BoolNull(v **bool) error {
+ err := dec.decodeBoolNull(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// String decodes the next key to a *string.
// If next key is not a JSON string nor null, InvalidUnmarshalError will be returned.
func (dec *Decoder) String(v *string) error {
@@ -483,6 +812,18 @@ func (dec *Decoder) String(v *string) error {
return nil
}
+// StringNull decodes the next key to a **string.
+// If next key is not a JSON string nor null, InvalidUnmarshalError will be returned.
+// If a `null` is encountered, gojay does not change the value of the pointer.
+func (dec *Decoder) StringNull(v **string) error {
+ err := dec.decodeStringNull(v)
+ if err != nil {
+ return err
+ }
+ dec.called |= 1
+ return nil
+}
+
// AddTime decodes the next key to a *time.Time with the given format
func (dec *Decoder) AddTime(v *time.Time, format string) error {
return dec.Time(v, format)
diff --git a/decode_bool.go b/decode_bool.go
@@ -52,6 +52,54 @@ func (dec *Decoder) decodeBool(v *bool) error {
}
return nil
}
+func (dec *Decoder) decodeBoolNull(v **bool) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch dec.data[dec.cursor] {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case 't':
+ dec.cursor++
+ err := dec.assertTrue()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(bool)
+ }
+ **v = true
+ dec.cursor++
+ return nil
+ case 'f':
+ dec.cursor++
+ err := dec.assertFalse()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(bool)
+ }
+ **v = false
+ dec.cursor++
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return nil
+}
func (dec *Decoder) assertTrue() error {
i := 0
diff --git a/decode_bool_test.go b/decode_bool_test.go
@@ -238,6 +238,245 @@ func TestDecoderBool(t *testing.T) {
}
}
+func TestDecoderBoolNull(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult bool
+ expectations func(t *testing.T, v *bool, err error)
+ }{
+ {
+ name: "true-basic",
+ json: "true",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.Nil(t, err, "err should be nil")
+ assert.True(t, *v, "result should be true")
+ },
+ },
+ {
+ name: "false-basic",
+ json: "false",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.Nil(t, err, "err should be nil")
+ assert.False(t, *v, "result should be false")
+ },
+ },
+ {
+ name: "null-basic",
+ json: "null",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.Nil(t, err, "err should be nil")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "true-error",
+ json: "taue",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be false")
+ },
+ },
+ {
+ name: "true-error2",
+ json: "trae",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "true-error3",
+ json: "trua",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "true-error4",
+ json: "truea",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "true-error5",
+ json: "t",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "true-error6",
+ json: "a",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error",
+ json: "fulse",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error2",
+ json: "fause",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error3",
+ json: "falze",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error4",
+ json: "falso",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error5",
+ json: "falsea",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error6",
+ json: "f",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "false-error7",
+ json: "a",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error",
+ json: "nall",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error2",
+ json: "nual",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error3",
+ json: "nula",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error4",
+ json: "nulle",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error5",
+ json: "n",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-error6",
+ json: "a",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-skip",
+ json: "{}",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.NotNil(t, err, "err should not be nil")
+ assert.IsType(t, InvalidUnmarshalError(""), err, "err should be of type InvalidUnmarshalError")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ {
+ name: "null-skip",
+ json: "",
+ expectations: func(t *testing.T, v *bool, err error) {
+ assert.Nil(t, err, "err should not be nil")
+ assert.Nil(t, v, "result should be nil")
+ },
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ var v = struct {
+ b *bool
+ }{}
+ err := Unmarshal([]byte(testCase.json), &v.b)
+ testCase.expectations(t, v.b, err)
+ })
+ }
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(bool)
+ var dec = NewDecoder(strings.NewReader(`folse`))
+ err := dec.BoolNull(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
func TestDecoderBoolDecoderAPI(t *testing.T) {
var v bool
dec := BorrowDecoder(strings.NewReader("true"))
diff --git a/decode_number_float.go b/decode_number_float.go
@@ -48,6 +48,51 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeFloat64Null(v **float64) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getFloat()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(float64)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getFloatNegative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(float64)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getFloatNegative() (float64, error) {
// look for following numbers
@@ -198,6 +243,51 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeFloat32Null(v **float32) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getFloat32()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(float32)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getFloat32Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(float32)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getFloat32Negative() (float32, error) {
// look for following numbers
diff --git a/decode_number_float_test.go b/decode_number_float_test.go
@@ -324,12 +324,647 @@ func TestDecoderFloat64(t *testing.T) {
})
}
+func TestDecoderFloat64Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult float64
+ resultIsNil bool
+ err bool
+ errType interface{}
+ }{
+ {
+ name: "basic-float",
+ json: "1.1",
+ expectedResult: 1.1,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: " 1e2",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+06",
+ expectedResult: 5000000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "basic-err1",
+ json: "0.",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-err2",
+ json: "-1.",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exp-err",
+ json: "0e-20",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exp-err3",
+ json: "-9e-60",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exp-err4",
+ json: "0.e-2",
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exp-err5",
+ json: "-5.E-2",
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+005",
+ expectedResult: 800000,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2",
+ expectedResult: 0.01,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5e-6",
+ expectedResult: 0.000005,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0.003,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0.00008,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+06",
+ expectedResult: -5000000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-float2",
+ json: "877 ",
+ expectedResult: 877,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+005",
+ expectedResult: -800000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8.2e-005",
+ expectedResult: -0.000082,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2.4595,
+ },
+ {
+ name: "basic-float2",
+ json: "877",
+ expectedResult: 877,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7.8876,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595e1",
+ expectedResult: 24.595,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876e002",
+ expectedResult: -788.76,
+ },
+ {
+ name: "basic-float3",
+ json: "-0.1234",
+ expectedResult: -0.1234,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.002e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "0e9223372036000000000 ",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "exponent-err",
+ json: "0.1e ",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "exponent-err",
+ json: "0e",
+ expectedResult: 0,
+ err: true,
+ resultIsNil: true,
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ resultIsNil: true,
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ resultIsNil: true,
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*float64)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult*1000000, math.Round(*v*1000000), fmt.Sprintf("v must be equal to %f", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(float64)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(float64)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.FloatNull(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(float64)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.AddFloat64Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
func TestDecoderFloat32(t *testing.T) {
testCases := []struct {
name string
json string
expectedResult float32
- skipResult bool
+ skipResult bool
+ err bool
+ errType interface{}
+ }{
+ {
+ name: "basic-float",
+ json: "1.1",
+ expectedResult: 1.1,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1e2",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+06",
+ expectedResult: 5000000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-err1",
+ json: "0.",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-err2",
+ json: "-1.",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exp-err",
+ json: "0e-20",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exp-err3",
+ json: "-9e-60",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exp-err4",
+ json: "0.e-2",
+ err: true,
+ },
+ {
+ name: "exp-err5",
+ json: "-5.E-2",
+ err: true,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-null-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+005",
+ expectedResult: 800000,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2",
+ expectedResult: 0.01,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5e-6",
+ expectedResult: 0.000005,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0.003,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0.00008,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+06",
+ expectedResult: -5000000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+005",
+ expectedResult: -800000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8.2e-005",
+ expectedResult: -0.000082,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.0023249242000242e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.002e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2.4595,
+ },
+ {
+ name: "basic-float2",
+ json: "877",
+ expectedResult: 877,
+ },
+ {
+ name: "basic-float2",
+ json: "877 ",
+ expectedResult: 877,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7.8876,
+ },
+ {
+ name: "basic-float",
+ json: "2.459e1",
+ expectedResult: 24.59,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876e002",
+ expectedResult: -788.76,
+ },
+ {
+ name: "basic-float3",
+ json: "-0.1234",
+ expectedResult: -0.1234,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "exponent-err",
+ json: "0e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v float32
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ if !testCase.skipResult {
+ assert.Equal(
+ t,
+ float64(testCase.expectedResult*1000000), math.Round(float64(v*1000000)),
+ fmt.Sprintf("v must be equal to %f", testCase.expectedResult),
+ )
+ }
+ })
+ }
+ t.Run("pool-error", func(t *testing.T) {
+ result := float32(1)
+ dec := NewDecoder(nil)
+ dec.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err shouldnt be nil")
+ assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
+ }()
+ _ = dec.DecodeFloat32(&result)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+ })
+ t.Run("decoder-api", func(t *testing.T) {
+ var v float32
+ dec := NewDecoder(strings.NewReader(`1.25`))
+ defer dec.Release()
+ err := dec.DecodeFloat32(&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-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(``))
+ defer dec.Release()
+ err := dec.DecodeFloat32(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
+func TestDecoderFloat32Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult float32
+ resultIsNil bool
err bool
errType interface{}
}{
@@ -345,59 +980,65 @@ func TestDecoderFloat32(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp2",
- json: "5e+06",
+ json: "5e+06 ",
expectedResult: 5000000,
},
{
name: "basic-exponent-positive-positive-exp3",
- json: "3e+3",
+ json: " 3e+3",
expectedResult: 3000,
},
{
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-err1",
json: "0.",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-err2",
json: "-1.",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "exp-err",
json: "0e-20",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "exp-err3",
json: "-9e-60",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
- name: "exp-err4",
- json: "0.e-2",
- skipResult: true,
- err: true,
+ name: "exp-err4",
+ json: "0.e-2",
+ err: true,
+ resultIsNil: true,
},
{
- name: "exp-err5",
- json: "-5.E-2",
- skipResult: true,
- err: true,
+ name: "exp-err5",
+ json: "-5.E-2",
+ err: true,
+ resultIsNil: true,
},
{
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-null-err",
@@ -405,6 +1046,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-null-err",
@@ -412,6 +1054,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-negative-err",
@@ -419,12 +1062,14 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "exponent-err-",
json: "0.1e",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-negative-err",
@@ -432,6 +1077,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-exponent-positive-positive-exp4",
@@ -440,7 +1086,7 @@ func TestDecoderFloat32(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp",
- json: "1e-2",
+ json: " 1e-2",
expectedResult: 0.01,
},
{
@@ -488,30 +1134,35 @@ func TestDecoderFloat32(t *testing.T) {
json: "1e10000000000 ",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-exp-too-big",
json: "1.0023249242000242e10000000000 ",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-exp-too-big",
json: "1.002e10000000000 ",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-exp-too-big",
json: "1.00232492420002423545849009",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-exp-too-big",
json: "1.00232492420002423545849009e10000000000 ",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "basic-float",
@@ -554,6 +1205,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "error",
@@ -561,12 +1213,14 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "exponent-err",
json: "0e",
expectedResult: 0,
err: true,
+ resultIsNil: true,
},
{
name: "invalid-type",
@@ -574,12 +1228,13 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidUnmarshalError(""),
+ resultIsNil: true,
},
}
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v float32
+ var v = (*float32)(nil)
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -594,48 +1249,27 @@ func TestDecoderFloat32(t *testing.T) {
} else {
assert.Nil(t, err, "Err must be nil")
}
- if !testCase.skipResult {
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
assert.Equal(
t,
- float64(testCase.expectedResult*1000000), math.Round(float64(v*1000000)),
+ float64(testCase.expectedResult*1000000), math.Round(float64(*v*1000000)),
fmt.Sprintf("v must be equal to %f", testCase.expectedResult),
)
}
})
}
- t.Run("pool-error", func(t *testing.T) {
- result := float32(1)
- dec := NewDecoder(nil)
- dec.Release()
- defer func() {
- err := recover()
- assert.NotNil(t, err, "err shouldnt be nil")
- assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
- }()
- _ = dec.DecodeFloat32(&result)
- assert.True(t, false, "should not be called as decoder should have panicked")
- })
- t.Run("decoder-api", func(t *testing.T) {
- var v float32
- dec := NewDecoder(strings.NewReader(`1.25`))
- defer dec.Release()
- err := dec.DecodeFloat32(&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-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-invalid-json", func(t *testing.T) {
+ var v = new(float32)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
- t.Run("decoder-api-json-error", func(t *testing.T) {
- var v float32
- dec := NewDecoder(strings.NewReader(``))
- defer dec.Release()
- err := dec.DecodeFloat32(&v)
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(float32)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Float32Null(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
diff --git a/decode_number_int.go b/decode_number_int.go
@@ -61,6 +61,59 @@ func (dec *Decoder) decodeInt(v *int) error {
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeIntNull(v **int) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ // we don't look for 0 as leading zeros are invalid per RFC
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getInt64()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int)
+ }
+ **v = int(val)
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getInt64Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int)
+ }
+ **v = -int(val)
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ 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,
+ ),
+ )
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
+
// DecodeInt16 reads the next JSON-encoded value from its input and stores it in the int16 pointed to by v.
//
// See the documentation for Unmarshal for details about the conversion of JSON into a Go value.
@@ -110,6 +163,52 @@ func (dec *Decoder) decodeInt16(v *int16) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeInt16Null(v **int16) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ // we don't look for 0 as leading zeros are invalid per RFC
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getInt16()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int16)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getInt16Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int16)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getInt16Negative() (int16, error) {
// look for following numbers
@@ -298,6 +397,52 @@ func (dec *Decoder) decodeInt8(v *int8) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeInt8Null(v **int8) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ // we don't look for 0 as leading zeros are invalid per RFC
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getInt8()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int8)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getInt8Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int8)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getInt8Negative() (int8, error) {
// look for following numbers
@@ -484,6 +629,51 @@ func (dec *Decoder) decodeInt32(v *int32) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeInt32Null(v **int32) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getInt32()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int32)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getInt32Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int32)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getInt32Negative() (int32, error) {
// look for following numbers
@@ -672,6 +862,51 @@ func (dec *Decoder) decodeInt64(v *int64) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeInt64Null(v **int64) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getInt64()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int64)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.cursor = dec.cursor + 1
+ val, err := dec.getInt64Negative()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(int64)
+ }
+ **v = -val
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getInt64Negative() (int64, error) {
// look for following numbers
diff --git a/decode_number_int_test.go b/decode_number_int_test.go
@@ -309,14 +309,14 @@ func TestDecoderInt(t *testing.T) {
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
-
-func TestDecoderInt64(t *testing.T) {
+func TestDecoderIntNull(t *testing.T) {
testCases := []struct {
name string
json string
- expectedResult int64
+ expectedResult int
err bool
errType interface{}
+ resultIsNil bool
}{
{
name: "basic-positive",
@@ -325,7 +325,7 @@ func TestDecoderInt64(t *testing.T) {
},
{
name: "basic-positive2",
- json: " 1039405",
+ json: "1039405",
expectedResult: 1039405,
},
{
@@ -337,24 +337,25 @@ func TestDecoderInt64(t *testing.T) {
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
- name: "basic-null-err",
- json: "nxll",
+ name: "basic-negative-err",
+ json: "-",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
name: "basic-negative-err",
- json: "-",
+ json: "-q",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
- name: "basic-negative-err",
- json: "-q",
+ name: "basic-null-err",
+ json: "nxll",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
@@ -373,27 +374,24 @@ func TestDecoderInt64(t *testing.T) {
},
{
name: "basic-big-overflow",
- json: " 9223372036854775808",
- expectedResult: 0,
- err: true,
- },
- {
- name: "basic-big-overflow",
- json: " 9223372036854775827",
+ json: "9223372036854775808",
expectedResult: 0,
err: true,
+ errType: InvalidUnmarshalError(""),
},
{
name: "basic-big-overflow2",
json: "92233720368547758089",
expectedResult: 0,
err: true,
+ errType: InvalidUnmarshalError(""),
},
{
name: "basic-big-overflow3",
json: "92233720368547758089 ",
expectedResult: 0,
err: true,
+ errType: InvalidUnmarshalError(""),
},
{
name: "basic-negative2",
@@ -401,6 +399,12 @@ func TestDecoderInt64(t *testing.T) {
expectedResult: -2349557,
},
{
+ name: "exponent-err-too-big",
+ json: "0e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "basic-float",
json: "2.4595",
expectedResult: 2,
@@ -412,6 +416,11 @@ func TestDecoderInt64(t *testing.T) {
},
{
name: "basic-float2",
+ json: "-7.8876 ",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
json: "-7.8876a",
expectedResult: 0,
err: true,
@@ -423,10 +432,15 @@ func TestDecoderInt64(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp2",
- json: "5e+06 ",
+ json: "5e+06",
expectedResult: 5000000,
},
{
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5.01e+10",
+ expectedResult: 50100000000,
+ },
+ {
name: "basic-exponent-positive-positive-exp3",
json: "3e+3",
expectedResult: 3000,
@@ -438,7 +452,7 @@ func TestDecoderInt64(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp",
- json: "1e-2 ",
+ json: "1e-2",
expectedResult: 0,
},
{
@@ -452,13 +466,6 @@ func TestDecoderInt64(t *testing.T) {
expectedResult: 0,
},
{
- name: "error3",
- json: "0E40",
- expectedResult: 0,
- err: true,
- errType: InvalidJSONError(""),
- },
- {
name: "basic-exponent-positive-negative-exp4",
json: "8e-005",
expectedResult: 0,
@@ -474,11 +481,6 @@ func TestDecoderInt64(t *testing.T) {
expectedResult: -5000000,
},
{
- name: "basic-exponent-negative-positive-exp2",
- json: "-5.4e+06",
- expectedResult: -5400000,
- },
- {
name: "basic-exponent-negative-positive-exp3",
json: "-3e03",
expectedResult: -3000,
@@ -489,47 +491,24 @@ func TestDecoderInt64(t *testing.T) {
expectedResult: -800000,
},
{
- name: "exponent-err-too-big",
- json: "0e10000000000000000000",
- expectedResult: 0,
- err: true,
- },
- {
- name: "exponent-err-too-big",
- json: "0e1000000000000000000000000 ",
- expectedResult: 0,
- err: true,
- },
- {
- name: "exponent-err-too-big",
- json: "0.1e1000000000",
- expectedResult: 0,
- err: true,
- },
- {
- name: "exponent-err-too-big",
- json: "0.1932242242424244244e1000000000000000000000000",
+ name: "error1",
+ json: "132zz4",
expectedResult: 0,
err: true,
},
{
- name: "basic-exponent-negative-positive-exp4",
- json: "8ea+00a5",
+ name: "negative-error2",
+ json: " -1213xdde2323 ",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
- name: "basic-exponent-err",
- json: "3e",
- expectedResult: 0,
- err: true,
- },
- {
- name: "error1",
- json: "132zz4",
+ name: "error3",
+ json: "-8e+00$aa5",
expectedResult: 0,
err: true,
+ errType: InvalidJSONError(""),
},
{
name: "error4",
@@ -539,17 +518,17 @@ func TestDecoderInt64(t *testing.T) {
errType: InvalidJSONError(""),
},
{
- name: "error5",
- json: "0E40",
+ name: "exponent-err-",
+ json: "0.1e",
expectedResult: 0,
err: true,
- errType: InvalidJSONError(""),
},
{
- name: "exponent-err-",
- json: "0.1e",
+ name: "error5",
+ json: "0E40",
expectedResult: 0,
err: true,
+ errType: InvalidJSONError(""),
},
{
name: "error6",
@@ -558,6 +537,7 @@ func TestDecoderInt64(t *testing.T) {
err: true,
errType: InvalidJSONError(""),
},
+
{
name: "error7",
json: "-5.e-2",
@@ -576,11 +556,11 @@ func TestDecoderInt64(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v int64
+ var v = (*int)(nil)
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
- if testCase.errType != nil {
+ if testCase.errType != nil && err != nil {
assert.IsType(
t,
testCase.errType,
@@ -588,55 +568,36 @@ func TestDecoderInt64(t *testing.T) {
fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
)
}
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
} else {
- assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
}
- assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
})
}
- t.Run("pool-error", func(t *testing.T) {
- result := int64(1)
- dec := NewDecoder(nil)
- dec.Release()
- defer func() {
- err := recover()
- assert.NotNil(t, err, "err shouldnt be nil")
- assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
- }()
- _ = dec.DecodeInt64(&result)
- assert.True(t, false, "should not be called as decoder should have panicked")
- })
- t.Run("decoder-api", func(t *testing.T) {
- var v int64
- dec := NewDecoder(strings.NewReader(`33`))
- defer dec.Release()
- err := dec.DecodeInt64(&v)
- 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(``))
- defer dec.Release()
- err := dec.DecodeInt64(&v)
+ var v = new(int)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(int)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.IntNull(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
-func TestDecoderInt32(t *testing.T) {
+func TestDecoderInt64(t *testing.T) {
testCases := []struct {
name string
json string
- expectedResult int32
+ expectedResult int64
err bool
errType interface{}
}{
@@ -689,34 +650,40 @@ func TestDecoderInt32(t *testing.T) {
errType: InvalidJSONError(""),
},
{
- name: "basic-negative2",
- json: "-2349557",
- expectedResult: -2349557,
- },
- {
name: "basic-big",
- json: " 2147483647",
- expectedResult: 2147483647,
+ json: "9223372036854775807",
+ expectedResult: 9223372036854775807,
},
{
name: "basic-big-overflow",
- json: " 2147483648",
+ json: " 9223372036854775808",
expectedResult: 0,
err: true,
},
{
name: "basic-big-overflow",
- json: " 2147483657",
+ json: " 9223372036854775827",
expectedResult: 0,
err: true,
},
{
name: "basic-big-overflow2",
- json: "21474836483",
+ json: "92233720368547758089",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow3",
+ json: "92233720368547758089 ",
expectedResult: 0,
err: true,
},
{
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: -2349557,
+ },
+ {
name: "basic-float",
json: "2.4595",
expectedResult: 2,
@@ -734,34 +701,12 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp",
- json: "1.2E2",
- expectedResult: 120,
- },
- {
- name: "exponent-err-too-big",
- json: "0e10000000000000000000",
- expectedResult: 0,
- err: true,
- },
- {
- name: "exponent-err-too-big",
- json: "0.1932242242424244244e1000000000000000000000000",
- expectedResult: 0,
- err: true,
- },
- {
- name: "basic-exponent-positive-positive-exp1",
- json: "3.5e+005 ",
- expectedResult: 350000,
- },
- {
- name: "basic-exponent-positive-positive-exp1",
- json: "3.5e+005",
- expectedResult: 350000,
+ json: "1e2",
+ expectedResult: 100,
},
{
name: "basic-exponent-positive-positive-exp2",
- json: "5e+06",
+ json: "5e+06 ",
expectedResult: 5000000,
},
{
@@ -771,7 +716,7 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp4",
- json: "8e+005 ",
+ json: "8e+005",
expectedResult: 800000,
},
{
@@ -781,7 +726,7 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp2",
- json: "5E-6",
+ json: "5e-6",
expectedResult: 0,
},
{
@@ -790,6 +735,13 @@ func TestDecoderInt32(t *testing.T) {
expectedResult: 0,
},
{
+ name: "error3",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
name: "basic-exponent-positive-negative-exp4",
json: "8e-005",
expectedResult: 0,
@@ -805,6 +757,11 @@ func TestDecoderInt32(t *testing.T) {
expectedResult: -5000000,
},
{
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5.4e+06",
+ expectedResult: -5400000,
+ },
+ {
name: "basic-exponent-negative-positive-exp3",
json: "-3e03",
expectedResult: -3000,
@@ -815,14 +772,14 @@ func TestDecoderInt32(t *testing.T) {
expectedResult: -800000,
},
{
- name: "exponent-err-",
- json: "0.1e",
+ name: "exponent-err-too-big",
+ json: "0e10000000000000000000",
expectedResult: 0,
err: true,
},
{
name: "exponent-err-too-big",
- json: "0.1e10000000000000000000",
+ json: "0e1000000000000000000000000 ",
expectedResult: 0,
err: true,
},
@@ -834,25 +791,1702 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "exponent-err-too-big",
- json: "0.1e1000000000 ",
+ json: "0.1932242242424244244e1000000000000000000000000",
expectedResult: 0,
err: true,
},
{
- name: "exponent-err-too-big",
- json: "0e100000000000",
+ name: "basic-exponent-negative-positive-exp4",
+ json: "8ea+00a5",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error1",
+ json: "132zz4",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error4",
+ json: "0.E----",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error5",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error6",
+ json: "0.e-9",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error7",
+ json: "-5.e-2",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v int64
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ })
+ }
+ t.Run("pool-error", func(t *testing.T) {
+ result := int64(1)
+ dec := NewDecoder(nil)
+ dec.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err shouldnt be nil")
+ assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
+ }()
+ _ = dec.DecodeInt64(&result)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+ })
+ t.Run("decoder-api", func(t *testing.T) {
+ var v int64
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.DecodeInt64(&v)
+ 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(``))
+ defer dec.Release()
+ err := dec.DecodeInt64(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+func TestDecoderInt64Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult int64
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: -2,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-big",
+ json: "9223372036854775807",
+ expectedResult: 9223372036854775807,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 9223372036854775808",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 9223372036854775827",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "92233720368547758089",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow3",
+ json: "92233720368547758089 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: -2349557,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876a",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1e2",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+06 ",
+ expectedResult: 5000000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+005",
+ expectedResult: 800000,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5e-6",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0,
+ },
+ {
+ name: "error3",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+06",
+ expectedResult: -5000000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5.4e+06",
+ expectedResult: -5400000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+005",
+ expectedResult: -800000,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e1000000000000000000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e1000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1932242242424244244e1000000000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "8ea+00a5",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error1",
+ json: "132zz4",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error4",
+ json: "0.E----",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error5",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error6",
+ json: "0.e-9",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error7",
+ json: "-5.e-2",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*int64)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(int64)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(int64)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Int64Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
+func TestDecoderInt32(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult int32
+ err bool
+ errType interface{}
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: -2,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: -2349557,
+ },
+ {
+ name: "basic-big",
+ json: " 2147483647",
+ expectedResult: 2147483647,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 2147483648",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 2147483657",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "21474836483",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876a",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1.2E2",
+ expectedResult: 120,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1932242242424244244e1000000000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+005 ",
+ expectedResult: 350000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+005",
+ expectedResult: 350000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+06",
+ expectedResult: 5000000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+005 ",
+ expectedResult: 800000,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5E-6",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+06",
+ expectedResult: -5000000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+005",
+ expectedResult: -800000,
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e1000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e1000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e100000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e100000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error3",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error4",
+ json: "0.E----",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error5",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error6",
+ json: "0.e-9",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error7",
+ json: "-5.e-2",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-float",
+ json: "8.32 ",
+ expectedResult: 8,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "8ea00$aa5",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error2",
+ json: "-8e+00$aa5",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v int32
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ })
+ }
+ t.Run("pool-error", func(t *testing.T) {
+ result := int32(1)
+ dec := NewDecoder(nil)
+ dec.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err shouldnt be nil")
+ assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
+ }()
+ _ = dec.DecodeInt32(&result)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+
+ })
+ t.Run("decoder-api", func(t *testing.T) {
+ var v int32
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.DecodeInt32(&v)
+ 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(``))
+ defer dec.Release()
+ err := dec.DecodeInt32(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+func TestDecoderInt32Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult int32
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: -2,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: -2349557,
+ },
+ {
+ name: "basic-big",
+ json: " 2147483647",
+ expectedResult: 2147483647,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 2147483648",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 2147483657",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "21474836483",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876a",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1.2E2",
+ expectedResult: 120,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1932242242424244244e1000000000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+005 ",
+ expectedResult: 350000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+005",
+ expectedResult: 350000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+06",
+ expectedResult: 5000000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+005 ",
+ expectedResult: 800000,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5E-6",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+06",
+ expectedResult: -5000000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+005",
+ expectedResult: -800000,
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e1000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e1000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e100000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e100000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error3",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error4",
+ json: "0.E----",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error5",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error6",
+ json: "0.e-9",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error7",
+ json: "-5.e-2",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-float",
+ json: "8.32 ",
+ expectedResult: 8,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "8ea00$aa5",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error2",
+ json: "-8e+00$aa5",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*int32)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ return
+ }
+
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(int32)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(int32)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Int32Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
+func TestDecoderInt16(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult int16
+ err bool
+ errType interface{}
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 5321",
+ expectedResult: 5321,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: -2,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2456",
+ expectedResult: -2456,
+ },
+ {
+ name: "basic-big",
+ json: " 24566",
+ expectedResult: 24566,
+ },
+ {
+ 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,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "21474836483",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876a",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1.2E2",
+ expectedResult: 120,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+001 ",
+ expectedResult: 35,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+002",
+ expectedResult: 350,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+03",
+ expectedResult: 5000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+02 ",
+ expectedResult: 800,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5E-6",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1932242242424244244e1000000000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+03",
+ expectedResult: -5000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+003",
+ expectedResult: -8000,
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "8.32 ",
+ expectedResult: 8,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "8ea00$aa5",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error2",
+ json: "-8e+00$aa5",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error3",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error4",
+ json: "0.E----",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error5",
+ json: "0E40",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error6",
+ json: "0.e-9",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error7",
+ json: "0.e",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error8",
+ json: "-5.e-2",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v int16
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ })
+ }
+ t.Run("pool-error", func(t *testing.T) {
+ result := int16(1)
+ dec := NewDecoder(nil)
+ dec.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err shouldnt be nil")
+ assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
+ }()
+ _ = dec.DecodeInt16(&result)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+
+ })
+ t.Run("decoder-api", func(t *testing.T) {
+ var v int16
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.DecodeInt16(&v)
+ 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(``))
+ defer dec.Release()
+ err := dec.DecodeInt16(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+func TestDecoderInt16Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult int16
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 5321",
+ expectedResult: 5321,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: -2,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2456",
+ expectedResult: -2456,
+ },
+ {
+ name: "basic-big",
+ json: " 24566",
+ expectedResult: 24566,
+ },
+ {
+ 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,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "21474836483",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: -7,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876a",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp",
+ json: "1.2E2",
+ expectedResult: 120,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+001 ",
+ expectedResult: 35,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp1",
+ json: "3.5e+002",
+ expectedResult: 350,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp2",
+ json: "5e+03",
+ expectedResult: 5000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp3",
+ json: "3e+3",
+ expectedResult: 3000,
+ },
+ {
+ name: "basic-exponent-positive-positive-exp4",
+ json: "8e+02 ",
+ expectedResult: 800,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp",
+ json: "1e-2 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp2",
+ json: "5E-6",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp3",
+ json: "3e-3",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-005",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp",
+ json: "-1e2",
+ expectedResult: -100,
+ },
+ {
+ name: "exponent-err-",
+ json: "0.1e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "exponent-err-too-big",
+ json: "0.1932242242424244244e1000000000000000000000000",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+03",
+ expectedResult: -5000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e03",
+ expectedResult: -3000,
+ },
+ {
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+003",
+ expectedResult: -8000,
+ },
+ {
+ name: "basic-exponent-err",
+ json: "3e",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "8.32 ",
+ expectedResult: 8,
+ },
+ {
+ name: "error",
+ json: "83zez4",
expectedResult: 0,
err: true,
+ errType: InvalidJSONError(""),
},
{
- name: "exponent-err-too-big",
- json: "0e100000000000 ",
+ name: "error",
+ json: "8ea00$aa5",
expectedResult: 0,
err: true,
+ errType: InvalidJSONError(""),
},
{
- name: "basic-exponent-err",
- json: "3e",
+ name: "error2",
+ json: "-8e+00$aa5",
expectedResult: 0,
err: true,
},
@@ -886,37 +2520,19 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "error7",
- json: "-5.e-2",
- expectedResult: 0,
- err: true,
- errType: InvalidJSONError(""),
- },
- {
- name: "basic-float",
- json: "8.32 ",
- expectedResult: 8,
- },
- {
- name: "error",
- json: "83zez4",
+ json: "0.e",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
- name: "error",
- json: "8ea00$aa5",
+ name: "error8",
+ json: "-5.e-2",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
- name: "error2",
- json: "-8e+00$aa5",
- expectedResult: 0,
- err: true,
- },
- {
name: "invalid-type",
json: `"string"`,
expectedResult: 0,
@@ -927,7 +2543,7 @@ func TestDecoderInt32(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v int32
+ var v = (*int16)(nil)
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -939,56 +2555,36 @@ func TestDecoderInt32(t *testing.T) {
fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
)
}
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
} else {
- assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
}
- assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
})
}
- t.Run("pool-error", func(t *testing.T) {
- result := int32(1)
- dec := NewDecoder(nil)
- dec.Release()
- defer func() {
- err := recover()
- assert.NotNil(t, err, "err shouldnt be nil")
- assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
- }()
- _ = dec.DecodeInt32(&result)
- assert.True(t, false, "should not be called as decoder should have panicked")
-
- })
- t.Run("decoder-api", func(t *testing.T) {
- var v int32
- dec := NewDecoder(strings.NewReader(`33`))
- defer dec.Release()
- err := dec.DecodeInt32(&v)
- 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(``))
- defer dec.Release()
- err := dec.DecodeInt32(&v)
+ var v = new(int16)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(int16)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Int16Null(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
-func TestDecoderInt16(t *testing.T) {
+func TestDecoderInt8(t *testing.T) {
testCases := []struct {
name string
json string
- expectedResult int16
+ expectedResult int8
err bool
errType interface{}
}{
@@ -999,8 +2595,8 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-positive2",
- json: " 5321",
- expectedResult: 5321,
+ json: " 127",
+ expectedResult: 127,
},
{
name: "basic-negative",
@@ -1013,22 +2609,22 @@ func TestDecoderInt16(t *testing.T) {
expectedResult: 0,
},
{
- name: "basic-null-err",
- json: "nxll",
+ name: "basic-negative-err",
+ json: "-",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
name: "basic-negative-err",
- json: "-",
+ json: "-q",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
},
{
- name: "basic-negative-err",
- json: "-q",
+ name: "basic-null-err",
+ json: "nxll",
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
@@ -1042,29 +2638,29 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-negative2",
- json: "-2456",
- expectedResult: -2456,
+ json: "-123",
+ expectedResult: -123,
},
{
name: "basic-big",
- json: " 24566",
- expectedResult: 24566,
+ json: " 43",
+ expectedResult: 43,
},
{
name: "basic-big-overflow",
- json: "66535",
+ json: " 2147483648",
expectedResult: 0,
err: true,
},
{
name: "basic-big-overflow",
- json: "32768",
+ json: "137",
expectedResult: 0,
err: true,
},
{
name: "basic-big-overflow",
- json: " 2147483648",
+ json: "128",
expectedResult: 0,
err: true,
},
@@ -1102,23 +2698,13 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp1",
- json: "3.5e+002",
- expectedResult: 350,
+ json: "3.5e+001",
+ expectedResult: 35,
},
{
name: "basic-exponent-positive-positive-exp2",
- json: "5e+03",
- expectedResult: 5000,
- },
- {
- name: "basic-exponent-positive-positive-exp3",
- json: "3e+3",
- expectedResult: 3000,
- },
- {
- name: "basic-exponent-positive-positive-exp4",
- json: "8e+02 ",
- expectedResult: 800,
+ json: "5e+01",
+ expectedResult: 50,
},
{
name: "basic-exponent-positive-negative-exp",
@@ -1137,7 +2723,17 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp4",
- json: "8e-005",
+ json: "8e-1 ",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e1 ",
+ expectedResult: 80,
+ },
+ {
+ name: "basic-exponent-positive-negative-exp4",
+ json: "8e-1",
expectedResult: 0,
},
{
@@ -1146,26 +2742,31 @@ func TestDecoderInt16(t *testing.T) {
expectedResult: -100,
},
{
- name: "exponent-err-",
- json: "0.1e",
- expectedResult: 0,
- err: true,
+ name: "basic-exponent-negative-positive-exp2",
+ json: "-5e+01",
+ expectedResult: -50,
},
{
- name: "exponent-err-too-big",
- json: "0.1e10000000000000000000",
+ name: "basic-exponent-negative-positive-exp3",
+ json: "-3e01",
+ expectedResult: -30,
+ },
+ {
+ name: "error3",
+ json: "0E40",
expectedResult: 0,
err: true,
+ errType: InvalidJSONError(""),
},
{
- name: "exponent-err-too-big",
- json: "0.1e10000000000 ",
+ name: "exponent-err-",
+ json: "0.1e",
expectedResult: 0,
err: true,
},
{
name: "exponent-err-too-big",
- json: "0e10000000000 ",
+ json: "0.1e10000000000000000000",
expectedResult: 0,
err: true,
},
@@ -1176,19 +2777,21 @@ func TestDecoderInt16(t *testing.T) {
err: true,
},
{
- name: "basic-exponent-negative-positive-exp2",
- json: "-5e+03",
- expectedResult: -5000,
+ name: "basic-exponent-negative-positive-exp4",
+ json: "-8e+001",
+ expectedResult: -80,
},
{
- name: "basic-exponent-negative-positive-exp3",
- json: "-3e03",
- expectedResult: -3000,
+ name: "exponent-err-too-big2",
+ json: "0e100 ",
+ expectedResult: 0,
+ err: true,
},
{
- name: "basic-exponent-negative-positive-exp4",
- json: "-8e+003",
- expectedResult: -8000,
+ name: "exponent-err-too-big2",
+ json: "0.1e100 ",
+ expectedResult: 0,
+ err: true,
},
{
name: "basic-exponent-err",
@@ -1222,13 +2825,6 @@ func TestDecoderInt16(t *testing.T) {
err: true,
},
{
- name: "error3",
- json: "0E40",
- expectedResult: 0,
- err: true,
- errType: InvalidJSONError(""),
- },
- {
name: "error4",
json: "0.E----",
expectedResult: 0,
@@ -1264,6 +2860,13 @@ func TestDecoderInt16(t *testing.T) {
errType: InvalidJSONError(""),
},
{
+ name: "error8",
+ json: "-5.01e",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
name: "invalid-type",
json: `"string"`,
expectedResult: 0,
@@ -1274,7 +2877,7 @@ func TestDecoderInt16(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v int16
+ var v int8
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -1293,7 +2896,7 @@ func TestDecoderInt16(t *testing.T) {
})
}
t.Run("pool-error", func(t *testing.T) {
- result := int16(1)
+ result := int8(1)
dec := NewDecoder(nil)
dec.Release()
defer func() {
@@ -1301,43 +2904,43 @@ func TestDecoderInt16(t *testing.T) {
assert.NotNil(t, err, "err shouldnt be nil")
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
}()
- _ = dec.DecodeInt16(&result)
+ _ = dec.DecodeInt8(&result)
assert.True(t, false, "should not be called as decoder should have panicked")
})
t.Run("decoder-api", func(t *testing.T) {
- var v int16
+ var v int8
dec := NewDecoder(strings.NewReader(`33`))
defer dec.Release()
- err := dec.DecodeInt16(&v)
+ err := dec.DecodeInt8(&v)
assert.Nil(t, err, "Err must be nil")
- assert.Equal(t, int16(33), v, "v must be equal to 33")
+ assert.Equal(t, int8(33), v, "v must be equal to 33")
})
t.Run("decoder-api2", func(t *testing.T) {
- var v int16
+ 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, int16(33), v, "v must be equal to 33")
+ assert.Equal(t, int8(33), v, "v must be equal to 33")
})
t.Run("decoder-api-invalid-json", func(t *testing.T) {
- var v int16
+ var v int8
dec := NewDecoder(strings.NewReader(``))
defer dec.Release()
- err := dec.DecodeInt16(&v)
+ err := dec.DecodeInt8(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
-
-func TestDecoderInt8(t *testing.T) {
+func TestDecoderInt8Null(t *testing.T) {
testCases := []struct {
name string
json string
expectedResult int8
err bool
errType interface{}
+ resultIsNil bool
}{
{
name: "basic-positive",
@@ -1358,6 +2961,7 @@ func TestDecoderInt8(t *testing.T) {
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-negative-err",
@@ -1628,7 +3232,7 @@ func TestDecoderInt8(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v int8
+ var v = (*int8)(nil)
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -1640,46 +3244,26 @@ func TestDecoderInt8(t *testing.T) {
fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
)
}
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
} else {
- assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
}
- assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
})
}
- t.Run("pool-error", func(t *testing.T) {
- result := int8(1)
- dec := NewDecoder(nil)
- dec.Release()
- defer func() {
- err := recover()
- assert.NotNil(t, err, "err shouldnt be nil")
- assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
- }()
- _ = dec.DecodeInt8(&result)
- assert.True(t, false, "should not be called as decoder should have panicked")
-
- })
- t.Run("decoder-api", func(t *testing.T) {
- var v int8
- dec := NewDecoder(strings.NewReader(`33`))
- defer dec.Release()
- err := dec.DecodeInt8(&v)
- 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(``))
- defer dec.Release()
- err := dec.DecodeInt8(&v)
+ var v = new(int8)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(int8)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Int8Null(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
diff --git a/decode_number_uint.go b/decode_number_uint.go
@@ -52,6 +52,50 @@ func (dec *Decoder) decodeUint8(v *uint8) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeUint8Null(v **uint8) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getUint8()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint8)
+ }
+ **v = val
+ return nil
+ case '-': // if negative, we just set it to 0 and set error
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint8)
+ }
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getUint8() (uint8, error) {
var end = dec.cursor
@@ -122,6 +166,50 @@ func (dec *Decoder) decodeUint16(v *uint16) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeUint16Null(v **uint16) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getUint16()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint16)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint16)
+ }
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getUint16() (uint16, error) {
var end = dec.cursor
@@ -192,6 +280,50 @@ func (dec *Decoder) decodeUint32(v *uint32) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeUint32Null(v **uint32) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getUint32()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint32)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint32)
+ }
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getUint32() (uint32, error) {
var end = dec.cursor
@@ -261,6 +393,50 @@ func (dec *Decoder) decodeUint64(v *uint64) error {
}
return dec.raiseInvalidJSONErr(dec.cursor)
}
+func (dec *Decoder) decodeUint64Null(v **uint64) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch c := dec.data[dec.cursor]; c {
+ case ' ', '\n', '\t', '\r', ',':
+ continue
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ val, err := dec.getUint64()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint64)
+ }
+ **v = val
+ return nil
+ case '-':
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(uint64)
+ }
+ return nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return dec.raiseInvalidJSONErr(dec.cursor)
+}
func (dec *Decoder) getUint64() (uint64, error) {
var end = dec.cursor
diff --git a/decode_number_uint_test.go b/decode_number_uint_test.go
@@ -163,12 +163,473 @@ func TestDecoderUint64(t *testing.T) {
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
+func TestDecoderUint64Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult uint64
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-big",
+ json: "18446744073709551615",
+ expectedResult: 18446744073709551615,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "18446744073709551616",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "18446744073709551625",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "184467440737095516161",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error1",
+ json: "132zz4",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*uint64)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(uint64)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(uint64)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Uint64Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+
+func TestDecoderUint32(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult uint32
+ err bool
+ errType interface{}
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405 ",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big",
+ json: "4294967295",
+ expectedResult: 4294967295,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 4294967298",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "4294967395",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "42949672983",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "invalid-json",
+ json: `123invalid`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v uint32
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ } else {
+ assert.Nil(t, err, "Err must be nil")
+ }
+ assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ })
+ }
+ t.Run("pool-error", func(t *testing.T) {
+ result := uint32(1)
+ dec := NewDecoder(nil)
+ dec.Release()
+ defer func() {
+ err := recover()
+ assert.NotNil(t, err, "err shouldnt be nil")
+ assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
+ }()
+ _ = dec.DecodeUint32(&result)
+ assert.True(t, false, "should not be called as decoder should have panicked")
+ })
+ t.Run("decoder-api", func(t *testing.T) {
+ var v uint32
+ dec := NewDecoder(strings.NewReader(`33`))
+ defer dec.Release()
+ err := dec.DecodeUint32(&v)
+ assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, uint32(33), v, "v must be equal to 33")
+ })
+ t.Run("decoder-api-json-error", func(t *testing.T) {
+ var v uint32
+ dec := NewDecoder(strings.NewReader(``))
+ defer dec.Release()
+ err := dec.DecodeUint32(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
+func TestDecoderUint32Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult uint32
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 1039405 ",
+ expectedResult: 1039405,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-2349557",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big",
+ json: "4294967295",
+ expectedResult: 4294967295,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 4294967298",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: "4294967395",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "42949672983",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "invalid-json",
+ json: `123invalid`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*uint32)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(uint32)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(uint32)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Uint32Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
-func TestDecoderUint32(t *testing.T) {
+func TestDecoderUint16(t *testing.T) {
testCases := []struct {
name string
json string
- expectedResult uint32
+ expectedResult uint16
err bool
errType interface{}
}{
@@ -179,8 +640,8 @@ func TestDecoderUint32(t *testing.T) {
},
{
name: "basic-positive2",
- json: " 1039405 ",
- expectedResult: 1039405,
+ json: " 3224 ",
+ expectedResult: 3224,
},
{
name: "basic-negative",
@@ -208,15 +669,29 @@ func TestDecoderUint32(t *testing.T) {
errType: InvalidJSONError(""),
},
{
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-overflow",
+ json: "335346564",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
name: "basic-negative2",
- json: "-2349557",
+ json: "-24467",
expectedResult: 0,
err: true,
},
{
name: "basic-big",
- json: "4294967295",
- expectedResult: 4294967295,
+ json: "54546",
+ expectedResult: 54546,
},
{
name: "basic-big-overflow",
@@ -226,7 +701,13 @@ func TestDecoderUint32(t *testing.T) {
},
{
name: "basic-big-overflow",
- json: "4294967395",
+ json: " 65537",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 66537",
expectedResult: 0,
err: true,
},
@@ -279,7 +760,7 @@ func TestDecoderUint32(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v uint32
+ var v uint16
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -298,7 +779,7 @@ func TestDecoderUint32(t *testing.T) {
})
}
t.Run("pool-error", func(t *testing.T) {
- result := uint32(1)
+ result := uint16(1)
dec := NewDecoder(nil)
dec.Release()
defer func() {
@@ -306,34 +787,42 @@ func TestDecoderUint32(t *testing.T) {
assert.NotNil(t, err, "err shouldnt be nil")
assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
}()
- _ = dec.DecodeUint32(&result)
+ _ = dec.DecodeUint16(&result)
assert.True(t, false, "should not be called as decoder should have panicked")
})
t.Run("decoder-api", func(t *testing.T) {
- var v uint32
+ var v uint16
dec := NewDecoder(strings.NewReader(`33`))
defer dec.Release()
- err := dec.DecodeUint32(&v)
+ err := dec.DecodeUint16(&v)
assert.Nil(t, err, "Err must be nil")
- assert.Equal(t, uint32(33), v, "v must be equal to 33")
+ 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 uint32
+ var v uint16
dec := NewDecoder(strings.NewReader(``))
defer dec.Release()
- err := dec.DecodeUint32(&v)
+ err := dec.DecodeUint16(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
-
-func TestDecoderUint16(t *testing.T) {
+func TestDecoderUint16Null(t *testing.T) {
testCases := []struct {
name string
json string
expectedResult uint16
err bool
errType interface{}
+ resultIsNil bool
}{
{
name: "basic-positive",
@@ -355,6 +844,7 @@ func TestDecoderUint16(t *testing.T) {
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-null-err",
@@ -462,7 +952,7 @@ func TestDecoderUint16(t *testing.T) {
for _, testCase := range testCases {
t.Run(testCase.name, func(t *testing.T) {
json := []byte(testCase.json)
- var v uint16
+ var v = (*uint16)(nil)
err := Unmarshal(json, &v)
if testCase.err {
assert.NotNil(t, err, "Err must not be nil")
@@ -474,45 +964,26 @@ func TestDecoderUint16(t *testing.T) {
fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
)
}
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
} else {
- assert.Nil(t, err, "Err must be nil")
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
}
- assert.Equal(t, testCase.expectedResult, v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
})
}
- t.Run("pool-error", func(t *testing.T) {
- result := uint16(1)
- dec := NewDecoder(nil)
- dec.Release()
- defer func() {
- err := recover()
- assert.NotNil(t, err, "err shouldnt be nil")
- assert.IsType(t, InvalidUsagePooledDecoderError(""), err, "err should be of type InvalidUsagePooledDecoderError")
- }()
- _ = dec.DecodeUint16(&result)
- assert.True(t, false, "should not be called as decoder should have panicked")
- })
- t.Run("decoder-api", func(t *testing.T) {
- var v uint16
- dec := NewDecoder(strings.NewReader(`33`))
- defer dec.Release()
- err := dec.DecodeUint16(&v)
- 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-invalid-json", func(t *testing.T) {
+ var v = new(uint16)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
- t.Run("decoder-api-json-error", func(t *testing.T) {
- var v uint16
- dec := NewDecoder(strings.NewReader(``))
- defer dec.Release()
- err := dec.DecodeUint16(&v)
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(uint16)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Uint16Null(&v)
assert.NotNil(t, err, "Err must not be nil")
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
@@ -696,3 +1167,165 @@ func TestDecoderUint8(t *testing.T) {
assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
})
}
+
+func TestDecoderUint8Null(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult uint8
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-positive",
+ json: "100",
+ expectedResult: 100,
+ },
+ {
+ name: "basic-positive2",
+ json: " 255 ",
+ expectedResult: 255,
+ },
+ {
+ name: "basic-negative",
+ json: "-2",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-null",
+ json: "null",
+ expectedResult: 0,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-null-err",
+ json: "nxll",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-skip-data-err",
+ json: "trua",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative2",
+ json: "-234",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big",
+ json: "200",
+ expectedResult: 200,
+ },
+ {
+ name: "basic-overflow",
+ json: "256",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "basic-overflow",
+ json: "274",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "basic-big-overflow",
+ json: " 4294967298",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-big-overflow2",
+ json: "42949672983",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-float",
+ json: "2.4595",
+ expectedResult: 2,
+ },
+ {
+ name: "basic-float2",
+ json: "-7.8876",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "error",
+ json: "83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "error",
+ json: "-83zez4",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-type",
+ json: `"string"`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidUnmarshalError(""),
+ },
+ {
+ name: "invalid-json",
+ json: `123invalid`,
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ }
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ json := []byte(testCase.json)
+ var v = (*uint8)(nil)
+ err := Unmarshal(json, &v)
+ if testCase.err {
+ assert.NotNil(t, err, "Err must not be nil")
+ if testCase.errType != nil {
+ assert.IsType(
+ t,
+ testCase.errType,
+ err,
+ fmt.Sprintf("err should be of type %s", reflect.TypeOf(err).String()),
+ )
+ }
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, v)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *v, fmt.Sprintf("v must be equal to %d", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json", func(t *testing.T) {
+ var v = new(uint8)
+ err := Unmarshal([]byte(``), &v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(uint8)
+ var dec = NewDecoder(strings.NewReader(``))
+ err := dec.Uint8Null(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
diff --git a/decode_object_test.go b/decode_object_test.go
@@ -3,12 +3,19 @@ package gojay
import (
"fmt"
"io"
+ "reflect"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
+func makePointer(v interface{}) interface{} {
+ var ptr = reflect.New(reflect.TypeOf(v))
+ ptr.Elem().Set(reflect.ValueOf(v))
+ return ptr.Interface()
+}
+
func TestDecodeObjectBasic(t *testing.T) {
testCases := []struct {
name string
@@ -22,33 +29,62 @@ func TestDecodeObjectBasic(t *testing.T) {
name: "basic",
json: `{
"testStr": "hello world!",
+ "testStrNull": "hello world!",
"testInt": 4535,
+ "testIntNull": 4535,
"testBool": true,
+ "testBoolNull": true,
"testFloat32": 2.345,
+ "testFloat32Null": 2.345,
"testFloat64": 123.677,
+ "testFloat64Null": 123.677,
"testInt8": 23,
+ "testInt8Null": 23,
"testInt16": 1245,
+ "testInt16Null": 1245,
"testInt32": 456778,
+ "testInt32Null": 456778,
"testInt64": 1446685358,
+ "testInt64Null": 1446685358,
"testUint8": 255,
+ "testUint8Null": 255,
"testUint16": 3455,
+ "testUint16Null": 3455,
"testUint32": 343443,
- "testUint64": 545665757
+ "testUint32Null": 343443,
+ "testUint64": 545665757,
+ "testUint64Null": 545665757,
+ "testSubObjectNull": {
+ "testStr": "1"
+ }
}`,
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,
+ testStr: "hello world!",
+ testStrNull: makePointer("hello world!").(*string),
+ testInt: 4535,
+ testIntNull: makePointer(4535).(*int),
+ testBool: true,
+ testBoolNull: makePointer(true).(*bool),
+ testFloat32: 2.345,
+ testFloat32Null: makePointer(float32(2.345)).(*float32),
+ testFloat64: 123.677,
+ testFloat64Null: makePointer(float64(123.677)).(*float64),
+ testInt8: 23,
+ testInt8Null: makePointer(int8(23)).(*int8),
+ testInt16: 1245,
+ testInt16Null: makePointer(int16(1245)).(*int16),
+ testInt32: 456778,
+ testInt32Null: makePointer(int32(456778)).(*int32),
+ testInt64: 1446685358,
+ testInt64Null: makePointer(int64(1446685358)).(*int64),
+ testUint8: 255,
+ testUint8Null: makePointer(uint8(255)).(*uint8),
+ testUint16: 3455,
+ testUint16Null: makePointer(uint16(3455)).(*uint16),
+ testUint32: 343443,
+ testUint32Null: makePointer(uint32(343443)).(*uint32),
+ testUint64: 545665757,
+ testUint64Null: makePointer(uint64(545665757)).(*uint64),
},
err: false,
},
@@ -1377,6 +1413,10 @@ func TestSkipObject(t *testing.T) {
json: `"key":"value\\\\\\\" hello"}`,
},
{
+ name: "basic-escaped",
+ json: `"key":"value\\\\\\\\"}`,
+ },
+ {
name: "basic-err",
json: ``,
err: true,
diff --git a/decode_string.go b/decode_string.go
@@ -20,7 +20,7 @@ func (dec *Decoder) decodeString(v *string) error {
// is string
continue
case '"':
- dec.cursor = dec.cursor + 1
+ dec.cursor++
start, end, err := dec.getString()
if err != nil {
return err
@@ -51,6 +51,47 @@ func (dec *Decoder) decodeString(v *string) error {
return nil
}
+func (dec *Decoder) decodeStringNull(v **string) error {
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch dec.data[dec.cursor] {
+ case ' ', '\n', '\t', '\r', ',':
+ // is string
+ continue
+ case '"':
+ dec.cursor++
+ start, end, err := dec.getString()
+ if err != nil {
+ return err
+ }
+ if *v == nil {
+ *v = new(string)
+ }
+ // we do minus one to remove the last quote
+ d := dec.data[start : end-1]
+ **v = *(*string)(unsafe.Pointer(&d))
+ dec.cursor = end
+ return nil
+ // is nil
+ case 'n':
+ dec.cursor++
+ err := dec.assertNull()
+ if err != nil {
+ return err
+ }
+ dec.cursor++
+ return nil
+ default:
+ dec.err = dec.makeInvalidUnmarshalErr(v)
+ err := dec.skipData()
+ if err != nil {
+ return err
+ }
+ return nil
+ }
+ }
+ return nil
+}
+
func (dec *Decoder) parseEscapedString() error {
if dec.cursor >= dec.length && !dec.read() {
return dec.raiseInvalidJSONErr(dec.cursor)
diff --git a/decode_string_test.go b/decode_string_test.go
@@ -319,6 +319,329 @@ func TestDecoderString(t *testing.T) {
})
}
}
+func TestDecoderStringNull(t *testing.T) {
+ testCases := []struct {
+ name string
+ json string
+ expectedResult string
+ err bool
+ errType interface{}
+ resultIsNil bool
+ }{
+ {
+ name: "basic-string",
+ json: `"string"`,
+ expectedResult: "string",
+ err: false,
+ },
+ {
+ name: "string-solidus",
+ json: `"\/"`,
+ expectedResult: "/",
+ err: false,
+ },
+ {
+ name: "basic-string",
+ json: ``,
+ expectedResult: "",
+ err: false,
+ resultIsNil: true,
+ },
+ {
+ name: "basic-string",
+ json: `""`,
+ expectedResult: "",
+ err: false,
+ },
+ {
+ name: "basic-string2",
+ json: `"hello world!"`,
+ expectedResult: "hello world!",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\n"`,
+ expectedResult: "\n",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\\n"`,
+ expectedResult: `\n`,
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\t"`,
+ expectedResult: "\t",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\\t"`,
+ expectedResult: `\t`,
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\b"`,
+ expectedResult: "\b",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\\b"`,
+ expectedResult: `\b`,
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\f"`,
+ expectedResult: "\f",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\\f"`,
+ expectedResult: `\f`,
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\r"`,
+ expectedResult: "\r",
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\`,
+ expectedResult: "",
+ err: true,
+ },
+ {
+ name: "escape-control-char-solidus",
+ json: `"\/"`,
+ expectedResult: "/",
+ err: false,
+ },
+ {
+ name: "escape-control-char-solidus",
+ json: `"/"`,
+ expectedResult: "/",
+ err: false,
+ },
+ {
+ name: "escape-control-char-solidus-escape-char",
+ json: `"\\/"`,
+ expectedResult: `\/`,
+ err: false,
+ },
+ {
+ name: "escape-control-char",
+ json: `"\\r"`,
+ expectedResult: `\r`,
+ err: false,
+ },
+ {
+ name: "utf8",
+ json: `"𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕 𠴕 𠵼 𠵿"`,
+ expectedResult: "𠜎 𠜱 𠝹 𠱓 𠱸 𠲖 𠳏 𠳕 𠴕 𠵼 𠵿",
+ err: false,
+ },
+ {
+ name: "utf8-code-point",
+ json: `"\u06fc"`,
+ expectedResult: `ۼ`,
+ err: false,
+ },
+ {
+ name: "utf8-code-point-escaped",
+ json: `"\\u2070"`,
+ expectedResult: `\u2070`,
+ err: false,
+ },
+ {
+ name: "utf8-code-point-err",
+ json: `"\u2Z70"`,
+ expectedResult: ``,
+ err: true,
+ },
+ {
+ name: "utf16-surrogate",
+ json: `"\uD834\uDD1E"`,
+ expectedResult: `𝄞`,
+ err: false,
+ },
+ {
+ name: "utf16-surrogate",
+ json: `"\uD834\\"`,
+ expectedResult: `�\`,
+ err: false,
+ },
+ {
+ name: "utf16-surrogate",
+ json: `"\uD834\uD834"`,
+ expectedResult: "�\x00\x00\x00",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate",
+ json: `"\uD834"`,
+ expectedResult: `�`,
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-err",
+ json: `"\uD834\`,
+ expectedResult: ``,
+ err: true,
+ },
+ {
+ name: "utf16-surrogate-err2",
+ json: `"\uD834\uDZ1E`,
+ expectedResult: ``,
+ err: true,
+ },
+ {
+ name: "utf16-surrogate-err3",
+ json: `"\uD834`,
+ expectedResult: ``,
+ err: true,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\t"`,
+ expectedResult: "�\t",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\n"`,
+ expectedResult: "�\n",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\f"`,
+ expectedResult: "�\f",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\b"`,
+ expectedResult: "�\b",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\r"`,
+ expectedResult: "�\r",
+ err: false,
+ },
+ {
+ name: "utf16-surrogate-followed-by-control-char",
+ json: `"\uD834\h"`,
+ expectedResult: "",
+ err: true,
+ },
+ {
+ name: "null",
+ json: `null`,
+ expectedResult: "",
+ resultIsNil: true,
+ },
+ {
+ name: "null-err",
+ json: `nall`,
+ expectedResult: "",
+ err: true,
+ },
+ {
+ name: "escape quote err",
+ json: `"test string \" escaped"`,
+ expectedResult: `test string " escaped`,
+ err: false,
+ },
+ {
+ name: "escape quote err2",
+ json: `"test string \t escaped"`,
+ expectedResult: "test string \t escaped",
+ err: false,
+ },
+ {
+ name: "escape quote err2",
+ json: `"test string \r escaped"`,
+ expectedResult: "test string \r escaped",
+ err: false,
+ },
+ {
+ name: "escape quote err2",
+ json: `"test string \b escaped"`,
+ expectedResult: "test string \b escaped",
+ err: false,
+ },
+ {
+ name: "escape quote err",
+ json: `"test string \n escaped"`,
+ expectedResult: "test string \n escaped",
+ err: false,
+ },
+ {
+ name: "escape quote err",
+ json: `"test string \\\" escaped`,
+ expectedResult: ``,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "escape quote err",
+ json: `"test string \\\l escaped"`,
+ expectedResult: ``,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "invalid-json",
+ json: `invalid`,
+ expectedResult: ``,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "string-complex",
+ json: ` "string with spaces and \"escape\"d \"quotes\" and escaped line returns \n and escaped \\\\ escaped char"`,
+ expectedResult: "string with spaces and \"escape\"d \"quotes\" and escaped line returns \n and escaped \\\\ escaped char",
+ },
+ }
+
+ for _, testCase := range testCases {
+ t.Run(testCase.name, func(t *testing.T) {
+ str := (*string)(nil)
+ err := Unmarshal([]byte(testCase.json), &str)
+ if testCase.err {
+ assert.NotNil(t, err, "err should not be nil")
+ if testCase.errType != nil {
+ assert.IsType(t, testCase.errType, err, "err should of the given type")
+ }
+ return
+ }
+ assert.Nil(t, err, "Err must be nil")
+ if testCase.resultIsNil {
+ assert.Nil(t, str)
+ } else {
+ assert.Equal(t, testCase.expectedResult, *str, fmt.Sprintf("v must be equal to %s", testCase.expectedResult))
+ }
+ })
+ }
+ t.Run("decoder-api-invalid-json2", func(t *testing.T) {
+ var v = new(string)
+ var dec = NewDecoder(strings.NewReader(`a`))
+ err := dec.StringNull(&v)
+ assert.NotNil(t, err, "Err must not be nil")
+ assert.IsType(t, InvalidJSONError(""), err, "err should be of type InvalidJSONError")
+ })
+}
func TestDecoderStringInvalidType(t *testing.T) {
json := []byte(`1`)
var v string
diff --git a/decode_test.go b/decode_test.go
@@ -1,8 +1,8 @@
package gojay
import (
+ "bytes"
"fmt"
- "io"
"reflect"
"testing"
@@ -35,14 +35,15 @@ func (t *testDecodeSlice) UnmarshalJSONArray(dec *Decoder) error {
return nil
}
-// Unmarshal tests
-func TestUnmarshalAllTypes(t *testing.T) {
- testCases := []struct {
- name string
- v interface{}
- d []byte
- expectations func(err error, v interface{}, t *testing.T)
- }{
+type allTypeDecodeTestCase struct {
+ name string
+ v interface{}
+ d []byte
+ expectations func(err error, v interface{}, t *testing.T)
+}
+
+func allTypesTestCases() []allTypeDecodeTestCase {
+ return []allTypeDecodeTestCase{
{
v: new(string),
d: []byte(`"test string"`),
@@ -54,346 +55,281 @@ func TestUnmarshalAllTypes(t *testing.T) {
},
},
{
- v: new(string),
- d: []byte(`null`),
- name: "test decode string null",
+ v: new(*string),
+ d: []byte(`"test string"`),
+ name: "test decode string",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*string)
+ vt := v.(**string)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "", *vt, "v must be equal to 1")
+ assert.Equal(t, "test string", **vt, "v must be equal to 1")
},
},
{
- v: new(int),
- d: []byte(`1`),
- name: "test decode int",
+ v: new(string),
+ d: []byte(`null`),
+ name: "test decode string null",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int)
+ vt := v.(*string)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, 1, *vt, "v must be equal to 1")
+ assert.Equal(t, "", *vt, "v must be equal to 1")
},
},
{
- v: new(int64),
- d: []byte(`1`),
- name: "test decode int64",
+ v: new(*string),
+ d: []byte(`null`),
+ name: "test decode string null",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int64)
+ vt := v.(**string)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, int64(1), *vt, "v must be equal to 1")
+ assert.Nil(t, *vt, "v must be nil")
},
},
{
- v: new(uint64),
+ v: new(*string),
d: []byte(`1`),
- name: "test decode uint64",
- expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint64)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, uint64(1), *vt, "v must be equal to 1")
- },
- },
- {
- v: new(uint64),
- d: []byte(`-1`),
- name: "test decode uint64 negative",
+ name: "test decode string null",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint64)
- assert.NotNil(t, err, "err must not be nil")
- assert.Equal(t, uint64(0), *vt, "v must be equal to 1")
+ vt := v.(**string)
+ assert.NotNil(t, err, "err must be nil")
+ assert.Nil(t, *vt, "v must be nil")
},
},
{
- v: new(int32),
+
+ v: new(int),
d: []byte(`1`),
- name: "test decode int32",
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int32)
+ vt := v.(*int)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, int32(1), *vt, "v must be equal to 1")
+ assert.Equal(t, 1, *vt, "v must be equal to 1")
},
},
{
- v: new(uint32),
+ v: new(*int),
d: []byte(`1`),
- name: "test decode uint32",
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint32)
+ vt := v.(**int)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, uint32(1), *vt, "v must be equal to 1")
- },
- },
- {
- v: new(uint32),
- d: []byte(`-1`),
- name: "test decode uint32 negative",
- expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint32)
- assert.NotNil(t, err, "err must not be nil")
- assert.Equal(t, uint32(0), *vt, "v must be equal to 1")
+ assert.Equal(t, 1, **vt, "v must be equal to 1")
},
},
{
- v: new(float64),
- d: []byte(`1.15`),
- name: "test decode float64",
+ v: new(*int),
+ d: []byte(`""`),
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*float64)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, float64(1.15), *vt, "v must be equal to 1")
+ assert.NotNil(t, err, "err must be nil")
},
},
{
- v: new(float64),
- d: []byte(`null`),
- name: "test decode float64 null",
+ v: new(*int8),
+ d: []byte(`1`),
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*float64)
+ vt := v.(**int8)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, float64(0), *vt, "v must be equal to 1")
+ assert.Equal(t, int8(1), **vt, "v must be equal to 1")
},
},
{
- v: new(bool),
- d: []byte(`true`),
- name: "test decode bool true",
+ v: new(*int8),
+ d: []byte(`""`),
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*bool)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, true, *vt, "v must be equal to 1")
+ assert.NotNil(t, err, "err must be nil")
},
},
{
- v: new(bool),
- d: []byte(`false`),
- name: "test decode bool false",
+ v: new(*int16),
+ d: []byte(`1`),
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*bool)
+ vt := v.(**int16)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, false, *vt, "v must be equal to 1")
+ assert.Equal(t, int16(1), **vt, "v must be equal to 1")
},
},
{
- v: new(bool),
- d: []byte(`null`),
- name: "test decode bool null",
+ v: new(*int16),
+ d: []byte(`""`),
+ name: "test decode int",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*bool)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, false, *vt, "v must be equal to 1")
+ assert.NotNil(t, err, "err must be nil")
},
},
{
- v: new(testDecodeObj),
- d: []byte(`{"test":"test"}`),
- name: "test decode object",
+ v: new(int64),
+ d: []byte(`1`),
+ name: "test decode int64",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*testDecodeObj)
+ vt := v.(*int64)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "test", vt.test, "v.test must be equal to 'test'")
+ assert.Equal(t, int64(1), *vt, "v must be equal to 1")
},
},
{
- v: new(testDecodeObj),
- d: []byte(`{"test":null}`),
- name: "test decode object null key",
+ v: new(*int64),
+ d: []byte(`1`),
+ name: "test decode int64",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*testDecodeObj)
+ vt := v.(**int64)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "", vt.test, "v.test must be equal to 'test'")
+ assert.Equal(t, int64(1), **vt, "v must be equal to 1")
},
},
{
- v: new(testDecodeObj),
- d: []byte(`null`),
- name: "test decode object null",
+ v: new(*int64),
+ d: []byte(`""`),
+ name: "test decode int64",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*testDecodeObj)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "", vt.test, "v.test must be equal to 'test'")
+ assert.NotNil(t, err, "err must be nil")
},
},
{
- v: new(testDecodeSlice),
- d: []byte(`[{"test":"test"}]`),
- name: "test decode slice",
+ v: new(uint64),
+ d: []byte(`1`),
+ name: "test decode uint64",
expectations: func(err error, v interface{}, t *testing.T) {
- vtPtr := v.(*testDecodeSlice)
- vt := *vtPtr
+ vt := v.(*uint64)
assert.Nil(t, err, "err must be nil")
- assert.Len(t, vt, 1, "len of vt must be 1")
- assert.Equal(t, "test", vt[0].test, "vt[0].test must be equal to 'test'")
+ assert.Equal(t, uint64(1), *vt, "v must be equal to 1")
},
},
{
- v: new(testDecodeSlice),
- d: []byte(`[{"test":"test"},{"test":"test2"}]`),
- name: "test decode slice",
+ v: new(*uint64),
+ d: []byte(`1`),
+ name: "test decode uint64",
expectations: func(err error, v interface{}, t *testing.T) {
- vtPtr := v.(*testDecodeSlice)
- vt := *vtPtr
+ vt := v.(**uint64)
assert.Nil(t, err, "err must be nil")
- assert.Len(t, vt, 2, "len of vt must be 2")
- assert.Equal(t, "test", vt[0].test, "vt[0].test must be equal to 'test'")
- assert.Equal(t, "test2", vt[1].test, "vt[1].test must be equal to 'test2'")
+ assert.Equal(t, uint64(1), **vt, "v must be equal to 1")
},
},
{
- v: new(struct{}),
- d: []byte(`{"test":"test"}`),
- name: "test decode invalid type",
+ v: new(uint64),
+ d: []byte(`-1`),
+ name: "test decode uint64 negative",
expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(*uint64)
assert.NotNil(t, err, "err must not be nil")
- assert.IsType(t, InvalidUnmarshalError(""), err, "err must be of type InvalidUnmarshalError")
- assert.Equal(t, fmt.Sprintf(invalidUnmarshalErrorMsg, reflect.TypeOf(v).String()), err.Error(), "err message should be equal to invalidUnmarshalErrorMsg")
+ assert.Equal(t, uint64(0), *vt, "v must be equal to 1")
},
},
- }
- for _, testCase := range testCases {
- testCase := testCase
- t.Run(testCase.name, func(*testing.T) {
- err := Unmarshal(testCase.d, testCase.v)
- testCase.expectations(err, testCase.v, t)
- })
- }
-}
-
-// Decode tests
-
-type TestReader struct {
- data string
- done bool
-}
-
-func (r *TestReader) Read(b []byte) (int, error) {
- if !r.done {
- n := copy(b, r.data)
- r.done = true
- return n, nil
- }
- return 0, io.EOF
-}
-
-func TestDecodeAllTypes(t *testing.T) {
- testCases := []struct {
- name string
- v interface{}
- r TestReader
- expectations func(err error, v interface{}, t *testing.T)
- }{
{
- v: new(string),
- r: TestReader{`"test string"`, false},
- name: "test decode string",
+ v: new(int32),
+ d: []byte(`1`),
+ name: "test decode int32",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*string)
+ vt := v.(*int32)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "test string", *vt, "v must be equal to 1")
+ assert.Equal(t, int32(1), *vt, "v must be equal to 1")
},
},
{
- v: new(string),
- r: TestReader{`null`, false},
- name: "test decode string null",
+ v: new(*int32),
+ d: []byte(`1`),
+ name: "test decode int32",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*string)
+ vt := v.(**int32)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, "", *vt, "v must be equal to 1")
+ assert.Equal(t, int32(1), **vt, "v must be equal to 1")
},
},
{
- v: new(int),
- r: TestReader{`1`, false},
- name: "test decode int",
+ v: new(uint32),
+ d: []byte(`1`),
+ name: "test decode uint32",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int)
+ vt := v.(*uint32)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, 1, *vt, "v must be equal to 1")
+ assert.Equal(t, uint32(1), *vt, "v must be equal to 1")
},
},
{
- v: new(int64),
- r: TestReader{`1`, false},
- name: "test decode int64",
+ v: new(*uint32),
+ d: []byte(`1`),
+ name: "test decode uint32",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int64)
+ vt := v.(**uint32)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, int64(1), *vt, "v must be equal to 1")
+ assert.Equal(t, uint32(1), **vt, "v must be equal to 1")
},
},
{
- v: new(uint64),
- r: TestReader{`1`, false},
- name: "test decode uint64",
+ v: new(uint32),
+ d: []byte(`-1`),
+ name: "test decode uint32 negative",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint64)
- assert.Nil(t, err, "err must be nil")
- assert.Equal(t, uint64(1), *vt, "v must be equal to 1")
+ vt := v.(*uint32)
+ assert.NotNil(t, err, "err must not be nil")
+ assert.Equal(t, uint32(0), *vt, "v must be equal to 1")
},
},
{
- v: new(uint64),
- r: TestReader{`-1`, false},
- name: "test decode uint64 negative",
+ v: new(*uint16),
+ d: []byte(`1`),
+ name: "test decode uint16",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint64)
- assert.NotNil(t, err, "err must not be nil")
- assert.Equal(t, uint64(0), *vt, "v must be equal to 1")
+ 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(int32),
- r: TestReader{`1`, false},
- name: "test decode int32",
+ v: new(*uint8),
+ d: []byte(`1`),
+ name: "test decode uint8",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*int32)
+ vt := v.(**uint8)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, int32(1), *vt, "v must be equal to 1")
+ assert.Equal(t, uint8(1), **vt, "v must be equal to 1")
},
},
{
- v: new(uint32),
- r: TestReader{`1`, false},
- name: "test decode uint32",
+ v: new(float64),
+ d: []byte(`1.15`),
+ name: "test decode float64",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint32)
+ vt := v.(*float64)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, uint32(1), *vt, "v must be equal to 1")
+ assert.Equal(t, float64(1.15), *vt, "v must be equal to 1")
},
},
{
- v: new(uint32),
- r: TestReader{`-1`, false},
- name: "test decode uint32 negative",
+ v: new(*float64),
+ d: []byte(`1.15`),
+ name: "test decode float64",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*uint32)
- assert.NotNil(t, err, "err must not be nil")
- assert.Equal(t, uint32(0), *vt, "v must be equal to 1")
+ vt := v.(**float64)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, float64(1.15), **vt, "v must be equal to 1")
},
},
{
v: new(float64),
- r: TestReader{`1.15`, false},
- name: "test decode float64",
+ d: []byte(`null`),
+ name: "test decode float64 null",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*float64)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, float64(1.15), *vt, "v must be equal to 1")
+ assert.Equal(t, float64(0), *vt, "v must be equal to 1")
},
},
{
- v: new(float64),
- r: TestReader{`null`, false},
+ v: new(*float32),
+ d: []byte(`1.15`),
name: "test decode float64 null",
expectations: func(err error, v interface{}, t *testing.T) {
- vt := v.(*float64)
+ vt := v.(**float32)
assert.Nil(t, err, "err must be nil")
- assert.Equal(t, float64(0), *vt, "v must be equal to 1")
+ assert.Equal(t, float32(1.15), **vt, "v must be equal to 1")
},
},
{
v: new(bool),
- r: TestReader{`true`, false},
+ d: []byte(`true`),
name: "test decode bool true",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*bool)
@@ -402,8 +338,18 @@ func TestDecodeAllTypes(t *testing.T) {
},
},
{
+ v: new(*bool),
+ d: []byte(`true`),
+ name: "test decode bool true",
+ expectations: func(err error, v interface{}, t *testing.T) {
+ vt := v.(**bool)
+ assert.Nil(t, err, "err must be nil")
+ assert.Equal(t, true, **vt, "v must be equal to 1")
+ },
+ },
+ {
v: new(bool),
- r: TestReader{`false`, false},
+ d: []byte(`false`),
name: "test decode bool false",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*bool)
@@ -413,7 +359,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(bool),
- r: TestReader{`null`, false},
+ d: []byte(`null`),
name: "test decode bool null",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*bool)
@@ -423,7 +369,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(testDecodeObj),
- r: TestReader{`{"test":"test"}`, false},
+ d: []byte(`{"test":"test"}`),
name: "test decode object",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*testDecodeObj)
@@ -433,7 +379,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(testDecodeObj),
- r: TestReader{`{"test":null}`, false},
+ d: []byte(`{"test":null}`),
name: "test decode object null key",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*testDecodeObj)
@@ -443,7 +389,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(testDecodeObj),
- r: TestReader{`null`, false},
+ d: []byte(`null`),
name: "test decode object null",
expectations: func(err error, v interface{}, t *testing.T) {
vt := v.(*testDecodeObj)
@@ -453,7 +399,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(testDecodeSlice),
- r: TestReader{`[{"test":"test"}]`, false},
+ d: []byte(`[{"test":"test"}]`),
name: "test decode slice",
expectations: func(err error, v interface{}, t *testing.T) {
vtPtr := v.(*testDecodeSlice)
@@ -465,7 +411,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(testDecodeSlice),
- r: TestReader{`[{"test":"test"},{"test":"test2"}]`, false},
+ d: []byte(`[{"test":"test"},{"test":"test2"}]`),
name: "test decode slice",
expectations: func(err error, v interface{}, t *testing.T) {
vtPtr := v.(*testDecodeSlice)
@@ -478,7 +424,7 @@ func TestDecodeAllTypes(t *testing.T) {
},
{
v: new(struct{}),
- r: TestReader{`{"test":"test"}`, false},
+ d: []byte(`{"test":"test"}`),
name: "test decode invalid type",
expectations: func(err error, v interface{}, t *testing.T) {
assert.NotNil(t, err, "err must not be nil")
@@ -487,10 +433,25 @@ func TestDecodeAllTypes(t *testing.T) {
},
},
}
- for _, testCase := range testCases {
+}
+
+// Unmarshal tests
+func TestUnmarshalAllTypes(t *testing.T) {
+ for _, testCase := range allTypesTestCases() {
+ testCase := testCase
+ t.Run(testCase.name, func(*testing.T) {
+ err := Unmarshal(testCase.d, testCase.v)
+ testCase.expectations(err, testCase.v, t)
+ })
+ }
+}
+
+// Decode tests
+func TestDecodeAllTypes(t *testing.T) {
+ for _, testCase := range allTypesTestCases() {
testCase := testCase
t.Run(testCase.name, func(*testing.T) {
- dec := NewDecoder(&testCase.r)
+ dec := NewDecoder(bytes.NewReader(testCase.d))
err := dec.Decode(testCase.v)
testCase.expectations(err, testCase.v, t)
})
diff --git a/encode_interface_test.go b/encode_interface_test.go
@@ -112,7 +112,11 @@ var encoderTestCases = []struct {
},
},
{
- v: &testObject{"漢字", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1.1, true, &testObject{}, testSliceInts{}},
+ v: &testObject{
+ "漢字", nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil,
+ 1, nil, 1, nil, 1, nil, 1, nil, 1.1, nil, 1.1, nil, true, nil,
+ &testObject{}, testSliceInts{},
+ },
expectations: func(t *testing.T, b string, err error) {
assert.Nil(t, err, "err should be nil")
assert.Equal(t, `{"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`, string(b), `string(b) should equal {"testStr":"漢字","testInt":1,"testInt64":1,"testInt32":1,"testInt16":1,"testInt8":1,"testUint64":1,"testUint32":1,"testUint16":1,"testUint8":1,"testFloat64":1.1,"testFloat32":1.1,"testBool":true}`)
diff --git a/encode_object_test.go b/encode_object_test.go
@@ -83,7 +83,11 @@ func TestEncoderObjectEncodeAPI(t *testing.T) {
t.Run("encode-basic", func(t *testing.T) {
builder := &strings.Builder{}
enc := NewEncoder(builder)
- err := enc.EncodeObject(&testObject{"漢字", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1.1, true, &testObject{}, testSliceInts{}})
+ err := enc.EncodeObject(&testObject{
+ "漢字", nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil,
+ 1, nil, 1, nil, 1.1, nil, 1.1, nil, true, nil,
+ &testObject{}, testSliceInts{},
+ })
assert.Nil(t, err, "Error should be nil")
assert.Equal(
t,
@@ -96,7 +100,11 @@ func TestEncoderObjectEncodeAPI(t *testing.T) {
func TestEncoderObjectMarshalAPI(t *testing.T) {
t.Run("marshal-basic", func(t *testing.T) {
- r, err := Marshal(&testObject{"漢字", 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.1, 1.1, true, &testObject{}, testSliceInts{}})
+ r, err := Marshal(&testObject{
+ "漢字", nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1, nil, 1,
+ nil, 1, nil, 1, nil, 1.1, nil, 1.1, nil, true, nil,
+ &testObject{}, testSliceInts{},
+ })
assert.Nil(t, err, "Error should be nil")
assert.Equal(
t,
diff --git a/gojay_test.go b/gojay_test.go
@@ -1,21 +1,34 @@
package gojay
type testObject struct {
- testStr string
- testInt int
- testInt64 int64
- testInt32 int32
- testInt16 int16
- testInt8 int8
- testUint64 uint64
- testUint32 uint32
- testUint16 uint16
- testUint8 uint8
- testFloat64 float64
- testFloat32 float32
- testBool bool
- testSubObject *testObject
- testSubArray testSliceInts
+ testStr string
+ testStrNull *string
+ testInt int
+ testIntNull *int
+ testInt64 int64
+ testInt64Null *int64
+ testInt32 int32
+ testInt32Null *int32
+ testInt16 int16
+ testInt16Null *int16
+ testInt8 int8
+ testInt8Null *int8
+ testUint64 uint64
+ testUint64Null *uint64
+ testUint32 uint32
+ testUint32Null *uint32
+ testUint16 uint16
+ testUint16Null *uint16
+ testUint8 uint8
+ testUint8Null *uint8
+ testFloat64 float64
+ testFloat64Null *float64
+ testFloat32 float32
+ testFloat32Null *float32
+ testBool bool
+ testBoolNull *bool
+ testSubObject *testObject
+ testSubArray testSliceInts
}
// make sure it implements interfaces
@@ -46,36 +59,62 @@ func (t *testObject) UnmarshalJSONObject(dec *Decoder, k string) error {
switch k {
case "testStr":
return dec.AddString(&t.testStr)
+ case "testStrNull":
+ return dec.AddStringNull(&t.testStrNull)
case "testInt":
return dec.AddInt(&t.testInt)
+ case "testIntNull":
+ return dec.AddIntNull(&t.testIntNull)
case "testInt64":
return dec.AddInt64(&t.testInt64)
+ case "testInt64Null":
+ return dec.AddInt64Null(&t.testInt64Null)
case "testInt32":
return dec.AddInt32(&t.testInt32)
+ case "testInt32Null":
+ return dec.AddInt32Null(&t.testInt32Null)
case "testInt16":
return dec.AddInt16(&t.testInt16)
+ case "testInt16Null":
+ return dec.AddInt16Null(&t.testInt16Null)
case "testInt8":
return dec.AddInt8(&t.testInt8)
+ case "testInt8Null":
+ return dec.AddInt8Null(&t.testInt8Null)
case "testUint64":
return dec.AddUint64(&t.testUint64)
+ case "testUint64Null":
+ return dec.AddUint64Null(&t.testUint64Null)
case "testUint32":
return dec.AddUint32(&t.testUint32)
+ case "testUint32Null":
+ return dec.AddUint32Null(&t.testUint32Null)
case "testUint16":
return dec.AddUint16(&t.testUint16)
+ case "testUint16Null":
+ return dec.AddUint16Null(&t.testUint16Null)
case "testUint8":
return dec.AddUint8(&t.testUint8)
+ case "testUint8Null":
+ return dec.AddUint8Null(&t.testUint8Null)
case "testFloat64":
return dec.AddFloat(&t.testFloat64)
+ case "testFloat64Null":
+ return dec.AddFloatNull(&t.testFloat64Null)
case "testFloat32":
return dec.AddFloat32(&t.testFloat32)
+ case "testFloat32Null":
+ return dec.AddFloat32Null(&t.testFloat32Null)
case "testBool":
return dec.AddBool(&t.testBool)
+ case "testBoolNull":
+ return dec.AddBoolNull(&t.testBoolNull)
}
return nil
}
func (t *testObject) NKeys() int {
- return 13
+ return 28
}
type testObject0Keys struct {