diff --git a/.golangci.yml b/.golangci.yml index 6bdcb8f..d667ce3 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -62,6 +62,10 @@ issues: - path: rtype.go linters: - golint + - stylecheck + - path: error.go + linters: + - staticcheck # Maximum issues count per one linter. Set to 0 to disable. Default is 50. max-issues-per-linter: 0 diff --git a/decode_compile.go b/decode_compile.go index 8ec2fd0..67b2f0b 100644 --- a/decode_compile.go +++ b/decode_compile.go @@ -7,6 +7,8 @@ import ( "strings" "unicode" "unsafe" + + "github.com/goccy/go-json/internal/runtime" ) var ( @@ -327,16 +329,16 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD structName = typ.Name() for i := 0; i < fieldNum; i++ { field := typ.Field(i) - if isIgnoredStructField(field) { + if runtime.IsIgnoredStructField(field) { continue } isUnexportedField := unicode.IsLower([]rune(field.Name)[0]) - tag := structTagFromField(field) + tag := runtime.StructTagFromField(field) dec, err := decodeCompile(type2rtype(field.Type), structName, field.Name, structTypeToDecoder) if err != nil { return nil, err } - if field.Anonymous && !tag.isTaggedKey { + if field.Anonymous && !tag.IsTaggedKey { if stDec, ok := dec.(*structDecoder); ok { if type2rtype(field.Type) == typ { // recursive definition @@ -414,19 +416,19 @@ func decodeCompileStruct(typ *rtype, structName, fieldName string, structTypeToD } } } else { - if tag.isString { + if tag.IsString { dec = newWrappedStringDecoder(type2rtype(field.Type), dec, structName, field.Name) } var key string - if tag.key != "" { - key = tag.key + if tag.Key != "" { + key = tag.Key } else { key = field.Name } fieldSet := &structFieldSet{ dec: dec, offset: field.Offset, - isTaggedKey: tag.isTaggedKey, + isTaggedKey: tag.IsTaggedKey, key: key, keyLen: int64(len(key)), } diff --git a/indent.go b/indent.go deleted file mode 100644 index 31c28b1..0000000 --- a/indent.go +++ /dev/null @@ -1,108 +0,0 @@ -package json - -import "bytes" - -func encodeWithIndent(dst *bytes.Buffer, src []byte, prefix, indentStr string) error { - length := int64(len(src)) - indentNum := 0 - indentBytes := []byte(indentStr) - for cursor := int64(0); cursor < length; cursor++ { - c := src[cursor] - switch c { - case ' ', '\t', '\n', '\r': - continue - case '"': - if err := dst.WriteByte(c); err != nil { - return err - } - for { - cursor++ - if err := dst.WriteByte(src[cursor]); err != nil { - return err - } - switch src[cursor] { - case '\\': - cursor++ - if err := dst.WriteByte(src[cursor]); err != nil { - return err - } - case '"': - goto LOOP_END - case nul: - return errUnexpectedEndOfJSON("string", length) - } - } - case '{': - if cursor+1 < length && src[cursor+1] == '}' { - if _, err := dst.Write([]byte{'{', '}'}); err != nil { - return err - } - cursor++ - } else { - indentNum++ - b := []byte{c, '\n'} - b = append(b, prefix...) - b = append(b, bytes.Repeat(indentBytes, indentNum)...) - if _, err := dst.Write(b); err != nil { - return err - } - } - case '}': - indentNum-- - if indentNum < 0 { - return errInvalidCharacter('}', "}", cursor) - } - b := []byte{'\n'} - b = append(b, prefix...) - b = append(b, bytes.Repeat(indentBytes, indentNum)...) - b = append(b, c) - if _, err := dst.Write(b); err != nil { - return err - } - case '[': - if cursor+1 < length && src[cursor+1] == ']' { - if _, err := dst.Write([]byte{'[', ']'}); err != nil { - return err - } - cursor++ - } else { - indentNum++ - b := []byte{c, '\n'} - b = append(b, prefix...) - b = append(b, bytes.Repeat(indentBytes, indentNum)...) - if _, err := dst.Write(b); err != nil { - return err - } - } - case ']': - indentNum-- - if indentNum < 0 { - return errInvalidCharacter(']', "]", cursor) - } - b := []byte{'\n'} - b = append(b, prefix...) - b = append(b, bytes.Repeat(indentBytes, indentNum)...) - b = append(b, c) - if _, err := dst.Write(b); err != nil { - return err - } - case ':': - if _, err := dst.Write([]byte{':', ' '}); err != nil { - return err - } - case ',': - b := []byte{',', '\n'} - b = append(b, prefix...) - b = append(b, bytes.Repeat(indentBytes, indentNum)...) - if _, err := dst.Write(b); err != nil { - return err - } - default: - if err := dst.WriteByte(c); err != nil { - return err - } - } - LOOP_END: - } - return nil -} diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 7d2ba7b..a03459c 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -21,42 +21,41 @@ import ( const uintptrSize = 4 << (^uintptr(0) >> 63) var ( - load = encoder.Load - store = encoder.Store - loadNPtr = encoder.LoadNPtr - ptrToPtr = encoder.PtrToPtr - ptrToNPtr = encoder.PtrToNPtr - ptrToUnsafePtr = encoder.PtrToUnsafePtr - ptrToInterface = encoder.PtrToInterface - ptrToUint64 = encoder.PtrToUint64 - ptrToFloat32 = encoder.PtrToFloat32 - ptrToFloat64 = encoder.PtrToFloat64 - ptrToString = encoder.PtrToString - ptrToBool = encoder.PtrToBool - ptrToBytes = encoder.PtrToBytes - ptrToNumber = encoder.PtrToNumber - ptrToSlice = encoder.PtrToSlice - appendInt = encoder.AppendInt - appendUint = encoder.AppendUint - appendFloat32 = encoder.AppendFloat32 - appendFloat64 = encoder.AppendFloat64 - appendString = encoder.AppendString - appendBool = encoder.AppendBool - appendByteSlice = encoder.AppendByteSlice - appendNumber = encoder.AppendNumber - appendMarshalJSON = encoder.AppendMarshalJSON - appendMarshalText = encoder.AppendMarshalText - appendNull = encoder.AppendNull - appendComma = encoder.AppendComma - appendStructEnd = encoder.AppendStructEnd - errUnsupportedValue = encoder.ErrUnsupportedValue - errUnsupportedFloat = encoder.ErrUnsupportedFloat - errMarshalerWithCode = encoder.ErrMarshalerWithCode - mapiterinit = encoder.MapIterInit - mapiterkey = encoder.MapIterKey - mapitervalue = encoder.MapIterValue - mapiternext = encoder.MapIterNext - maplen = encoder.MapLen + load = encoder.Load + store = encoder.Store + loadNPtr = encoder.LoadNPtr + ptrToPtr = encoder.PtrToPtr + ptrToNPtr = encoder.PtrToNPtr + ptrToUnsafePtr = encoder.PtrToUnsafePtr + ptrToInterface = encoder.PtrToInterface + ptrToUint64 = encoder.PtrToUint64 + ptrToFloat32 = encoder.PtrToFloat32 + ptrToFloat64 = encoder.PtrToFloat64 + ptrToString = encoder.PtrToString + ptrToBool = encoder.PtrToBool + ptrToBytes = encoder.PtrToBytes + ptrToNumber = encoder.PtrToNumber + ptrToSlice = encoder.PtrToSlice + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendString + appendBool = encoder.AppendBool + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + appendMarshalJSON = encoder.AppendMarshalJSON + appendMarshalText = encoder.AppendMarshalText + appendNull = encoder.AppendNull + appendComma = encoder.AppendComma + appendStructEnd = encoder.AppendStructEnd + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen ) type emptyInterface struct { diff --git a/internal/encoder/vm_escaped/vm.go b/internal/encoder/vm_escaped/vm.go index 53eba06..59edf0e 100644 --- a/internal/encoder/vm_escaped/vm.go +++ b/internal/encoder/vm_escaped/vm.go @@ -21,42 +21,41 @@ import ( const uintptrSize = 4 << (^uintptr(0) >> 63) var ( - load = encoder.Load - store = encoder.Store - loadNPtr = encoder.LoadNPtr - ptrToPtr = encoder.PtrToPtr - ptrToNPtr = encoder.PtrToNPtr - ptrToUnsafePtr = encoder.PtrToUnsafePtr - ptrToInterface = encoder.PtrToInterface - ptrToUint64 = encoder.PtrToUint64 - ptrToFloat32 = encoder.PtrToFloat32 - ptrToFloat64 = encoder.PtrToFloat64 - ptrToString = encoder.PtrToString - ptrToBool = encoder.PtrToBool - ptrToBytes = encoder.PtrToBytes - ptrToNumber = encoder.PtrToNumber - ptrToSlice = encoder.PtrToSlice - appendInt = encoder.AppendInt - appendUint = encoder.AppendUint - appendFloat32 = encoder.AppendFloat32 - appendFloat64 = encoder.AppendFloat64 - appendString = encoder.AppendEscapedString - appendBool = encoder.AppendBool - appendByteSlice = encoder.AppendByteSlice - appendNumber = encoder.AppendNumber - appendMarshalJSON = encoder.AppendMarshalJSON - appendMarshalText = encoder.AppendMarshalText - appendNull = encoder.AppendNull - appendComma = encoder.AppendComma - appendStructEnd = encoder.AppendStructEnd - errUnsupportedValue = encoder.ErrUnsupportedValue - errUnsupportedFloat = encoder.ErrUnsupportedFloat - errMarshalerWithCode = encoder.ErrMarshalerWithCode - mapiterinit = encoder.MapIterInit - mapiterkey = encoder.MapIterKey - mapitervalue = encoder.MapIterValue - mapiternext = encoder.MapIterNext - maplen = encoder.MapLen + load = encoder.Load + store = encoder.Store + loadNPtr = encoder.LoadNPtr + ptrToPtr = encoder.PtrToPtr + ptrToNPtr = encoder.PtrToNPtr + ptrToUnsafePtr = encoder.PtrToUnsafePtr + ptrToInterface = encoder.PtrToInterface + ptrToUint64 = encoder.PtrToUint64 + ptrToFloat32 = encoder.PtrToFloat32 + ptrToFloat64 = encoder.PtrToFloat64 + ptrToString = encoder.PtrToString + ptrToBool = encoder.PtrToBool + ptrToBytes = encoder.PtrToBytes + ptrToNumber = encoder.PtrToNumber + ptrToSlice = encoder.PtrToSlice + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendEscapedString + appendBool = encoder.AppendBool + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + appendMarshalJSON = encoder.AppendMarshalJSON + appendMarshalText = encoder.AppendMarshalText + appendNull = encoder.AppendNull + appendComma = encoder.AppendComma + appendStructEnd = encoder.AppendStructEnd + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen ) type emptyInterface struct { diff --git a/internal/encoder/vm_escaped_indent/vm.go b/internal/encoder/vm_escaped_indent/vm.go index e64d975..992d1bc 100644 --- a/internal/encoder/vm_escaped_indent/vm.go +++ b/internal/encoder/vm_escaped_indent/vm.go @@ -16,43 +16,42 @@ import ( const uintptrSize = 4 << (^uintptr(0) >> 63) var ( - load = encoder.Load - store = encoder.Store - loadNPtr = encoder.LoadNPtr - ptrToPtr = encoder.PtrToPtr - ptrToNPtr = encoder.PtrToNPtr - ptrToUnsafePtr = encoder.PtrToUnsafePtr - ptrToInterface = encoder.PtrToInterface - ptrToUint64 = encoder.PtrToUint64 - ptrToFloat32 = encoder.PtrToFloat32 - ptrToFloat64 = encoder.PtrToFloat64 - ptrToString = encoder.PtrToString - ptrToBool = encoder.PtrToBool - ptrToBytes = encoder.PtrToBytes - ptrToNumber = encoder.PtrToNumber - ptrToSlice = encoder.PtrToSlice - appendInt = encoder.AppendInt - appendUint = encoder.AppendUint - appendFloat32 = encoder.AppendFloat32 - appendFloat64 = encoder.AppendFloat64 - appendString = encoder.AppendEscapedString - appendBool = encoder.AppendBool - appendByteSlice = encoder.AppendByteSlice - appendNumber = encoder.AppendNumber - appendMarshalJSON = encoder.AppendMarshalJSONIndent - appendMarshalText = encoder.AppendMarshalTextIndent - appendNull = encoder.AppendNull - appendComma = encoder.AppendCommaIndent - appendIndent = encoder.AppendIndent - appendStructEnd = encoder.AppendStructEndIndent - errUnsupportedValue = encoder.ErrUnsupportedValue - errUnsupportedFloat = encoder.ErrUnsupportedFloat - errMarshalerWithCode = encoder.ErrMarshalerWithCode - mapiterinit = encoder.MapIterInit - mapiterkey = encoder.MapIterKey - mapitervalue = encoder.MapIterValue - mapiternext = encoder.MapIterNext - maplen = encoder.MapLen + load = encoder.Load + store = encoder.Store + loadNPtr = encoder.LoadNPtr + ptrToPtr = encoder.PtrToPtr + ptrToNPtr = encoder.PtrToNPtr + ptrToUnsafePtr = encoder.PtrToUnsafePtr + ptrToInterface = encoder.PtrToInterface + ptrToUint64 = encoder.PtrToUint64 + ptrToFloat32 = encoder.PtrToFloat32 + ptrToFloat64 = encoder.PtrToFloat64 + ptrToString = encoder.PtrToString + ptrToBool = encoder.PtrToBool + ptrToBytes = encoder.PtrToBytes + ptrToNumber = encoder.PtrToNumber + ptrToSlice = encoder.PtrToSlice + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendEscapedString + appendBool = encoder.AppendBool + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + appendMarshalJSON = encoder.AppendMarshalJSONIndent + appendMarshalText = encoder.AppendMarshalTextIndent + appendNull = encoder.AppendNull + appendComma = encoder.AppendCommaIndent + appendIndent = encoder.AppendIndent + appendStructEnd = encoder.AppendStructEndIndent + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen ) type emptyInterface struct { diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 34f49a9..52e7869 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -22,43 +22,42 @@ import ( const uintptrSize = 4 << (^uintptr(0) >> 63) var ( - load = encoder.Load - store = encoder.Store - loadNPtr = encoder.LoadNPtr - ptrToPtr = encoder.PtrToPtr - ptrToNPtr = encoder.PtrToNPtr - ptrToUnsafePtr = encoder.PtrToUnsafePtr - ptrToInterface = encoder.PtrToInterface - ptrToUint64 = encoder.PtrToUint64 - ptrToFloat32 = encoder.PtrToFloat32 - ptrToFloat64 = encoder.PtrToFloat64 - ptrToString = encoder.PtrToString - ptrToBool = encoder.PtrToBool - ptrToBytes = encoder.PtrToBytes - ptrToNumber = encoder.PtrToNumber - ptrToSlice = encoder.PtrToSlice - appendInt = encoder.AppendInt - appendUint = encoder.AppendUint - appendFloat32 = encoder.AppendFloat32 - appendFloat64 = encoder.AppendFloat64 - appendString = encoder.AppendString - appendBool = encoder.AppendBool - appendByteSlice = encoder.AppendByteSlice - appendNumber = encoder.AppendNumber - appendMarshalJSON = encoder.AppendMarshalJSONIndent - appendMarshalText = encoder.AppendMarshalTextIndent - appendNull = encoder.AppendNull - appendComma = encoder.AppendCommaIndent - appendIndent = encoder.AppendIndent - appendStructEnd = encoder.AppendStructEndIndent - errUnsupportedValue = encoder.ErrUnsupportedValue - errUnsupportedFloat = encoder.ErrUnsupportedFloat - errMarshalerWithCode = encoder.ErrMarshalerWithCode - mapiterinit = encoder.MapIterInit - mapiterkey = encoder.MapIterKey - mapitervalue = encoder.MapIterValue - mapiternext = encoder.MapIterNext - maplen = encoder.MapLen + load = encoder.Load + store = encoder.Store + loadNPtr = encoder.LoadNPtr + ptrToPtr = encoder.PtrToPtr + ptrToNPtr = encoder.PtrToNPtr + ptrToUnsafePtr = encoder.PtrToUnsafePtr + ptrToInterface = encoder.PtrToInterface + ptrToUint64 = encoder.PtrToUint64 + ptrToFloat32 = encoder.PtrToFloat32 + ptrToFloat64 = encoder.PtrToFloat64 + ptrToString = encoder.PtrToString + ptrToBool = encoder.PtrToBool + ptrToBytes = encoder.PtrToBytes + ptrToNumber = encoder.PtrToNumber + ptrToSlice = encoder.PtrToSlice + appendInt = encoder.AppendInt + appendUint = encoder.AppendUint + appendFloat32 = encoder.AppendFloat32 + appendFloat64 = encoder.AppendFloat64 + appendString = encoder.AppendString + appendBool = encoder.AppendBool + appendByteSlice = encoder.AppendByteSlice + appendNumber = encoder.AppendNumber + appendMarshalJSON = encoder.AppendMarshalJSONIndent + appendMarshalText = encoder.AppendMarshalTextIndent + appendNull = encoder.AppendNull + appendComma = encoder.AppendCommaIndent + appendIndent = encoder.AppendIndent + appendStructEnd = encoder.AppendStructEndIndent + errUnsupportedValue = encoder.ErrUnsupportedValue + errUnsupportedFloat = encoder.ErrUnsupportedFloat + mapiterinit = encoder.MapIterInit + mapiterkey = encoder.MapIterKey + mapitervalue = encoder.MapIterValue + mapiternext = encoder.MapIterNext + maplen = encoder.MapLen ) type emptyInterface struct { diff --git a/internal/runtime/rtype.go b/internal/runtime/rtype.go index c73223d..4db10de 100644 --- a/internal/runtime/rtype.go +++ b/internal/runtime/rtype.go @@ -252,8 +252,9 @@ func IfaceIndir(*Type) bool //go:noescape func RType2Type(t *Type) reflect.Type +//go:nolint structcheck type emptyInterface struct { - typ *Type + _ *Type ptr unsafe.Pointer } diff --git a/rtype.go b/rtype.go index 6d06865..3459884 100644 --- a/rtype.go +++ b/rtype.go @@ -18,10 +18,6 @@ func rtype_ptrTo(t *rtype) *rtype { return runtime.PtrTo(t) } -func ifaceIndir(t *rtype) bool { - return runtime.IfaceIndir(t) -} - func rtype2type(t *rtype) reflect.Type { return runtime.RType2Type(t) } diff --git a/struct_field.go b/struct_field.go deleted file mode 100644 index 5a85cff..0000000 --- a/struct_field.go +++ /dev/null @@ -1,81 +0,0 @@ -package json - -import ( - "reflect" - "strings" - "unicode" -) - -func getTag(field reflect.StructField) string { - return field.Tag.Get("json") -} - -func isIgnoredStructField(field reflect.StructField) bool { - if field.PkgPath != "" { - if field.Anonymous { - if !(field.Type.Kind() == reflect.Ptr && field.Type.Elem().Kind() == reflect.Struct) && field.Type.Kind() != reflect.Struct { - return true - } - } else { - // private field - return true - } - } - tag := getTag(field) - return tag == "-" -} - -type structTag struct { - key string - isTaggedKey bool - isOmitEmpty bool - isString bool - field reflect.StructField -} - -type structTags []*structTag - -func (t structTags) existsKey(key string) bool { - for _, tt := range t { - if tt.key == key { - return true - } - } - return false -} - -func isValidTag(s string) bool { - if s == "" { - return false - } - for _, c := range s { - switch { - case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c): - // Backslash and quote chars are reserved, but - // otherwise any punctuation chars are allowed - // in a tag name. - case !unicode.IsLetter(c) && !unicode.IsDigit(c): - return false - } - } - return true -} - -func structTagFromField(field reflect.StructField) *structTag { - keyName := field.Name - tag := getTag(field) - st := &structTag{field: field} - opts := strings.Split(tag, ",") - if len(opts) > 0 { - if opts[0] != "" && isValidTag(opts[0]) { - keyName = opts[0] - st.isTaggedKey = true - } - } - st.key = keyName - if len(opts) > 1 { - st.isOmitEmpty = opts[1] == "omitempty" - st.isString = opts[1] == "string" - } - return st -}