diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..6550bf5 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,58 @@ +run: + skip-files: + - encode_optype.go + - ".*_test\\.go$" + +linters-settings: + govet: + enable-all: true + disable: + - shadow + +linters: + enable-all: true + disable: + - dogsled + - dupl + - exhaustive + - funlen + - gci + - gochecknoglobals + - gochecknoinits + - gocognit + - gocritic + - gocyclo + - godot + - godox + - goerr113 + - gofumpt + - gomnd + - gosec + - interfacer + - lll + - nakedret + - nestif + - nlreturn + - testpackage + - wsl + +issues: + exclude-rules: + # not needed + - path: /*.go + text: "ST1003: should not use underscores in package names" + linters: + - stylecheck + - path: /*.go + text: "don't use an underscore in package name" + linters: + - golint + - path: rtype.go + linters: + - golint + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 diff --git a/decode.go b/decode.go index 255a7b5..66dcc17 100644 --- a/decode.go +++ b/decode.go @@ -21,9 +21,8 @@ type decoder interface { } type Decoder struct { - s *stream - disallowUnknownFields bool - structTypeToDecoder map[uintptr]decoder + s *stream + structTypeToDecoder map[uintptr]decoder } type decoderMap struct { @@ -240,11 +239,12 @@ func (d *Decoder) Token() (Token, error) { if s.read() { continue } - return nil, io.EOF + goto END default: return nil, errInvalidCharacter(s.char(), "token", s.totalOffset()) } } +END: return nil, io.EOF } diff --git a/decode_bytes.go b/decode_bytes.go index e563c4a..a82fe06 100644 --- a/decode_bytes.go +++ b/decode_bytes.go @@ -147,7 +147,6 @@ func (d *bytesDecoder) decodeBinary(buf []byte, cursor int64, p unsafe.Pointer) } cursor++ } - return nil, 0, errUnexpectedEndOfJSON("[]byte", cursor) case '[': if d.sliceDecoder == nil { return nil, 0, &UnmarshalTypeError{ diff --git a/decode_compile.go b/decode_compile.go index 3e3d82f..cd07394 100644 --- a/decode_compile.go +++ b/decode_compile.go @@ -309,7 +309,7 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod // recursive definition continue } - d.removeConflictFields(fieldMap, conflictedMap, stDec, uintptr(field.Offset)) + d.removeConflictFields(fieldMap, conflictedMap, stDec, field.Offset) } else if pdec, ok := dec.(*ptrDecoder); ok { contentDec := pdec.contentDecoder() if pdec.typ == typ { @@ -326,7 +326,7 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod if !exists { fieldSet := &structFieldSet{ dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec), - offset: uintptr(field.Offset), + offset: field.Offset, isTaggedKey: v.isTaggedKey, } fieldMap[k] = fieldSet @@ -347,7 +347,7 @@ func (d *Decoder) compileStruct(typ *rtype, structName, fieldName string) (decod if v.isTaggedKey { fieldSet := &structFieldSet{ dec: newAnonymousFieldDecoder(pdec.typ, v.offset, v.dec), - offset: uintptr(field.Offset), + offset: field.Offset, isTaggedKey: v.isTaggedKey, } fieldMap[k] = fieldSet diff --git a/decode_context.go b/decode_context.go index 13ec668..23e0d3f 100644 --- a/decode_context.go +++ b/decode_context.go @@ -142,5 +142,4 @@ func skipValue(buf []byte, cursor int64) (int64, error) { } cursor++ } - return cursor, errUnexpectedEndOfJSON("value of object", cursor) } diff --git a/decode_int.go b/decode_int.go index b752101..fb0d3c7 100644 --- a/decode_int.go +++ b/decode_int.go @@ -149,7 +149,6 @@ func (d *intDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) } } - return nil, 0, errUnexpectedEndOfJSON("number(integer)", cursor) } func (d *intDecoder) decodeStream(s *stream, p unsafe.Pointer) error { diff --git a/decode_interface.go b/decode_interface.go index 840718e..3590f0c 100644 --- a/decode_interface.go +++ b/decode_interface.go @@ -143,7 +143,6 @@ func (d *interfaceDecoder) decodeStream(s *stream, p unsafe.Pointer) error { } s.cursor++ } - return errUnexpectedEndOfJSON("string", s.totalOffset()) case 't': if err := trueBytes(s); err != nil { return err @@ -229,7 +228,6 @@ func (d *interfaceDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (i } cursor++ } - return 0, errUnexpectedEndOfJSON("string", cursor) case 't': if cursor+3 >= int64(len(buf)) { return 0, errUnexpectedEndOfJSON("bool(true)", cursor) diff --git a/decode_map.go b/decode_map.go index e59f0f7..8a26dd6 100644 --- a/decode_map.go +++ b/decode_map.go @@ -94,7 +94,6 @@ func (d *mapDecoder) decodeStream(s *stream, p unsafe.Pointer) error { return errExpected("comma after object value", s.totalOffset()) } } - return nil } func (d *mapDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (int64, error) { @@ -151,7 +150,6 @@ func (d *mapDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (int64, if err != nil { return 0, err } - cursor = valueCursor mapassign(d.mapType, mapValue, unsafe.Pointer(&key), unsafe.Pointer(&value)) cursor = skipWhiteSpace(buf, valueCursor) if buf[cursor] == '}' { diff --git a/decode_ptr.go b/decode_ptr.go index 2b507bf..b7d0fd3 100644 --- a/decode_ptr.go +++ b/decode_ptr.go @@ -28,6 +28,7 @@ func (d *ptrDecoder) contentDecoder() decoder { return dec.contentDecoder() } +//nolint:golint //go:linkname unsafe_New reflect.unsafe_New func unsafe_New(*rtype) unsafe.Pointer diff --git a/decode_stream.go b/decode_stream.go index ca9d7d4..9907505 100644 --- a/decode_stream.go +++ b/decode_stream.go @@ -16,7 +16,6 @@ type stream struct { r io.Reader offset int64 cursor int64 - readPos int64 allRead bool useNumber bool disallowUnknownFields bool @@ -200,5 +199,4 @@ func (s *stream) skipValue() error { } s.cursor++ } - return errUnexpectedEndOfJSON("value of object", s.offset) } diff --git a/decode_string.go b/decode_string.go index f26a9b4..a90f911 100644 --- a/decode_string.go +++ b/decode_string.go @@ -150,6 +150,7 @@ RETRY: return nil } +//nolint:deadcode,unused func appendCoerceInvalidUTF8(b []byte, s []byte) []byte { c := [4]byte{} @@ -298,7 +299,6 @@ func (d *stringDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, err } cursor++ } - return nil, 0, errUnexpectedEndOfJSON("string", cursor) case 'n': buflen := int64(len(buf)) if cursor+3 >= buflen { diff --git a/decode_struct.go b/decode_struct.go index 4ed88d8..0110f97 100644 --- a/decode_struct.go +++ b/decode_struct.go @@ -93,7 +93,6 @@ func (d *structDecoder) decodeStream(s *stream, p unsafe.Pointer) error { } s.cursor++ } - return nil } func (d *structDecoder) decode(buf []byte, cursor int64, p unsafe.Pointer) (int64, error) { diff --git a/decode_uint.go b/decode_uint.go index be242ee..cc67922 100644 --- a/decode_uint.go +++ b/decode_uint.go @@ -70,12 +70,12 @@ func (d *uintDecoder) decodeStreamByte(s *stream) ([]byte, error) { } num := s.buf[start:s.cursor] return num, nil - default: - return nil, d.typeError([]byte{s.char()}, s.totalOffset()) case nul: if s.read() { continue } + default: + return nil, d.typeError([]byte{s.char()}, s.totalOffset()) } break } diff --git a/encode.go b/encode.go index ad6aa78..1d13270 100644 --- a/encode.go +++ b/encode.go @@ -128,7 +128,7 @@ func (e *Encoder) SetIndent(prefix, indent string) { func marshal(v interface{}, opt EncodeOption) ([]byte, error) { ctx := takeEncodeRuntimeContext() - buf, err := encode(ctx, v, EncodeOptionHTMLEscape) + buf, err := encode(ctx, v, opt|EncodeOptionHTMLEscape) if err != nil { releaseEncodeRuntimeContext(ctx) return nil, err @@ -149,7 +149,7 @@ func marshal(v interface{}, opt EncodeOption) ([]byte, error) { func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) { ctx := takeEncodeRuntimeContext() - buf, err := encodeNoEscape(ctx, v, EncodeOptionHTMLEscape) + buf, err := encodeNoEscape(ctx, v, opt|EncodeOptionHTMLEscape) if err != nil { releaseEncodeRuntimeContext(ctx) return nil, err @@ -170,7 +170,7 @@ func marshalNoEscape(v interface{}, opt EncodeOption) ([]byte, error) { func marshalIndent(v interface{}, prefix, indent string, opt EncodeOption) ([]byte, error) { ctx := takeEncodeRuntimeContext() - buf, err := encodeIndent(ctx, v, prefix, indent, EncodeOptionHTMLEscape) + buf, err := encodeIndent(ctx, v, prefix, indent, opt|EncodeOptionHTMLEscape) if err != nil { releaseEncodeRuntimeContext(ctx) return nil, err @@ -320,10 +320,6 @@ func encodeBool(b []byte, v bool) []byte { return append(b, "false"...) } -func encodeBytes(dst []byte, src []byte) []byte { - return append(dst, src...) -} - func encodeNull(b []byte) []byte { return append(b, "null"...) } diff --git a/encode_compile.go b/encode_compile.go index 06f21a0..048a3f4 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -73,7 +73,7 @@ func setupOpcodeSets() error { } } } - addrRange := uintptr(max) - uintptr(min) + addrRange := max - min if addrRange == 0 { return fmt.Errorf("failed to get address range of types") } @@ -87,9 +87,7 @@ func setupOpcodeSets() error { } func init() { - if err := setupOpcodeSets(); err != nil { - // fallback to slow path - } + _ = setupOpcodeSets() } func encodeCompileToGetCodeSetSlowPath(typeptr uintptr) (*opcodeSet, error) { @@ -772,6 +770,7 @@ func encodeTypeToHeaderType(ctx *encodeCompileContext, code *opcode) opType { ptrNum++ code = code.next ctx.decIndex() + continue } break } @@ -896,6 +895,7 @@ func encodeTypeToFieldType(ctx *encodeCompileContext, code *opcode) opType { ptrNum++ code = code.next ctx.decIndex() + continue } break } @@ -1155,7 +1155,7 @@ type structFieldPair struct { linked bool } -func encodeAnonymousStructFieldPairMap(typ *rtype, tags structTags, named string, valueCode *opcode) map[string][]structFieldPair { +func encodeAnonymousStructFieldPairMap(tags structTags, named string, valueCode *opcode) map[string][]structFieldPair { anonymousFields := map[string][]structFieldPair{} f := valueCode var prevAnonymousField *opcode @@ -1197,7 +1197,7 @@ func encodeAnonymousStructFieldPairMap(typ *rtype, tags structTags, named string isTaggedKey: f.isTaggedKey, }) if f.next != nil && f.nextField != f.next && f.next.op.codeType() == codeStructField { - for k, v := range encodeAnonymousStructFieldPairMap(typ, tags, named, f.next) { + for k, v := range encodeAnonymousStructFieldPairMap(tags, named, f.next) { anonymousFields[k] = append(anonymousFields[k], v...) } } @@ -1323,7 +1323,7 @@ func encodeCompileStruct(ctx *encodeCompileContext, isPtr bool) (*opcode, error) if tag.isTaggedKey { tagKey = tag.key } - for k, v := range encodeAnonymousStructFieldPairMap(typ, tags, tagKey, valueCode) { + for k, v := range encodeAnonymousStructFieldPairMap(tags, tagKey, valueCode) { anonymousFields[k] = append(anonymousFields[k], v...) } } diff --git a/encode_context.go b/encode_context.go index 692f9d7..83ceb12 100644 --- a/encode_context.go +++ b/encode_context.go @@ -28,7 +28,6 @@ func (m *mapslice) Swap(i, j int) { } type encodeMapContext struct { - iter unsafe.Pointer pos []int slice *mapslice buf []byte diff --git a/encode_opcode.go b/encode_opcode.go index 96492e2..44f38c5 100644 --- a/encode_opcode.go +++ b/encode_opcode.go @@ -124,7 +124,6 @@ func (c *opcode) beforeLastCode() *opcode { } code = nextCode } - return nil } func (c *opcode) totalLength() int { diff --git a/encode_opcode_test.go b/encode_opcode_test.go new file mode 100644 index 0000000..919a688 --- /dev/null +++ b/encode_opcode_test.go @@ -0,0 +1,18 @@ +package json + +import ( + "testing" + "unsafe" +) + +func TestDumpOpcode(t *testing.T) { + var v interface{} = 1 + header := (*interfaceHeader)(unsafe.Pointer(&v)) + typ := header.typ + typeptr := uintptr(unsafe.Pointer(typ)) + codeSet, err := encodeCompileToGetCodeSet(typeptr) + if err != nil { + t.Fatal(err) + } + codeSet.code.dump() +} diff --git a/encode_string.go b/encode_string.go index 9dca7a5..a0c1280 100644 --- a/encode_string.go +++ b/encode_string.go @@ -347,345 +347,6 @@ var needEscape = [256]bool{ 0xff: true, } -// htmlSafeSet holds the value true if the ASCII character with the given -// array position can be safely represented inside a JSON string, embedded -// inside of HTML