123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package optdec
- import (
- "encoding"
- "encoding/json"
- "unsafe"
- "reflect"
- "github.com/bytedance/sonic/internal/rt"
- )
- type efaceDecoder struct {
- }
- func (d *efaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
- /* check the defined pointer type for issue 379 */
- eface := (*rt.GoEface)(vp)
- /*
- not pointer type, or nil pointer, or self-pointed interface{}, such as
- ```go
- var v interface{}
- v = &v
- return v
- ``` see `issue758_test.go`.
- */
- if eface.Value == nil || eface.Type.Kind() != reflect.Ptr || eface.Value == vp {
- ret, err := node.AsEface(ctx)
- if err != nil {
- return err
- }
- *(*interface{})(vp) = ret
- return nil
- }
- if node.IsNull() {
- if eface.Type.Indirect() || (!eface.Type.Indirect() && eface.Type.Pack().Elem().Kind() != reflect.Ptr) {
- *(*interface{})(vp) = nil
- return nil
- }
- }
- etp := rt.PtrElem(eface.Type)
- vp = eface.Value
- if eface.Type.IsNamed() {
- // check named pointer type, avoid call its `Unmarshaler`
- newp := vp
- etp = eface.Type
- vp = unsafe.Pointer(&newp)
- } else if !eface.Type.Indirect() {
- // check direct value
- etp = rt.UnpackType(eface.Type.Pack().Elem())
- }
- dec, err := findOrCompile(etp)
- if err != nil {
- return err
- }
- return dec.FromDom(vp, node, ctx)
- }
- type ifaceDecoder struct {
- typ *rt.GoType
- }
- func (d *ifaceDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
- if node.IsNull() {
- *(*unsafe.Pointer)(vp) = nil
- return nil
- }
- iface := *(*rt.GoIface)(vp)
- if iface.Itab == nil {
- return error_type(d.typ)
- }
- vt := iface.Itab.Vt
- if vt.Kind() != reflect.Ptr || iface.Value == nil {
- return error_type(d.typ)
- }
- etp := rt.PtrElem(vt)
- vp = iface.Value
- /* check the defined pointer type for issue 379 */
- if vt.IsNamed() {
- newp := vp
- etp = vt
- vp = unsafe.Pointer(&newp)
- }
- dec, err := findOrCompile(etp)
- if err != nil {
- return err
- }
- return dec.FromDom(vp, node, ctx)
- }
- type unmarshalTextDecoder struct {
- typ *rt.GoType
- }
- func (d *unmarshalTextDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
- if node.IsNull() {
- *(*unsafe.Pointer)(vp) = nil
- return nil
- }
- txt, ok := node.AsStringText(ctx)
- if !ok {
- return error_mismatch(node, ctx, d.typ.Pack())
- }
- v := *(*interface{})(unsafe.Pointer(&rt.GoEface{
- Type: d.typ,
- Value: vp,
- }))
- // fast path
- if u, ok := v.(encoding.TextUnmarshaler); ok {
- return u.UnmarshalText(txt)
- }
- // slow path
- rv := reflect.ValueOf(v)
- if u, ok := rv.Interface().(encoding.TextUnmarshaler); ok {
- return u.UnmarshalText(txt)
- }
- return error_type(d.typ)
- }
- type unmarshalJSONDecoder struct {
- typ *rt.GoType
- strOpt bool
- }
- func (d *unmarshalJSONDecoder) FromDom(vp unsafe.Pointer, node Node, ctx *context) error {
- v := *(*interface{})(unsafe.Pointer(&rt.GoEface{
- Type: d.typ,
- Value: vp,
- }))
- var input []byte
- if d.strOpt && node.IsNull() {
- input = []byte("null")
- } else if d.strOpt {
- s, ok := node.AsStringText(ctx)
- if !ok {
- return error_mismatch(node, ctx, d.typ.Pack())
- }
- input = s
- } else {
- input = []byte(node.AsRaw(ctx))
- }
- // fast path
- if u, ok := v.(json.Unmarshaler); ok {
- return u.UnmarshalJSON((input))
- }
- // slow path
- rv := reflect.ValueOf(v)
- if u, ok := rv.Interface().(json.Unmarshaler); ok {
- return u.UnmarshalJSON(input)
- }
- return error_type(d.typ)
- }
|