From ff871cb20dc30659ff01a7cee48d4638558c6186 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 19 Mar 2021 23:31:29 +0900 Subject: [PATCH 1/3] Add bytes test --- cover_bool_test.go | 21 + cover_bytes_test.go | 1828 ++++++++++++++++++++ cover_float32_test.go | 21 + cover_float64_test.go | 21 + cover_helper_test.go | 16 + cover_int16_test.go | 21 + cover_int32_test.go | 21 + cover_int64_test.go | 21 + cover_int8_test.go | 21 + cover_int_test.go | 21 + cover_string_test.go | 21 + cover_uint16_test.go | 21 + cover_uint32_test.go | 21 + cover_uint64_test.go | 21 + cover_uint8_test.go | 21 + cover_uint_test.go | 21 + internal/encoder/compiler.go | 255 ++- internal/encoder/opcode.go | 8 + internal/encoder/vm/util.go | 11 +- internal/encoder/vm/vm.go | 6 - internal/encoder/vm_escaped/util.go | 11 +- internal/encoder/vm_escaped/vm.go | 6 - internal/encoder/vm_escaped_indent/util.go | 11 +- internal/encoder/vm_escaped_indent/vm.go | 4 - internal/encoder/vm_indent/util.go | 11 +- internal/encoder/vm_indent/vm.go | 4 - 26 files changed, 2418 insertions(+), 47 deletions(-) create mode 100644 cover_bytes_test.go diff --git a/cover_bool_test.go b/cover_bool_test.go index fcf8342..6dd6cc5 100644 --- a/cover_bool_test.go +++ b/cover_bool_test.go @@ -32,6 +32,27 @@ func TestCoverBool(t *testing.T) { name string data interface{} }{ + { + name: "Bool", + data: bool(true), + }, + { + name: "BoolPtr", + data: boolptr(true), + }, + { + name: "BoolPtr3", + data: boolptr3(true), + }, + { + name: "BoolPtrNil", + data: (*bool)(nil), + }, + { + name: "BoolPtr3Nil", + data: (***bool)(nil), + }, + // HeadBoolZero { name: "HeadBoolZero", diff --git a/cover_bytes_test.go b/cover_bytes_test.go new file mode 100644 index 0000000..7e08d83 --- /dev/null +++ b/cover_bytes_test.go @@ -0,0 +1,1828 @@ +package json_test + +import ( + "bytes" + "fmt" + "testing" + + "github.com/goccy/go-json" +) + +func TestCoverBytes(t *testing.T) { + type structBytes struct { + A []byte `json:"a"` + } + type structBytesOmitEmpty struct { + A []byte `json:"a,omitempty"` + } + type structBytesBytes struct { + A []byte `json:"a,bytes"` + } + + type structBytesPtr struct { + A *[]byte `json:"a"` + } + type structBytesPtrOmitEmpty struct { + A *[]byte `json:"a,omitempty"` + } + type structBytesPtrBytes struct { + A *[]byte `json:"a,bytes"` + } + + tests := []struct { + name string + data interface{} + }{ + { + name: "Bytes", + data: []byte("a"), + }, + { + name: "BytesPtr", + data: []byte("a"), + }, + { + name: "BytesPtr3", + data: bytesptr3([]byte("a")), + }, + { + name: "BytesPtrNil", + data: (*[]byte)(nil), + }, + { + name: "BytesPtr3Nil", + data: (***[]byte)(nil), + }, + + // HeadBytesZero + { + name: "HeadBytesZero", + data: struct { + A []byte `json:"a"` + }{}, + }, + { + name: "HeadBytesZeroOmitEmpty", + data: struct { + A []byte `json:"a,omitempty"` + }{}, + }, + { + name: "HeadBytesZeroString", + data: struct { + A []byte `json:"a,string"` + }{}, + }, + + // HeadBytes + { + name: "HeadString", + data: struct { + A []byte `json:"a"` + }{A: []byte("foo")}, + }, + { + name: "HeadBytesOmitEmpty", + data: struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")}, + }, + { + name: "HeadBytesString", + data: struct { + A []byte `json:"a,string"` + }{A: []byte("foo")}, + }, + + // HeadBytesPtr + { + name: "HeadBytesPtr", + data: struct { + A *[]byte `json:"a"` + }{A: bytesptr([]byte("foo"))}, + }, + { + name: "HeadBytesPtrOmitEmpty", + data: struct { + A *[]byte `json:"a,omitempty"` + }{A: bytesptr([]byte("foo"))}, + }, + { + name: "HeadBytesPtrString", + data: struct { + A *[]byte `json:"a,string"` + }{A: bytesptr([]byte("foo"))}, + }, + + // HeadBytesPtrNil + { + name: "HeadBytesPtrNil", + data: struct { + A *[]byte `json:"a"` + }{A: nil}, + }, + { + name: "HeadBytesPtrNilOmitEmpty", + data: struct { + A *[]byte `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "HeadBytesPtrNilString", + data: struct { + A *[]byte `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadBytesZero + { + name: "PtrHeadBytesZero", + data: &struct { + A []byte `json:"a"` + }{}, + }, + { + name: "PtrHeadBytesZeroOmitEmpty", + data: &struct { + A []byte `json:"a,omitempty"` + }{}, + }, + { + name: "PtrHeadBytesZeroString", + data: &struct { + A []byte `json:"a,string"` + }{}, + }, + + // PtrHeadBytes + { + name: "PtrHeadString", + data: &struct { + A []byte `json:"a"` + }{A: []byte("foo")}, + }, + { + name: "PtrHeadBytesOmitEmpty", + data: &struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")}, + }, + { + name: "PtrHeadBytesString", + data: &struct { + A []byte `json:"a,string"` + }{A: []byte("foo")}, + }, + + // PtrHeadBytesPtr + { + name: "PtrHeadBytesPtr", + data: &struct { + A *[]byte `json:"a"` + }{A: bytesptr([]byte("foo"))}, + }, + { + name: "PtrHeadBytesPtrOmitEmpty", + data: &struct { + A *[]byte `json:"a,omitempty"` + }{A: bytesptr([]byte("foo"))}, + }, + { + name: "PtrHeadBytesPtrString", + data: &struct { + A *[]byte `json:"a,string"` + }{A: bytesptr([]byte("foo"))}, + }, + + // PtrHeadBytesPtrNil + { + name: "PtrHeadBytesPtrNil", + data: &struct { + A *[]byte `json:"a"` + }{A: nil}, + }, + { + name: "PtrHeadBytesPtrNilOmitEmpty", + data: &struct { + A *[]byte `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadBytesPtrNilString", + data: &struct { + A *[]byte `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadBytesNil + { + name: "PtrHeadBytesNil", + data: (*struct { + A *[]byte `json:"a"` + })(nil), + }, + { + name: "PtrHeadBytesNilOmitEmpty", + data: (*struct { + A *[]byte `json:"a,omitempty"` + })(nil), + }, + { + name: "PtrHeadBytesNilString", + data: (*struct { + A *[]byte `json:"a,string"` + })(nil), + }, + + // HeadBytesZeroMultiFields + { + name: "HeadBytesZeroMultiFields", + data: struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{}, + }, + { + name: "HeadBytesZeroMultiFieldsOmitEmpty", + data: struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + C []byte `json:"c,omitempty"` + }{}, + }, + { + name: "HeadBytesZeroMultiFieldsString", + data: struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + C []byte `json:"c,string"` + }{}, + }, + + // HeadBytesMultiFields + { + name: "HeadBytesMultiFields", + data: struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte([]byte("baz"))}, + }, + { + name: "HeadBytesMultiFieldsOmitEmpty", + data: struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + C []byte `json:"c,omitempty"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte([]byte("baz"))}, + }, + { + name: "HeadBytesMultiFieldsString", + data: struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + C []byte `json:"c,string"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte([]byte("baz"))}, + }, + + // HeadBytesPtrMultiFields + { + name: "HeadBytesPtrMultiFields", + data: struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + C *[]byte `json:"c"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte([]byte("baz")))}, + }, + { + name: "HeadBytesPtrMultiFieldsOmitEmpty", + data: struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + C *[]byte `json:"c,omitempty"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte([]byte("baz")))}, + }, + { + name: "HeadBytesPtrMultiFieldsString", + data: struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + C *[]byte `json:"c,string"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte([]byte("baz")))}, + }, + + // HeadBytesPtrNilMultiFields + { + name: "HeadBytesPtrNilMultiFields", + data: struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + C *[]byte `json:"c"` + }{A: nil, B: nil, C: nil}, + }, + { + name: "HeadBytesPtrNilMultiFieldsOmitEmpty", + data: struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + C *[]byte `json:"c,omitempty"` + }{A: nil, B: nil, C: nil}, + }, + { + name: "HeadBytesPtrNilMultiFieldsString", + data: struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + C *[]byte `json:"c,string"` + }{A: nil, B: nil, C: nil}, + }, + + // PtrHeadBytesZeroMultiFields + { + name: "PtrHeadBytesZeroMultiFields", + data: &struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{}, + }, + { + name: "PtrHeadBytesZeroMultiFieldsOmitEmpty", + data: &struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + C []byte `json:"c,omitempty"` + }{}, + }, + { + name: "PtrHeadBytesZeroMultiFieldsString", + data: &struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + C []byte `json:"c,string"` + }{}, + }, + + // PtrHeadBytesMultiFields + { + name: "PtrHeadBytesMultiFields", + data: &struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte("baz")}, + }, + { + name: "PtrHeadBytesMultiFieldsOmitEmpty", + data: &struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + C []byte `json:"c,omitempty"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte("baz")}, + }, + { + name: "PtrHeadBytesMultiFieldsString", + data: &struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + C []byte `json:"c,string"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte("baz")}, + }, + + // PtrHeadBytesPtrMultiFields + { + name: "PtrHeadBytesPtrMultiFields", + data: &struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + C *[]byte `json:"c"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte("baz"))}, + }, + { + name: "PtrHeadBytesPtrMultiFieldsOmitEmpty", + data: &struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + C *[]byte `json:"c,omitempty"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte("baz"))}, + }, + { + name: "PtrHeadBytesPtrMultiFieldsString", + data: &struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + C *[]byte `json:"c,string"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar")), C: bytesptr([]byte("baz"))}, + }, + + // PtrHeadBytesPtrNilMultiFields + { + name: "PtrHeadBytesPtrNilMultiFields", + data: &struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + C *[]byte `json:"c"` + }{A: nil, B: nil, C: nil}, + }, + { + name: "PtrHeadBytesPtrNilMultiFieldsOmitEmpty", + data: &struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + C *[]byte `json:"c,omitempty"` + }{A: nil, B: nil, C: nil}, + }, + { + name: "PtrHeadBytesPtrNilMultiFieldsString", + data: &struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + C *[]byte `json:"c,string"` + }{A: nil, B: nil, C: nil}, + }, + + // PtrHeadBytesNilMultiFields + { + name: "PtrHeadBytesNilMultiFields", + data: (*struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + C *[]byte `json:"c"` + })(nil), + }, + { + name: "PtrHeadBytesNilMultiFieldsOmitEmpty", + data: (*struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + C *[]byte `json:"c,omitempty"` + })(nil), + }, + { + name: "PtrHeadBytesNilMultiFieldsString", + data: (*struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + C *[]byte `json:"c,string"` + })(nil), + }, + + // HeadBytesZeroNotRoot + { + name: "HeadBytesZeroNotRoot", + data: struct { + A struct { + A []byte `json:"a"` + } + }{}, + }, + { + name: "HeadBytesZeroNotRootOmitEmpty", + data: struct { + A struct { + A []byte `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadBytesZeroNotRootString", + data: struct { + A struct { + A []byte `json:"a,string"` + } + }{}, + }, + + // HeadBytesNotRoot + { + name: "HeadBytesNotRoot", + data: struct { + A struct { + A []byte `json:"a"` + } + }{A: struct { + A []byte `json:"a"` + }{A: []byte("foo")}}, + }, + { + name: "HeadBytesNotRootOmitEmpty", + data: struct { + A struct { + A []byte `json:"a,omitempty"` + } + }{A: struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")}}, + }, + { + name: "HeadBytesNotRootString", + data: struct { + A struct { + A []byte `json:"a,string"` + } + }{A: struct { + A []byte `json:"a,string"` + }{A: []byte("foo")}}, + }, + + // HeadBytesPtrNotRoot + { + name: "HeadBytesPtrNotRoot", + data: struct { + A struct { + A *[]byte `json:"a"` + } + }{A: struct { + A *[]byte `json:"a"` + }{bytesptr([]byte("foo"))}}, + }, + { + name: "HeadBytesPtrNotRootOmitEmpty", + data: struct { + A struct { + A *[]byte `json:"a,omitempty"` + } + }{A: struct { + A *[]byte `json:"a,omitempty"` + }{bytesptr([]byte("foo"))}}, + }, + { + name: "HeadBytesPtrNotRootString", + data: struct { + A struct { + A *[]byte `json:"a,string"` + } + }{A: struct { + A *[]byte `json:"a,string"` + }{bytesptr([]byte("foo"))}}, + }, + + // HeadBytesPtrNilNotRoot + { + name: "HeadBytesPtrNilNotRoot", + data: struct { + A struct { + A *[]byte `json:"a"` + } + }{}, + }, + { + name: "HeadBytesPtrNilNotRootOmitEmpty", + data: struct { + A struct { + A *[]byte `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadBytesPtrNilNotRootString", + data: struct { + A struct { + A *[]byte `json:"a,string"` + } + }{}, + }, + + // PtrHeadBytesZeroNotRoot + { + name: "PtrHeadBytesZeroNotRoot", + data: struct { + A *struct { + A []byte `json:"a"` + } + }{A: new(struct { + A []byte `json:"a"` + })}, + }, + { + name: "PtrHeadBytesZeroNotRootOmitEmpty", + data: struct { + A *struct { + A []byte `json:"a,omitempty"` + } + }{A: new(struct { + A []byte `json:"a,omitempty"` + })}, + }, + { + name: "PtrHeadBytesZeroNotRootString", + data: struct { + A *struct { + A []byte `json:"a,string"` + } + }{A: new(struct { + A []byte `json:"a,string"` + })}, + }, + + // PtrHeadBytesNotRoot + { + name: "PtrHeadBytesNotRoot", + data: struct { + A *struct { + A []byte `json:"a"` + } + }{A: &(struct { + A []byte `json:"a"` + }{A: []byte("foo")})}, + }, + { + name: "PtrHeadBytesNotRootOmitEmpty", + data: struct { + A *struct { + A []byte `json:"a,omitempty"` + } + }{A: &(struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")})}, + }, + { + name: "PtrHeadBytesNotRootString", + data: struct { + A *struct { + A []byte `json:"a,string"` + } + }{A: &(struct { + A []byte `json:"a,string"` + }{A: []byte("foo")})}, + }, + + // PtrHeadBytesPtrNotRoot + { + name: "PtrHeadBytesPtrNotRoot", + data: struct { + A *struct { + A *[]byte `json:"a"` + } + }{A: &(struct { + A *[]byte `json:"a"` + }{A: bytesptr([]byte("foo"))})}, + }, + { + name: "PtrHeadBytesPtrNotRootOmitEmpty", + data: struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } + }{A: &(struct { + A *[]byte `json:"a,omitempty"` + }{A: bytesptr([]byte("foo"))})}, + }, + { + name: "PtrHeadBytesPtrNotRootString", + data: struct { + A *struct { + A *[]byte `json:"a,string"` + } + }{A: &(struct { + A *[]byte `json:"a,string"` + }{A: bytesptr([]byte("foo"))})}, + }, + + // PtrHeadBytesPtrNilNotRoot + { + name: "PtrHeadBytesPtrNilNotRoot", + data: struct { + A *struct { + A *[]byte `json:"a"` + } + }{A: &(struct { + A *[]byte `json:"a"` + }{A: nil})}, + }, + { + name: "PtrHeadBytesPtrNilNotRootOmitEmpty", + data: struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } + }{A: &(struct { + A *[]byte `json:"a,omitempty"` + }{A: nil})}, + }, + { + name: "PtrHeadBytesPtrNilNotRootString", + data: struct { + A *struct { + A *[]byte `json:"a,string"` + } + }{A: &(struct { + A *[]byte `json:"a,string"` + }{A: nil})}, + }, + + // PtrHeadBytesNilNotRoot + { + name: "PtrHeadBytesNilNotRoot", + data: struct { + A *struct { + A *[]byte `json:"a"` + } + }{A: nil}, + }, + { + name: "PtrHeadBytesNilNotRootOmitEmpty", + data: struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } `json:",omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadBytesNilNotRootString", + data: struct { + A *struct { + A *[]byte `json:"a,string"` + } `json:",string"` + }{A: nil}, + }, + + // HeadBytesZeroMultiFieldsNotRoot + { + name: "HeadBytesZeroMultiFieldsNotRoot", + data: struct { + A struct { + A []byte `json:"a"` + } + B struct { + B []byte `json:"b"` + } + }{}, + }, + { + name: "HeadBytesZeroMultiFieldsNotRootOmitEmpty", + data: struct { + A struct { + A []byte `json:"a,omitempty"` + } + B struct { + B []byte `json:"b,omitempty"` + } + }{}, + }, + { + name: "HeadBytesZeroMultiFieldsNotRootString", + data: struct { + A struct { + A []byte `json:"a,string"` + } + B struct { + B []byte `json:"b,string"` + } + }{}, + }, + + // HeadBytesMultiFieldsNotRoot + { + name: "HeadBytesMultiFieldsNotRoot", + data: struct { + A struct { + A []byte `json:"a"` + } + B struct { + B []byte `json:"b"` + } + }{A: struct { + A []byte `json:"a"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b"` + }{B: []byte("bar")}}, + }, + { + name: "HeadBytesMultiFieldsNotRootOmitEmpty", + data: struct { + A struct { + A []byte `json:"a,omitempty"` + } + B struct { + B []byte `json:"b,omitempty"` + } + }{A: struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b,omitempty"` + }{B: []byte("bar")}}, + }, + { + name: "HeadBytesMultiFieldsNotRootString", + data: struct { + A struct { + A []byte `json:"a,string"` + } + B struct { + B []byte `json:"b,string"` + } + }{A: struct { + A []byte `json:"a,string"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b,string"` + }{B: []byte("bar")}}, + }, + + // HeadBytesPtrMultiFieldsNotRoot + { + name: "HeadBytesPtrMultiFieldsNotRoot", + data: struct { + A struct { + A *[]byte `json:"a"` + } + B struct { + B *[]byte `json:"b"` + } + }{A: struct { + A *[]byte `json:"a"` + }{A: bytesptr([]byte("foo"))}, B: struct { + B *[]byte `json:"b"` + }{B: bytesptr([]byte("bar"))}}, + }, + { + name: "HeadBytesPtrMultiFieldsNotRootOmitEmpty", + data: struct { + A struct { + A *[]byte `json:"a,omitempty"` + } + B struct { + B *[]byte `json:"b,omitempty"` + } + }{A: struct { + A *[]byte `json:"a,omitempty"` + }{A: bytesptr([]byte("foo"))}, B: struct { + B *[]byte `json:"b,omitempty"` + }{B: bytesptr([]byte("bar"))}}, + }, + { + name: "HeadBytesPtrMultiFieldsNotRootString", + data: struct { + A struct { + A *[]byte `json:"a,string"` + } + B struct { + B *[]byte `json:"b,string"` + } + }{A: struct { + A *[]byte `json:"a,string"` + }{A: bytesptr([]byte("foo"))}, B: struct { + B *[]byte `json:"b,string"` + }{B: bytesptr([]byte("bar"))}}, + }, + + // HeadBytesPtrNilMultiFieldsNotRoot + { + name: "HeadBytesPtrNilMultiFieldsNotRoot", + data: struct { + A struct { + A *[]byte `json:"a"` + } + B struct { + B *[]byte `json:"b"` + } + }{A: struct { + A *[]byte `json:"a"` + }{A: nil}, B: struct { + B *[]byte `json:"b"` + }{B: nil}}, + }, + { + name: "HeadBytesPtrNilMultiFieldsNotRootOmitEmpty", + data: struct { + A struct { + A *[]byte `json:"a,omitempty"` + } + B struct { + B *[]byte `json:"b,omitempty"` + } + }{A: struct { + A *[]byte `json:"a,omitempty"` + }{A: nil}, B: struct { + B *[]byte `json:"b,omitempty"` + }{B: nil}}, + }, + { + name: "HeadBytesPtrNilMultiFieldsNotRootString", + data: struct { + A struct { + A *[]byte `json:"a,string"` + } + B struct { + B *[]byte `json:"b,string"` + } + }{A: struct { + A *[]byte `json:"a,string"` + }{A: nil}, B: struct { + B *[]byte `json:"b,string"` + }{B: nil}}, + }, + + // PtrHeadBytesZeroMultiFieldsNotRoot + { + name: "PtrHeadBytesZeroMultiFieldsNotRoot", + data: &struct { + A struct { + A []byte `json:"a"` + } + B struct { + B []byte `json:"b"` + } + }{}, + }, + { + name: "PtrHeadBytesZeroMultiFieldsNotRootOmitEmpty", + data: &struct { + A struct { + A []byte `json:"a,omitempty"` + } + B struct { + B []byte `json:"b,omitempty"` + } + }{}, + }, + { + name: "PtrHeadBytesZeroMultiFieldsNotRootString", + data: &struct { + A struct { + A []byte `json:"a,string"` + } + B struct { + B []byte `json:"b,string"` + } + }{}, + }, + + // PtrHeadBytesMultiFieldsNotRoot + { + name: "PtrHeadBytesMultiFieldsNotRoot", + data: &struct { + A struct { + A []byte `json:"a"` + } + B struct { + B []byte `json:"b"` + } + }{A: struct { + A []byte `json:"a"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b"` + }{B: []byte("bar")}}, + }, + { + name: "PtrHeadBytesMultiFieldsNotRootOmitEmpty", + data: &struct { + A struct { + A []byte `json:"a,omitempty"` + } + B struct { + B []byte `json:"b,omitempty"` + } + }{A: struct { + A []byte `json:"a,omitempty"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b,omitempty"` + }{B: []byte("bar")}}, + }, + { + name: "PtrHeadBytesMultiFieldsNotRootString", + data: &struct { + A struct { + A []byte `json:"a,string"` + } + B struct { + B []byte `json:"b,string"` + } + }{A: struct { + A []byte `json:"a,string"` + }{A: []byte("foo")}, B: struct { + B []byte `json:"b,string"` + }{B: []byte("bar")}}, + }, + + // PtrHeadBytesPtrMultiFieldsNotRoot + { + name: "PtrHeadBytesPtrMultiFieldsNotRoot", + data: &struct { + A *struct { + A *[]byte `json:"a"` + } + B *struct { + B *[]byte `json:"b"` + } + }{A: &(struct { + A *[]byte `json:"a"` + }{A: bytesptr([]byte("foo"))}), B: &(struct { + B *[]byte `json:"b"` + }{B: bytesptr([]byte("bar"))})}, + }, + { + name: "PtrHeadBytesPtrMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } + B *struct { + B *[]byte `json:"b,omitempty"` + } + }{A: &(struct { + A *[]byte `json:"a,omitempty"` + }{A: bytesptr([]byte("foo"))}), B: &(struct { + B *[]byte `json:"b,omitempty"` + }{B: bytesptr([]byte("bar"))})}, + }, + { + name: "PtrHeadBytesPtrMultiFieldsNotRootString", + data: &struct { + A *struct { + A *[]byte `json:"a,string"` + } + B *struct { + B *[]byte `json:"b,string"` + } + }{A: &(struct { + A *[]byte `json:"a,string"` + }{A: bytesptr([]byte("foo"))}), B: &(struct { + B *[]byte `json:"b,string"` + }{B: bytesptr([]byte("bar"))})}, + }, + + // PtrHeadBytesPtrNilMultiFieldsNotRoot + { + name: "PtrHeadBytesPtrNilMultiFieldsNotRoot", + data: &struct { + A *struct { + A *[]byte `json:"a"` + } + B *struct { + B *[]byte `json:"b"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesPtrNilMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } + B *struct { + B *[]byte `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesPtrNilMultiFieldsNotRootString", + data: &struct { + A *struct { + A *[]byte `json:"a,string"` + } + B *struct { + B *[]byte `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadBytesNilMultiFieldsNotRoot + { + name: "PtrHeadBytesNilMultiFieldsNotRoot", + data: (*struct { + A *struct { + A *[]byte `json:"a"` + } + B *struct { + B *[]byte `json:"b"` + } + })(nil), + }, + { + name: "PtrHeadBytesNilMultiFieldsNotRootOmitEmpty", + data: (*struct { + A *struct { + A *[]byte `json:"a,omitempty"` + } + B *struct { + B *[]byte `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadBytesNilMultiFieldsNotRootString", + data: (*struct { + A *struct { + A *[]byte `json:"a,string"` + } + B *struct { + B *[]byte `json:"b,string"` + } + })(nil), + }, + + // PtrHeadBytesDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesDoubleMultiFieldsNotRoot", + data: &struct { + A *struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + } + B *struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + } + }{A: &(struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte("baz")}), B: &(struct { + A []byte `json:"a"` + B []byte `json:"b"` + C []byte `json:"c"` + }{A: []byte("foo"), B: []byte("bar"), C: []byte("baz")})}, + }, + { + name: "PtrHeadBytesDoubleMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + B *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + }{A: &(struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + }{A: []byte("foo"), B: []byte("bar")}), B: &(struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + }{A: []byte("foo"), B: []byte("bar")})}, + }, + { + name: "PtrHeadBytesDoubleMultiFieldsNotRootString", + data: &struct { + A *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + B *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + }{A: &(struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + }{A: []byte("foo"), B: []byte("bar")}), B: &(struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + }{A: []byte("foo"), B: []byte("bar")})}, + }, + + // PtrHeadBytesNilDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRoot", + data: &struct { + A *struct { + A []byte `json:"a"` + B []byte `json:"b"` + } + B *struct { + A []byte `json:"a"` + B []byte `json:"b"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + B *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRootString", + data: &struct { + A *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + B *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadBytesNilDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRoot", + data: (*struct { + A *struct { + A []byte `json:"a"` + B []byte `json:"b"` + } + B *struct { + A []byte `json:"a"` + B []byte `json:"b"` + } + })(nil), + }, + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRootOmitEmpty", + data: (*struct { + A *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + B *struct { + A []byte `json:"a,omitempty"` + B []byte `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadBytesNilDoubleMultiFieldsNotRootString", + data: (*struct { + A *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + B *struct { + A []byte `json:"a,string"` + B []byte `json:"b,string"` + } + })(nil), + }, + + // PtrHeadBytesPtrDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesPtrDoubleMultiFieldsNotRoot", + data: &struct { + A *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + B *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + }{A: &(struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))}), B: &(struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))})}, + }, + { + name: "PtrHeadBytesPtrDoubleMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + B *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + }{A: &(struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))}), B: &(struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))})}, + }, + { + name: "PtrHeadBytesPtrDoubleMultiFieldsNotRootString", + data: &struct { + A *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + B *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + }{A: &(struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))}), B: &(struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + }{A: bytesptr([]byte("foo")), B: bytesptr([]byte("bar"))})}, + }, + + // PtrHeadBytesPtrNilDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRoot", + data: &struct { + A *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + B *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRootOmitEmpty", + data: &struct { + A *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + B *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRootString", + data: &struct { + A *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + B *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadBytesPtrNilDoubleMultiFieldsNotRoot + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRoot", + data: (*struct { + A *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + B *struct { + A *[]byte `json:"a"` + B *[]byte `json:"b"` + } + })(nil), + }, + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRootOmitEmpty", + data: (*struct { + A *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + B *struct { + A *[]byte `json:"a,omitempty"` + B *[]byte `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadBytesPtrNilDoubleMultiFieldsNotRootString", + data: (*struct { + A *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + B *struct { + A *[]byte `json:"a,string"` + B *[]byte `json:"b,string"` + } + })(nil), + }, + + // AnonymousHeadBytes + { + name: "AnonymousHeadString", + data: struct { + structBytes + B []byte `json:"b"` + }{ + structBytes: structBytes{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + { + name: "AnonymousHeadBytesOmitEmpty", + data: struct { + structBytesOmitEmpty + B []byte `json:"b,omitempty"` + }{ + structBytesOmitEmpty: structBytesOmitEmpty{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + { + name: "AnonymousHeadBytesString", + data: struct { + structBytesBytes + B []byte `json:"b,string"` + }{ + structBytesBytes: structBytesBytes{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + + // PtrAnonymousHeadBytes + { + name: "PtrAnonymousHeadString", + data: struct { + *structBytes + B []byte `json:"b"` + }{ + structBytes: &structBytes{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + { + name: "PtrAnonymousHeadBytesOmitEmpty", + data: struct { + *structBytesOmitEmpty + B []byte `json:"b,omitempty"` + }{ + structBytesOmitEmpty: &structBytesOmitEmpty{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + { + name: "PtrAnonymousHeadBytesString", + data: struct { + *structBytesBytes + B []byte `json:"b,string"` + }{ + structBytesBytes: &structBytesBytes{A: []byte("foo")}, + B: []byte("bar"), + }, + }, + + // NilPtrAnonymousHeadBytes + { + name: "NilPtrAnonymousHeadString", + data: struct { + *structBytes + B []byte `json:"b"` + }{ + structBytes: nil, + B: []byte("baz"), + }, + }, + { + name: "NilPtrAnonymousHeadBytesOmitEmpty", + data: struct { + *structBytesOmitEmpty + B []byte `json:"b,omitempty"` + }{ + structBytesOmitEmpty: nil, + B: []byte("baz"), + }, + }, + { + name: "NilPtrAnonymousHeadBytesString", + data: struct { + *structBytesBytes + B []byte `json:"b,string"` + }{ + structBytesBytes: nil, + B: []byte("baz"), + }, + }, + + // AnonymousHeadBytesPtr + { + name: "AnonymousHeadBytesPtr", + data: struct { + structBytesPtr + B *[]byte `json:"b"` + }{ + structBytesPtr: structBytesPtr{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + { + name: "AnonymousHeadBytesPtrOmitEmpty", + data: struct { + structBytesPtrOmitEmpty + B *[]byte `json:"b,omitempty"` + }{ + structBytesPtrOmitEmpty: structBytesPtrOmitEmpty{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + { + name: "AnonymousHeadBytesPtrString", + data: struct { + structBytesPtrBytes + B *[]byte `json:"b,string"` + }{ + structBytesPtrBytes: structBytesPtrBytes{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + + // AnonymousHeadBytesPtrNil + { + name: "AnonymousHeadBytesPtrNil", + data: struct { + structBytesPtr + B *[]byte `json:"b"` + }{ + structBytesPtr: structBytesPtr{A: nil}, + B: bytesptr([]byte("foo")), + }, + }, + { + name: "AnonymousHeadBytesPtrNilOmitEmpty", + data: struct { + structBytesPtrOmitEmpty + B *[]byte `json:"b,omitempty"` + }{ + structBytesPtrOmitEmpty: structBytesPtrOmitEmpty{A: nil}, + B: bytesptr([]byte("foo")), + }, + }, + { + name: "AnonymousHeadBytesPtrNilString", + data: struct { + structBytesPtrBytes + B *[]byte `json:"b,string"` + }{ + structBytesPtrBytes: structBytesPtrBytes{A: nil}, + B: bytesptr([]byte("foo")), + }, + }, + + // PtrAnonymousHeadBytesPtr + { + name: "PtrAnonymousHeadBytesPtr", + data: struct { + *structBytesPtr + B *[]byte `json:"b"` + }{ + structBytesPtr: &structBytesPtr{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + { + name: "PtrAnonymousHeadBytesPtrOmitEmpty", + data: struct { + *structBytesPtrOmitEmpty + B *[]byte `json:"b,omitempty"` + }{ + structBytesPtrOmitEmpty: &structBytesPtrOmitEmpty{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + { + name: "PtrAnonymousHeadBytesPtrString", + data: struct { + *structBytesPtrBytes + B *[]byte `json:"b,string"` + }{ + structBytesPtrBytes: &structBytesPtrBytes{A: bytesptr([]byte("foo"))}, + B: bytesptr([]byte("bar")), + }, + }, + + // NilPtrAnonymousHeadBytesPtr + { + name: "NilPtrAnonymousHeadBytesPtr", + data: struct { + *structBytesPtr + B *[]byte `json:"b"` + }{ + structBytesPtr: nil, + B: bytesptr([]byte("foo")), + }, + }, + { + name: "NilPtrAnonymousHeadBytesPtrOmitEmpty", + data: struct { + *structBytesPtrOmitEmpty + B *[]byte `json:"b,omitempty"` + }{ + structBytesPtrOmitEmpty: nil, + B: bytesptr([]byte("foo")), + }, + }, + { + name: "NilPtrAnonymousHeadBytesPtrString", + data: struct { + *structBytesPtrBytes + B *[]byte `json:"b,string"` + }{ + structBytesPtrBytes: nil, + B: bytesptr([]byte("foo")), + }, + }, + + // AnonymousHeadBytesOnly + { + name: "AnonymousHeadBytesOnly", + data: struct { + structBytes + }{ + structBytes: structBytes{A: []byte("foo")}, + }, + }, + { + name: "AnonymousHeadBytesOnlyOmitEmpty", + data: struct { + structBytesOmitEmpty + }{ + structBytesOmitEmpty: structBytesOmitEmpty{A: []byte("foo")}, + }, + }, + { + name: "AnonymousHeadBytesOnlyString", + data: struct { + structBytesBytes + }{ + structBytesBytes: structBytesBytes{A: []byte("foo")}, + }, + }, + + // PtrAnonymousHeadBytesOnly + { + name: "PtrAnonymousHeadBytesOnly", + data: struct { + *structBytes + }{ + structBytes: &structBytes{A: []byte("foo")}, + }, + }, + { + name: "PtrAnonymousHeadBytesOnlyOmitEmpty", + data: struct { + *structBytesOmitEmpty + }{ + structBytesOmitEmpty: &structBytesOmitEmpty{A: []byte("foo")}, + }, + }, + { + name: "PtrAnonymousHeadBytesOnlyString", + data: struct { + *structBytesBytes + }{ + structBytesBytes: &structBytesBytes{A: []byte("foo")}, + }, + }, + + // NilPtrAnonymousHeadBytesOnly + { + name: "NilPtrAnonymousHeadBytesOnly", + data: struct { + *structBytes + }{ + structBytes: nil, + }, + }, + { + name: "NilPtrAnonymousHeadBytesOnlyOmitEmpty", + data: struct { + *structBytesOmitEmpty + }{ + structBytesOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadBytesOnlyString", + data: struct { + *structBytesBytes + }{ + structBytesBytes: nil, + }, + }, + + // AnonymousHeadBytesPtrOnly + { + name: "AnonymousHeadBytesPtrOnly", + data: struct { + structBytesPtr + }{ + structBytesPtr: structBytesPtr{A: bytesptr([]byte("foo"))}, + }, + }, + { + name: "AnonymousHeadBytesPtrOnlyOmitEmpty", + data: struct { + structBytesPtrOmitEmpty + }{ + structBytesPtrOmitEmpty: structBytesPtrOmitEmpty{A: bytesptr([]byte("foo"))}, + }, + }, + { + name: "AnonymousHeadBytesPtrOnlyString", + data: struct { + structBytesPtrBytes + }{ + structBytesPtrBytes: structBytesPtrBytes{A: bytesptr([]byte("foo"))}, + }, + }, + + // AnonymousHeadBytesPtrNilOnly + { + name: "AnonymousHeadBytesPtrNilOnly", + data: struct { + structBytesPtr + }{ + structBytesPtr: structBytesPtr{A: nil}, + }, + }, + { + name: "AnonymousHeadBytesPtrNilOnlyOmitEmpty", + data: struct { + structBytesPtrOmitEmpty + }{ + structBytesPtrOmitEmpty: structBytesPtrOmitEmpty{A: nil}, + }, + }, + { + name: "AnonymousHeadBytesPtrNilOnlyString", + data: struct { + structBytesPtrBytes + }{ + structBytesPtrBytes: structBytesPtrBytes{A: nil}, + }, + }, + + // PtrAnonymousHeadBytesPtrOnly + { + name: "PtrAnonymousHeadBytesPtrOnly", + data: struct { + *structBytesPtr + }{ + structBytesPtr: &structBytesPtr{A: bytesptr([]byte("foo"))}, + }, + }, + { + name: "PtrAnonymousHeadBytesPtrOnlyOmitEmpty", + data: struct { + *structBytesPtrOmitEmpty + }{ + structBytesPtrOmitEmpty: &structBytesPtrOmitEmpty{A: bytesptr([]byte("foo"))}, + }, + }, + { + name: "PtrAnonymousHeadBytesPtrOnlyString", + data: struct { + *structBytesPtrBytes + }{ + structBytesPtrBytes: &structBytesPtrBytes{A: bytesptr([]byte("foo"))}, + }, + }, + + // NilPtrAnonymousHeadBytesPtrOnly + { + name: "NilPtrAnonymousHeadBytesPtrOnly", + data: struct { + *structBytesPtr + }{ + structBytesPtr: nil, + }, + }, + { + name: "NilPtrAnonymousHeadBytesPtrOnlyOmitEmpty", + data: struct { + *structBytesPtrOmitEmpty + }{ + structBytesPtrOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadBytesPtrOnlyString", + data: struct { + *structBytesPtrBytes + }{ + structBytesPtrBytes: nil, + }, + }, + } + for _, test := range tests { + fmt.Println("name = ", test.name) + for _, indent := range []bool{true, false} { + for _, htmlEscape := range []bool{true, false} { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(htmlEscape) + if indent { + enc.SetIndent("", " ") + } + if err := enc.Encode(test.data); err != nil { + t.Fatalf("%s(htmlEscape:%v,indent:%v): %v: %s", test.name, htmlEscape, indent, test.data, err) + } + stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) + if buf.String() != stdresult { + t.Errorf("%s(htmlEscape:%v,indent:%v): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, indent, stdresult, buf.String()) + } + } + } + } +} diff --git a/cover_float32_test.go b/cover_float32_test.go index 1b49bd8..6dcf608 100644 --- a/cover_float32_test.go +++ b/cover_float32_test.go @@ -32,6 +32,27 @@ func TestCoverFloat32(t *testing.T) { name string data interface{} }{ + { + name: "Float32", + data: float32(10), + }, + { + name: "Float32Ptr", + data: float32ptr(10), + }, + { + name: "Float32Ptr3", + data: float32ptr3(10), + }, + { + name: "Float32PtrNil", + data: (*float32)(nil), + }, + { + name: "Float32Ptr3Nil", + data: (***float32)(nil), + }, + // HeadFloat32Zero { name: "HeadFloat32Zero", diff --git a/cover_float64_test.go b/cover_float64_test.go index 4d046af..42bf2fd 100644 --- a/cover_float64_test.go +++ b/cover_float64_test.go @@ -32,6 +32,27 @@ func TestCoverFloat64(t *testing.T) { name string data interface{} }{ + { + name: "Float64", + data: float64(10), + }, + { + name: "Float64Ptr", + data: float64ptr(10), + }, + { + name: "Float64Ptr3", + data: float64ptr3(10), + }, + { + name: "Float64PtrNil", + data: (*float64)(nil), + }, + { + name: "Float64Ptr3Nil", + data: (***float64)(nil), + }, + // HeadFloat64Zero { name: "HeadFloat64Zero", diff --git a/cover_helper_test.go b/cover_helper_test.go index 107635a..d93de01 100644 --- a/cover_helper_test.go +++ b/cover_helper_test.go @@ -6,19 +6,35 @@ import ( ) func intptr(v int) *int { return &v } +func intptr3(v int) ***int { vv := &v; vvv := &vv; return &vvv } func int8ptr(v int8) *int8 { return &v } +func int8ptr3(v int8) ***int8 { vv := &v; vvv := &vv; return &vvv } func int16ptr(v int16) *int16 { return &v } +func int16ptr3(v int16) ***int16 { vv := &v; vvv := &vv; return &vvv } func int32ptr(v int32) *int32 { return &v } +func int32ptr3(v int32) ***int32 { vv := &v; vvv := &vv; return &vvv } func int64ptr(v int64) *int64 { return &v } +func int64ptr3(v int64) ***int64 { vv := &v; vvv := &vv; return &vvv } func uptr(v uint) *uint { return &v } +func uintptr3(v uint) ***uint { vv := &v; vvv := &vv; return &vvv } func uint8ptr(v uint8) *uint8 { return &v } +func uint8ptr3(v uint8) ***uint8 { vv := &v; vvv := &vv; return &vvv } func uint16ptr(v uint16) *uint16 { return &v } +func uint16ptr3(v uint16) ***uint16 { vv := &v; vvv := &vv; return &vvv } func uint32ptr(v uint32) *uint32 { return &v } +func uint32ptr3(v uint32) ***uint32 { vv := &v; vvv := &vv; return &vvv } func uint64ptr(v uint64) *uint64 { return &v } +func uint64ptr3(v uint64) ***uint64 { vv := &v; vvv := &vv; return &vvv } func float32ptr(v float32) *float32 { return &v } +func float32ptr3(v float32) ***float32 { vv := &v; vvv := &vv; return &vvv } func float64ptr(v float64) *float64 { return &v } +func float64ptr3(v float64) ***float64 { vv := &v; vvv := &vv; return &vvv } func stringptr(v string) *string { return &v } +func stringptr3(v string) ***string { vv := &v; vvv := &vv; return &vvv } func boolptr(v bool) *bool { return &v } +func boolptr3(v bool) ***bool { vv := &v; vvv := &vv; return &vvv } +func bytesptr(v []byte) *[]byte { return &v } +func bytesptr3(v []byte) ***[]byte { vv := &v; vvv := &vv; return &vvv } func sliceptr(v []int) *[]int { return &v } func arrayptr(v [2]int) *[2]int { return &v } func mapptr(v map[string]int) *map[string]int { return &v } diff --git a/cover_int16_test.go b/cover_int16_test.go index 612f18c..f16a944 100644 --- a/cover_int16_test.go +++ b/cover_int16_test.go @@ -32,6 +32,27 @@ func TestCoverInt16(t *testing.T) { name string data interface{} }{ + { + name: "Int16", + data: int16(10), + }, + { + name: "Int16Ptr", + data: int16ptr(10), + }, + { + name: "Int16Ptr3", + data: int16ptr3(10), + }, + { + name: "Int16PtrNil", + data: (*int16)(nil), + }, + { + name: "Int16Ptr3Nil", + data: (***int16)(nil), + }, + // HeadInt16Zero { name: "HeadInt16Zero", diff --git a/cover_int32_test.go b/cover_int32_test.go index f48c7fe..71cd397 100644 --- a/cover_int32_test.go +++ b/cover_int32_test.go @@ -32,6 +32,27 @@ func TestCoverInt32(t *testing.T) { name string data interface{} }{ + { + name: "Int32", + data: int32(10), + }, + { + name: "Int32Ptr", + data: int32ptr(10), + }, + { + name: "Int32Ptr3", + data: int32ptr3(10), + }, + { + name: "Int32PtrNil", + data: (*int32)(nil), + }, + { + name: "Int32Ptr3Nil", + data: (***int32)(nil), + }, + // HeadInt32Zero { name: "HeadInt32Zero", diff --git a/cover_int64_test.go b/cover_int64_test.go index 8804e8c..0879cbf 100644 --- a/cover_int64_test.go +++ b/cover_int64_test.go @@ -32,6 +32,27 @@ func TestCoverInt64(t *testing.T) { name string data interface{} }{ + { + name: "Int64", + data: int64(10), + }, + { + name: "Int64Ptr", + data: int64ptr(10), + }, + { + name: "Int64Ptr3", + data: int64ptr3(10), + }, + { + name: "Int64PtrNil", + data: (*int64)(nil), + }, + { + name: "Int64Ptr3Nil", + data: (***int64)(nil), + }, + // HeadInt64Zero { name: "HeadInt64Zero", diff --git a/cover_int8_test.go b/cover_int8_test.go index a355560..673b67b 100644 --- a/cover_int8_test.go +++ b/cover_int8_test.go @@ -32,6 +32,27 @@ func TestCoverInt8(t *testing.T) { name string data interface{} }{ + { + name: "Int8", + data: int8(10), + }, + { + name: "Int8Ptr", + data: int8ptr(10), + }, + { + name: "Int8Ptr3", + data: int8ptr3(10), + }, + { + name: "Int8PtrNil", + data: (*int8)(nil), + }, + { + name: "Int8Ptr3Nil", + data: (***int8)(nil), + }, + // HeadInt8Zero { name: "HeadInt8Zero", diff --git a/cover_int_test.go b/cover_int_test.go index 0154d7f..d05b11a 100644 --- a/cover_int_test.go +++ b/cover_int_test.go @@ -32,6 +32,27 @@ func TestCoverInt(t *testing.T) { name string data interface{} }{ + { + name: "Int", + data: 10, + }, + { + name: "IntPtr", + data: intptr(10), + }, + { + name: "IntPtr3", + data: intptr3(10), + }, + { + name: "IntPtrNil", + data: (*int)(nil), + }, + { + name: "IntPtr3Nil", + data: (***int)(nil), + }, + // HeadIntZero { name: "HeadIntZero", diff --git a/cover_string_test.go b/cover_string_test.go index d80d296..1d0f389 100644 --- a/cover_string_test.go +++ b/cover_string_test.go @@ -32,6 +32,27 @@ func TestCoverString(t *testing.T) { name string data interface{} }{ + { + name: "String", + data: string("a"), + }, + { + name: "StringPtr", + data: stringptr("a"), + }, + { + name: "StringPtr3", + data: stringptr3("a"), + }, + { + name: "StringPtrNil", + data: (*string)(nil), + }, + { + name: "StringPtr3Nil", + data: (***string)(nil), + }, + // HeadStringZero { name: "HeadStringZero", diff --git a/cover_uint16_test.go b/cover_uint16_test.go index 446b69f..f14470a 100644 --- a/cover_uint16_test.go +++ b/cover_uint16_test.go @@ -32,6 +32,27 @@ func TestCoverUint16(t *testing.T) { name string data interface{} }{ + { + name: "Uint16", + data: uint16(10), + }, + { + name: "Uint16Ptr", + data: uint16ptr(10), + }, + { + name: "Uint16Ptr3", + data: uint16ptr3(10), + }, + { + name: "Uint16PtrNil", + data: (*uint16)(nil), + }, + { + name: "Uint16Ptr3Nil", + data: (***uint16)(nil), + }, + // HeadUint16Zero { name: "HeadUint16Zero", diff --git a/cover_uint32_test.go b/cover_uint32_test.go index 6e58ce5..a0fb2f5 100644 --- a/cover_uint32_test.go +++ b/cover_uint32_test.go @@ -32,6 +32,27 @@ func TestCoverUint32(t *testing.T) { name string data interface{} }{ + { + name: "Uint32", + data: uint32(10), + }, + { + name: "Uint32Ptr", + data: uint32ptr(10), + }, + { + name: "Uint32Ptr3", + data: uint32ptr3(10), + }, + { + name: "Uint32PtrNil", + data: (*uint32)(nil), + }, + { + name: "Uint32Ptr3Nil", + data: (***uint32)(nil), + }, + // HeadUint32Zero { name: "HeadUint32Zero", diff --git a/cover_uint64_test.go b/cover_uint64_test.go index 354cda5..4b56d54 100644 --- a/cover_uint64_test.go +++ b/cover_uint64_test.go @@ -32,6 +32,27 @@ func TestCoverUint64(t *testing.T) { name string data interface{} }{ + { + name: "Uint64", + data: uint64(10), + }, + { + name: "Uint64Ptr", + data: uint64ptr(10), + }, + { + name: "Uint64Ptr3", + data: uint64ptr3(10), + }, + { + name: "Uint64PtrNil", + data: (*uint64)(nil), + }, + { + name: "Uint64Ptr3Nil", + data: (***uint64)(nil), + }, + // HeadUint64Zero { name: "HeadUint64Zero", diff --git a/cover_uint8_test.go b/cover_uint8_test.go index 96c2a5f..640e8f6 100644 --- a/cover_uint8_test.go +++ b/cover_uint8_test.go @@ -32,6 +32,27 @@ func TestCoverUint8(t *testing.T) { name string data interface{} }{ + { + name: "Uint8", + data: uint8(10), + }, + { + name: "Uint8Ptr", + data: uint8ptr(10), + }, + { + name: "Uint8Ptr3", + data: uint8ptr3(10), + }, + { + name: "Uint8PtrNil", + data: (*uint8)(nil), + }, + { + name: "Uint8Ptr3Nil", + data: (***uint8)(nil), + }, + // HeadUint8Zero { name: "HeadUint8Zero", diff --git a/cover_uint_test.go b/cover_uint_test.go index 46d1e0c..99e355e 100644 --- a/cover_uint_test.go +++ b/cover_uint_test.go @@ -32,6 +32,27 @@ func TestCoverUint(t *testing.T) { name string data interface{} }{ + { + name: "Uint", + data: uint(10), + }, + { + name: "UintPtr", + data: uptr(10), + }, + { + name: "UintPtr3", + data: uintptr3(10), + }, + { + name: "UintPtrNil", + data: (*uint)(nil), + }, + { + name: "UintPtr3Nil", + data: (***uint)(nil), + }, + // HeadUintZero { name: "HeadUintZero", diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 03817a8..e14eea7 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -90,12 +90,25 @@ func compileHead(ctx *compileContext) (*Opcode, error) { case implementsMarshalText(typ): return compileMarshalText(ctx) } - if typ.Kind() == reflect.Map { + switch typ.Kind() { + case reflect.Slice: + elem := typ.Elem() + if elem.Kind() == reflect.Uint8 { + p := runtime.PtrTo(elem) + if !p.Implements(marshalJSONType) && !p.Implements(marshalTextType) { + if isPtr { + return compileBytesPtr(ctx) + } + return compileBytes(ctx) + } + } + return compileSlice(ctx) + case reflect.Map: if isPtr { return compilePtr(ctx.withType(runtime.PtrTo(typ))) } return compileMap(ctx.withType(typ)) - } else if typ.Kind() == reflect.Struct { + case reflect.Struct: code, err := compileStruct(ctx.withType(typ), isPtr) if err != nil { return nil, err @@ -103,16 +116,88 @@ func compileHead(ctx *compileContext) (*Opcode, error) { optimizeStructEnd(code) linkRecursiveCode(code) return code, nil - } else if isPtr && typ.Implements(marshalTextType) { - typ = orgType + case reflect.Int: + if isPtr { + return compileIntPtr(ctx) + } + return compileInt(ctx) + case reflect.Int8: + if isPtr { + return compileInt8Ptr(ctx) + } + return compileInt8(ctx) + case reflect.Int16: + if isPtr { + return compileInt16Ptr(ctx) + } + return compileInt16(ctx) + case reflect.Int32: + if isPtr { + return compileInt32Ptr(ctx) + } + return compileInt32(ctx) + case reflect.Int64: + if isPtr { + return compileInt64Ptr(ctx) + } + return compileInt64(ctx) + case reflect.Uint, reflect.Uintptr: + if isPtr { + return compileUintPtr(ctx) + } + return compileUint(ctx) + case reflect.Uint8: + if isPtr { + return compileUint8Ptr(ctx) + } + return compileUint8(ctx) + case reflect.Uint16: + if isPtr { + return compileUint16Ptr(ctx) + } + return compileUint16(ctx) + case reflect.Uint32: + if isPtr { + return compileUint32Ptr(ctx) + } + return compileUint32(ctx) + case reflect.Uint64: + if isPtr { + return compileUint64Ptr(ctx) + } + return compileUint64(ctx) + case reflect.Float32: + if isPtr { + return compileFloat32Ptr(ctx) + } + return compileFloat32(ctx) + case reflect.Float64: + if isPtr { + return compileFloat64Ptr(ctx) + } + return compileFloat64(ctx) + case reflect.String: + if isPtr { + return compileStringPtr(ctx) + } + return compileString(ctx) + case reflect.Bool: + if isPtr { + return compileBoolPtr(ctx) + } + return compileBool(ctx) + default: + if isPtr && typ.Implements(marshalTextType) { + typ = orgType + } + code, err := compile(ctx.withType(typ), isPtr) + if err != nil { + return nil, err + } + optimizeStructEnd(code) + linkRecursiveCode(code) + return code, nil } - code, err := compile(ctx.withType(typ), isPtr) - if err != nil { - return nil, err - } - optimizeStructEnd(code) - linkRecursiveCode(code) - return code, nil } func linkRecursiveCode(c *Opcode) { @@ -418,6 +503,15 @@ func compileInt(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileIntPtr(ctx *compileContext) (*Opcode, error) { + code, err := compileInt(ctx) + if err != nil { + return nil, err + } + code.Op = OpIntPtr + return code, nil +} + func compileInt8(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpInt) code.setMaskAndRshiftNum(8) @@ -425,6 +519,15 @@ func compileInt8(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileInt8Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileInt8(ctx) + if err != nil { + return nil, err + } + code.Op = OpIntPtr + return code, nil +} + func compileInt16(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpInt) code.setMaskAndRshiftNum(16) @@ -432,6 +535,15 @@ func compileInt16(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileInt16Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileInt16(ctx) + if err != nil { + return nil, err + } + code.Op = OpIntPtr + return code, nil +} + func compileInt32(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpInt) code.setMaskAndRshiftNum(32) @@ -439,6 +551,15 @@ func compileInt32(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileInt32Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileInt32(ctx) + if err != nil { + return nil, err + } + code.Op = OpIntPtr + return code, nil +} + func compileInt64(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpInt) code.setMaskAndRshiftNum(64) @@ -446,6 +567,15 @@ func compileInt64(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileInt64Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileInt64(ctx) + if err != nil { + return nil, err + } + code.Op = OpIntPtr + return code, nil +} + func compileUint(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpUint) code.setMaskAndRshiftNum(intSize) @@ -453,6 +583,15 @@ func compileUint(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileUintPtr(ctx *compileContext) (*Opcode, error) { + code, err := compileUint(ctx) + if err != nil { + return nil, err + } + code.Op = OpUintPtr + return code, nil +} + func compileUint8(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpUint) code.setMaskAndRshiftNum(8) @@ -460,6 +599,15 @@ func compileUint8(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileUint8Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileUint8(ctx) + if err != nil { + return nil, err + } + code.Op = OpUintPtr + return code, nil +} + func compileUint16(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpUint) code.setMaskAndRshiftNum(16) @@ -467,6 +615,15 @@ func compileUint16(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileUint16Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileUint16(ctx) + if err != nil { + return nil, err + } + code.Op = OpUintPtr + return code, nil +} + func compileUint32(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpUint) code.setMaskAndRshiftNum(32) @@ -474,6 +631,15 @@ func compileUint32(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileUint32Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileUint32(ctx) + if err != nil { + return nil, err + } + code.Op = OpUintPtr + return code, nil +} + func compileUint64(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpUint) code.setMaskAndRshiftNum(64) @@ -481,6 +647,15 @@ func compileUint64(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileUint64Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileUint64(ctx) + if err != nil { + return nil, err + } + code.Op = OpUintPtr + return code, nil +} + func compileIntString(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpIntString) code.setMaskAndRshiftNum(intSize) @@ -557,12 +732,30 @@ func compileFloat32(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileFloat32Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileFloat32(ctx) + if err != nil { + return nil, err + } + code.Op = OpFloat32Ptr + return code, nil +} + func compileFloat64(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpFloat64) ctx.incIndex() return code, nil } +func compileFloat64Ptr(ctx *compileContext) (*Opcode, error) { + code, err := compileFloat64(ctx) + if err != nil { + return nil, err + } + code.Op = OpFloat64Ptr + return code, nil +} + func compileString(ctx *compileContext) (*Opcode, error) { var op OpType if ctx.typ == runtime.Type2RType(jsonNumberType) { @@ -575,24 +768,64 @@ func compileString(ctx *compileContext) (*Opcode, error) { return code, nil } +func compileStringPtr(ctx *compileContext) (*Opcode, error) { + code, err := compileString(ctx) + if err != nil { + return nil, err + } + if code.Op == OpNumber { + code.Op = OpNumberPtr + } else { + code.Op = OpStringPtr + } + return code, nil +} + func compileBool(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpBool) ctx.incIndex() return code, nil } +func compileBoolPtr(ctx *compileContext) (*Opcode, error) { + code, err := compileBool(ctx) + if err != nil { + return nil, err + } + code.Op = OpBoolPtr + return code, nil +} + func compileBytes(ctx *compileContext) (*Opcode, error) { code := newOpCode(ctx, OpBytes) ctx.incIndex() return code, nil } +func compileBytesPtr(ctx *compileContext) (*Opcode, error) { + code, err := compileBytes(ctx) + if err != nil { + return nil, err + } + code.Op = OpBytesPtr + return code, nil +} + func compileInterface(ctx *compileContext) (*Opcode, error) { code := newInterfaceCode(ctx) ctx.incIndex() return code, nil } +func compileInterfacePtr(ctx *compileContext) (*Opcode, error) { + code, err := compileInterface(ctx) + if err != nil { + return nil, err + } + code.Op = OpInterfacePtr + return code, nil +} + func compileSlice(ctx *compileContext) (*Opcode, error) { elem := ctx.typ.Elem() size := elem.Size() diff --git a/internal/encoder/opcode.go b/internal/encoder/opcode.go index 07d9c05..875d4b2 100644 --- a/internal/encoder/opcode.go +++ b/internal/encoder/opcode.go @@ -96,6 +96,10 @@ func (c *Opcode) ToHeaderType() OpType { return OpStructHeadBool case OpBoolPtr: return OpStructHeadBoolPtr + case OpBytes: + return OpStructHeadBytes + case OpBytesPtr: + return OpStructHeadBytesPtr case OpMap: return OpStructHeadMap case OpMapPtr: @@ -153,6 +157,10 @@ func (c *Opcode) ToFieldType() OpType { return OpStructFieldBool case OpBoolPtr: return OpStructFieldBoolPtr + case OpBytes: + return OpStructFieldBytes + case OpBytesPtr: + return OpStructFieldBytesPtr case OpMap: return OpStructFieldMap case OpMapPtr: diff --git a/internal/encoder/vm/util.go b/internal/encoder/vm/util.go index e3ab131..954b0d0 100644 --- a/internal/encoder/vm/util.go +++ b/internal/encoder/vm/util.go @@ -18,13 +18,16 @@ func store(base uintptr, idx uintptr, p uintptr) { **(**uintptr)(unsafe.Pointer(&addr)) = p } -func loadNPtr(base uintptr, idx uintptr, _ int) uintptr { +func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { addr := base + idx p := **(**uintptr)(unsafe.Pointer(&addr)) - if p == 0 { - return 0 + for i := 0; i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) } - return ptrToPtr(p) + return p } func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go index 31a83f8..3ce0300 100644 --- a/internal/encoder/vm/vm.go +++ b/internal/encoder/vm/vm.go @@ -2024,9 +2024,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '{') } b = append(b, code.Key...) - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p+code.Offset)) - b = append(b, '"') b = appendComma(b) code = code.Next case encoder.OpStructPtrHeadBytesPtr: @@ -2131,9 +2129,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendComma(b) code = code.Next @@ -4386,9 +4382,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendStructEnd(b) code = code.Next diff --git a/internal/encoder/vm_escaped/util.go b/internal/encoder/vm_escaped/util.go index 2bf9be9..3628780 100644 --- a/internal/encoder/vm_escaped/util.go +++ b/internal/encoder/vm_escaped/util.go @@ -18,13 +18,16 @@ func store(base uintptr, idx uintptr, p uintptr) { **(**uintptr)(unsafe.Pointer(&addr)) = p } -func loadNPtr(base uintptr, idx uintptr, _ int) uintptr { +func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { addr := base + idx p := **(**uintptr)(unsafe.Pointer(&addr)) - if p == 0 { - return 0 + for i := 0; i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) } - return ptrToPtr(p) + return p } func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } diff --git a/internal/encoder/vm_escaped/vm.go b/internal/encoder/vm_escaped/vm.go index 1619fa2..563db6d 100644 --- a/internal/encoder/vm_escaped/vm.go +++ b/internal/encoder/vm_escaped/vm.go @@ -2024,9 +2024,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt b = append(b, '{') } b = append(b, code.EscapedKey...) - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p+code.Offset)) - b = append(b, '"') b = appendComma(b) code = code.Next case encoder.OpStructPtrHeadBytesPtr: @@ -2131,9 +2129,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendComma(b) code = code.Next @@ -4386,9 +4382,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendStructEnd(b) code = code.Next diff --git a/internal/encoder/vm_escaped_indent/util.go b/internal/encoder/vm_escaped_indent/util.go index fc26d4d..383105b 100644 --- a/internal/encoder/vm_escaped_indent/util.go +++ b/internal/encoder/vm_escaped_indent/util.go @@ -19,13 +19,16 @@ func store(base uintptr, idx uintptr, p uintptr) { **(**uintptr)(unsafe.Pointer(&addr)) = p } -func loadNPtr(base uintptr, idx uintptr, _ int) uintptr { +func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { addr := base + idx p := **(**uintptr)(unsafe.Pointer(&addr)) - if p == 0 { - return 0 + for i := 0; i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) } - return ptrToPtr(p) + return p } func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } diff --git a/internal/encoder/vm_escaped_indent/vm.go b/internal/encoder/vm_escaped_indent/vm.go index 723d2b5..b66b20f 100644 --- a/internal/encoder/vm_escaped_indent/vm.go +++ b/internal/encoder/vm_escaped_indent/vm.go @@ -2230,9 +2230,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendComma(b) code = code.Next @@ -4848,9 +4846,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next diff --git a/internal/encoder/vm_indent/util.go b/internal/encoder/vm_indent/util.go index 9c68aae..cbcf54f 100644 --- a/internal/encoder/vm_indent/util.go +++ b/internal/encoder/vm_indent/util.go @@ -19,13 +19,16 @@ func store(base uintptr, idx uintptr, p uintptr) { **(**uintptr)(unsafe.Pointer(&addr)) = p } -func loadNPtr(base uintptr, idx uintptr, _ int) uintptr { +func loadNPtr(base uintptr, idx uintptr, ptrNum int) uintptr { addr := base + idx p := **(**uintptr)(unsafe.Pointer(&addr)) - if p == 0 { - return 0 + for i := 0; i < ptrNum; i++ { + if p == 0 { + return 0 + } + p = ptrToPtr(p) } - return ptrToPtr(p) + return p } func ptrToUint64(p uintptr) uint64 { return **(**uint64)(unsafe.Pointer(&p)) } diff --git a/internal/encoder/vm_indent/vm.go b/internal/encoder/vm_indent/vm.go index 780ea91..420d9f2 100644 --- a/internal/encoder/vm_indent/vm.go +++ b/internal/encoder/vm_indent/vm.go @@ -2236,9 +2236,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendComma(b) code = code.Next @@ -4854,9 +4852,7 @@ func Run(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet, opt if p == 0 { b = appendNull(b) } else { - b = append(b, '"') b = appendByteSlice(b, ptrToBytes(p)) - b = append(b, '"') } b = appendStructEnd(ctx, b, code.Indent-1) code = code.Next From b2bbd63168e53066df65cb1acccef4b6daf3f3c6 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 19 Mar 2021 23:47:29 +0900 Subject: [PATCH 2/3] Fix compiler for encoder --- cover_bytes_test.go | 2 -- internal/encoder/compiler.go | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/cover_bytes_test.go b/cover_bytes_test.go index 7e08d83..49eff88 100644 --- a/cover_bytes_test.go +++ b/cover_bytes_test.go @@ -2,7 +2,6 @@ package json_test import ( "bytes" - "fmt" "testing" "github.com/goccy/go-json" @@ -1806,7 +1805,6 @@ func TestCoverBytes(t *testing.T) { }, } for _, test := range tests { - fmt.Println("name = ", test.name) for _, indent := range []bool{true, false} { for _, htmlEscape := range []bool{true, false} { var buf bytes.Buffer diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index e14eea7..100456b 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -92,6 +92,7 @@ func compileHead(ctx *compileContext) (*Opcode, error) { } switch typ.Kind() { case reflect.Slice: + ctx := ctx.withType(typ) elem := typ.Elem() if elem.Kind() == reflect.Uint8 { p := runtime.PtrTo(elem) @@ -117,71 +118,85 @@ func compileHead(ctx *compileContext) (*Opcode, error) { linkRecursiveCode(code) return code, nil case reflect.Int: + ctx := ctx.withType(typ) if isPtr { return compileIntPtr(ctx) } return compileInt(ctx) case reflect.Int8: + ctx := ctx.withType(typ) if isPtr { return compileInt8Ptr(ctx) } return compileInt8(ctx) case reflect.Int16: + ctx := ctx.withType(typ) if isPtr { return compileInt16Ptr(ctx) } return compileInt16(ctx) case reflect.Int32: + ctx := ctx.withType(typ) if isPtr { return compileInt32Ptr(ctx) } return compileInt32(ctx) case reflect.Int64: + ctx := ctx.withType(typ) if isPtr { return compileInt64Ptr(ctx) } return compileInt64(ctx) case reflect.Uint, reflect.Uintptr: + ctx := ctx.withType(typ) if isPtr { return compileUintPtr(ctx) } return compileUint(ctx) case reflect.Uint8: + ctx := ctx.withType(typ) if isPtr { return compileUint8Ptr(ctx) } return compileUint8(ctx) case reflect.Uint16: + ctx := ctx.withType(typ) if isPtr { return compileUint16Ptr(ctx) } return compileUint16(ctx) case reflect.Uint32: + ctx := ctx.withType(typ) if isPtr { return compileUint32Ptr(ctx) } return compileUint32(ctx) case reflect.Uint64: + ctx := ctx.withType(typ) if isPtr { return compileUint64Ptr(ctx) } return compileUint64(ctx) case reflect.Float32: + ctx := ctx.withType(typ) if isPtr { return compileFloat32Ptr(ctx) } return compileFloat32(ctx) case reflect.Float64: + ctx := ctx.withType(typ) if isPtr { return compileFloat64Ptr(ctx) } return compileFloat64(ctx) case reflect.String: + ctx := ctx.withType(typ) if isPtr { return compileStringPtr(ctx) } return compileString(ctx) case reflect.Bool: + ctx := ctx.withType(typ) if isPtr { return compileBoolPtr(ctx) } From ef2906180783d2a51f07bc63630e85c4e8b1839f Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Fri, 19 Mar 2021 23:55:01 +0900 Subject: [PATCH 3/3] Fix error by linter --- internal/encoder/compiler.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/encoder/compiler.go b/internal/encoder/compiler.go index 100456b..14344da 100644 --- a/internal/encoder/compiler.go +++ b/internal/encoder/compiler.go @@ -201,6 +201,12 @@ func compileHead(ctx *compileContext) (*Opcode, error) { return compileBoolPtr(ctx) } return compileBool(ctx) + case reflect.Interface: + ctx := ctx.withType(typ) + if isPtr { + return compileInterfacePtr(ctx) + } + return compileInterface(ctx) default: if isPtr && typ.Implements(marshalTextType) { typ = orgType