diff options
Diffstat (limited to 'vendor/github.com/goccy/go-json/internal/encoder')
7 files changed, 119 insertions, 14 deletions
diff --git a/vendor/github.com/goccy/go-json/internal/encoder/code.go b/vendor/github.com/goccy/go-json/internal/encoder/code.go index 8d62a9cd5..5b08faefc 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/code.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/code.go @@ -397,7 +397,10 @@ func (c *StructCode) lastFieldCode(field *StructFieldCode, firstField *Opcode) *  func (c *StructCode) lastAnonymousFieldCode(firstField *Opcode) *Opcode {  	// firstField is special StructHead operation for anonymous structure.  	// So, StructHead's next operation is truly struct head operation. -	lastField := firstField.Next +	for firstField.Op == OpStructHead || firstField.Op == OpStructField { +		firstField = firstField.Next +	} +	lastField := firstField  	for lastField.NextField != nil {  		lastField = lastField.NextField  	} @@ -437,11 +440,6 @@ func (c *StructCode) ToOpcode(ctx *compileContext) Opcodes {  		}  		if isEndField {  			endField := fieldCodes.Last() -			if isEmbeddedStruct(field) { -				firstField.End = endField -				lastField := c.lastAnonymousFieldCode(firstField) -				lastField.NextField = endField -			}  			if len(codes) > 0 {  				codes.First().End = endField  			} else { @@ -698,7 +696,15 @@ func (c *StructFieldCode) addStructEndCode(ctx *compileContext, codes Opcodes) O  		Indent:     ctx.indent,  	}  	codes.Last().Next = end -	codes.First().NextField = end +	code := codes.First() +	for code.Op == OpStructField || code.Op == OpStructHead { +		code = code.Next +	} +	for code.NextField != nil { +		code = code.NextField +	} +	code.NextField = end +  	codes = codes.Add(end)  	ctx.incOpcodeIndex()  	return codes diff --git a/vendor/github.com/goccy/go-json/internal/encoder/compiler.go b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go index 3b3ff3fde..3ae39ba8c 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/compiler.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/compiler.go @@ -617,6 +617,13 @@ func (c *Compiler) structCode(typ *runtime.Type, isPtr bool) (*StructCode, error  	return code, nil  } +func toElemType(t *runtime.Type) *runtime.Type { +	for t.Kind() == reflect.Ptr { +		t = t.Elem() +	} +	return t +} +  func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTag, isPtr, isOnlyOneFirstField bool) (*StructFieldCode, error) {  	field := tag.Field  	fieldType := runtime.Type2RType(field.Type) @@ -626,7 +633,7 @@ func (c *Compiler) structFieldCode(structCode *StructCode, tag *runtime.StructTa  		key:           tag.Key,  		tag:           tag,  		offset:        field.Offset, -		isAnonymous:   field.Anonymous && !tag.IsTaggedKey, +		isAnonymous:   field.Anonymous && !tag.IsTaggedKey && toElemType(fieldType).Kind() == reflect.Struct,  		isTaggedKey:   tag.IsTaggedKey,  		isNilableType: c.isNilableType(fieldType),  		isNilCheck:    true, diff --git a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go index 05fc3ce04..df22f5542 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/opcode.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/opcode.go @@ -1,7 +1,9 @@  package encoder  import ( +	"bytes"  	"fmt" +	"sort"  	"strings"  	"unsafe" @@ -555,6 +557,87 @@ func (c *Opcode) Dump() string {  	return strings.Join(codes, "\n")  } +func (c *Opcode) DumpDOT() string { +	type edge struct { +		from, to *Opcode +		label    string +		weight   int +	} +	var edges []edge + +	b := &bytes.Buffer{} +	fmt.Fprintf(b, "digraph \"%p\" {\n", c.Type) +	fmt.Fprintln(b, "mclimit=1.5;\nrankdir=TD;\nordering=out;\nnode[shape=box];") +	for code := c; !code.IsEnd(); { +		label := code.Op.String() +		fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, label) +		if p := code.Next; p != nil { +			edges = append(edges, edge{ +				from:   code, +				to:     p, +				label:  "Next", +				weight: 10, +			}) +		} +		if p := code.NextField; p != nil { +			edges = append(edges, edge{ +				from:   code, +				to:     p, +				label:  "NextField", +				weight: 2, +			}) +		} +		if p := code.End; p != nil { +			edges = append(edges, edge{ +				from:   code, +				to:     p, +				label:  "End", +				weight: 1, +			}) +		} +		if p := code.Jmp; p != nil { +			edges = append(edges, edge{ +				from:   code, +				to:     p.Code, +				label:  "Jmp", +				weight: 1, +			}) +		} + +		switch code.Op.CodeType() { +		case CodeSliceHead: +			code = code.Next +		case CodeMapHead: +			code = code.Next +		case CodeArrayElem, CodeSliceElem: +			code = code.End +		case CodeMapKey: +			code = code.End +		case CodeMapValue: +			code = code.Next +		case CodeMapEnd: +			code = code.Next +		case CodeStructField: +			code = code.Next +		case CodeStructEnd: +			code = code.Next +		default: +			code = code.Next +		} +		if code.IsEnd() { +			fmt.Fprintf(b, "\"%p\" [label=%q];\n", code, code.Op.String()) +		} +	} +	sort.Slice(edges, func(i, j int) bool { +		return edges[i].to.DisplayIdx < edges[j].to.DisplayIdx +	}) +	for _, e := range edges { +		fmt.Fprintf(b, "\"%p\" -> \"%p\" [label=%q][weight=%d];\n", e.from, e.to, e.label, e.weight) +	} +	fmt.Fprint(b, "}") +	return b.String() +} +  func newSliceHeaderCode(ctx *compileContext, typ *runtime.Type) *Opcode {  	idx := opcodeOffset(ctx.ptrIndex)  	ctx.incPtrIndex() diff --git a/vendor/github.com/goccy/go-json/internal/encoder/option.go b/vendor/github.com/goccy/go-json/internal/encoder/option.go index 82d5ce3e7..12c58e46c 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/option.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/option.go @@ -23,6 +23,7 @@ type Option struct {  	ColorScheme *ColorScheme  	Context     context.Context  	DebugOut    io.Writer +	DebugDOTOut io.WriteCloser  }  type EncodeFormat struct { diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go b/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go index fbbc0de44..82b6dd47f 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm/debug_vm.go @@ -2,6 +2,7 @@ package vm  import (  	"fmt" +	"io"  	"github.com/goccy/go-json/internal/encoder"  ) @@ -14,6 +15,11 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)  		} else {  			code = codeSet.NoescapeKeyCode  		} +		if wc := ctx.Option.DebugDOTOut; wc != nil { +			_, _ = io.WriteString(wc, code.DumpDOT()) +			wc.Close() +			ctx.Option.DebugDOTOut = nil +		}  		if err := recover(); err != nil {  			w := ctx.Option.DebugOut diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go index 60e4a8ed5..2395abec9 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_color_indent/util.go @@ -189,7 +189,7 @@ func appendNullComma(ctx *encoder.RuntimeContext, b []byte) []byte {  }  func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { -	return append(b, ':', ' ') +	return append(b[:len(b)-2], ':', ' ')  }  func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { @@ -229,8 +229,9 @@ func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {  func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {  	last := len(b) - 1 -	b[last] = '\n' -	b = appendIndent(ctx, b, code.Indent-1) +	// replace comma to newline +	b[last-1] = '\n' +	b = appendIndent(ctx, b[:last], code.Indent)  	return append(b, '}', ',', '\n')  } diff --git a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go index fca8f1855..6cb745e39 100644 --- a/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go +++ b/vendor/github.com/goccy/go-json/internal/encoder/vm_indent/util.go @@ -133,7 +133,7 @@ func appendNullComma(_ *encoder.RuntimeContext, b []byte) []byte {  }  func appendColon(_ *encoder.RuntimeContext, b []byte) []byte { -	return append(b, ':', ' ') +	return append(b[:len(b)-2], ':', ' ')  }  func appendMapKeyValue(ctx *encoder.RuntimeContext, code *encoder.Opcode, b, key, value []byte) []byte { @@ -173,8 +173,9 @@ func appendEmptyObject(_ *encoder.RuntimeContext, b []byte) []byte {  func appendObjectEnd(ctx *encoder.RuntimeContext, code *encoder.Opcode, b []byte) []byte {  	last := len(b) - 1 -	b[last] = '\n' -	b = appendIndent(ctx, b, code.Indent-1) +	// replace comma to newline +	b[last-1] = '\n' +	b = appendIndent(ctx, b[:last], code.Indent)  	return append(b, '}', ',', '\n')  }  | 
