forked from mirror/go-json
Merge pull request #284 from goccy/feature/fix-281
Fix encoding of not empty interface type
This commit is contained in:
commit
e152fc2225
|
@ -2108,3 +2108,29 @@ func TestEmbeddedNotFirstField(t *testing.T) {
|
||||||
t.Fatalf("failed to encode embedded structure. expected = %q but got %q", expected, got)
|
t.Fatalf("failed to encode embedded structure. expected = %q but got %q", expected, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type implementedMethodIface interface {
|
||||||
|
M()
|
||||||
|
}
|
||||||
|
|
||||||
|
type implementedIfaceType struct {
|
||||||
|
A int
|
||||||
|
B string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (implementedIfaceType) M() {}
|
||||||
|
|
||||||
|
func TestImplementedMethodInterfaceType(t *testing.T) {
|
||||||
|
data := []implementedIfaceType{implementedIfaceType{}}
|
||||||
|
expected, err := stdjson.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
got, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !bytes.Equal(expected, got) {
|
||||||
|
t.Fatalf("failed to encode implemented method interface type. expected:[%q] but got:[%q]", expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
|
@ -185,16 +186,28 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
||||||
iface := (*emptyInterface)(ptrToUnsafePtr(p))
|
var (
|
||||||
if iface.ptr == nil {
|
typ *runtime.Type
|
||||||
|
ifacePtr unsafe.Pointer
|
||||||
|
)
|
||||||
|
up := ptrToUnsafePtr(p)
|
||||||
|
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
|
||||||
|
iface := (*nonEmptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.itab.typ
|
||||||
|
} else {
|
||||||
|
iface := (*emptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.typ
|
||||||
|
}
|
||||||
|
if ifacePtr == nil {
|
||||||
b = appendNull(ctx, b)
|
b = appendNull(ctx, b)
|
||||||
b = appendComma(ctx, b)
|
b = appendComma(ctx, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(typ)))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
||||||
|
|
||||||
end := ifaceCodeSet.EndCode
|
end := ifaceCodeSet.EndCode
|
||||||
store(ctxptr, c.Idx, uintptr(iface.ptr))
|
store(ctxptr, c.Idx, uintptr(ifacePtr))
|
||||||
store(ctxptr, end.Idx, oldOffset)
|
store(ctxptr, end.Idx, oldOffset)
|
||||||
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
||||||
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
||||||
|
|
|
@ -13,15 +13,16 @@ const uintptrSize = 4 << (^uintptr(0) >> 63)
|
||||||
type OpFlags uint16
|
type OpFlags uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
AnonymousHeadFlags OpFlags = 1 << 0
|
AnonymousHeadFlags OpFlags = 1 << 0
|
||||||
AnonymousKeyFlags OpFlags = 1 << 1
|
AnonymousKeyFlags OpFlags = 1 << 1
|
||||||
IndirectFlags OpFlags = 1 << 2
|
IndirectFlags OpFlags = 1 << 2
|
||||||
IsTaggedKeyFlags OpFlags = 1 << 3
|
IsTaggedKeyFlags OpFlags = 1 << 3
|
||||||
NilCheckFlags OpFlags = 1 << 4
|
NilCheckFlags OpFlags = 1 << 4
|
||||||
AddrForMarshalerFlags OpFlags = 1 << 5
|
AddrForMarshalerFlags OpFlags = 1 << 5
|
||||||
IsNextOpPtrTypeFlags OpFlags = 1 << 6
|
IsNextOpPtrTypeFlags OpFlags = 1 << 6
|
||||||
IsNilableTypeFlags OpFlags = 1 << 7
|
IsNilableTypeFlags OpFlags = 1 << 7
|
||||||
MarshalerContextFlags OpFlags = 1 << 8
|
MarshalerContextFlags OpFlags = 1 << 8
|
||||||
|
NonEmptyInterfaceFlags OpFlags = 1 << 9
|
||||||
)
|
)
|
||||||
|
|
||||||
type Opcode struct {
|
type Opcode struct {
|
||||||
|
@ -743,6 +744,10 @@ func newMapEndCode(ctx *compileContext, head *Opcode) *Opcode {
|
||||||
}
|
}
|
||||||
|
|
||||||
func newInterfaceCode(ctx *compileContext) *Opcode {
|
func newInterfaceCode(ctx *compileContext) *Opcode {
|
||||||
|
var flag OpFlags
|
||||||
|
if ctx.typ.NumMethod() > 0 {
|
||||||
|
flag |= NonEmptyInterfaceFlags
|
||||||
|
}
|
||||||
return &Opcode{
|
return &Opcode{
|
||||||
Op: OpInterface,
|
Op: OpInterface,
|
||||||
Idx: opcodeOffset(ctx.ptrIndex),
|
Idx: opcodeOffset(ctx.ptrIndex),
|
||||||
|
@ -750,6 +755,7 @@ func newInterfaceCode(ctx *compileContext) *Opcode {
|
||||||
Type: ctx.typ,
|
Type: ctx.typ,
|
||||||
DisplayIdx: ctx.opcodeIndex,
|
DisplayIdx: ctx.opcodeIndex,
|
||||||
Indent: ctx.indent,
|
Indent: ctx.indent,
|
||||||
|
Flags: flag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,15 @@ type emptyInterface struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nonEmptyInterface struct {
|
||||||
|
itab *struct {
|
||||||
|
ityp *runtime.Type // static interface type
|
||||||
|
typ *runtime.Type // dynamic concrete type
|
||||||
|
// unused fields...
|
||||||
|
}
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func errUnimplementedOp(op encoder.OpType) error {
|
func errUnimplementedOp(op encoder.OpType) error {
|
||||||
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
|
@ -185,16 +186,28 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
||||||
iface := (*emptyInterface)(ptrToUnsafePtr(p))
|
var (
|
||||||
if iface.ptr == nil {
|
typ *runtime.Type
|
||||||
|
ifacePtr unsafe.Pointer
|
||||||
|
)
|
||||||
|
up := ptrToUnsafePtr(p)
|
||||||
|
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
|
||||||
|
iface := (*nonEmptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.itab.typ
|
||||||
|
} else {
|
||||||
|
iface := (*emptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.typ
|
||||||
|
}
|
||||||
|
if ifacePtr == nil {
|
||||||
b = appendNull(ctx, b)
|
b = appendNull(ctx, b)
|
||||||
b = appendComma(ctx, b)
|
b = appendComma(ctx, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(typ)))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
||||||
|
|
||||||
end := ifaceCodeSet.EndCode
|
end := ifaceCodeSet.EndCode
|
||||||
store(ctxptr, c.Idx, uintptr(iface.ptr))
|
store(ctxptr, c.Idx, uintptr(ifacePtr))
|
||||||
store(ctxptr, end.Idx, oldOffset)
|
store(ctxptr, end.Idx, oldOffset)
|
||||||
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
||||||
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
||||||
|
|
|
@ -26,6 +26,15 @@ type emptyInterface struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nonEmptyInterface struct {
|
||||||
|
itab *struct {
|
||||||
|
ityp *runtime.Type // static interface type
|
||||||
|
typ *runtime.Type // dynamic concrete type
|
||||||
|
// unused fields...
|
||||||
|
}
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func errUnimplementedOp(op encoder.OpType) error {
|
func errUnimplementedOp(op encoder.OpType) error {
|
||||||
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
return fmt.Errorf("encoder: opcode %s has not been implemented", op)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
|
@ -185,16 +186,28 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
||||||
iface := (*emptyInterface)(ptrToUnsafePtr(p))
|
var (
|
||||||
if iface.ptr == nil {
|
typ *runtime.Type
|
||||||
|
ifacePtr unsafe.Pointer
|
||||||
|
)
|
||||||
|
up := ptrToUnsafePtr(p)
|
||||||
|
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
|
||||||
|
iface := (*nonEmptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.itab.typ
|
||||||
|
} else {
|
||||||
|
iface := (*emptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.typ
|
||||||
|
}
|
||||||
|
if ifacePtr == nil {
|
||||||
b = appendNull(ctx, b)
|
b = appendNull(ctx, b)
|
||||||
b = appendComma(ctx, b)
|
b = appendComma(ctx, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(typ)))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
||||||
|
|
||||||
end := ifaceCodeSet.EndCode
|
end := ifaceCodeSet.EndCode
|
||||||
store(ctxptr, c.Idx, uintptr(iface.ptr))
|
store(ctxptr, c.Idx, uintptr(ifacePtr))
|
||||||
store(ctxptr, end.Idx, oldOffset)
|
store(ctxptr, end.Idx, oldOffset)
|
||||||
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
||||||
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
||||||
|
|
|
@ -28,6 +28,15 @@ type emptyInterface struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nonEmptyInterface struct {
|
||||||
|
itab *struct {
|
||||||
|
ityp *runtime.Type // static interface type
|
||||||
|
typ *runtime.Type // dynamic concrete type
|
||||||
|
// unused fields...
|
||||||
|
}
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func errUnimplementedOp(op encoder.OpType) error {
|
func errUnimplementedOp(op encoder.OpType) error {
|
||||||
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
|
@ -185,16 +186,28 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
||||||
iface := (*emptyInterface)(ptrToUnsafePtr(p))
|
var (
|
||||||
if iface.ptr == nil {
|
typ *runtime.Type
|
||||||
|
ifacePtr unsafe.Pointer
|
||||||
|
)
|
||||||
|
up := ptrToUnsafePtr(p)
|
||||||
|
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
|
||||||
|
iface := (*nonEmptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.itab.typ
|
||||||
|
} else {
|
||||||
|
iface := (*emptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.typ
|
||||||
|
}
|
||||||
|
if ifacePtr == nil {
|
||||||
b = appendNull(ctx, b)
|
b = appendNull(ctx, b)
|
||||||
b = appendComma(ctx, b)
|
b = appendComma(ctx, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(typ)))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
||||||
|
|
||||||
end := ifaceCodeSet.EndCode
|
end := ifaceCodeSet.EndCode
|
||||||
store(ctxptr, c.Idx, uintptr(iface.ptr))
|
store(ctxptr, c.Idx, uintptr(ifacePtr))
|
||||||
store(ctxptr, end.Idx, oldOffset)
|
store(ctxptr, end.Idx, oldOffset)
|
||||||
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
||||||
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
||||||
|
|
|
@ -35,6 +35,15 @@ type emptyInterface struct {
|
||||||
ptr unsafe.Pointer
|
ptr unsafe.Pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type nonEmptyInterface struct {
|
||||||
|
itab *struct {
|
||||||
|
ityp *runtime.Type // static interface type
|
||||||
|
typ *runtime.Type // dynamic concrete type
|
||||||
|
// unused fields...
|
||||||
|
}
|
||||||
|
ptr unsafe.Pointer
|
||||||
|
}
|
||||||
|
|
||||||
func errUnimplementedOp(op encoder.OpType) error {
|
func errUnimplementedOp(op encoder.OpType) error {
|
||||||
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
return fmt.Errorf("encoder (indent): opcode %s has not been implemented", op)
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/goccy/go-json/internal/encoder"
|
"github.com/goccy/go-json/internal/encoder"
|
||||||
|
"github.com/goccy/go-json/internal/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]byte, error) {
|
||||||
|
@ -185,16 +186,28 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
ctx.SeenPtr = append(ctx.SeenPtr, p)
|
||||||
iface := (*emptyInterface)(ptrToUnsafePtr(p))
|
var (
|
||||||
if iface.ptr == nil {
|
typ *runtime.Type
|
||||||
|
ifacePtr unsafe.Pointer
|
||||||
|
)
|
||||||
|
up := ptrToUnsafePtr(p)
|
||||||
|
if code.Flags&encoder.NonEmptyInterfaceFlags != 0 {
|
||||||
|
iface := (*nonEmptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.itab.typ
|
||||||
|
} else {
|
||||||
|
iface := (*emptyInterface)(up)
|
||||||
|
ifacePtr = iface.ptr
|
||||||
|
typ = iface.typ
|
||||||
|
}
|
||||||
|
if ifacePtr == nil {
|
||||||
b = appendNull(ctx, b)
|
b = appendNull(ctx, b)
|
||||||
b = appendComma(ctx, b)
|
b = appendComma(ctx, b)
|
||||||
code = code.Next
|
code = code.Next
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
ctx.KeepRefs = append(ctx.KeepRefs, up)
|
||||||
ctx.KeepRefs = append(ctx.KeepRefs, unsafe.Pointer(iface))
|
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(typ)))
|
||||||
ifaceCodeSet, err := encoder.CompileToGetCodeSet(uintptr(unsafe.Pointer(iface.typ)))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -223,7 +236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet) ([]b
|
||||||
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
ctxptr = ctx.Ptr() + ptrOffset // assign new ctxptr
|
||||||
|
|
||||||
end := ifaceCodeSet.EndCode
|
end := ifaceCodeSet.EndCode
|
||||||
store(ctxptr, c.Idx, uintptr(iface.ptr))
|
store(ctxptr, c.Idx, uintptr(ifacePtr))
|
||||||
store(ctxptr, end.Idx, oldOffset)
|
store(ctxptr, end.Idx, oldOffset)
|
||||||
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
store(ctxptr, end.ElemIdx, uintptr(unsafe.Pointer(code.Next)))
|
||||||
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
storeIndent(ctxptr, end, uintptr(oldBaseIndent))
|
||||||
|
|
Loading…
Reference in New Issue