go-json/decode_unmarshal_json.go

94 lines
2.1 KiB
Go
Raw Normal View History

2020-05-08 14:22:57 +03:00
package json
import (
"unsafe"
)
type unmarshalJSONDecoder struct {
2020-11-21 20:47:18 +03:00
typ *rtype
isDoublePointer bool
structName string
fieldName string
2020-05-08 14:22:57 +03:00
}
func newUnmarshalJSONDecoder(typ *rtype, structName, fieldName string) *unmarshalJSONDecoder {
return &unmarshalJSONDecoder{
typ: typ,
structName: structName,
fieldName: fieldName,
}
}
2020-11-27 11:11:53 +03:00
func (d *unmarshalJSONDecoder) annotateError(cursor int64, err error) {
switch e := err.(type) {
case *UnmarshalTypeError:
e.Struct = d.structName
e.Field = d.fieldName
case *SyntaxError:
e.Offset = cursor
}
2020-05-08 14:22:57 +03:00
}
2020-11-19 06:47:42 +03:00
func (d *unmarshalJSONDecoder) decodeStream(s *stream, p unsafe.Pointer) error {
2020-07-30 16:41:53 +03:00
s.skipWhiteSpace()
start := s.cursor
if err := s.skipValue(); err != nil {
return err
}
src := s.buf[start:s.cursor]
2020-11-21 20:47:18 +03:00
if d.isDoublePointer {
newptr := unsafe_New(d.typ.Elem())
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: d.typ,
ptr: newptr,
}))
if err := v.(Unmarshaler).UnmarshalJSON(src); err != nil {
2020-11-27 11:11:53 +03:00
d.annotateError(s.cursor, err)
2020-11-21 20:47:18 +03:00
return err
}
*(*unsafe.Pointer)(p) = newptr
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: d.typ,
ptr: p,
}))
if err := v.(Unmarshaler).UnmarshalJSON(src); err != nil {
2020-11-27 11:11:53 +03:00
d.annotateError(s.cursor, err)
2020-11-21 20:47:18 +03:00
return err
}
2020-07-30 16:41:53 +03:00
}
return nil
}
2020-11-19 06:47:42 +03:00
func (d *unmarshalJSONDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (int64, error) {
2020-05-08 14:22:57 +03:00
cursor = skipWhiteSpace(buf, cursor)
start := cursor
end, err := skipValue(buf, cursor)
if err != nil {
return 0, err
}
src := buf[start:end]
2020-11-21 20:47:18 +03:00
if d.isDoublePointer {
newptr := unsafe_New(d.typ.Elem())
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: d.typ,
ptr: newptr,
}))
if err := v.(Unmarshaler).UnmarshalJSON(src); err != nil {
2020-11-27 11:11:53 +03:00
d.annotateError(cursor, err)
2020-11-21 20:47:18 +03:00
return 0, err
}
*(*unsafe.Pointer)(p) = newptr
} else {
v := *(*interface{})(unsafe.Pointer(&interfaceHeader{
typ: d.typ,
ptr: p,
}))
if err := v.(Unmarshaler).UnmarshalJSON(src); err != nil {
2020-11-27 11:11:53 +03:00
d.annotateError(cursor, err)
2020-11-21 20:47:18 +03:00
return 0, err
}
2020-05-08 14:22:57 +03:00
}
return end, nil
}