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 { if node.IsNull() { *(*interface{})(vp) = interface{}(nil) return nil } eface := *(*rt.GoEface)(vp) // not pointer type, or nil pointer, or *interface{} if eface.Value == nil || eface.Type.Kind() != reflect.Ptr || rt.PtrElem(eface.Type) == anyType { ret, err := node.AsEface(ctx) if err != nil { return err } *(*interface{})(vp) = ret return nil } etp := rt.PtrElem(eface.Type) vp = eface.Value /* check the defined pointer type for issue 379 */ if eface.Type.IsNamed() { newp := vp etp = eface.Type vp = unsafe.Pointer(&newp) } 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 // not pointer type, or nil pointer, or *interface{} if vp == nil || vt.Kind() != reflect.Ptr || rt.PtrElem(vt) == anyType { ret, err := node.AsEface(ctx) if err != nil { return err } *(*interface{})(vp) = ret return nil } 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) }