From 135a3c0cfbff43208c35bc9f6a9b6ee5dce6dd97 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Mon, 11 Jan 2021 19:47:33 +0900 Subject: [PATCH 1/4] Use NoEscapedString --- encode_vm.go | 10 +++------- encode_vm_indent.go | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/encode_vm.go b/encode_vm.go index ace6e73..eef71ab 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -301,11 +301,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte if err != nil { return nil, errMarshaler(code, err) } - if e.enabledHTMLEscape { - b = encodeEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) - } else { - b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) - } + b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) b = encodeComma(b) } code = code.next @@ -3501,7 +3497,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } } b = append(b, code.key...) - b = encodeEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) + b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) b = encodeComma(b) code = code.next } @@ -3532,7 +3528,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } } b = append(b, code.key...) - b = encodeEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) + b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) b = encodeComma(b) code = code.next } diff --git a/encode_vm_indent.go b/encode_vm_indent.go index 69b2208..1955437 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -4165,7 +4165,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( if err := compact(&buf, bb, e.enabledHTMLEscape); err != nil { return nil, err } - b = encodeEscapedString(b, buf.String()) + b = encodeNoEscapedString(b, buf.String()) b = encodeIndentComma(b) code = code.next case opStructFieldStringTagMarshalText: From 8ab0aa7168ba7d5c896337f53e71ae68a1bf6cb1 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Tue, 12 Jan 2021 02:40:12 +0900 Subject: [PATCH 2/4] Add test cases of omitempty/string tag for int type --- coverage_test.go | 223 +++++++++++++++++++++++++++ encode_vm.go | 272 ++++++++++++++++++++++----------- encode_vm_escaped.go | 293 +++++++++++++++++++++++------------- encode_vm_escaped_indent.go | 214 +++++++++++++++++++------- encode_vm_indent.go | 214 +++++++++++++++++++------- 5 files changed, 925 insertions(+), 291 deletions(-) diff --git a/coverage_test.go b/coverage_test.go index e47fd83..d75b8a3 100644 --- a/coverage_test.go +++ b/coverage_test.go @@ -34,6 +34,7 @@ func TestCoverStructHeadInt(t *testing.T) { indentExpected string data interface{} }{ + // HeadIntZero { name: "HeadIntZero", expected: `{"a":0}`, @@ -46,6 +47,30 @@ func TestCoverStructHeadInt(t *testing.T) { A int `json:"a"` }{}, }, + { + name: "HeadIntZeroOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A int `json:"a,omitempty"` + }{}, + }, + { + name: "HeadIntZeroString", + expected: `{"a":"0"}`, + indentExpected: ` +{ + "a": "0" +} +`, + data: struct { + A int `json:"a,string"` + }{}, + }, + + // HeadInt { name: "HeadInt", expected: `{"a":1}`, @@ -58,6 +83,32 @@ func TestCoverStructHeadInt(t *testing.T) { A int `json:"a"` }{A: 1}, }, + { + name: "HeadIntOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + A int `json:"a,omitempty"` + }{A: 1}, + }, + { + name: "HeadIntString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + A int `json:"a,string"` + }{A: 1}, + }, + + // HeadIntPtr { name: "HeadIntPtr", expected: `{"a":1}`, @@ -70,6 +121,32 @@ func TestCoverStructHeadInt(t *testing.T) { A *int `json:"a"` }{A: intptr(1)}, }, + { + name: "HeadIntPtrOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}, + }, + { + name: "HeadIntPtrString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + A *int `json:"a,string"` + }{A: intptr(1)}, + }, + + // HeadIntPtrNil { name: "HeadIntPtrNil", expected: `{"a":null}`, @@ -82,6 +159,30 @@ func TestCoverStructHeadInt(t *testing.T) { A *int `json:"a"` }{A: nil}, }, + { + name: "HeadIntPtrNilOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *int `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "HeadIntPtrNilString", + expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, + data: struct { + A *int `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadIntZero { name: "PtrHeadIntZero", expected: `{"a":0}`, @@ -94,6 +195,30 @@ func TestCoverStructHeadInt(t *testing.T) { A int `json:"a"` }{}, }, + { + name: "PtrHeadIntZeroOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A int `json:"a,omitempty"` + }{}, + }, + { + name: "PtrHeadIntZeroString", + expected: `{"a":"0"}`, + indentExpected: ` +{ + "a": "0" +} +`, + data: &struct { + A int `json:"a,string"` + }{}, + }, + + // PtrHeadInt { name: "PtrHeadInt", expected: `{"a":1}`, @@ -106,6 +231,32 @@ func TestCoverStructHeadInt(t *testing.T) { A int `json:"a"` }{A: 1}, }, + { + name: "PtrHeadIntOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: &struct { + A int `json:"a,omitempty"` + }{A: 1}, + }, + { + name: "PtrHeadIntString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: &struct { + A int `json:"a,string"` + }{A: 1}, + }, + + // PtrHeadIntPtr { name: "PtrHeadIntPtr", expected: `{"a":1}`, @@ -118,6 +269,32 @@ func TestCoverStructHeadInt(t *testing.T) { A *int `json:"a"` }{A: intptr(1)}, }, + { + name: "PtrHeadIntPtrOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: &struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}, + }, + { + name: "PtrHeadIntPtrString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: &struct { + A *int `json:"a,string"` + }{A: intptr(1)}, + }, + + // PtrHeadIntPtrNil { name: "PtrHeadIntPtrNil", expected: `{"a":null}`, @@ -130,6 +307,30 @@ func TestCoverStructHeadInt(t *testing.T) { A *int `json:"a"` }{A: nil}, }, + { + name: "PtrHeadIntPtrNilOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *int `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadIntPtrNilString", + expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, + data: &struct { + A *int `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadIntNil { name: "PtrHeadIntNil", expected: `null`, @@ -140,6 +341,28 @@ null A *int `json:"a"` })(nil), }, + { + name: "PtrHeadIntNilOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *int `json:"a,omitempty"` + })(nil), + }, + { + name: "PtrHeadIntNilString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *int `json:"a,string"` + })(nil), + }, + + // HeadIntZeroMultiFields { name: "HeadIntZeroMultiFields", expected: `{"a":0,"b":0}`, diff --git a/encode_vm.go b/encode_vm.go index eef71ab..23e2eb8 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -648,6 +648,51 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrHeadIntOnly, opStructFieldHeadIntOnly: p := load(ctxptr, code.idx) b = append(b, '{') @@ -655,6 +700,25 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = appendInt(b, int64(e.ptrToInt(p))) b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntOnly, opStructFieldHeadOmitEmptyIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + v := int64(e.ptrToInt(p)) + if v != 0 { + b = append(b, code.key...) + b = appendInt(b, v) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntOnly, opStructFieldHeadStringTagIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -677,6 +741,49 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p = e.ptrToPtr(p) + if p != 0 { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } else { + b = append(b, '{') + b = append(b, code.key...) + p = e.ptrToPtr(p) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -698,6 +805,48 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadOmitEmptyIntPtrOnly: + b = append(b, '{') + p := load(ctxptr, code.idx) + if p != 0 { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.key...) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldHeadIntNPtr: p := load(ctxptr, code.idx) if p == 0 { @@ -732,6 +881,45 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -2694,51 +2882,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte store(ctxptr, code.idx, p) } } - case opStructFieldPtrHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - b = appendInt(b, int64(v)) - b = encodeComma(b) - code = code.next - } - } - case opStructFieldPtrAnonymousHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - b = appendInt(b, int64(v)) - b = encodeComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3567,45 +3710,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, ptr+code.offset) } - case opStructFieldPtrHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - b = append(b, code.key...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeComma(b) - code = code.next - } - case opStructFieldPtrAnonymousHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - b = append(b, code.key...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index 7432ee2..df037a6 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -610,6 +610,51 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrHeadIntOnly, opStructFieldHeadIntOnly: p := load(ctxptr, code.idx) b = append(b, '{') @@ -617,6 +662,25 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = appendInt(b, int64(e.ptrToInt(p))) b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntOnly, opStructFieldHeadOmitEmptyIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + v := int64(e.ptrToInt(p)) + if v != 0 { + b = append(b, code.escapedKey...) + b = appendInt(b, v) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntOnly, opStructFieldHeadStringTagIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -639,6 +703,49 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p = e.ptrToPtr(p) + if p != 0 { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } else { + b = append(b, '{') + b = append(b, code.escapedKey...) + p = e.ptrToPtr(p) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -660,6 +767,48 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadOmitEmptyIntPtrOnly: + b = append(b, '{') + p := load(ctxptr, code.idx) + if p != 0 { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.escapedKey...) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldHeadIntNPtr: p := load(ctxptr, code.idx) if p == 0 { @@ -694,6 +843,45 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -2663,72 +2851,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) store(ctxptr, code.idx, p) } } - case opStructFieldPtrHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - b = appendInt(b, int64(v)) - b = encodeComma(b) - code = code.next - } - } - case opStructFieldPtrHeadOmitEmptyIntOnly: - p := load(ctxptr, code.idx) - if p == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - break - } - fallthrough - case opStructFieldHeadOmitEmptyIntOnly: - ptr := load(ctxptr, code.idx) - b = append(b, '{') - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - b = appendInt(b, int64(v)) - b = encodeComma(b) - code = code.next - } - case opStructFieldPtrAnonymousHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - b = appendInt(b, int64(v)) - b = encodeComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3557,45 +3679,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, ptr+code.offset) } - case opStructFieldPtrHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - b = append(b, code.escapedKey...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeComma(b) - code = code.next - } - case opStructFieldPtrAnonymousHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - b = append(b, code.escapedKey...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { diff --git a/encode_vm_escaped_indent.go b/encode_vm_escaped_indent.go index 6e65642..9947634 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -646,6 +646,54 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrHeadIntOnly, opStructFieldHeadIntOnly: p := load(ctxptr, code.idx) b = append(b, '{', '\n') @@ -655,6 +703,28 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = appendInt(b, int64(e.ptrToInt(p))) b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntOnly, opStructFieldHeadOmitEmptyIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + v := int64(e.ptrToInt(p)) + if v != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, v) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntOnly, opStructFieldHeadStringTagIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -679,6 +749,53 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + p = e.ptrToPtr(p) + if p != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -702,6 +819,52 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if p != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldHeadIntNPtr: p := load(ctxptr, code.idx) if p == 0 { @@ -2719,34 +2882,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op store(ctxptr, code.idx, p) } } - case opStructFieldPtrHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.escapedKey...) - b = append(b, ' ') - b = appendInt(b, int64(v)) - b = encodeIndentComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3164,29 +3299,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op code = code.next store(ctxptr, code.idx, p) } - case opStructFieldPtrHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = append(b, '{', '\n') - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.escapedKey...) - b = append(b, ' ', '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeIndentComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { diff --git a/encode_vm_indent.go b/encode_vm_indent.go index 1955437..b523d96 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -646,6 +646,54 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrHeadIntOnly, opStructFieldHeadIntOnly: p := load(ctxptr, code.idx) b = append(b, '{', '\n') @@ -655,6 +703,28 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = appendInt(b, int64(e.ptrToInt(p))) b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntOnly, opStructFieldHeadOmitEmptyIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + v := int64(e.ptrToInt(p)) + if v != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, v) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntOnly, opStructFieldHeadStringTagIntOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -679,6 +749,53 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{', '\n') + p = e.ptrToPtr(p) + if p != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -702,6 +819,52 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if p != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldHeadIntNPtr: p := load(ctxptr, code.idx) if p == 0 { @@ -2719,34 +2882,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( store(ctxptr, code.idx, p) } } - case opStructFieldPtrHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - v := e.ptrToInt(ptr + code.offset) - if v == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.key...) - b = append(b, ' ') - b = appendInt(b, int64(v)) - b = encodeIndentComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3164,29 +3299,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( code = code.next store(ctxptr, code.idx, p) } - case opStructFieldPtrHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagInt: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = append(b, '{', '\n') - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.key...) - b = append(b, ' ', '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = encodeIndentComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { From fd1085102c2ab24de859c7dfa03bdf05dba3c95c Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Wed, 13 Jan 2021 00:14:46 +0900 Subject: [PATCH 3/4] Fix opcode for end of omitempty int type --- coverage_test.go | 322 ++++++++++++++++++++++++++++++++++++ encode_vm.go | 68 +++++--- encode_vm_escaped.go | 68 +++++--- encode_vm_escaped_indent.go | 84 +++++++--- encode_vm_indent.go | 86 +++++++--- 5 files changed, 541 insertions(+), 87 deletions(-) diff --git a/coverage_test.go b/coverage_test.go index d75b8a3..66a168a 100644 --- a/coverage_test.go +++ b/coverage_test.go @@ -377,6 +377,33 @@ null B int `json:"b"` }{}, }, + { + name: "HeadIntZeroMultiFieldsOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{}, + }, + { + name: "HeadIntZeroMultiFields", + expected: `{"a":"0","b":"0"}`, + indentExpected: ` +{ + "a": "0", + "b": "0" +} +`, + data: struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{}, + }, + + // HeadIntMultiFields { name: "HeadIntMultiFields", expected: `{"a":1,"b":2}`, @@ -391,6 +418,36 @@ null B int `json:"b"` }{A: 1, B: 2}, }, + { + name: "HeadIntMultiFieldsOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 1, B: 2}, + }, + { + name: "HeadIntMultiFieldsString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 1, B: 2}, + }, + + // HeadIntPtrMultiFields { name: "HeadIntPtrMultiFields", expected: `{"a":1,"b":2}`, @@ -405,6 +462,36 @@ null B *int `json:"b"` }{A: intptr(1), B: intptr(2)}, }, + { + name: "HeadIntPtrMultiFieldsOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(1), B: intptr(2)}, + }, + { + name: "HeadIntPtrMultiFieldsString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(1), B: intptr(2)}, + }, + + // HeadIntPtrNilMultiFields { name: "HeadIntPtrNilMultiFields", expected: `{"a":null,"b":null}`, @@ -419,6 +506,33 @@ null B *int `json:"b"` }{A: nil, B: nil}, }, + { + name: "HeadIntPtrNilMultiFieldsOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: nil, B: nil}, + }, + { + name: "HeadIntPtrNilMultiFieldsString", + expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, + data: struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: nil, B: nil}, + }, + + // PtrHeadIntZeroMultiFields { name: "PtrHeadIntZeroMultiFields", expected: `{"a":0,"b":0}`, @@ -433,6 +547,33 @@ null B int `json:"b"` }{}, }, + { + name: "PtrHeadIntZeroMultiFieldsOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{}, + }, + { + name: "PtrHeadIntZeroMultiFieldsString", + expected: `{"a":"0","b":"0"}`, + indentExpected: ` +{ + "a": "0", + "b": "0" +} +`, + data: &struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{}, + }, + + // PtrHeadIntMultiFields { name: "PtrHeadIntMultiFields", expected: `{"a":1,"b":2}`, @@ -447,6 +588,36 @@ null B int `json:"b"` }{A: 1, B: 2}, }, + { + name: "PtrHeadIntMultiFieldsOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: &struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 1, B: 2}, + }, + { + name: "PtrHeadIntMultiFieldsString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: &struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 1, B: 2}, + }, + + // PtrHeadIntPtrMultiFields { name: "PtrHeadIntPtrMultiFields", expected: `{"a":1,"b":2}`, @@ -461,6 +632,36 @@ null B *int `json:"b"` }{A: intptr(1), B: intptr(2)}, }, + { + name: "PtrHeadIntPtrMultiFieldsOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: &struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(1), B: intptr(2)}, + }, + { + name: "PtrHeadIntPtrMultiFieldsString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: &struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(1), B: intptr(2)}, + }, + + // PtrHeadIntPtrNilMultiFields { name: "PtrHeadIntPtrNilMultiFields", expected: `{"a":null,"b":null}`, @@ -475,6 +676,33 @@ null B *int `json:"b"` }{A: nil, B: nil}, }, + { + name: "PtrHeadIntPtrNilMultiFieldsOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntPtrNilMultiFieldsString", + expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, + data: &struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: nil, B: nil}, + }, + + // PtrHeadIntNilMultiFields { name: "PtrHeadIntNilMultiFields", expected: `null`, @@ -486,6 +714,30 @@ null B *int `json:"b"` })(nil), }, + { + name: "PtrHeadIntNilMultiFieldsOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + })(nil), + }, + { + name: "PtrHeadIntNilMultiFieldsString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + })(nil), + }, + + // HeadIntZeroNotRoot { name: "HeadIntZeroNotRoot", expected: `{"A":{"a":0}}`, @@ -502,6 +754,38 @@ null } }{}, }, + { + name: "HeadIntZeroNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadIntZeroNotRootString", + expected: `{"A":{"a":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + }{}, + }, + + // HeadIntNotRoot { name: "HeadIntNotRoot", expected: `{"A":{"a":1}}`, @@ -520,6 +804,44 @@ null A int `json:"a"` }{A: 1}}, }, + { + name: "HeadIntNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + }{A: struct { + A int `json:"a,omitempty"` + }{A: 1}}, + }, + { + name: "HeadIntNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + }{A: struct { + A int `json:"a,string"` + }{A: 1}}, + }, + + // HeadIntPtrNotRoot { name: "HeadIntPtrNotRoot", expected: `{"A":{"a":1}}`, diff --git a/encode_vm.go b/encode_vm.go index 23e2eb8..88f6e85 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -5127,6 +5127,29 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next case opStructAnonymousEnd: code = code.next + case opStructEndInt: + ptr := load(ctxptr, code.headIdx) + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = appendStructEnd(b) + code = code.next + case opStructEndOmitEmptyInt: + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) + if v != 0 { + b = append(b, code.key...) + b = appendInt(b, int64(v)) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagInt: + ptr := load(ctxptr, code.headIdx) + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = appendStructEnd(b) + code = code.next case opStructEndIntPtr: b = append(b, code.key...) ptr := load(ctxptr, code.headIdx) @@ -5138,6 +5161,28 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = appendStructEnd(b) code = code.next + case opStructEndOmitEmptyIntPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p))) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagIntPtr: + b = append(b, code.key...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + } + b = appendStructEnd(b) + code = code.next case opStructEndIntNPtr: b = append(b, code.key...) ptr := load(ctxptr, code.headIdx) @@ -5155,12 +5200,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = appendStructEnd(b) code = code.next - case opStructEndInt: - ptr := load(ctxptr, code.headIdx) - b = append(b, code.key...) - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = appendStructEnd(b) - code = code.next case opStructEndInt8Ptr: b = append(b, code.key...) ptr := load(ctxptr, code.headIdx) @@ -5426,15 +5465,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeNoEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) b = appendStructEnd(b) code = code.next - case opStructEndOmitEmptyInt: - ptr := load(ctxptr, code.headIdx) - v := e.ptrToInt(ptr + code.offset) - if v != 0 { - b = append(b, code.key...) - b = appendInt(b, int64(v)) - } - b = appendStructEnd(b) - code = code.next case opStructEndOmitEmptyInt8: ptr := load(ctxptr, code.headIdx) v := e.ptrToInt8(ptr + code.offset) @@ -5596,14 +5626,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = appendStructEnd(b) code = code.next - case opStructEndStringTagInt: - ptr := load(ctxptr, code.headIdx) - b = append(b, code.key...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = appendStructEnd(b) - code = code.next case opStructEndStringTagInt8: ptr := load(ctxptr, code.headIdx) b = append(b, code.key...) diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index df037a6..64cc918 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -5155,6 +5155,29 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next case opStructAnonymousEnd: code = code.next + case opStructEndInt: + ptr := load(ctxptr, code.headIdx) + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = appendStructEnd(b) + code = code.next + case opStructEndOmitEmptyInt: + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) + if v != 0 { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(v)) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagInt: + ptr := load(ctxptr, code.headIdx) + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = appendStructEnd(b) + code = code.next case opStructEndIntPtr: b = append(b, code.escapedKey...) ptr := load(ctxptr, code.headIdx) @@ -5166,6 +5189,28 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = appendStructEnd(b) code = code.next + case opStructEndOmitEmptyIntPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p))) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagIntPtr: + b = append(b, code.escapedKey...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + } + b = appendStructEnd(b) + code = code.next case opStructEndIntNPtr: b = append(b, code.escapedKey...) ptr := load(ctxptr, code.headIdx) @@ -5183,12 +5228,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = appendStructEnd(b) code = code.next - case opStructEndInt: - ptr := load(ctxptr, code.headIdx) - b = append(b, code.escapedKey...) - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = appendStructEnd(b) - code = code.next case opStructEndInt8Ptr: b = append(b, code.escapedKey...) ptr := load(ctxptr, code.headIdx) @@ -5454,15 +5493,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeEscapedString(b, *(*string)(unsafe.Pointer(&bytes))) b = appendStructEnd(b) code = code.next - case opStructEndOmitEmptyInt: - ptr := load(ctxptr, code.headIdx) - v := e.ptrToInt(ptr + code.offset) - if v != 0 { - b = append(b, code.escapedKey...) - b = appendInt(b, int64(v)) - } - b = appendStructEnd(b) - code = code.next case opStructEndOmitEmptyInt8: ptr := load(ctxptr, code.headIdx) v := e.ptrToInt8(ptr + code.offset) @@ -5624,14 +5654,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = appendStructEnd(b) code = code.next - case opStructEndStringTagInt: - ptr := load(ctxptr, code.headIdx) - b = append(b, code.escapedKey...) - b = append(b, '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = appendStructEnd(b) - code = code.next case opStructEndStringTagInt8: ptr := load(ctxptr, code.headIdx) b = append(b, code.escapedKey...) diff --git a/encode_vm_escaped_indent.go b/encode_vm_escaped_indent.go index 9947634..adc3c29 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -4321,6 +4321,35 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndOmitEmptyInt: + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) + if v != 0 { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = e.appendStructEndIndent(b, code.indent-1) + } else { + last := len(b) - 1 + if b[last-1] == '{' { + // doesn't exist any fields + b[last] = '}' + } else { + b = append(b, '}') + } + b = encodeIndentComma(b) + } + code = code.next + case opStructEndStringTagInt: + ptr := load(ctxptr, code.headIdx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndIntPtr: b = e.encodeIndent(b, code.indent) b = append(b, code.escapedKey...) @@ -4334,6 +4363,41 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndOmitEmptyIntPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = e.appendStructEndIndent(b, code.indent-1) + } else { + last := len(b) - 1 + if b[last-1] == '{' { + // doesn't exist any fields + b[last] = '}' + } else { + b = append(b, '}') + } + b = encodeIndentComma(b) + } + code = code.next + case opStructEndStringTagIntPtr: + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndInt8: b = e.encodeIndent(b, code.indent) b = append(b, code.escapedKey...) @@ -4615,17 +4679,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, buf.Bytes()...) b = e.appendStructEndIndent(b, code.indent-1) code = code.next - case opStructEndOmitEmptyInt: - ptr := load(ctxptr, code.headIdx) - v := e.ptrToInt(ptr + code.offset) - if v != 0 { - b = e.encodeIndent(b, code.indent) - b = append(b, code.escapedKey...) - b = append(b, ' ') - b = appendInt(b, int64(v)) - } - b = e.appendStructEndIndent(b, code.indent-1) - code = code.next case opStructEndOmitEmptyInt8: ptr := load(ctxptr, code.headIdx) v := e.ptrToInt8(ptr + code.offset) @@ -4783,15 +4836,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = e.appendStructEndIndent(b, code.indent-1) code = code.next - case opStructEndStringTagInt: - ptr := load(ctxptr, code.headIdx) - b = e.encodeIndent(b, code.indent) - b = append(b, code.escapedKey...) - b = append(b, ' ', '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = e.appendStructEndIndent(b, code.indent-1) - code = code.next case opStructEndStringTagInt8: ptr := load(ctxptr, code.headIdx) b = e.encodeIndent(b, code.indent) diff --git a/encode_vm_indent.go b/encode_vm_indent.go index b523d96..c5d5e8a 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -756,7 +756,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( p := load(ctxptr, code.idx) if p == 0 { b = encodeNull(b) - b = encodeComma(b) + b = encodeIndentComma(b) code = code.end.next } else { b = append(b, '{', '\n') @@ -4321,6 +4321,35 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndOmitEmptyInt: + ptr := load(ctxptr, code.headIdx) + v := e.ptrToInt(ptr + code.offset) + if v != 0 { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = e.appendStructEndIndent(b, code.indent-1) + } else { + last := len(b) - 1 + if b[last-1] == '{' { + // doesn't exist any fields + b[last] = '}' + } else { + b = append(b, '}') + } + b = encodeIndentComma(b) + } + code = code.next + case opStructEndStringTagInt: + ptr := load(ctxptr, code.headIdx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ', '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndIntPtr: b = e.encodeIndent(b, code.indent) b = append(b, code.key...) @@ -4334,6 +4363,41 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndOmitEmptyIntPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = e.appendStructEndIndent(b, code.indent-1) + } else { + last := len(b) - 1 + if b[last-1] == '{' { + // doesn't exist any fields + b[last] = '}' + } else { + b = append(b, '}') + } + b = encodeIndentComma(b) + } + code = code.next + case opStructEndStringTagIntPtr: + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = append(b, `""`...) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p))) + b = append(b, '"') + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndInt8: b = e.encodeIndent(b, code.indent) b = append(b, code.key...) @@ -4615,17 +4679,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, buf.Bytes()...) b = e.appendStructEndIndent(b, code.indent-1) code = code.next - case opStructEndOmitEmptyInt: - ptr := load(ctxptr, code.headIdx) - v := e.ptrToInt(ptr + code.offset) - if v != 0 { - b = e.encodeIndent(b, code.indent) - b = append(b, code.key...) - b = append(b, ' ') - b = appendInt(b, int64(v)) - } - b = e.appendStructEndIndent(b, code.indent-1) - code = code.next case opStructEndOmitEmptyInt8: ptr := load(ctxptr, code.headIdx) v := e.ptrToInt8(ptr + code.offset) @@ -4783,15 +4836,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = e.appendStructEndIndent(b, code.indent-1) code = code.next - case opStructEndStringTagInt: - ptr := load(ctxptr, code.headIdx) - b = e.encodeIndent(b, code.indent) - b = append(b, code.key...) - b = append(b, ' ', '"') - b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) - b = append(b, '"') - b = e.appendStructEndIndent(b, code.indent-1) - code = code.next case opStructEndStringTagInt8: ptr := load(ctxptr, code.headIdx) b = e.encodeIndent(b, code.indent) From 67a7ac450b1eeaf30a9d61e9e4401a16d7d4e9a1 Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 14 Jan 2021 00:02:58 +0900 Subject: [PATCH 4/4] Add test cases for int type --- coverage_test.go | 1423 ++++++++++++++++++++++++++++++++++- encode_compile.go | 12 +- encode_vm.go | 210 ++++-- encode_vm_escaped.go | 210 ++++-- encode_vm_escaped_indent.go | 228 +++++- encode_vm_indent.go | 228 +++++- 6 files changed, 2141 insertions(+), 170 deletions(-) diff --git a/coverage_test.go b/coverage_test.go index 66a168a..8180886 100644 --- a/coverage_test.go +++ b/coverage_test.go @@ -24,9 +24,22 @@ func TestCoverStructHeadInt(t *testing.T) { type structInt struct { A int `json:"a"` } + type structIntOmitEmpty struct { + A int `json:"a,omitempty"` + } + type structIntString struct { + A int `json:"a,string"` + } + type structIntPtr struct { A *int `json:"a"` } + type structIntPtrOmitEmpty struct { + A *int `json:"a,omitempty"` + } + type structIntPtrString struct { + A *int `json:"a,string"` + } tests := []struct { name string @@ -171,10 +184,10 @@ func TestCoverStructHeadInt(t *testing.T) { }, { name: "HeadIntPtrNilString", - expected: `{"a":""}`, + expected: `{"a":null}`, indentExpected: ` { - "a": "" + "a": null } `, data: struct { @@ -319,10 +332,10 @@ func TestCoverStructHeadInt(t *testing.T) { }, { name: "PtrHeadIntPtrNilString", - expected: `{"a":""}`, + expected: `{"a":null}`, indentExpected: ` { - "a": "" + "a": null } `, data: &struct { @@ -519,11 +532,11 @@ null }, { name: "HeadIntPtrNilMultiFieldsString", - expected: `{"a":"","b":""}`, + expected: `{"a":null,"b":null}`, indentExpected: ` { - "a": "", - "b": "" + "a": null, + "b": null } `, data: struct { @@ -689,11 +702,11 @@ null }, { name: "PtrHeadIntPtrNilMultiFieldsString", - expected: `{"a":"","b":""}`, + expected: `{"a":null,"b":null}`, indentExpected: ` { - "a": "", - "b": "" + "a": null, + "b": null } `, data: &struct { @@ -860,6 +873,44 @@ null A *int `json:"a"` }{intptr(1)}}, }, + { + name: "HeadIntPtrNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{intptr(1)}}, + }, + { + name: "HeadIntPtrNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{intptr(1)}}, + }, + + // HeadIntPtrNilNotRoot { name: "HeadIntPtrNilNotRoot", expected: `{"A":{"a":null}}`, @@ -876,6 +927,38 @@ null } }{}, }, + { + name: "HeadIntPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadIntPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + }{}, + }, + + // PtrHeadIntZeroNotRoot { name: "PtrHeadIntZeroNotRoot", expected: `{"A":{"a":0}}`, @@ -894,6 +977,42 @@ null A int `json:"a"` })}, }, + { + name: "PtrHeadIntZeroNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A int `json:"a,omitempty"` + } + }{A: new(struct { + A int `json:"a,omitempty"` + })}, + }, + { + name: "PtrHeadIntZeroNotRootString", + expected: `{"A":{"a":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + } +} +`, + data: struct { + A *struct { + A int `json:"a,string"` + } + }{A: new(struct { + A int `json:"a,string"` + })}, + }, + + // PtrHeadIntNotRoot { name: "PtrHeadIntNotRoot", expected: `{"A":{"a":1}}`, @@ -912,6 +1031,44 @@ null A int `json:"a"` }{A: 1})}, }, + { + name: "PtrHeadIntNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A *struct { + A int `json:"a,omitempty"` + } + }{A: &(struct { + A int `json:"a,omitempty"` + }{A: 1})}, + }, + { + name: "PtrHeadIntNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A *struct { + A int `json:"a,string"` + } + }{A: &(struct { + A int `json:"a,string"` + }{A: 1})}, + }, + + // PtrHeadIntPtrNotRoot { name: "PtrHeadIntPtrNotRoot", expected: `{"A":{"a":1}}`, @@ -930,6 +1087,44 @@ null A *int `json:"a"` }{A: intptr(1)})}, }, + { + name: "PtrHeadIntPtrNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)})}, + }, + { + name: "PtrHeadIntPtrNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: intptr(1)})}, + }, + + // PtrHeadIntPtrNilNotRoot { name: "PtrHeadIntPtrNilNotRoot", expected: `{"A":{"a":null}}`, @@ -948,6 +1143,42 @@ null A *int `json:"a"` }{A: nil})}, }, + { + name: "PtrHeadIntPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: nil})}, + }, + { + name: "PtrHeadIntPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: nil})}, + }, + + // PtrHeadIntNilNotRoot { name: "PtrHeadIntNilNotRoot", expected: `{"A":null}`, @@ -962,6 +1193,34 @@ null } }{A: nil}, }, + { + name: "PtrHeadIntNilNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } `json:",omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadIntNilNotRootString", + expected: `{"A":null}`, + indentExpected: ` +{ + "A": null +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } `json:",string"` + }{A: nil}, + }, + + // HeadIntZeroMultiFieldsNotRoot { name: "HeadIntZeroMultiFieldsNotRoot", expected: `{"A":{"a":0},"B":{"b":0}}`, @@ -984,6 +1243,48 @@ null } }{}, }, + { + name: "HeadIntZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{}, + }, + { + name: "HeadIntZeroMultiFieldsNotRootString", + expected: `{"A":{"a":"0"},"B":{"b":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + }, + "B": { + "b": "0" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{}, + }, + + // HeadIntMultiFieldsNotRoot { name: "HeadIntMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1010,6 +1311,60 @@ null B int `json:"b"` }{B: 2}}, }, + { + name: "HeadIntMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{A: struct { + A int `json:"a,omitempty"` + }{A: 1}, B: struct { + B int `json:"b,omitempty"` + }{B: 2}}, + }, + { + name: "HeadIntMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{A: struct { + A int `json:"a,string"` + }{A: 1}, B: struct { + B int `json:"b,string"` + }{B: 2}}, + }, + + // HeadIntPtrMultiFieldsNotRoot { name: "HeadIntPtrMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1036,6 +1391,60 @@ null B *int `json:"b"` }{B: intptr(2)}}, }, + { + name: "HeadIntPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + B struct { + B *int `json:"b,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}, B: struct { + B *int `json:"b,omitempty"` + }{B: intptr(2)}}, + }, + { + name: "HeadIntPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + B struct { + B *int `json:"b,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{A: intptr(1)}, B: struct { + B *int `json:"b,string"` + }{B: intptr(2)}}, + }, + + // HeadIntPtrNilMultiFieldsNotRoot { name: "HeadIntPtrNilMultiFieldsNotRoot", expected: `{"A":{"a":null},"B":{"b":null}}`, @@ -1062,6 +1471,56 @@ null B *int `json:"b"` }{B: nil}}, }, + { + name: "HeadIntPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + B struct { + B *int `json:"b,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{A: nil}, B: struct { + B *int `json:"b,omitempty"` + }{B: nil}}, + }, + { + name: "HeadIntPtrNilMultiFieldsNotRootString", + expected: `{"A":{"a":null},"B":{"b":null}}`, + indentExpected: ` +{ + "A": { + "a": null + }, + "B": { + "b": null + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + B struct { + B *int `json:"b,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{A: nil}, B: struct { + B *int `json:"b,string"` + }{B: nil}}, + }, + + // PtrHeadIntZeroMultiFieldsNotRoot { name: "PtrHeadIntZeroMultiFieldsNotRoot", expected: `{"A":{"a":0},"B":{"b":0}}`, @@ -1084,6 +1543,48 @@ null } }{}, }, + { + name: "PtrHeadIntZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: &struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{}, + }, + { + name: "PtrHeadIntZeroMultiFieldsNotRootString", + expected: `{"A":{"a":"0"},"B":{"b":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + }, + "B": { + "b": "0" + } +} +`, + data: &struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{}, + }, + + // PtrHeadIntMultiFieldsNotRoot { name: "PtrHeadIntMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1110,6 +1611,60 @@ null B int `json:"b"` }{B: 2}}, }, + { + name: "PtrHeadIntMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: &struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{A: struct { + A int `json:"a,omitempty"` + }{A: 1}, B: struct { + B int `json:"b,omitempty"` + }{B: 2}}, + }, + { + name: "PtrHeadIntMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: &struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{A: struct { + A int `json:"a,string"` + }{A: 1}, B: struct { + B int `json:"b,string"` + }{B: 2}}, + }, + + // PtrHeadIntPtrMultiFieldsNotRoot { name: "PtrHeadIntPtrMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1136,6 +1691,60 @@ null B *int `json:"b"` }{B: intptr(2)})}, }, + { + name: "PtrHeadIntPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + } + B *struct { + B *int `json:"b,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}), B: &(struct { + B *int `json:"b,omitempty"` + }{B: intptr(2)})}, + }, + { + name: "PtrHeadIntPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + } + B *struct { + B *int `json:"b,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: intptr(1)}), B: &(struct { + B *int `json:"b,string"` + }{B: intptr(2)})}, + }, + + // PtrHeadIntPtrNilMultiFieldsNotRoot { name: "PtrHeadIntPtrNilMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1154,6 +1763,41 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + } `json:",omitempty"` + B *struct { + B *int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntPtrNilMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + } `json:",string"` + B *struct { + B *int `json:"b,string"` + } `json:",string"` + }{A: nil, B: nil}, + }, + + // PtrHeadIntNilMultiFieldsNotRoot { name: "PtrHeadIntNilMultiFieldsNotRoot", expected: `null`, @@ -1169,6 +1813,38 @@ null } })(nil), }, + { + name: "PtrHeadIntNilMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,omitempty"` + } + B *struct { + B *int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntNilMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,string"` + } + B *struct { + B *int `json:"b,string"` + } + })(nil), + }, + + // PtrHeadIntDoubleMultiFieldsNotRoot { name: "PtrHeadIntDoubleMultiFieldsNotRoot", expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, @@ -1201,6 +1877,72 @@ null B int `json:"b"` }{A: 3, B: 4})}, }, + { + name: "PtrHeadIntDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, + indentExpected: ` +{ + "A": { + "a": 1, + "b": 2 + }, + "B": { + "a": 3, + "b": 4 + } +} +`, + data: &struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + }{A: &(struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 1, B: 2}), B: &(struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 3, B: 4})}, + }, + { + name: "PtrHeadIntDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"1","b":"2"},"B":{"a":"3","b":"4"}}`, + indentExpected: ` +{ + "A": { + "a": "1", + "b": "2" + }, + "B": { + "a": "3", + "b": "4" + } +} +`, + data: &struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + }{A: &(struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 1, B: 2}), B: &(struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 3, B: 4})}, + }, + + // PtrHeadIntNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1221,6 +1963,45 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } `json:",omitempty"` + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadIntNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntNilDoubleMultiFieldsNotRoot", expected: `null`, @@ -1238,6 +2019,42 @@ null } })(nil), }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + })(nil), + }, + + // PtrHeadIntPtrDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrDoubleMultiFieldsNotRoot", expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, @@ -1270,6 +2087,72 @@ null B *int `json:"b"` }{A: intptr(3), B: intptr(4)})}, }, + { + name: "PtrHeadIntPtrDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, + indentExpected: ` +{ + "A": { + "a": 1, + "b": 2 + }, + "B": { + "a": 3, + "b": 4 + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(1), B: intptr(2)}), B: &(struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(3), B: intptr(4)})}, + }, + { + name: "PtrHeadIntPtrDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"1","b":"2"},"B":{"a":"3","b":"4"}}`, + indentExpected: ` +{ + "A": { + "a": "1", + "b": "2" + }, + "B": { + "a": "3", + "b": "4" + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(1), B: intptr(2)}), B: &(struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(3), B: intptr(4)})}, + }, + + // PtrHeadIntPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1290,6 +2173,45 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } `json:",omitempty"` + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadIntPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRoot", expected: `null`, @@ -1307,6 +2229,42 @@ null } })(nil), }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + })(nil), + }, + + // AnonymousHeadInt { name: "AnonymousHeadInt", expected: `{"a":1,"b":2}`, @@ -1324,6 +2282,42 @@ null B: 2, }, }, + { + name: "AnonymousHeadIntOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: structIntOmitEmpty{A: 1}, + B: 2, + }, + }, + { + name: "AnonymousHeadIntString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + structIntString + B int `json:"b,string"` + }{ + structIntString: structIntString{A: 1}, + B: 2, + }, + }, + + // PtrAnonymousHeadInt { name: "PtrAnonymousHeadInt", expected: `{"a":1,"b":2}`, @@ -1341,6 +2335,42 @@ null B: 2, }, }, + { + name: "PtrAnonymousHeadIntOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + *structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: &structIntOmitEmpty{A: 1}, + B: 2, + }, + }, + { + name: "PtrAnonymousHeadIntString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + *structIntString + B int `json:"b,string"` + }{ + structIntString: &structIntString{A: 1}, + B: 2, + }, + }, + + // NilPtrAnonymousHeadInt { name: "NilPtrAnonymousHeadInt", expected: `{"b":2}`, @@ -1357,6 +2387,40 @@ null B: 2, }, }, + { + name: "NilPtrAnonymousHeadIntOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + *structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: nil, + B: 2, + }, + }, + { + name: "NilPtrAnonymousHeadIntString", + expected: `{"b":"2"}`, + indentExpected: ` +{ + "b": "2" +} +`, + data: struct { + *structIntString + B int `json:"b,string"` + }{ + structIntString: nil, + B: 2, + }, + }, + + // AnonymousHeadIntPtr { name: "AnonymousHeadIntPtr", expected: `{"a":1,"b":2}`, @@ -1374,6 +2438,42 @@ null B: intptr(2), }, }, + { + name: "AnonymousHeadIntPtrOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: intptr(1)}, + B: intptr(2), + }, + }, + { + name: "AnonymousHeadIntPtrString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: structIntPtrString{A: intptr(1)}, + B: intptr(2), + }, + }, + + // AnonymousHeadIntPtrNil { name: "AnonymousHeadIntPtrNil", expected: `{"a":null,"b":2}`, @@ -1391,6 +2491,41 @@ null B: intptr(2), }, }, + { + name: "AnonymousHeadIntPtrNilOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: nil}, + B: intptr(2), + }, + }, + { + name: "AnonymousHeadIntPtrNilString", + expected: `{"a":null,"b":"2"}`, + indentExpected: ` +{ + "a": null, + "b": "2" +} +`, + data: struct { + structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: structIntPtrString{A: nil}, + B: intptr(2), + }, + }, + + // PtrAnonymousHeadIntPtr { name: "PtrAnonymousHeadIntPtr", expected: `{"a":1,"b":2}`, @@ -1408,6 +2543,42 @@ null B: intptr(2), }, }, + { + name: "PtrAnonymousHeadIntPtrOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + *structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: &structIntPtrOmitEmpty{A: intptr(1)}, + B: intptr(2), + }, + }, + { + name: "PtrAnonymousHeadIntPtrString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + *structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: &structIntPtrString{A: intptr(1)}, + B: intptr(2), + }, + }, + + // NilPtrAnonymousHeadIntPtr { name: "NilPtrAnonymousHeadIntPtr", expected: `{"b":2}`, @@ -1424,6 +2595,40 @@ null B: intptr(2), }, }, + { + name: "NilPtrAnonymousHeadIntPtrOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + *structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: nil, + B: intptr(2), + }, + }, + { + name: "NilPtrAnonymousHeadIntPtrString", + expected: `{"b":"2"}`, + indentExpected: ` +{ + "b": "2" +} +`, + data: struct { + *structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: nil, + B: intptr(2), + }, + }, + + // AnonymousHeadIntOnly { name: "AnonymousHeadIntOnly", expected: `{"a":1}`, @@ -1438,6 +2643,36 @@ null structInt: structInt{A: 1}, }, }, + { + name: "AnonymousHeadIntOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + structIntOmitEmpty + }{ + structIntOmitEmpty: structIntOmitEmpty{A: 1}, + }, + }, + { + name: "AnonymousHeadIntOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + structIntString + }{ + structIntString: structIntString{A: 1}, + }, + }, + + // PtrAnonymousHeadIntOnly { name: "PtrAnonymousHeadIntOnly", expected: `{"a":1}`, @@ -1452,6 +2687,36 @@ null structInt: &structInt{A: 1}, }, }, + { + name: "PtrAnonymousHeadIntOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + *structIntOmitEmpty + }{ + structIntOmitEmpty: &structIntOmitEmpty{A: 1}, + }, + }, + { + name: "PtrAnonymousHeadIntOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + *structIntString + }{ + structIntString: &structIntString{A: 1}, + }, + }, + + // NilPtrAnonymousHeadIntOnly { name: "NilPtrAnonymousHeadIntOnly", expected: `{}`, @@ -1464,6 +2729,32 @@ null structInt: nil, }, }, + { + name: "NilPtrAnonymousHeadIntOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntOmitEmpty + }{ + structIntOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadIntOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntString + }{ + structIntString: nil, + }, + }, + + // AnonymousHeadIntPtrOnly { name: "AnonymousHeadIntPtrOnly", expected: `{"a":1}`, @@ -1478,6 +2769,36 @@ null structIntPtr: structIntPtr{A: intptr(1)}, }, }, + { + name: "AnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: intptr(1)}, + }, + }, + { + name: "AnonymousHeadIntPtrOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + structIntPtrString + }{ + structIntPtrString: structIntPtrString{A: intptr(1)}, + }, + }, + + // AnonymousHeadIntPtrNilOnly { name: "AnonymousHeadIntPtrNilOnly", expected: `{"a":null}`, @@ -1492,6 +2813,34 @@ null structIntPtr: structIntPtr{A: nil}, }, }, + { + name: "AnonymousHeadIntPtrNilOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: nil}, + }, + }, + { + name: "AnonymousHeadIntPtrNilOnlyString", + expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, + data: struct { + structIntPtrString + }{ + structIntPtrString: structIntPtrString{A: nil}, + }, + }, + + // PtrAnonymousHeadIntPtrOnly { name: "PtrAnonymousHeadIntPtrOnly", expected: `{"a":1}`, @@ -1506,6 +2855,36 @@ null structIntPtr: &structIntPtr{A: intptr(1)}, }, }, + { + name: "PtrAnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + *structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: &structIntPtrOmitEmpty{A: intptr(1)}, + }, + }, + { + name: "PtrAnonymousHeadIntPtrOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + *structIntPtrString + }{ + structIntPtrString: &structIntPtrString{A: intptr(1)}, + }, + }, + + // NilPtrAnonymousHeadIntPtrOnly { name: "NilPtrAnonymousHeadIntPtrOnly", expected: `{}`, @@ -1518,6 +2897,30 @@ null structIntPtr: nil, }, }, + { + name: "NilPtrAnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadIntPtrOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntPtrString + }{ + structIntPtrString: nil, + }, + }, } for _, test := range tests { for _, indent := range []bool{true, false} { diff --git a/encode_compile.go b/encode_compile.go index dbbb806..cece1e9 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -105,7 +105,17 @@ func (e *Encoder) convertHeadOnlyCode(c *opcode, isPtrHead bool) { } c.op = opStructFieldHeadOnly case opStructFieldHeadOmitEmpty: - return + e.convertHeadOnlyCode(c.next, false) + if !strings.Contains(c.next.op.String(), "Only") { + return + } + c.op = opStructFieldHeadOmitEmptyOnly + case opStructFieldHeadStringTag: + e.convertHeadOnlyCode(c.next, false) + if !strings.Contains(c.next.op.String(), "Only") { + return + } + c.op = opStructFieldHeadStringTagOnly case opStructFieldPtrHead: } diff --git a/encode_vm.go b/encode_vm.go index 88f6e85..58956ff 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -615,7 +615,30 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{') if !code.anonymousKey { @@ -624,6 +647,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{') + if !code.anonymousKey { + if ptr != 0 { + b = append(b, code.key...) + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } + } case opStructFieldAnonymousHead: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -632,6 +668,26 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, ptr) } + case opStructFieldPtrAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + code = code.next + store(ctxptr, code.idx, p) + } + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -775,7 +831,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = append(b, code.key...) p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -839,7 +895,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = append(b, '{') b = append(b, code.key...) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -930,6 +986,33 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -948,6 +1031,44 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = append(b, code.key...) + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -966,6 +1087,44 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.key...) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2839,49 +2998,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - code = code.next - store(ctxptr, code.idx, p) - } - } - case opStructFieldPtrAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -5175,7 +5291,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index 64cc918..e08fde6 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -577,15 +577,49 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: + p := load(ctxptr, code.idx) b = append(b, '{') if !code.anonymousKey { b = append(b, code.escapedKey...) } - p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + if !code.anonymousKey { + if p != 0 { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } + } case opStructFieldAnonymousHead: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -594,6 +628,26 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, ptr) } + case opStructFieldPtrAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -737,7 +791,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = append(b, code.escapedKey...) p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -801,7 +855,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = append(b, '{') b = append(b, code.escapedKey...) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -892,6 +946,33 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -910,6 +991,44 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = append(b, code.escapedKey...) + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -928,6 +1047,44 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.escapedKey...) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2808,49 +2965,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - code = code.next - store(ctxptr, code.idx, p) - } - } - case opStructFieldPtrAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -5203,7 +5317,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_escaped_indent.go b/encode_vm_escaped_indent.go index adc3c29..1194054 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -617,7 +617,34 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = e.encodeIndent(b, code.indent) + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, '{', '\n') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{', '\n') if !code.anonymousKey { @@ -628,6 +655,19 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if !code.anonymousKey && ptr != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -787,7 +827,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, ' ') p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -857,7 +897,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, code.escapedKey...) b = append(b, ' ') if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -903,6 +943,43 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -915,6 +992,37 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -935,6 +1043,48 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -955,6 +1105,48 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2855,33 +3047,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.escapedKey...) - b = append(b, ' ') - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3286,7 +3451,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op case opStructFieldHeadStringTag: ptr := load(ctxptr, code.idx) if ptr == 0 { - b = e.encodeIndent(b, code.indent) b = encodeNull(b) b = encodeIndentComma(b) code = code.end.next @@ -4390,7 +4554,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_indent.go b/encode_vm_indent.go index c5d5e8a..5e2976d 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -617,7 +617,34 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = e.encodeIndent(b, code.indent) + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, '{', '\n') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{', '\n') if !code.anonymousKey { @@ -628,6 +655,19 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if !code.anonymousKey && ptr != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -787,7 +827,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, ' ') p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -857,7 +897,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, code.key...) b = append(b, ' ') if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -903,6 +943,43 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -915,6 +992,37 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -935,6 +1043,48 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -955,6 +1105,48 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2855,33 +3047,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.key...) - b = append(b, ' ') - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3286,7 +3451,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( case opStructFieldHeadStringTag: ptr := load(ctxptr, code.idx) if ptr == 0 { - b = e.encodeIndent(b, code.indent) b = encodeNull(b) b = encodeIndentComma(b) code = code.end.next @@ -4390,7 +4554,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p)))