mirror of https://github.com/goccy/go-json.git
Refactor Unmarshal/UnmarshalNoEscape
This commit is contained in:
parent
3b7d5a6996
commit
3f90e88a94
89
decode.go
89
decode.go
|
@ -20,8 +20,7 @@ type decoder interface {
|
|||
}
|
||||
|
||||
type Decoder struct {
|
||||
s *stream
|
||||
structTypeToDecoder map[uintptr]decoder
|
||||
s *stream
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -33,6 +32,51 @@ const (
|
|||
nul = '\000'
|
||||
)
|
||||
|
||||
func unmarshal(data []byte, v interface{}) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
header.typ.escape()
|
||||
return decode(src, header)
|
||||
}
|
||||
|
||||
func unmarshalNoEscape(data []byte, v interface{}) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to the end
|
||||
copy(src, data)
|
||||
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
return decode(src, header)
|
||||
}
|
||||
|
||||
func decode(src []byte, header *interfaceHeader) error {
|
||||
typ := header.typ
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
|
||||
// noescape trick for header.typ ( *reflect.rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
ptr := uintptr(header.ptr)
|
||||
|
||||
if err := validateType(copiedType, ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(typeptr, typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := dec.decode(src, 0, header.ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateType(typ *rtype, p uintptr) error {
|
||||
if typ.Kind() != reflect.Ptr || p == 0 {
|
||||
return &InvalidUnmarshalError{Type: rtype2type(typ)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from r.
|
||||
//
|
||||
// The decoder introduces its own buffering and may
|
||||
|
@ -50,45 +94,6 @@ func (d *Decoder) Buffered() io.Reader {
|
|||
return d.s.buffered()
|
||||
}
|
||||
|
||||
func (d *Decoder) validateType(typ *rtype, p uintptr) error {
|
||||
if typ.Kind() != reflect.Ptr || p == 0 {
|
||||
return &InvalidUnmarshalError{Type: rtype2type(typ)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decode(src []byte, header *interfaceHeader) error {
|
||||
typ := header.typ
|
||||
typeptr := uintptr(unsafe.Pointer(typ))
|
||||
|
||||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
ptr := uintptr(header.ptr)
|
||||
|
||||
if err := d.validateType(copiedType, ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
dec, err := decodeCompileToGetDecoder(typeptr, typ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := dec.decode(src, 0, header.ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeForUnmarshal(src []byte, v interface{}) error {
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
header.typ.escape()
|
||||
return d.decode(src, header)
|
||||
}
|
||||
|
||||
func (d *Decoder) decodeForUnmarshalNoEscape(src []byte, v interface{}) error {
|
||||
header := (*interfaceHeader)(unsafe.Pointer(&v))
|
||||
return d.decode(src, header)
|
||||
}
|
||||
|
||||
func (d *Decoder) prepareForDecode() error {
|
||||
s := d.s
|
||||
for {
|
||||
|
@ -123,7 +128,7 @@ func (d *Decoder) Decode(v interface{}) error {
|
|||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**rtype)(unsafe.Pointer(&typeptr))
|
||||
|
||||
if err := d.validateType(copiedType, ptr); err != nil {
|
||||
if err := validateType(copiedType, ptr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
10
json.go
10
json.go
|
@ -262,17 +262,11 @@ func MarshalIndentWithOption(v interface{}, prefix, indent string, optFuncs ...E
|
|||
// character U+FFFD.
|
||||
//
|
||||
func Unmarshal(data []byte, v interface{}) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to end
|
||||
copy(src, data)
|
||||
var dec Decoder
|
||||
return dec.decodeForUnmarshal(src, v)
|
||||
return unmarshal(data, v)
|
||||
}
|
||||
|
||||
func UnmarshalNoEscape(data []byte, v interface{}) error {
|
||||
src := make([]byte, len(data)+1) // append nul byte to end
|
||||
copy(src, data)
|
||||
var dec Decoder
|
||||
return dec.decodeForUnmarshalNoEscape(src, v)
|
||||
return unmarshalNoEscape(data, v)
|
||||
}
|
||||
|
||||
// A Token holds a value of one of these types:
|
||||
|
|
Loading…
Reference in New Issue