[chore]: Bump github.com/gin-gonic/gin from 1.9.0 to 1.9.1 (#1855)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This commit is contained in:
dependabot[bot] 2023-06-01 22:20:16 +01:00 committed by GitHub
commit 55aacaf4b0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
138 changed files with 27543 additions and 25484 deletions

View file

@ -1,3 +1,35 @@
# v0.10.2 - 2023/03/20
### New features
* Support DebugDOT option for debugging encoder ( #440 )
### Fix bugs
* Fix combination of embedding structure and omitempty option ( #442 )
# v0.10.1 - 2023/03/13
### Fix bugs
* Fix checkptr error for array decoder ( #415 )
* Fix added buffer size check when decoding key ( #430 )
* Fix handling of anonymous fields other than struct ( #431 )
* Fix to not optimize when lower conversion can't handle byte-by-byte ( #432 )
* Fix a problem that MarshalIndent does not work when UnorderedMap is specified ( #435 )
* Fix mapDecoder.DecodeStream() for empty objects containing whitespace ( #425 )
* Fix an issue that could not set the correct NextField for fields in the embedded structure ( #438 )
# v0.10.0 - 2022/11/29
### New features
* Support JSON Path ( #250 )
### Fix bugs
* Fix marshaler for map's key ( #409 )
# v0.9.11 - 2022/08/18
### Fix bugs

View file

@ -19,7 +19,9 @@ type arrayDecoder struct {
}
func newArrayDecoder(dec Decoder, elemType *runtime.Type, alen int, structName, fieldName string) *arrayDecoder {
zeroValue := *(*unsafe.Pointer)(unsafe_New(elemType))
// workaround to avoid checkptr errors. cannot use `*(*unsafe.Pointer)(unsafe_New(elemType))` directly.
zeroValuePtr := unsafe_New(elemType)
zeroValue := **(**unsafe.Pointer)(unsafe.Pointer(&zeroValuePtr))
return &arrayDecoder{
valueDecoder: dec,
elemType: elemType,

View file

@ -88,7 +88,7 @@ func (d *mapDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) erro
mapValue = makemap(d.mapType, 0)
}
s.cursor++
if s.equalChar('}') {
if s.skipWhiteSpace() == '}' {
*(*unsafe.Pointer)(p) = mapValue
s.cursor++
return nil

View file

@ -51,6 +51,14 @@ func init() {
}
}
func toASCIILower(s string) string {
b := []byte(s)
for i := range b {
b[i] = largeToSmallTable[b[i]]
}
return string(b)
}
func newStructDecoder(structName, fieldName string, fieldMap map[string]*structFieldSet) *structDecoder {
return &structDecoder{
fieldMap: fieldMap,
@ -91,6 +99,10 @@ func (d *structDecoder) tryOptimize() {
for k, v := range d.fieldMap {
key := strings.ToLower(k)
if key != k {
if key != toASCIILower(k) {
d.isTriedOptimize = true
return
}
// already exists same key (e.g. Hello and HELLO has same lower case key
if _, exists := conflicted[key]; exists {
d.isTriedOptimize = true
@ -158,49 +170,53 @@ func (d *structDecoder) tryOptimize() {
}
// decode from '\uXXXX'
func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64) {
func decodeKeyCharByUnicodeRune(buf []byte, cursor int64) ([]byte, int64, error) {
const defaultOffset = 4
const surrogateOffset = 6
if cursor+defaultOffset >= int64(len(buf)) {
return nil, 0, errors.ErrUnexpectedEndOfJSON("escaped string", cursor)
}
r := unicodeToRune(buf[cursor : cursor+defaultOffset])
if utf16.IsSurrogate(r) {
cursor += defaultOffset
if cursor+surrogateOffset >= int64(len(buf)) || buf[cursor] != '\\' || buf[cursor+1] != 'u' {
return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1
return []byte(string(unicode.ReplacementChar)), cursor + defaultOffset - 1, nil
}
cursor += 2
r2 := unicodeToRune(buf[cursor : cursor+defaultOffset])
if r := utf16.DecodeRune(r, r2); r != unicode.ReplacementChar {
return []byte(string(r)), cursor + defaultOffset - 1
return []byte(string(r)), cursor + defaultOffset - 1, nil
}
}
return []byte(string(r)), cursor + defaultOffset - 1
return []byte(string(r)), cursor + defaultOffset - 1, nil
}
func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64) {
func decodeKeyCharByEscapedChar(buf []byte, cursor int64) ([]byte, int64, error) {
c := buf[cursor]
cursor++
switch c {
case '"':
return []byte{'"'}, cursor
return []byte{'"'}, cursor, nil
case '\\':
return []byte{'\\'}, cursor
return []byte{'\\'}, cursor, nil
case '/':
return []byte{'/'}, cursor
return []byte{'/'}, cursor, nil
case 'b':
return []byte{'\b'}, cursor
return []byte{'\b'}, cursor, nil
case 'f':
return []byte{'\f'}, cursor
return []byte{'\f'}, cursor, nil
case 'n':
return []byte{'\n'}, cursor
return []byte{'\n'}, cursor, nil
case 'r':
return []byte{'\r'}, cursor
return []byte{'\r'}, cursor, nil
case 't':
return []byte{'\t'}, cursor
return []byte{'\t'}, cursor, nil
case 'u':
return decodeKeyCharByUnicodeRune(buf, cursor)
}
return nil, cursor
return nil, cursor, nil
}
func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64, *structFieldSet, error) {
@ -242,7 +258,10 @@ func decodeKeyByBitmapUint8(d *structDecoder, buf []byte, cursor int64) (int64,
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\':
cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor)
if err != nil {
return 0, nil, err
}
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {
@ -305,7 +324,10 @@ func decodeKeyByBitmapUint16(d *structDecoder, buf []byte, cursor int64) (int64,
return 0, nil, errors.ErrUnexpectedEndOfJSON("string", cursor)
case '\\':
cursor++
chars, nextCursor := decodeKeyCharByEscapedChar(buf, cursor)
chars, nextCursor, err := decodeKeyCharByEscapedChar(buf, cursor)
if err != nil {
return 0, nil, err
}
for _, c := range chars {
curBit &= bitmap[keyIdx][largeToSmallTable[c]]
if curBit == 0 {

View file

@ -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

View file

@ -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,

View file

@ -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()

View file

@ -23,6 +23,7 @@ type Option struct {
ColorScheme *ColorScheme
Context context.Context
DebugOut io.Writer
DebugDOTOut io.WriteCloser
}
type EncodeFormat struct {

View file

@ -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

View file

@ -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')
}

View file

@ -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')
}

View file

@ -48,6 +48,13 @@ func DebugWith(w io.Writer) EncodeOptionFunc {
}
}
// DebugDOT sets the destination to write opcodes graph.
func DebugDOT(w io.WriteCloser) EncodeOptionFunc {
return func(opt *EncodeOption) {
opt.DebugDOTOut = w
}
}
// Colorize add an identifier for coloring to the string of the encoded result.
func Colorize(scheme *ColorScheme) EncodeOptionFunc {
return func(opt *EncodeOption) {