commit 8a6a58d6ae768be5203aef1e639c27c4ddd3b943
parent 1f3d8b54c1fd186494c8f1fe59f24e1f26a9cf18
Author: francoispqt <francois@parquet.ninja>
Date: Sat, 25 Aug 2018 22:12:03 +0800
add null decoding for primitive types
Diffstat:
M | decode.go | | | 341 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_bool.go | | | 57 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_bool_test.go | | | 232 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_number_float.go | | | 90 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_number_float_test.go | | | 667 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
M | decode_number_int.go | | | 235 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_number_int_test.go | | | 2165 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------ |
M | decode_number_uint.go | | | 176 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | decode_number_uint_test.go | | | 695 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | decode_string.go | | | 43 | ++++++++++++++++++++++++++++++++++++++++++- |
M | decode_string_test.go | | | 316 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
11 files changed, 4621 insertions(+), 396 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
@@ -9,6 +9,15 @@ func (dec *Decoder) DecodeBool(v *bool) error {
}
return dec.decodeBool(v)
}
+
+// DecodeBoolNull is like DecodeBool but it takes a **bool
+// if the JSON is `true` or `false` and the pointer is nil, gojay assigns a new pointer to a bool
+func (dec *Decoder) DecodeBoolNull(v **bool) error {
+ if dec.isPooled == 1 {
+ panic(InvalidUsagePooledDecoderError("Invalid usage of pooled decoder"))
+ }
+ return dec.decodeBoolNull(v)
+}
func (dec *Decoder) decodeBool(v *bool) error {
for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
switch dec.data[dec.cursor] {
@@ -52,6 +61,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,238 @@ 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)
+ })
+ }
+}
+
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,627 @@ 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))
+ }
+ })
+ }
+}
+
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 +960,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 +1026,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-null-err",
@@ -412,6 +1034,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-negative-err",
@@ -419,12 +1042,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 +1057,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "basic-exponent-positive-positive-exp4",
@@ -440,7 +1066,7 @@ func TestDecoderFloat32(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp",
- json: "1e-2",
+ json: " 1e-2",
expectedResult: 0.01,
},
{
@@ -488,30 +1114,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 +1185,7 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: 0,
err: true,
errType: InvalidJSONError(""),
+ resultIsNil: true,
},
{
name: "error",
@@ -561,12 +1193,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 +1208,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,10 +1229,12 @@ 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),
)
}
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,23 @@ 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)
- 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 +637,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 +688,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 +703,7 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "basic-exponent-positive-positive-exp4",
- json: "8e+005 ",
+ json: "8e+005",
expectedResult: 800000,
},
{
@@ -781,7 +713,7 @@ func TestDecoderInt32(t *testing.T) {
},
{
name: "basic-exponent-positive-negative-exp2",
- json: "5E-6",
+ json: "5e-6",
expectedResult: 0,
},
{
@@ -790,6 +722,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 +744,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 +759,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 +778,1676 @@ 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: "exponent-err-too-big",
- json: "0e100000000000 ",
+ 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))
+ }
+ })
+ }
+}
+
+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))
+ }
+ })
+ }
+}
+
+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: "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 +2481,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 +2504,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 +2516,23 @@ 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)
- 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 +2543,8 @@ func TestDecoderInt16(t *testing.T) {
},
{
name: "basic-positive2",
- json: " 5321",
- expectedResult: 5321,
+ json: " 127",
+ expectedResult: 127,
},
{
name: "basic-negative",
@@ -1013,22 +2557,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 +2586,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 +2646,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 +2671,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 +2690,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 +2725,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 +2773,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 +2808,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 +2825,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 +2844,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 +2852,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 +2909,7 @@ func TestDecoderInt8(t *testing.T) {
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-negative-err",
@@ -1628,7 +3180,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,47 +3192,14 @@ 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)
- 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,447 @@ 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))
+ }
+ })
+ }
+}
+
+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))
+ }
+ })
+ }
+}
-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 +614,8 @@ func TestDecoderUint32(t *testing.T) {
},
{
name: "basic-positive2",
- json: " 1039405 ",
- expectedResult: 1039405,
+ json: " 3224 ",
+ expectedResult: 3224,
},
{
name: "basic-negative",
@@ -208,15 +643,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 +675,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 +734,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 +753,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 +761,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 +818,7 @@ func TestDecoderUint16(t *testing.T) {
name: "basic-null",
json: "null",
expectedResult: 0,
+ resultIsNil: true,
},
{
name: "basic-null-err",
@@ -462,7 +926,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,48 +938,16 @@ 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-json-error", func(t *testing.T) {
- var v uint16
- dec := NewDecoder(strings.NewReader(``))
- defer dec.Release()
- 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 TestDecoderUint8(t *testing.T) {
@@ -696,3 +1128,152 @@ 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))
+ }
+ })
+ }
+}
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,322 @@ 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))
+ }
+ })
+ }
+}
func TestDecoderStringInvalidType(t *testing.T) {
json := []byte(`1`)
var v string