diff --git a/decode_array.go b/decode_array.go index a6a7f21..b6cd6aa 100644 --- a/decode_array.go +++ b/decode_array.go @@ -7,14 +7,18 @@ type arrayDecoder struct { size uintptr valueDecoder decoder alen int + structName string + fieldName string } -func newArrayDecoder(dec decoder, elemType *rtype, alen int) *arrayDecoder { +func newArrayDecoder(dec decoder, elemType *rtype, alen int, structName, fieldName string) *arrayDecoder { return &arrayDecoder{ valueDecoder: dec, elemType: elemType, size: elemType.Size(), alen: alen, + structName: structName, + fieldName: fieldName, } } diff --git a/decode_bool.go b/decode_bool.go index e50c41a..a733e43 100644 --- a/decode_bool.go +++ b/decode_bool.go @@ -4,10 +4,13 @@ import ( "unsafe" ) -type boolDecoder struct{} +type boolDecoder struct { + structName string + fieldName string +} -func newBoolDecoder() *boolDecoder { - return &boolDecoder{} +func newBoolDecoder(structName, fieldName string) *boolDecoder { + return &boolDecoder{structName: structName, fieldName: fieldName} } func trueBytes(s *stream) error { diff --git a/decode_bytes.go b/decode_bytes.go index 7a2f89d..4a9e612 100644 --- a/decode_bytes.go +++ b/decode_bytes.go @@ -5,10 +5,13 @@ import ( "unsafe" ) -type bytesDecoder struct{} +type bytesDecoder struct { + structName string + fieldName string +} -func newBytesDecoder() *bytesDecoder { - return &bytesDecoder{} +func newBytesDecoder(structName string, fieldName string) *bytesDecoder { + return &bytesDecoder{structName: structName, fieldName: fieldName} } func (d *bytesDecoder) decodeStream(s *stream, p unsafe.Pointer) error { diff --git a/decode_compile.go b/decode_compile.go index 15f0bee..be51732 100644 --- a/decode_compile.go +++ b/decode_compile.go @@ -17,10 +17,10 @@ func (d *Decoder) compileHead(typ *rtype) (decoder, error) { case rtype_ptrTo(typ).Implements(unmarshalTextType): return newUnmarshalTextDecoder(rtype_ptrTo(typ)), nil } - return d.compile(typ.Elem()) + return d.compile(typ.Elem(), "", "") } -func (d *Decoder) compile(typ *rtype) (decoder, error) { +func (d *Decoder) compile(typ *rtype, structName, fieldName string) (decoder, error) { switch { case typ.Implements(unmarshalJSONType): return newUnmarshalJSONDecoder(typ), nil @@ -34,202 +34,203 @@ func (d *Decoder) compile(typ *rtype) (decoder, error) { switch typ.Kind() { case reflect.Ptr: - return d.compilePtr(typ) + return d.compilePtr(typ, structName, fieldName) case reflect.Struct: - return d.compileStruct(typ) + return d.compileStruct(typ, structName, fieldName) case reflect.Slice: elem := typ.Elem() if elem.Kind() == reflect.Uint8 { - return d.compileBytes() + return d.compileBytes(structName, fieldName) } - return d.compileSlice(typ) + return d.compileSlice(typ, structName, fieldName) case reflect.Array: - return d.compileArray(typ) + return d.compileArray(typ, structName, fieldName) case reflect.Map: - return d.compileMap(typ) + return d.compileMap(typ, structName, fieldName) case reflect.Interface: - return d.compileInterface(typ) + return d.compileInterface(typ, structName, fieldName) case reflect.Uintptr: - return d.compileUint() + return d.compileUint(structName, fieldName) case reflect.Int: - return d.compileInt() + return d.compileInt(structName, fieldName) case reflect.Int8: - return d.compileInt8() + return d.compileInt8(structName, fieldName) case reflect.Int16: - return d.compileInt16() + return d.compileInt16(structName, fieldName) case reflect.Int32: - return d.compileInt32() + return d.compileInt32(structName, fieldName) case reflect.Int64: - return d.compileInt64() + return d.compileInt64(structName, fieldName) case reflect.Uint: - return d.compileUint() + return d.compileUint(structName, fieldName) case reflect.Uint8: - return d.compileUint8() + return d.compileUint8(structName, fieldName) case reflect.Uint16: - return d.compileUint16() + return d.compileUint16(structName, fieldName) case reflect.Uint32: - return d.compileUint32() + return d.compileUint32(structName, fieldName) case reflect.Uint64: - return d.compileUint64() + return d.compileUint64(structName, fieldName) case reflect.String: - return d.compileString() + return d.compileString(structName, fieldName) case reflect.Bool: - return d.compileBool() + return d.compileBool(structName, fieldName) case reflect.Float32: - return d.compileFloat32() + return d.compileFloat32(structName, fieldName) case reflect.Float64: - return d.compileFloat64() + return d.compileFloat64(structName, fieldName) } return nil, &UnsupportedTypeError{Type: rtype2type(typ)} } -func (d *Decoder) compilePtr(typ *rtype) (decoder, error) { - dec, err := d.compile(typ.Elem()) +func (d *Decoder) compilePtr(typ *rtype, structName, fieldName string) (decoder, error) { + dec, err := d.compile(typ.Elem(), structName, fieldName) if err != nil { return nil, err } - return newPtrDecoder(dec, typ.Elem()), nil + return newPtrDecoder(dec, typ.Elem(), structName, fieldName), nil } -func (d *Decoder) compileInt() (decoder, error) { - return newIntDecoder(func(p unsafe.Pointer, v int64) { +func (d *Decoder) compileInt(structName, fieldName string) (decoder, error) { + return newIntDecoder(structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int)(p) = int(v) }), nil } -func (d *Decoder) compileInt8() (decoder, error) { - return newIntDecoder(func(p unsafe.Pointer, v int64) { +func (d *Decoder) compileInt8(structName, fieldName string) (decoder, error) { + return newIntDecoder(structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int8)(p) = int8(v) }), nil } -func (d *Decoder) compileInt16() (decoder, error) { - return newIntDecoder(func(p unsafe.Pointer, v int64) { +func (d *Decoder) compileInt16(structName, fieldName string) (decoder, error) { + return newIntDecoder(structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int16)(p) = int16(v) }), nil } -func (d *Decoder) compileInt32() (decoder, error) { - return newIntDecoder(func(p unsafe.Pointer, v int64) { +func (d *Decoder) compileInt32(structName, fieldName string) (decoder, error) { + return newIntDecoder(structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int32)(p) = int32(v) }), nil } -func (d *Decoder) compileInt64() (decoder, error) { - return newIntDecoder(func(p unsafe.Pointer, v int64) { +func (d *Decoder) compileInt64(structName, fieldName string) (decoder, error) { + return newIntDecoder(structName, fieldName, func(p unsafe.Pointer, v int64) { *(*int64)(p) = v }), nil } -func (d *Decoder) compileUint() (decoder, error) { - return newUintDecoder(func(p unsafe.Pointer, v uint64) { +func (d *Decoder) compileUint(structName, fieldName string) (decoder, error) { + return newUintDecoder(structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint)(p) = uint(v) }), nil } -func (d *Decoder) compileUint8() (decoder, error) { - return newUintDecoder(func(p unsafe.Pointer, v uint64) { +func (d *Decoder) compileUint8(structName, fieldName string) (decoder, error) { + return newUintDecoder(structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint8)(p) = uint8(v) }), nil } -func (d *Decoder) compileUint16() (decoder, error) { - return newUintDecoder(func(p unsafe.Pointer, v uint64) { +func (d *Decoder) compileUint16(structName, fieldName string) (decoder, error) { + return newUintDecoder(structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint16)(p) = uint16(v) }), nil } -func (d *Decoder) compileUint32() (decoder, error) { - return newUintDecoder(func(p unsafe.Pointer, v uint64) { +func (d *Decoder) compileUint32(structName, fieldName string) (decoder, error) { + return newUintDecoder(structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint32)(p) = uint32(v) }), nil } -func (d *Decoder) compileUint64() (decoder, error) { - return newUintDecoder(func(p unsafe.Pointer, v uint64) { +func (d *Decoder) compileUint64(structName, fieldName string) (decoder, error) { + return newUintDecoder(structName, fieldName, func(p unsafe.Pointer, v uint64) { *(*uint64)(p) = v }), nil } -func (d *Decoder) compileFloat32() (decoder, error) { - return newFloatDecoder(func(p unsafe.Pointer, v float64) { +func (d *Decoder) compileFloat32(structName, fieldName string) (decoder, error) { + return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*float32)(p) = float32(v) }), nil } -func (d *Decoder) compileFloat64() (decoder, error) { - return newFloatDecoder(func(p unsafe.Pointer, v float64) { +func (d *Decoder) compileFloat64(structName, fieldName string) (decoder, error) { + return newFloatDecoder(structName, fieldName, func(p unsafe.Pointer, v float64) { *(*float64)(p) = v }), nil } -func (d *Decoder) compileString() (decoder, error) { - return newStringDecoder(), nil +func (d *Decoder) compileString(structName, fieldName string) (decoder, error) { + return newStringDecoder(structName, fieldName), nil } -func (d *Decoder) compileBool() (decoder, error) { - return newBoolDecoder(), nil +func (d *Decoder) compileBool(structName, fieldName string) (decoder, error) { + return newBoolDecoder(structName, fieldName), nil } -func (d *Decoder) compileBytes() (decoder, error) { - return newBytesDecoder(), nil +func (d *Decoder) compileBytes(structName, fieldName string) (decoder, error) { + return newBytesDecoder(structName, fieldName), nil } -func (d *Decoder) compileSlice(typ *rtype) (decoder, error) { +func (d *Decoder) compileSlice(typ *rtype, structName, fieldName string) (decoder, error) { elem := typ.Elem() - decoder, err := d.compile(elem) + decoder, err := d.compile(elem, structName, fieldName) if err != nil { return nil, err } - return newSliceDecoder(decoder, elem, elem.Size()), nil + return newSliceDecoder(decoder, elem, elem.Size(), structName, fieldName), nil } -func (d *Decoder) compileArray(typ *rtype) (decoder, error) { +func (d *Decoder) compileArray(typ *rtype, structName, fieldName string) (decoder, error) { elem := typ.Elem() - decoder, err := d.compile(elem) + decoder, err := d.compile(elem, structName, fieldName) if err != nil { return nil, err } - return newArrayDecoder(decoder, elem, typ.Len()), nil + return newArrayDecoder(decoder, elem, typ.Len(), structName, fieldName), nil } -func (d *Decoder) compileMap(typ *rtype) (decoder, error) { - keyDec, err := d.compile(typ.Key()) +func (d *Decoder) compileMap(typ *rtype, structName, fieldName string) (decoder, error) { + keyDec, err := d.compile(typ.Key(), structName, fieldName) if err != nil { return nil, err } - valueDec, err := d.compile(typ.Elem()) + valueDec, err := d.compile(typ.Elem(), structName, fieldName) if err != nil { return nil, err } - return newMapDecoder(typ, keyDec, valueDec), nil + return newMapDecoder(typ, keyDec, valueDec, structName, fieldName), nil } -func (d *Decoder) compileInterface(typ *rtype) (decoder, error) { - return newInterfaceDecoder(typ), nil +func (d *Decoder) compileInterface(typ *rtype, structName, fieldName string) (decoder, error) { + return newInterfaceDecoder(typ, structName, fieldName), nil } -func (d *Decoder) compileStruct(typ *rtype) (decoder, error) { +func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decoder, error) { fieldNum := typ.NumField() fieldMap := map[string]*structFieldSet{} typeptr := uintptr(unsafe.Pointer(typ)) if dec, exists := d.structTypeToDecoder[typeptr]; exists { return dec, nil } - structDec := newStructDecoder(fieldMap) + structDec := newStructDecoder(structName, fieldName, fieldMap) d.structTypeToDecoder[typeptr] = structDec + structName = typ.Name() for i := 0; i < fieldNum; i++ { field := typ.Field(i) if isIgnoredStructField(field) { continue } tag := structTagFromField(field) - dec, err := d.compile(type2rtype(field.Type)) + dec, err := d.compile(type2rtype(field.Type), structName, field.Name) if err != nil { return nil, err } if tag.isString { - dec = newWrappedStringDecoder(dec) + dec = newWrappedStringDecoder(dec, structName, field.Name) } fieldSet := &structFieldSet{dec: dec, offset: field.Offset} fieldMap[field.Name] = fieldSet diff --git a/decode_float.go b/decode_float.go index 09a15e4..61a8618 100644 --- a/decode_float.go +++ b/decode_float.go @@ -6,11 +6,13 @@ import ( ) type floatDecoder struct { - op func(unsafe.Pointer, float64) + op func(unsafe.Pointer, float64) + structName string + fieldName string } -func newFloatDecoder(op func(unsafe.Pointer, float64)) *floatDecoder { - return &floatDecoder{op: op} +func newFloatDecoder(structName, fieldName string, op func(unsafe.Pointer, float64)) *floatDecoder { + return &floatDecoder{op: op, structName: structName, fieldName: fieldName} } var ( diff --git a/decode_int.go b/decode_int.go index 02ee626..e75befd 100644 --- a/decode_int.go +++ b/decode_int.go @@ -3,11 +3,13 @@ package json import "unsafe" type intDecoder struct { - op func(unsafe.Pointer, int64) + op func(unsafe.Pointer, int64) + structName string + fieldName string } -func newIntDecoder(op func(unsafe.Pointer, int64)) *intDecoder { - return &intDecoder{op: op} +func newIntDecoder(structName, fieldName string, op func(unsafe.Pointer, int64)) *intDecoder { + return &intDecoder{op: op, structName: structName, fieldName: fieldName} } var ( diff --git a/decode_interface.go b/decode_interface.go index d9fbad7..b60c7c8 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -6,22 +6,26 @@ import ( ) type interfaceDecoder struct { - typ *rtype + typ *rtype + structName string + fieldName string } -func newInterfaceDecoder(typ *rtype) *interfaceDecoder { +func newInterfaceDecoder(typ *rtype, structName, fieldName string) *interfaceDecoder { return &interfaceDecoder{ - typ: typ, + typ: typ, + structName: structName, + fieldName: fieldName, } } func (d *interfaceDecoder) numDecoder(s *stream) decoder { if s.useNumber { - return newNumberDecoder(func(p unsafe.Pointer, v Number) { + return newNumberDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v Number) { *(*interface{})(p) = v }) } - return newFloatDecoder(func(p unsafe.Pointer, v float64) { + return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { *(*interface{})(p) = v }) } @@ -41,8 +45,10 @@ func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error { ptr := unsafe.Pointer(&v) if err := newMapDecoder( interfaceMapType, - newStringDecoder(), - newInterfaceDecoder(d.typ), + newStringDecoder(d.structName, d.fieldName), + newInterfaceDecoder(d.typ, d.structName, d.fieldName), + d.structName, + d.fieldName, ).decodeStream(s, ptr); err != nil { return err } @@ -52,9 +58,11 @@ func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error { var v []interface{} ptr := unsafe.Pointer(&v) if err := newSliceDecoder( - newInterfaceDecoder(d.typ), + newInterfaceDecoder(d.typ, d.structName, d.fieldName), d.typ, d.typ.Size(), + d.structName, + d.fieldName, ).decodeStream(s, ptr); err != nil { return err } @@ -121,8 +129,9 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (i ptr := unsafe.Pointer(&v) dec := newMapDecoder( interfaceMapType, - newStringDecoder(), - newInterfaceDecoder(d.typ), + newStringDecoder(d.structName, d.fieldName), + newInterfaceDecoder(d.typ, d.structName, d.fieldName), + d.structName, d.fieldName, ) cursor, err := dec.decode(buf, cursor, ptr) if err != nil { @@ -134,9 +143,10 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (i var v []interface{} ptr := unsafe.Pointer(&v) dec := newSliceDecoder( - newInterfaceDecoder(d.typ), + newInterfaceDecoder(d.typ, d.structName, d.fieldName), d.typ, d.typ.Size(), + d.structName, d.fieldName, ) cursor, err := dec.decode(buf, cursor, ptr) if err != nil { @@ -145,7 +155,7 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (i **(**interface{})(unsafe.Pointer(&p)) = v return cursor, nil case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': - return newFloatDecoder(func(p unsafe.Pointer, v float64) { + return newFloatDecoder(d.structName, d.fieldName, func(p unsafe.Pointer, v float64) { *(*interface{})(p) = v }).decode(buf, cursor, p) case '"': diff --git a/decode_map.go b/decode_map.go index 097805b..d921ab4 100644 --- a/decode_map.go +++ b/decode_map.go @@ -8,13 +8,17 @@ type mapDecoder struct { mapType *rtype keyDecoder decoder valueDecoder decoder + structName string + fieldName string } -func newMapDecoder(mapType *rtype, keyDec decoder, valueDec decoder) *mapDecoder { +func newMapDecoder(mapType *rtype, keyDec decoder, valueDec decoder, structName, fieldName string) *mapDecoder { return &mapDecoder{ mapType: mapType, keyDecoder: keyDec, valueDecoder: valueDec, + structName: structName, + fieldName: fieldName, } } diff --git a/decode_number.go b/decode_number.go index af94024..6f4f166 100644 --- a/decode_number.go +++ b/decode_number.go @@ -6,13 +6,17 @@ import ( type numberDecoder struct { *floatDecoder - op func(unsafe.Pointer, Number) + op func(unsafe.Pointer, Number) + structName string + fieldName string } -func newNumberDecoder(op func(unsafe.Pointer, Number)) *numberDecoder { +func newNumberDecoder(structName, fieldName string, op func(unsafe.Pointer, Number)) *numberDecoder { return &numberDecoder{ - floatDecoder: newFloatDecoder(nil), + floatDecoder: newFloatDecoder(structName, fieldName, nil), op: op, + structName: structName, + fieldName: fieldName, } } diff --git a/decode_ptr.go b/decode_ptr.go index 7773faa..bc575f6 100644 --- a/decode_ptr.go +++ b/decode_ptr.go @@ -5,12 +5,19 @@ import ( ) type ptrDecoder struct { - dec decoder - typ *rtype + dec decoder + typ *rtype + structName string + fieldName string } -func newPtrDecoder(dec decoder, typ *rtype) *ptrDecoder { - return &ptrDecoder{dec: dec, typ: typ} +func newPtrDecoder(dec decoder, typ *rtype, structName, fieldName string) *ptrDecoder { + return &ptrDecoder{ + dec: dec, + typ: typ, + structName: structName, + fieldName: fieldName, + } } //go:linkname unsafe_New reflect.unsafe_New diff --git a/decode_slice.go b/decode_slice.go index 4c211a1..0e59f0f 100644 --- a/decode_slice.go +++ b/decode_slice.go @@ -10,6 +10,8 @@ type sliceDecoder struct { valueDecoder decoder size uintptr arrayPool sync.Pool + structName string + fieldName string } // If use reflect.SliceHeader, data type is uintptr. @@ -21,7 +23,7 @@ type sliceHeader struct { cap int } -func newSliceDecoder(dec decoder, elemType *rtype, size uintptr) *sliceDecoder { +func newSliceDecoder(dec decoder, elemType *rtype, size uintptr, structName, fieldName string) *sliceDecoder { return &sliceDecoder{ valueDecoder: dec, elemType: elemType, @@ -36,6 +38,8 @@ func newSliceDecoder(dec decoder, elemType *rtype, size uintptr) *sliceDecoder { } }, }, + structName: structName, + fieldName: fieldName, } } diff --git a/decode_string.go b/decode_string.go index 662ef64..82b301a 100644 --- a/decode_string.go +++ b/decode_string.go @@ -1,16 +1,32 @@ package json import ( + "reflect" "unicode" "unicode/utf16" "unsafe" ) type stringDecoder struct { + structName string + fieldName string } -func newStringDecoder() *stringDecoder { - return &stringDecoder{} +func newStringDecoder(structName, fieldName string) *stringDecoder { + return &stringDecoder{ + structName: structName, + fieldName: fieldName, + } +} + +func (d *stringDecoder) errUnmarshalType(typeName string, offset int64) *UnmarshalTypeError { + return &UnmarshalTypeError{ + Value: typeName, + Type: reflect.TypeOf(""), + Offset: offset, + Struct: d.structName, + Field: d.fieldName, + } } func (d *stringDecoder) decodeStream(s *stream, p unsafe.Pointer) error { @@ -186,6 +202,10 @@ func (d *stringDecoder) decodeStreamByte(s *stream) ([]byte, error) { case ' ', '\n', '\t', '\r': s.cursor++ continue + case '[': + return nil, d.errUnmarshalType("array", s.totalOffset()) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return nil, d.errUnmarshalType("number", s.totalOffset()) case '"': return stringBytes(s) case 'n': @@ -208,6 +228,10 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err switch buf[cursor] { case ' ', '\n', '\t', '\r': cursor++ + case '[': + return nil, 0, d.errUnmarshalType("array", cursor) + case '-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9': + return nil, 0, d.errUnmarshalType("number", cursor) case '"': cursor++ start := cursor diff --git a/decode_struct.go b/decode_struct.go index f839cce..34854c1 100644 --- a/decode_struct.go +++ b/decode_struct.go @@ -13,12 +13,16 @@ type structFieldSet struct { type structDecoder struct { fieldMap map[string]*structFieldSet keyDecoder *stringDecoder + structName string + fieldName string } -func newStructDecoder(fieldMap map[string]*structFieldSet) *structDecoder { +func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder { return &structDecoder{ fieldMap: fieldMap, - keyDecoder: newStringDecoder(), + keyDecoder: newStringDecoder(structName, fieldName), + structName: structName, + fieldName: fieldName, } } diff --git a/decode_uint.go b/decode_uint.go index 903561e..1fd851b 100644 --- a/decode_uint.go +++ b/decode_uint.go @@ -3,11 +3,13 @@ package json import "unsafe" type uintDecoder struct { - op func(unsafe.Pointer, uint64) + op func(unsafe.Pointer, uint64) + structName string + fieldName string } -func newUintDecoder(op func(unsafe.Pointer, uint64)) *uintDecoder { - return &uintDecoder{op: op} +func newUintDecoder(structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { + return &uintDecoder{op: op, structName: structName, fieldName: fieldName} } var pow10u64 = [...]uint64{ diff --git a/decode_wrapped_string.go b/decode_wrapped_string.go index b49a2ec..94b5956 100644 --- a/decode_wrapped_string.go +++ b/decode_wrapped_string.go @@ -5,12 +5,16 @@ import "unsafe" type wrappedStringDecoder struct { dec decoder stringDecoder *stringDecoder + structName string + fieldName string } -func newWrappedStringDecoder(dec decoder) *wrappedStringDecoder { +func newWrappedStringDecoder(dec decoder, structName, fieldName string) *wrappedStringDecoder { return &wrappedStringDecoder{ dec: dec, - stringDecoder: newStringDecoder(), + stringDecoder: newStringDecoder(structName, fieldName), + structName: structName, + fieldName: fieldName, } }