mirror of
https://codeberg.org/superseriousbusiness/gotosocial.git
synced 2025-05-01 13:31:04 +03:00
migrate go version to 1.17 (#203)
* migrate go version to 1.17 * update contributing
This commit is contained in:
parent
e681aac589
commit
f2e5bedea6
282 changed files with 11863 additions and 12600 deletions
vendor/github.com/goccy/go-json/internal/encoder
276
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
276
vendor/github.com/goccy/go-json/internal/encoder/compiler.go
generated
vendored
|
@ -1,6 +1,7 @@
|
|||
package encoder
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
@ -13,13 +14,18 @@ import (
|
|||
"github.com/goccy/go-json/internal/runtime"
|
||||
)
|
||||
|
||||
type marshalerContext interface {
|
||||
MarshalJSON(context.Context) ([]byte, error)
|
||||
}
|
||||
|
||||
var (
|
||||
marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
cachedOpcodeSets []*OpcodeSet
|
||||
cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet
|
||||
typeAddr *runtime.TypeAddr
|
||||
marshalJSONType = reflect.TypeOf((*json.Marshaler)(nil)).Elem()
|
||||
marshalJSONContextType = reflect.TypeOf((*marshalerContext)(nil)).Elem()
|
||||
marshalTextType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
jsonNumberType = reflect.TypeOf(json.Number(""))
|
||||
cachedOpcodeSets []*OpcodeSet
|
||||
cachedOpcodeMap unsafe.Pointer // map[uintptr]*OpcodeSet
|
||||
typeAddr *runtime.TypeAddr
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -55,19 +61,36 @@ func compileToGetCodeSetSlowPath(typeptr uintptr) (*OpcodeSet, error) {
|
|||
// noescape trick for header.typ ( reflect.*rtype )
|
||||
copiedType := *(**runtime.Type)(unsafe.Pointer(&typeptr))
|
||||
|
||||
code, err := compileHead(&compileContext{
|
||||
noescapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code = copyOpcode(code)
|
||||
codeLength := code.TotalLength()
|
||||
escapeKeyCode, err := compileHead(&compileContext{
|
||||
typ: copiedType,
|
||||
structTypeToCompiledCode: map[uintptr]*CompiledCode{},
|
||||
escapeKey: true,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
noescapeKeyCode = copyOpcode(noescapeKeyCode)
|
||||
escapeKeyCode = copyOpcode(escapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(noescapeKeyCode)
|
||||
setTotalLengthToInterfaceOp(escapeKeyCode)
|
||||
interfaceNoescapeKeyCode := copyToInterfaceOpcode(noescapeKeyCode)
|
||||
interfaceEscapeKeyCode := copyToInterfaceOpcode(escapeKeyCode)
|
||||
codeLength := noescapeKeyCode.TotalLength()
|
||||
codeSet := &OpcodeSet{
|
||||
Type: copiedType,
|
||||
Code: code,
|
||||
CodeLength: codeLength,
|
||||
Type: copiedType,
|
||||
NoescapeKeyCode: noescapeKeyCode,
|
||||
EscapeKeyCode: escapeKeyCode,
|
||||
InterfaceNoescapeKeyCode: interfaceNoescapeKeyCode,
|
||||
InterfaceEscapeKeyCode: interfaceEscapeKeyCode,
|
||||
CodeLength: codeLength,
|
||||
EndCode: ToEndCode(interfaceNoescapeKeyCode),
|
||||
}
|
||||
storeOpcodeSet(typeptr, codeSet, opcodeMap)
|
||||
return codeSet, nil
|
||||
|
@ -100,7 +123,7 @@ func compileHead(ctx *compileContext) (*Opcode, error) {
|
|||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
p := runtime.PtrTo(elem)
|
||||
if !p.Implements(marshalJSONType) && !p.Implements(marshalTextType) {
|
||||
if !implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
|
||||
if isPtr {
|
||||
return compileBytesPtr(ctx)
|
||||
}
|
||||
|
@ -246,6 +269,7 @@ func linkRecursiveCode(c *Opcode) {
|
|||
continue
|
||||
}
|
||||
code.Jmp.Code = copyOpcode(code.Jmp.Code)
|
||||
|
||||
c := code.Jmp.Code
|
||||
c.End.Next = newEndOp(&compileContext{})
|
||||
c.Op = c.Op.PtrHeadToHead()
|
||||
|
@ -258,8 +282,8 @@ func linkRecursiveCode(c *Opcode) {
|
|||
lastCode.Length = lastCode.Idx + 2*uintptrSize
|
||||
|
||||
// extend length to alloc slot for elemIdx + length
|
||||
totalLength := uintptr(code.TotalLength() + 2)
|
||||
nextTotalLength := uintptr(c.TotalLength() + 2)
|
||||
totalLength := uintptr(code.TotalLength() + 3)
|
||||
nextTotalLength := uintptr(c.TotalLength() + 3)
|
||||
|
||||
c.End.Next.Op = OpRecursiveEnd
|
||||
|
||||
|
@ -268,6 +292,7 @@ func linkRecursiveCode(c *Opcode) {
|
|||
code.Jmp.Linked = true
|
||||
|
||||
linkRecursiveCode(code.Jmp.Code)
|
||||
|
||||
code = code.Next
|
||||
continue
|
||||
}
|
||||
|
@ -328,14 +353,14 @@ func optimizeStructEnd(c *Opcode) {
|
|||
}
|
||||
|
||||
func implementsMarshalJSON(typ *runtime.Type) bool {
|
||||
if !typ.Implements(marshalJSONType) {
|
||||
if !implementsMarshalJSONType(typ) {
|
||||
return false
|
||||
}
|
||||
if typ.Kind() != reflect.Ptr {
|
||||
return true
|
||||
}
|
||||
// type kind is reflect.Ptr
|
||||
if !typ.Elem().Implements(marshalJSONType) {
|
||||
if !implementsMarshalJSONType(typ.Elem()) {
|
||||
return true
|
||||
}
|
||||
// needs to dereference
|
||||
|
@ -372,7 +397,7 @@ func compile(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
elem := typ.Elem()
|
||||
if elem.Kind() == reflect.Uint8 {
|
||||
p := runtime.PtrTo(elem)
|
||||
if !p.Implements(marshalJSONType) && !p.Implements(marshalTextType) {
|
||||
if !implementsMarshalJSONType(p) && !p.Implements(marshalTextType) {
|
||||
return compileBytes(ctx)
|
||||
}
|
||||
}
|
||||
|
@ -474,8 +499,6 @@ func compileKey(ctx *compileContext) (*Opcode, error) {
|
|||
switch typ.Kind() {
|
||||
case reflect.Ptr:
|
||||
return compilePtr(ctx)
|
||||
case reflect.Interface:
|
||||
return compileInterface(ctx)
|
||||
case reflect.String:
|
||||
return compileString(ctx)
|
||||
case reflect.Int:
|
||||
|
@ -517,10 +540,17 @@ func compilePtr(ctx *compileContext) (*Opcode, error) {
|
|||
func compileMarshalJSON(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpMarshalJSON)
|
||||
typ := ctx.typ
|
||||
if !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType) {
|
||||
code.AddrForMarshaler = true
|
||||
if isPtrMarshalJSONType(typ) {
|
||||
code.Flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if typ.Implements(marshalJSONContextType) || runtime.PtrTo(typ).Implements(marshalJSONContextType) {
|
||||
code.Flags |= MarshalerContextFlags
|
||||
}
|
||||
if isNilableType(typ) {
|
||||
code.Flags |= IsNilableTypeFlags
|
||||
} else {
|
||||
code.Flags &= ^IsNilableTypeFlags
|
||||
}
|
||||
code.IsNilableType = isNilableType(typ)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -529,9 +559,13 @@ func compileMarshalText(ctx *compileContext) (*Opcode, error) {
|
|||
code := newOpCode(ctx, OpMarshalText)
|
||||
typ := ctx.typ
|
||||
if !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType) {
|
||||
code.AddrForMarshaler = true
|
||||
code.Flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if isNilableType(typ) {
|
||||
code.Flags |= IsNilableTypeFlags
|
||||
} else {
|
||||
code.Flags &= ^IsNilableTypeFlags
|
||||
}
|
||||
code.IsNilableType = isNilableType(typ)
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -540,7 +574,7 @@ const intSize = 32 << (^uint(0) >> 63)
|
|||
|
||||
func compileInt(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -556,7 +590,7 @@ func compileIntPtr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt8(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -572,7 +606,7 @@ func compileInt8Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt16(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -588,7 +622,7 @@ func compileInt16Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt32(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -604,7 +638,7 @@ func compileInt32Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileInt64(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpInt)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -620,7 +654,7 @@ func compileInt64Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -636,7 +670,7 @@ func compileUintPtr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint8(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -652,7 +686,7 @@ func compileUint8Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint16(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -668,7 +702,7 @@ func compileUint16Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint32(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -684,7 +718,7 @@ func compileUint32Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileUint64(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUint)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -700,70 +734,70 @@ func compileUint64Ptr(ctx *compileContext) (*Opcode, error) {
|
|||
|
||||
func compileIntString(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt8String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt16String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt32String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileInt64String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpIntString)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUintString(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(intSize)
|
||||
code.NumBitSize = intSize
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint8String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(8)
|
||||
code.NumBitSize = 8
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint16String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(16)
|
||||
code.NumBitSize = 16
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint32String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(32)
|
||||
code.NumBitSize = 32
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
||||
func compileUint64String(ctx *compileContext) (*Opcode, error) {
|
||||
code := newOpCode(ctx, OpUintString)
|
||||
code.setMaskAndRshiftNum(64)
|
||||
code.NumBitSize = 64
|
||||
ctx.incIndex()
|
||||
return code, nil
|
||||
}
|
||||
|
@ -879,7 +913,7 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code.Indirect = true
|
||||
code.Flags |= IndirectFlags
|
||||
|
||||
// header => opcode => elem => end
|
||||
// ^ |
|
||||
|
@ -891,7 +925,6 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
end := newOpCode(ctx, OpSliceEnd)
|
||||
ctx.incIndex()
|
||||
|
||||
header.Elem = elemCode
|
||||
header.End = end
|
||||
header.Next = code
|
||||
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
|
||||
|
@ -903,7 +936,7 @@ func compileSlice(ctx *compileContext) (*Opcode, error) {
|
|||
func compileListElem(ctx *compileContext) (*Opcode, error) {
|
||||
typ := ctx.typ
|
||||
switch {
|
||||
case !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType):
|
||||
case isPtrMarshalJSONType(typ):
|
||||
return compileMarshalJSON(ctx)
|
||||
case !typ.Implements(marshalTextType) && runtime.PtrTo(typ).Implements(marshalTextType):
|
||||
return compileMarshalText(ctx)
|
||||
|
@ -934,7 +967,7 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code.Indirect = true
|
||||
code.Flags |= IndirectFlags
|
||||
// header => opcode => elem => end
|
||||
// ^ |
|
||||
// |________|
|
||||
|
@ -945,7 +978,6 @@ func compileArray(ctx *compileContext) (*Opcode, error) {
|
|||
end := newOpCode(ctx, OpArrayEnd)
|
||||
ctx.incIndex()
|
||||
|
||||
header.Elem = elemCode
|
||||
header.End = end
|
||||
header.Next = code
|
||||
code.BeforeLastCode().Next = (*Opcode)(unsafe.Pointer(elemCode))
|
||||
|
@ -976,16 +1008,13 @@ func compileMap(ctx *compileContext) (*Opcode, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
valueCode.Indirect = true
|
||||
valueCode.Flags |= IndirectFlags
|
||||
|
||||
key := newMapKeyCode(ctx, header)
|
||||
ctx.incIndex()
|
||||
|
||||
ctx = ctx.decIndent()
|
||||
|
||||
header.MapKey = key
|
||||
header.MapValue = value
|
||||
|
||||
end := newMapEndCode(ctx, header)
|
||||
ctx.incIndex()
|
||||
|
||||
|
@ -1052,8 +1081,7 @@ func compiledCode(ctx *compileContext) *Opcode {
|
|||
func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
|
||||
op := optimizeStructHeader(valueCode, tag)
|
||||
fieldCode.Op = op
|
||||
fieldCode.Mask = valueCode.Mask
|
||||
fieldCode.RshiftNum = valueCode.RshiftNum
|
||||
fieldCode.NumBitSize = valueCode.NumBitSize
|
||||
fieldCode.PtrNum = valueCode.PtrNum
|
||||
if op.IsMultipleOpHead() {
|
||||
return valueCode.BeforeLastCode()
|
||||
|
@ -1065,9 +1093,8 @@ func structHeader(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag
|
|||
func structField(ctx *compileContext, fieldCode *Opcode, valueCode *Opcode, tag *runtime.StructTag) *Opcode {
|
||||
op := optimizeStructField(valueCode, tag)
|
||||
fieldCode.Op = op
|
||||
fieldCode.NumBitSize = valueCode.NumBitSize
|
||||
fieldCode.PtrNum = valueCode.PtrNum
|
||||
fieldCode.Mask = valueCode.Mask
|
||||
fieldCode.RshiftNum = valueCode.RshiftNum
|
||||
if op.IsMultipleOpField() {
|
||||
return valueCode.BeforeLastCode()
|
||||
}
|
||||
|
@ -1082,7 +1109,7 @@ func isNotExistsField(head *Opcode) bool {
|
|||
if head.Op != OpStructHead {
|
||||
return false
|
||||
}
|
||||
if !head.AnonymousHead {
|
||||
if (head.Flags & AnonymousHeadFlags) == 0 {
|
||||
return false
|
||||
}
|
||||
if head.Next == nil {
|
||||
|
@ -1117,7 +1144,7 @@ func optimizeAnonymousFields(head *Opcode) {
|
|||
if isNotExistsField(code.Next) {
|
||||
code.Next = code.NextField
|
||||
diff := code.Next.DisplayIdx - code.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
code.Next.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(code, removedFields)
|
||||
|
@ -1147,20 +1174,20 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
|
|||
isHeadOp := strings.Contains(f.Op.String(), "Head")
|
||||
if existsKey && f.Next != nil && strings.Contains(f.Next.Op.String(), "Recursive") {
|
||||
// through
|
||||
} else if isHeadOp && !f.AnonymousHead {
|
||||
} else if isHeadOp && (f.Flags&AnonymousHeadFlags) == 0 {
|
||||
if existsKey {
|
||||
// TODO: need to remove this head
|
||||
f.Op = OpStructHead
|
||||
f.AnonymousKey = true
|
||||
f.AnonymousHead = true
|
||||
f.Flags |= AnonymousKeyFlags
|
||||
f.Flags |= AnonymousHeadFlags
|
||||
} else if named == "" {
|
||||
f.AnonymousHead = true
|
||||
f.Flags |= AnonymousHeadFlags
|
||||
}
|
||||
} else if named == "" && f.Op == OpStructEnd {
|
||||
f.Op = OpStructAnonymousEnd
|
||||
} else if existsKey {
|
||||
diff := f.NextField.DisplayIdx - f.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
f.NextField.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(f, removedFields)
|
||||
|
@ -1179,7 +1206,7 @@ func anonymousStructFieldPairMap(tags runtime.StructTags, named string, valueCod
|
|||
anonymousFields[key] = append(anonymousFields[key], structFieldPair{
|
||||
prevField: prevAnonymousField,
|
||||
curField: f,
|
||||
isTaggedKey: f.IsTaggedKey,
|
||||
isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
|
||||
})
|
||||
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
|
||||
for k, v := range anonymousFieldPairRecursively(named, f.Next) {
|
||||
|
@ -1200,12 +1227,12 @@ func anonymousFieldPairRecursively(named string, valueCode *Opcode) map[string][
|
|||
f := valueCode
|
||||
var prevAnonymousField *Opcode
|
||||
for {
|
||||
if f.DisplayKey != "" && f.AnonymousHead {
|
||||
if f.DisplayKey != "" && (f.Flags&AnonymousHeadFlags) != 0 {
|
||||
key := fmt.Sprintf("%s.%s", named, f.DisplayKey)
|
||||
anonymousFields[key] = append(anonymousFields[key], structFieldPair{
|
||||
prevField: prevAnonymousField,
|
||||
curField: f,
|
||||
isTaggedKey: f.IsTaggedKey,
|
||||
isTaggedKey: (f.Flags & IsTaggedKeyFlags) != 0,
|
||||
})
|
||||
if f.Next != nil && f.NextField != f.Next && f.Next.Op.CodeType() == CodeStructField {
|
||||
for k, v := range anonymousFieldPairRecursively(named, f.Next) {
|
||||
|
@ -1238,11 +1265,11 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
if fieldPair.prevField == nil {
|
||||
// head operation
|
||||
fieldPair.curField.Op = OpStructHead
|
||||
fieldPair.curField.AnonymousHead = true
|
||||
fieldPair.curField.AnonymousKey = true
|
||||
fieldPair.curField.Flags |= AnonymousHeadFlags
|
||||
fieldPair.curField.Flags |= AnonymousKeyFlags
|
||||
} else {
|
||||
diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
fieldPair.curField.NextField.decOpcodeIndex()
|
||||
}
|
||||
removedFields[fieldPair.curField] = struct{}{}
|
||||
|
@ -1258,12 +1285,12 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
if fieldPair.prevField == nil {
|
||||
// head operation
|
||||
fieldPair.curField.Op = OpStructHead
|
||||
fieldPair.curField.AnonymousHead = true
|
||||
fieldPair.curField.AnonymousKey = true
|
||||
fieldPair.curField.Flags |= AnonymousHeadFlags
|
||||
fieldPair.curField.Flags |= AnonymousKeyFlags
|
||||
} else {
|
||||
diff := fieldPair.curField.NextField.DisplayIdx - fieldPair.curField.DisplayIdx
|
||||
removedFields[fieldPair.curField] = struct{}{}
|
||||
for i := 0; i < diff; i++ {
|
||||
for i := uint32(0); i < diff; i++ {
|
||||
fieldPair.curField.NextField.decOpcodeIndex()
|
||||
}
|
||||
linkPrevToNextField(fieldPair.curField, removedFields)
|
||||
|
@ -1273,7 +1300,7 @@ func optimizeConflictAnonymousFields(anonymousFields map[string][]structFieldPai
|
|||
}
|
||||
} else {
|
||||
for _, fieldPair := range taggedPairs {
|
||||
fieldPair.curField.IsTaggedKey = false
|
||||
fieldPair.curField.Flags &= ^IsTaggedKeyFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1390,7 +1417,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
valueCode = code
|
||||
}
|
||||
|
||||
if field.Anonymous {
|
||||
if field.Anonymous && !tag.IsTaggedKey {
|
||||
tagKey := ""
|
||||
if tag.IsTaggedKey {
|
||||
tagKey = tag.Key
|
||||
|
@ -1398,50 +1425,76 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
for k, v := range anonymousStructFieldPairMap(tags, tagKey, valueCode) {
|
||||
anonymousFields[k] = append(anonymousFields[k], v...)
|
||||
}
|
||||
|
||||
valueCode.decIndent()
|
||||
|
||||
// fix issue144
|
||||
if !(isPtr && strings.Contains(valueCode.Op.String(), "Marshal")) {
|
||||
valueCode.Indirect = indirect
|
||||
if indirect {
|
||||
valueCode.Flags |= IndirectFlags
|
||||
} else {
|
||||
valueCode.Flags &= ^IndirectFlags
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if indirect {
|
||||
// if parent is indirect type, set child indirect property to true
|
||||
valueCode.Indirect = indirect
|
||||
valueCode.Flags |= IndirectFlags
|
||||
} else {
|
||||
// if parent is not indirect type and child have only one field, set child indirect property to false
|
||||
if i == 0 && valueCode.NextField != nil && valueCode.NextField.Op == OpStructEnd {
|
||||
valueCode.Indirect = indirect
|
||||
// if parent is not indirect type, set child indirect property to false.
|
||||
// but if parent's indirect is false and isPtr is true, then indirect must be true.
|
||||
// Do this only if indirectConversion is enabled at the end of compileStruct.
|
||||
if i == 0 {
|
||||
valueCode.Flags &= ^IndirectFlags
|
||||
}
|
||||
}
|
||||
}
|
||||
key := fmt.Sprintf(`"%s":`, tag.Key)
|
||||
escapedKey := fmt.Sprintf(`%s:`, string(AppendEscapedString([]byte{}, tag.Key)))
|
||||
var flags OpFlags
|
||||
if indirect {
|
||||
flags |= IndirectFlags
|
||||
}
|
||||
if field.Anonymous {
|
||||
flags |= AnonymousKeyFlags
|
||||
}
|
||||
if tag.IsTaggedKey {
|
||||
flags |= IsTaggedKeyFlags
|
||||
}
|
||||
if nilcheck {
|
||||
flags |= NilCheckFlags
|
||||
}
|
||||
if addrForMarshaler {
|
||||
flags |= AddrForMarshalerFlags
|
||||
}
|
||||
if strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface {
|
||||
flags |= IsNextOpPtrTypeFlags
|
||||
}
|
||||
if isNilableType {
|
||||
flags |= IsNilableTypeFlags
|
||||
}
|
||||
var key string
|
||||
if ctx.escapeKey {
|
||||
rctx := &RuntimeContext{Option: &Option{Flag: HTMLEscapeOption}}
|
||||
key = fmt.Sprintf(`%s:`, string(AppendString(rctx, []byte{}, tag.Key)))
|
||||
} else {
|
||||
key = fmt.Sprintf(`"%s":`, tag.Key)
|
||||
}
|
||||
fieldCode := &Opcode{
|
||||
Type: valueCode.Type,
|
||||
DisplayIdx: fieldOpcodeIndex,
|
||||
Idx: opcodeOffset(fieldPtrIndex),
|
||||
Next: valueCode,
|
||||
Indent: ctx.indent,
|
||||
AnonymousKey: field.Anonymous,
|
||||
Key: []byte(key),
|
||||
EscapedKey: []byte(escapedKey),
|
||||
IsTaggedKey: tag.IsTaggedKey,
|
||||
DisplayKey: tag.Key,
|
||||
Offset: field.Offset,
|
||||
Indirect: indirect,
|
||||
Nilcheck: nilcheck,
|
||||
AddrForMarshaler: addrForMarshaler,
|
||||
IsNextOpPtrType: strings.Contains(valueCode.Op.String(), "Ptr") || valueCode.Op == OpInterface,
|
||||
IsNilableType: isNilableType,
|
||||
Idx: opcodeOffset(fieldPtrIndex),
|
||||
Next: valueCode,
|
||||
Flags: flags,
|
||||
Key: key,
|
||||
Offset: uint32(field.Offset),
|
||||
Type: valueCode.Type,
|
||||
DisplayIdx: fieldOpcodeIndex,
|
||||
Indent: ctx.indent,
|
||||
DisplayKey: tag.Key,
|
||||
}
|
||||
if fieldIdx == 0 {
|
||||
fieldCode.HeadIdx = fieldCode.Idx
|
||||
code = structHeader(ctx, fieldCode, valueCode, tag)
|
||||
head = fieldCode
|
||||
prevField = fieldCode
|
||||
} else {
|
||||
fieldCode.HeadIdx = head.HeadIdx
|
||||
fieldCode.Idx = head.Idx
|
||||
code.Next = fieldCode
|
||||
code = structField(ctx, fieldCode, valueCode, tag)
|
||||
prevField.NextField = fieldCode
|
||||
|
@ -1455,7 +1508,6 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
Op: OpStructEnd,
|
||||
Type: nil,
|
||||
Indent: ctx.indent,
|
||||
Next: newEndOp(ctx),
|
||||
}
|
||||
|
||||
ctx = ctx.decIndent()
|
||||
|
@ -1464,12 +1516,11 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
if head == nil {
|
||||
head = &Opcode{
|
||||
Op: OpStructHead,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
NextField: structEndCode,
|
||||
Type: typ,
|
||||
DisplayIdx: ctx.opcodeIndex,
|
||||
Idx: opcodeOffset(ctx.ptrIndex),
|
||||
HeadIdx: opcodeOffset(ctx.ptrIndex),
|
||||
Indent: ctx.indent,
|
||||
NextField: structEndCode,
|
||||
}
|
||||
structEndCode.PrevField = head
|
||||
ctx.incIndex()
|
||||
|
@ -1479,6 +1530,7 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
structEndCode.DisplayIdx = ctx.opcodeIndex
|
||||
structEndCode.Idx = opcodeOffset(ctx.ptrIndex)
|
||||
ctx.incIndex()
|
||||
structEndCode.Next = newEndOp(ctx)
|
||||
|
||||
if prevField != nil && prevField.NextField == nil {
|
||||
prevField.NextField = structEndCode
|
||||
|
@ -1494,15 +1546,23 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
|||
|
||||
delete(ctx.structTypeToCompiledCode, typeptr)
|
||||
|
||||
if !disableIndirectConversion && !head.Indirect && isPtr {
|
||||
head.Indirect = true
|
||||
if !disableIndirectConversion && (head.Flags&IndirectFlags == 0) && isPtr {
|
||||
headCode := head
|
||||
for strings.Contains(headCode.Op.String(), "Head") {
|
||||
headCode.Flags |= IndirectFlags
|
||||
headCode = headCode.Next
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func implementsMarshalJSONType(typ *runtime.Type) bool {
|
||||
return typ.Implements(marshalJSONType) || typ.Implements(marshalJSONContextType)
|
||||
}
|
||||
|
||||
func isPtrMarshalJSONType(typ *runtime.Type) bool {
|
||||
return !typ.Implements(marshalJSONType) && runtime.PtrTo(typ).Implements(marshalJSONType)
|
||||
return !implementsMarshalJSONType(typ) && implementsMarshalJSONType(runtime.PtrTo(typ))
|
||||
}
|
||||
|
||||
func isPtrMarshalTextType(typ *runtime.Type) bool {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue