From d8592558686f6c36c0a2a7390533977192e3eb4a Mon Sep 17 00:00:00 2001 From: Masaaki Goshima Date: Thu, 21 Jan 2021 00:22:20 +0900 Subject: [PATCH] Add test cases for string type --- cover_string_test.go | 2328 ++++++++++++++++++++++++++++++++++- encode_vm.go | 417 +++++-- encode_vm_escaped.go | 417 +++++-- encode_vm_escaped_indent.go | 558 ++++++++- encode_vm_indent.go | 558 ++++++++- 5 files changed, 3993 insertions(+), 285 deletions(-) diff --git a/cover_string_test.go b/cover_string_test.go index 739c588..04ae547 100644 --- a/cover_string_test.go +++ b/cover_string_test.go @@ -2,7 +2,6 @@ package json_test import ( "bytes" - "strings" "testing" "github.com/goccy/go-json" @@ -12,162 +11,791 @@ func TestCoverString(t *testing.T) { type structString struct { A string `json:"a"` } + type structStringOmitEmpty struct { + A string `json:"a,omitempty"` + } + type structStringString struct { + A string `json:"a,string"` + } + type structStringPtr struct { A *string `json:"a"` } + type structStringPtrOmitEmpty struct { + A *string `json:"a,omitempty"` + } + type structStringPtrString struct { + A *string `json:"a,string"` + } tests := []struct { - name string - expected string - data interface{} + name string + expected string + indentExpected string + data interface{} }{ + // HeadStringZero { name: "HeadStringZero", expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, data: struct { A string `json:"a"` }{}, }, + { + name: "HeadStringZeroOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A string `json:"a,omitempty"` + }{}, + }, + { + name: "HeadStringZeroString", + expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, + data: struct { + A string `json:"a,string"` + }{}, + }, + + // HeadString { name: "HeadString", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { A string `json:"a"` }{A: "foo"}, }, + { + name: "HeadStringOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + A string `json:"a,omitempty"` + }{A: "foo"}, + }, + { + name: "HeadStringString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + A string `json:"a,string"` + }{A: "foo"}, + }, + + // HeadStringPtr { name: "HeadStringPtr", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { A *string `json:"a"` }{A: stringptr("foo")}, }, + { + name: "HeadStringPtrOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + A *string `json:"a,omitempty"` + }{A: stringptr("foo")}, + }, + { + name: "HeadStringPtrString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + A *string `json:"a,string"` + }{A: stringptr("foo")}, + }, + + // HeadStringPtrNil { name: "HeadStringPtrNil", expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, data: struct { A *string `json:"a"` }{A: nil}, }, + { + name: "HeadStringPtrNilOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *string `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "HeadStringPtrNilString", + expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, + data: struct { + A *string `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadStringZero { name: "PtrHeadStringZero", expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, data: &struct { A string `json:"a"` }{}, }, + { + name: "PtrHeadStringZeroOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A string `json:"a,omitempty"` + }{}, + }, + { + name: "PtrHeadStringZeroString", + expected: `{"a":""}`, + indentExpected: ` +{ + "a": "" +} +`, + data: &struct { + A string `json:"a,string"` + }{}, + }, + + // PtrHeadString { name: "PtrHeadString", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: &struct { A string `json:"a"` }{A: "foo"}, }, + { + name: "PtrHeadStringOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: &struct { + A string `json:"a,omitempty"` + }{A: "foo"}, + }, + { + name: "PtrHeadStringString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: &struct { + A string `json:"a,string"` + }{A: "foo"}, + }, + + // PtrHeadStringPtr { name: "PtrHeadStringPtr", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: &struct { A *string `json:"a"` }{A: stringptr("foo")}, }, + { + name: "PtrHeadStringPtrOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: &struct { + A *string `json:"a,omitempty"` + }{A: stringptr("foo")}, + }, + { + name: "PtrHeadStringPtrString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: &struct { + A *string `json:"a,string"` + }{A: stringptr("foo")}, + }, + + // PtrHeadStringPtrNil { name: "PtrHeadStringPtrNil", expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, data: &struct { A *string `json:"a"` }{A: nil}, }, + { + name: "PtrHeadStringPtrNilOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *string `json:"a,omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadStringPtrNilString", + expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, + data: &struct { + A *string `json:"a,string"` + }{A: nil}, + }, + + // PtrHeadStringNil { name: "PtrHeadStringNil", expected: `null`, + indentExpected: ` +null +`, data: (*struct { A *string `json:"a"` })(nil), }, + { + name: "PtrHeadStringNilOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *string `json:"a,omitempty"` + })(nil), + }, + { + name: "PtrHeadStringNilString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *string `json:"a,string"` + })(nil), + }, + + // HeadStringZeroMultiFields { name: "HeadStringZeroMultiFields", expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, data: struct { A string `json:"a"` B string `json:"b"` }{}, }, + { + name: "HeadStringZeroMultiFieldsOmitEmpty", + expected: `{"a":"","b":""}`, + indentExpected: ` +{} +`, + data: struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{}, + }, + { + name: "HeadStringZeroMultiFieldsString", + expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, + data: struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{}, + }, + + // HeadStringMultiFields { name: "HeadStringMultiFields", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { A string `json:"a"` B string `json:"b"` }{A: "foo", B: "bar"}, }, + { + name: "HeadStringMultiFieldsOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{A: "foo", B: "bar"}, + }, + { + name: "HeadStringMultiFieldsString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{A: "foo", B: "bar"}, + }, + + // HeadStringPtrMultiFields { name: "HeadStringPtrMultiFields", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { A *string `json:"a"` B *string `json:"b"` }{A: stringptr("foo"), B: stringptr("bar")}, }, + { + name: "HeadStringPtrMultiFieldsOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: stringptr("foo"), B: stringptr("bar")}, + }, + { + name: "HeadStringPtrMultiFieldsString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: stringptr("foo"), B: stringptr("bar")}, + }, + + // HeadStringPtrNilMultiFields { name: "HeadStringPtrNilMultiFields", expected: `{"a":null,"b":null}`, + indentExpected: ` +{ + "a": null, + "b": null +} +`, data: struct { A *string `json:"a"` B *string `json:"b"` }{A: nil, B: nil}, }, + { + name: "HeadStringPtrNilMultiFieldsOmitEmpty", + expected: `{"a":null,"b":null}`, + indentExpected: ` +{} +`, + data: struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: nil, B: nil}, + }, + { + name: "HeadStringPtrNilMultiFieldsString", + expected: `{"a":null,"b":null}`, + indentExpected: ` +{ + "a": null, + "b": null +} +`, + data: struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: nil, B: nil}, + }, + + // PtrHeadStringZeroMultiFields { name: "PtrHeadStringZeroMultiFields", expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, data: &struct { A string `json:"a"` B string `json:"b"` }{}, }, + { + name: "PtrHeadStringZeroMultiFieldsOmitEmpty", + expected: `{"a":"","b":""}`, + indentExpected: ` +{} +`, + data: &struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{}, + }, + { + name: "PtrHeadStringZeroMultiFieldsString", + expected: `{"a":"","b":""}`, + indentExpected: ` +{ + "a": "", + "b": "" +} +`, + data: &struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{}, + }, + + // PtrHeadStringMultiFields { name: "PtrHeadStringMultiFields", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: &struct { A string `json:"a"` B string `json:"b"` }{A: "foo", B: "bar"}, }, + { + name: "PtrHeadStringMultiFieldsOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: &struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{A: "foo", B: "bar"}, + }, + { + name: "PtrHeadStringMultiFieldsString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: &struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{A: "foo", B: "bar"}, + }, + + // PtrHeadStringPtrMultiFields { name: "PtrHeadStringPtrMultiFields", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: &struct { A *string `json:"a"` B *string `json:"b"` }{A: stringptr("foo"), B: stringptr("bar")}, }, + { + name: "PtrHeadStringPtrMultiFieldsOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: &struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: stringptr("foo"), B: stringptr("bar")}, + }, + { + name: "PtrHeadStringPtrMultiFieldsString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: &struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: stringptr("foo"), B: stringptr("bar")}, + }, + + // PtrHeadStringPtrNilMultiFields { name: "PtrHeadStringPtrNilMultiFields", expected: `{"a":null,"b":null}`, + indentExpected: ` +{ + "a": null, + "b": null +} +`, data: &struct { A *string `json:"a"` B *string `json:"b"` }{A: nil, B: nil}, }, + { + name: "PtrHeadStringPtrNilMultiFieldsOmitEmpty", + expected: `{"a":null,"b":null}`, + indentExpected: ` +{} +`, + data: &struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadStringPtrNilMultiFieldsString", + expected: `{"a":null,"b":null}`, + indentExpected: ` +{ + "a": null, + "b": null +} +`, + data: &struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: nil, B: nil}, + }, + + // PtrHeadStringNilMultiFields { name: "PtrHeadStringNilMultiFields", expected: `null`, + indentExpected: ` +null +`, data: (*struct { A *string `json:"a"` B *string `json:"b"` })(nil), }, + { + name: "PtrHeadStringNilMultiFieldsOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + })(nil), + }, + { + name: "PtrHeadStringNilMultiFieldsString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + })(nil), + }, + + // HeadStringZeroNotRoot { name: "HeadStringZeroNotRoot", expected: `{"A":{"a":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + } +} +`, data: struct { A struct { A string `json:"a"` } }{}, }, + { + name: "HeadStringZeroNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A struct { + A string `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadStringZeroNotRootString", + expected: `{"A":{"a":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + } +} +`, + data: struct { + A struct { + A string `json:"a,string"` + } + }{}, + }, + + // HeadStringNotRoot { name: "HeadStringNotRoot", expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, data: struct { A struct { A string `json:"a"` @@ -176,9 +804,54 @@ func TestCoverString(t *testing.T) { A string `json:"a"` }{A: "foo"}}, }, + { + name: "HeadStringNotRootOmitEmpty", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A struct { + A string `json:"a,omitempty"` + } + }{A: struct { + A string `json:"a,omitempty"` + }{A: "foo"}}, + }, + { + name: "HeadStringNotRootString", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A struct { + A string `json:"a,string"` + } + }{A: struct { + A string `json:"a,string"` + }{A: "foo"}}, + }, + + // HeadStringPtrNotRoot { name: "HeadStringPtrNotRoot", expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, data: struct { A struct { A *string `json:"a"` @@ -187,18 +860,102 @@ func TestCoverString(t *testing.T) { A *string `json:"a"` }{stringptr("foo")}}, }, + { + name: "HeadStringPtrNotRootOmitEmpty", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A struct { + A *string `json:"a,omitempty"` + } + }{A: struct { + A *string `json:"a,omitempty"` + }{stringptr("foo")}}, + }, + { + name: "HeadStringPtrNotRootString", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A struct { + A *string `json:"a,string"` + } + }{A: struct { + A *string `json:"a,string"` + }{stringptr("foo")}}, + }, + + // HeadStringPtrNilNotRoot { name: "HeadStringPtrNilNotRoot", expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, data: struct { A struct { A *string `json:"a"` } }{}, }, + { + name: "HeadStringPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A struct { + A *string `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadStringPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A struct { + A *string `json:"a,string"` + } + }{}, + }, + + // PtrHeadStringZeroNotRoot { name: "PtrHeadStringZeroNotRoot", expected: `{"A":{"a":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + } +} +`, data: struct { A *struct { A string `json:"a"` @@ -207,9 +964,52 @@ func TestCoverString(t *testing.T) { A string `json:"a"` })}, }, + { + name: "PtrHeadStringZeroNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A string `json:"a,omitempty"` + } + }{A: new(struct { + A string `json:"a,omitempty"` + })}, + }, + { + name: "PtrHeadStringZeroNotRootString", + expected: `{"A":{"a":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + } +} +`, + data: struct { + A *struct { + A string `json:"a,string"` + } + }{A: new(struct { + A string `json:"a,string"` + })}, + }, + + // PtrHeadStringNotRoot { name: "PtrHeadStringNotRoot", expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, data: struct { A *struct { A string `json:"a"` @@ -218,9 +1018,54 @@ func TestCoverString(t *testing.T) { A string `json:"a"` }{A: "foo"})}, }, + { + name: "PtrHeadStringNotRootOmitEmpty", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A *struct { + A string `json:"a,omitempty"` + } + }{A: &(struct { + A string `json:"a,omitempty"` + }{A: "foo"})}, + }, + { + name: "PtrHeadStringNotRootString", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A *struct { + A string `json:"a,string"` + } + }{A: &(struct { + A string `json:"a,string"` + }{A: "foo"})}, + }, + + // PtrHeadStringPtrNotRoot { name: "PtrHeadStringPtrNotRoot", expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, data: struct { A *struct { A *string `json:"a"` @@ -229,9 +1074,54 @@ func TestCoverString(t *testing.T) { A *string `json:"a"` }{A: stringptr("foo")})}, }, + { + name: "PtrHeadStringPtrNotRootOmitEmpty", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A *struct { + A *string `json:"a,omitempty"` + } + }{A: &(struct { + A *string `json:"a,omitempty"` + }{A: stringptr("foo")})}, + }, + { + name: "PtrHeadStringPtrNotRootString", + expected: `{"A":{"a":"foo"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + } +} +`, + data: struct { + A *struct { + A *string `json:"a,string"` + } + }{A: &(struct { + A *string `json:"a,string"` + }{A: stringptr("foo")})}, + }, + + // PtrHeadStringPtrNilNotRoot { name: "PtrHeadStringPtrNilNotRoot", expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, data: struct { A *struct { A *string `json:"a"` @@ -240,18 +1130,97 @@ func TestCoverString(t *testing.T) { A *string `json:"a"` }{A: nil})}, }, + { + name: "PtrHeadStringPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A *string `json:"a,omitempty"` + } + }{A: &(struct { + A *string `json:"a,omitempty"` + }{A: nil})}, + }, + { + name: "PtrHeadStringPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A *struct { + A *string `json:"a,string"` + } + }{A: &(struct { + A *string `json:"a,string"` + }{A: nil})}, + }, + + // PtrHeadStringNilNotRoot { name: "PtrHeadStringNilNotRoot", expected: `{"A":null}`, + indentExpected: ` +{ + "A": null +} +`, data: struct { A *struct { A *string `json:"a"` } }{A: nil}, }, + { + name: "PtrHeadStringNilNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *struct { + A *string `json:"a,omitempty"` + } `json:",omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadStringNilNotRootString", + expected: `{"A":null}`, + indentExpected: ` +{ + "A": null +} +`, + data: struct { + A *struct { + A *string `json:"a,string"` + } `json:",string"` + }{A: nil}, + }, + + // HeadStringZeroMultiFieldsNotRoot { name: "HeadStringZeroMultiFieldsNotRoot", expected: `{"A":{"a":""},"B":{"b":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + }, + "B": { + "b": "" + } +} +`, data: struct { A struct { A string `json:"a"` @@ -261,9 +1230,61 @@ func TestCoverString(t *testing.T) { } }{}, }, + { + name: "HeadStringZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A string `json:"a,omitempty"` + } + B struct { + B string `json:"b,omitempty"` + } + }{}, + }, + { + name: "HeadStringZeroMultiFieldsNotRootString", + expected: `{"A":{"a":""},"B":{"b":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + }, + "B": { + "b": "" + } +} +`, + data: struct { + A struct { + A string `json:"a,string"` + } + B struct { + B string `json:"b,string"` + } + }{}, + }, + + // HeadStringMultiFieldsNotRoot { name: "HeadStringMultiFieldsNotRoot", expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, data: struct { A struct { A string `json:"a"` @@ -277,9 +1298,74 @@ func TestCoverString(t *testing.T) { B string `json:"b"` }{B: "bar"}}, }, + { + name: "HeadStringMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + + data: struct { + A struct { + A string `json:"a,omitempty"` + } + B struct { + B string `json:"b,omitempty"` + } + }{A: struct { + A string `json:"a,omitempty"` + }{A: "foo"}, B: struct { + B string `json:"b,omitempty"` + }{B: "bar"}}, + }, + { + name: "HeadStringMultiFieldsNotRootString", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: struct { + A struct { + A string `json:"a,string"` + } + B struct { + B string `json:"b,string"` + } + }{A: struct { + A string `json:"a,string"` + }{A: "foo"}, B: struct { + B string `json:"b,string"` + }{B: "bar"}}, + }, + + // HeadStringPtrMultiFieldsNotRoot { name: "HeadStringPtrMultiFieldsNotRoot", expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, data: struct { A struct { A *string `json:"a"` @@ -293,9 +1379,73 @@ func TestCoverString(t *testing.T) { B *string `json:"b"` }{B: stringptr("bar")}}, }, + { + name: "HeadStringPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: struct { + A struct { + A *string `json:"a,omitempty"` + } + B struct { + B *string `json:"b,omitempty"` + } + }{A: struct { + A *string `json:"a,omitempty"` + }{A: stringptr("foo")}, B: struct { + B *string `json:"b,omitempty"` + }{B: stringptr("bar")}}, + }, + { + name: "HeadStringPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: struct { + A struct { + A *string `json:"a,string"` + } + B struct { + B *string `json:"b,string"` + } + }{A: struct { + A *string `json:"a,string"` + }{A: stringptr("foo")}, B: struct { + B *string `json:"b,string"` + }{B: stringptr("bar")}}, + }, + + // HeadStringPtrNilMultiFieldsNotRoot { name: "HeadStringPtrNilMultiFieldsNotRoot", expected: `{"A":{"a":null},"B":{"b":null}}`, + indentExpected: ` +{ + "A": { + "a": null + }, + "B": { + "b": null + } +} +`, data: struct { A struct { A *string `json:"a"` @@ -309,9 +1459,69 @@ func TestCoverString(t *testing.T) { B *string `json:"b"` }{B: nil}}, }, + { + name: "HeadStringPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":null},"B":{"b":null}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A *string `json:"a,omitempty"` + } + B struct { + B *string `json:"b,omitempty"` + } + }{A: struct { + A *string `json:"a,omitempty"` + }{A: nil}, B: struct { + B *string `json:"b,omitempty"` + }{B: nil}}, + }, + { + name: "HeadStringPtrNilMultiFieldsNotRootString", + expected: `{"A":{"a":null},"B":{"b":null}}`, + indentExpected: ` +{ + "A": { + "a": null + }, + "B": { + "b": null + } +} +`, + data: struct { + A struct { + A *string `json:"a,string"` + } + B struct { + B *string `json:"b,string"` + } + }{A: struct { + A *string `json:"a,string"` + }{A: nil}, B: struct { + B *string `json:"b,string"` + }{B: nil}}, + }, + + // PtrHeadStringZeroMultiFieldsNotRoot { name: "PtrHeadStringZeroMultiFieldsNotRoot", expected: `{"A":{"a":""},"B":{"b":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + }, + "B": { + "b": "" + } +} +`, data: &struct { A struct { A string `json:"a"` @@ -321,9 +1531,61 @@ func TestCoverString(t *testing.T) { } }{}, }, + { + name: "PtrHeadStringZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: &struct { + A struct { + A string `json:"a,omitempty"` + } + B struct { + B string `json:"b,omitempty"` + } + }{}, + }, + { + name: "PtrHeadStringZeroMultiFieldsNotRootString", + expected: `{"A":{"a":""},"B":{"b":""}}`, + indentExpected: ` +{ + "A": { + "a": "" + }, + "B": { + "b": "" + } +} +`, + data: &struct { + A struct { + A string `json:"a,string"` + } + B struct { + B string `json:"b,string"` + } + }{}, + }, + + // PtrHeadStringMultiFieldsNotRoot { name: "PtrHeadStringMultiFieldsNotRoot", expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, data: &struct { A struct { A string `json:"a"` @@ -337,9 +1599,73 @@ func TestCoverString(t *testing.T) { B string `json:"b"` }{B: "bar"}}, }, + { + name: "PtrHeadStringMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: &struct { + A struct { + A string `json:"a,omitempty"` + } + B struct { + B string `json:"b,omitempty"` + } + }{A: struct { + A string `json:"a,omitempty"` + }{A: "foo"}, B: struct { + B string `json:"b,omitempty"` + }{B: "bar"}}, + }, + { + name: "PtrHeadStringMultiFieldsNotRootString", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: &struct { + A struct { + A string `json:"a,string"` + } + B struct { + B string `json:"b,string"` + } + }{A: struct { + A string `json:"a,string"` + }{A: "foo"}, B: struct { + B string `json:"b,string"` + }{B: "bar"}}, + }, + + // PtrHeadStringPtrMultiFieldsNotRoot { name: "PtrHeadStringPtrMultiFieldsNotRoot", expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, data: &struct { A *struct { A *string `json:"a"` @@ -353,9 +1679,69 @@ func TestCoverString(t *testing.T) { B *string `json:"b"` }{B: stringptr("bar")})}, }, + { + name: "PtrHeadStringPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A *string `json:"a,omitempty"` + } + B *struct { + B *string `json:"b,omitempty"` + } + }{A: &(struct { + A *string `json:"a,omitempty"` + }{A: stringptr("foo")}), B: &(struct { + B *string `json:"b,omitempty"` + }{B: stringptr("bar")})}, + }, + { + name: "PtrHeadStringPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"foo"},"B":{"b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo" + }, + "B": { + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A *string `json:"a,string"` + } + B *struct { + B *string `json:"b,string"` + } + }{A: &(struct { + A *string `json:"a,string"` + }{A: stringptr("foo")}), B: &(struct { + B *string `json:"b,string"` + }{B: stringptr("bar")})}, + }, + + // PtrHeadStringPtrNilMultiFieldsNotRoot { name: "PtrHeadStringPtrNilMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, data: &struct { A *struct { A *string `json:"a"` @@ -365,9 +1751,47 @@ func TestCoverString(t *testing.T) { } }{A: nil, B: nil}, }, + { + name: "PtrHeadStringPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *string `json:"a,omitempty"` + } + B *struct { + B *string `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadStringPtrNilMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *string `json:"a,string"` + } + B *struct { + B *string `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadStringNilMultiFieldsNotRoot { name: "PtrHeadStringNilMultiFieldsNotRoot", expected: `null`, + indentExpected: ` +null +`, data: (*struct { A *struct { A *string `json:"a"` @@ -377,9 +1801,53 @@ func TestCoverString(t *testing.T) { } })(nil), }, + { + name: "PtrHeadStringNilMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *string `json:"a,omitempty"` + } + B *struct { + B *string `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadStringNilMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *string `json:"a,string"` + } + B *struct { + B *string `json:"b,string"` + } + })(nil), + }, + + // PtrHeadStringDoubleMultiFieldsNotRoot { name: "PtrHeadStringDoubleMultiFieldsNotRoot", expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, data: &struct { A *struct { A string `json:"a"` @@ -397,9 +1865,81 @@ func TestCoverString(t *testing.T) { B string `json:"b"` }{A: "foo", B: "bar"})}, }, + { + name: "PtrHeadStringDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + B *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + }{A: &(struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{A: "foo", B: "bar"}), B: &(struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + }{A: "foo", B: "bar"})}, + }, + { + name: "PtrHeadStringDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + B *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + }{A: &(struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{A: "foo", B: "bar"}), B: &(struct { + A string `json:"a,string"` + B string `json:"b,string"` + }{A: "foo", B: "bar"})}, + }, + + // PtrHeadStringNilDoubleMultiFieldsNotRoot { name: "PtrHeadStringNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, data: &struct { A *struct { A string `json:"a"` @@ -411,9 +1951,51 @@ func TestCoverString(t *testing.T) { } }{A: nil, B: nil}, }, + { + name: "PtrHeadStringNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + B *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadStringNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + B *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadStringNilDoubleMultiFieldsNotRoot { name: "PtrHeadStringNilDoubleMultiFieldsNotRoot", expected: `null`, + indentExpected: ` +null +`, data: (*struct { A *struct { A string `json:"a"` @@ -425,9 +2007,57 @@ func TestCoverString(t *testing.T) { } })(nil), }, + { + name: "PtrHeadStringNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + B *struct { + A string `json:"a,omitempty"` + B string `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadStringNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + B *struct { + A string `json:"a,string"` + B string `json:"b,string"` + } + })(nil), + }, + + // PtrHeadStringPtrDoubleMultiFieldsNotRoot { name: "PtrHeadStringPtrDoubleMultiFieldsNotRoot", expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, data: &struct { A *struct { A *string `json:"a"` @@ -445,9 +2075,81 @@ func TestCoverString(t *testing.T) { B *string `json:"b"` }{A: stringptr("foo"), B: stringptr("bar")})}, }, + { + name: "PtrHeadStringPtrDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + B *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + }{A: &(struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: stringptr("foo"), B: stringptr("bar")}), B: &(struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + }{A: stringptr("foo"), B: stringptr("bar")})}, + }, + { + name: "PtrHeadStringPtrDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"foo","b":"bar"},"B":{"a":"foo","b":"bar"}}`, + indentExpected: ` +{ + "A": { + "a": "foo", + "b": "bar" + }, + "B": { + "a": "foo", + "b": "bar" + } +} +`, + data: &struct { + A *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + B *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + }{A: &(struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: stringptr("foo"), B: stringptr("bar")}), B: &(struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + }{A: stringptr("foo"), B: stringptr("bar")})}, + }, + + // PtrHeadStringPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, data: &struct { A *struct { A *string `json:"a"` @@ -459,9 +2161,51 @@ func TestCoverString(t *testing.T) { } }{A: nil, B: nil}, }, + { + name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + B *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + }{A: nil, B: nil}, + }, + { + name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + B *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadStringPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRoot", expected: `null`, + indentExpected: ` +null +`, data: (*struct { A *struct { A *string `json:"a"` @@ -473,9 +2217,51 @@ func TestCoverString(t *testing.T) { } })(nil), }, + { + name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + B *struct { + A *string `json:"a,omitempty"` + B *string `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadStringPtrNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + B *struct { + A *string `json:"a,string"` + B *string `json:"b,string"` + } + })(nil), + }, + + // AnonymousHeadString { name: "AnonymousHeadString", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { structString B string `json:"b"` @@ -484,9 +2270,51 @@ func TestCoverString(t *testing.T) { B: "bar", }, }, + { + name: "AnonymousHeadStringOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + structStringOmitEmpty + B string `json:"b,omitempty"` + }{ + structStringOmitEmpty: structStringOmitEmpty{A: "foo"}, + B: "bar", + }, + }, + { + name: "AnonymousHeadStringString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + structStringString + B string `json:"b,string"` + }{ + structStringString: structStringString{A: "foo"}, + B: "bar", + }, + }, + + // PtrAnonymousHeadString { name: "PtrAnonymousHeadString", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { *structString B string `json:"b"` @@ -495,9 +2323,50 @@ func TestCoverString(t *testing.T) { B: "bar", }, }, + { + name: "PtrAnonymousHeadStringOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + *structStringOmitEmpty + B string `json:"b,omitempty"` + }{ + structStringOmitEmpty: &structStringOmitEmpty{A: "foo"}, + B: "bar", + }, + }, + { + name: "PtrAnonymousHeadStringString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + *structStringString + B string `json:"b,string"` + }{ + structStringString: &structStringString{A: "foo"}, + B: "bar", + }, + }, + + // NilPtrAnonymousHeadString { name: "NilPtrAnonymousHeadString", expected: `{"b":"baz"}`, + indentExpected: ` +{ + "b": "baz" +} +`, data: struct { *structString B string `json:"b"` @@ -506,9 +2375,49 @@ func TestCoverString(t *testing.T) { B: "baz", }, }, + { + name: "NilPtrAnonymousHeadStringOmitEmpty", + expected: `{"b":"baz"}`, + indentExpected: ` +{ + "b": "baz" +} +`, + data: struct { + *structStringOmitEmpty + B string `json:"b,omitempty"` + }{ + structStringOmitEmpty: nil, + B: "baz", + }, + }, + { + name: "NilPtrAnonymousHeadStringString", + expected: `{"b":"baz"}`, + indentExpected: ` +{ + "b": "baz" +} +`, + data: struct { + *structStringString + B string `json:"b,string"` + }{ + structStringString: nil, + B: "baz", + }, + }, + + // AnonymousHeadStringPtr { name: "AnonymousHeadStringPtr", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { structStringPtr B *string `json:"b"` @@ -517,9 +2426,51 @@ func TestCoverString(t *testing.T) { B: stringptr("bar"), }, }, + { + name: "AnonymousHeadStringPtrOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + structStringPtrOmitEmpty + B *string `json:"b,omitempty"` + }{ + structStringPtrOmitEmpty: structStringPtrOmitEmpty{A: stringptr("foo")}, + B: stringptr("bar"), + }, + }, + { + name: "AnonymousHeadStringPtrString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + structStringPtrString + B *string `json:"b,string"` + }{ + structStringPtrString: structStringPtrString{A: stringptr("foo")}, + B: stringptr("bar"), + }, + }, + + // AnonymousHeadStringPtrNil { name: "AnonymousHeadStringPtrNil", expected: `{"a":null,"b":"foo"}`, + indentExpected: ` +{ + "a": null, + "b": "foo" +} +`, data: struct { structStringPtr B *string `json:"b"` @@ -528,9 +2479,50 @@ func TestCoverString(t *testing.T) { B: stringptr("foo"), }, }, + { + name: "AnonymousHeadStringPtrNilOmitEmpty", + expected: `{"b":"foo"}`, + indentExpected: ` +{ + "b": "foo" +} +`, + data: struct { + structStringPtrOmitEmpty + B *string `json:"b,omitempty"` + }{ + structStringPtrOmitEmpty: structStringPtrOmitEmpty{A: nil}, + B: stringptr("foo"), + }, + }, + { + name: "AnonymousHeadStringPtrNilString", + expected: `{"a":null,"b":"foo"}`, + indentExpected: ` +{ + "a": null, + "b": "foo" +} +`, + data: struct { + structStringPtrString + B *string `json:"b,string"` + }{ + structStringPtrString: structStringPtrString{A: nil}, + B: stringptr("foo"), + }, + }, + + // PtrAnonymousHeadStringPtr { name: "PtrAnonymousHeadStringPtr", expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, data: struct { *structStringPtr B *string `json:"b"` @@ -539,9 +2531,50 @@ func TestCoverString(t *testing.T) { B: stringptr("bar"), }, }, + { + name: "PtrAnonymousHeadStringPtrOmitEmpty", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + *structStringPtrOmitEmpty + B *string `json:"b,omitempty"` + }{ + structStringPtrOmitEmpty: &structStringPtrOmitEmpty{A: stringptr("foo")}, + B: stringptr("bar"), + }, + }, + { + name: "PtrAnonymousHeadStringPtrString", + expected: `{"a":"foo","b":"bar"}`, + indentExpected: ` +{ + "a": "foo", + "b": "bar" +} +`, + data: struct { + *structStringPtrString + B *string `json:"b,string"` + }{ + structStringPtrString: &structStringPtrString{A: stringptr("foo")}, + B: stringptr("bar"), + }, + }, + + // NilPtrAnonymousHeadStringPtr { name: "NilPtrAnonymousHeadStringPtr", expected: `{"b":"foo"}`, + indentExpected: ` +{ + "b": "foo" +} +`, data: struct { *structStringPtr B *string `json:"b"` @@ -550,80 +2583,349 @@ func TestCoverString(t *testing.T) { B: stringptr("foo"), }, }, + { + name: "NilPtrAnonymousHeadStringPtrOmitEmpty", + expected: `{"b":"foo"}`, + indentExpected: ` +{ + "b": "foo" +} +`, + data: struct { + *structStringPtrOmitEmpty + B *string `json:"b,omitempty"` + }{ + structStringPtrOmitEmpty: nil, + B: stringptr("foo"), + }, + }, + { + name: "NilPtrAnonymousHeadStringPtrString", + expected: `{"b":"foo"}`, + indentExpected: ` +{ + "b": "foo" +} +`, + data: struct { + *structStringPtrString + B *string `json:"b,string"` + }{ + structStringPtrString: nil, + B: stringptr("foo"), + }, + }, + + // AnonymousHeadStringOnly { name: "AnonymousHeadStringOnly", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { structString }{ structString: structString{A: "foo"}, }, }, + { + name: "AnonymousHeadStringOnlyOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + structStringOmitEmpty + }{ + structStringOmitEmpty: structStringOmitEmpty{A: "foo"}, + }, + }, + { + name: "AnonymousHeadStringOnlyString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + structStringString + }{ + structStringString: structStringString{A: "foo"}, + }, + }, + + // PtrAnonymousHeadStringOnly { name: "PtrAnonymousHeadStringOnly", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { *structString }{ structString: &structString{A: "foo"}, }, }, + { + name: "PtrAnonymousHeadStringOnlyOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + *structStringOmitEmpty + }{ + structStringOmitEmpty: &structStringOmitEmpty{A: "foo"}, + }, + }, + { + name: "PtrAnonymousHeadStringOnlyString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + *structStringString + }{ + structStringString: &structStringString{A: "foo"}, + }, + }, + + // NilPtrAnonymousHeadStringOnly { name: "NilPtrAnonymousHeadStringOnly", expected: `{}`, + indentExpected: ` +{} +`, data: struct { *structString }{ structString: nil, }, }, + { + name: "NilPtrAnonymousHeadStringOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structStringOmitEmpty + }{ + structStringOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadStringOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structStringString + }{ + structStringString: nil, + }, + }, + + // AnonymousHeadStringPtrOnly { name: "AnonymousHeadStringPtrOnly", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { structStringPtr }{ structStringPtr: structStringPtr{A: stringptr("foo")}, }, }, + { + name: "AnonymousHeadStringPtrOnlyOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + structStringPtrOmitEmpty + }{ + structStringPtrOmitEmpty: structStringPtrOmitEmpty{A: stringptr("foo")}, + }, + }, + { + name: "AnonymousHeadStringPtrOnlyString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + structStringPtrString + }{ + structStringPtrString: structStringPtrString{A: stringptr("foo")}, + }, + }, + + // AnonymousHeadStringPtrNilOnly { name: "AnonymousHeadStringPtrNilOnly", expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, data: struct { structStringPtr }{ structStringPtr: structStringPtr{A: nil}, }, }, + { + name: "AnonymousHeadStringPtrNilOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + structStringPtrOmitEmpty + }{ + structStringPtrOmitEmpty: structStringPtrOmitEmpty{A: nil}, + }, + }, + { + name: "AnonymousHeadStringPtrNilOnlyString", + expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, + data: struct { + structStringPtrString + }{ + structStringPtrString: structStringPtrString{A: nil}, + }, + }, + + // PtrAnonymousHeadStringPtrOnly { name: "PtrAnonymousHeadStringPtrOnly", expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, data: struct { *structStringPtr }{ structStringPtr: &structStringPtr{A: stringptr("foo")}, }, }, + { + name: "PtrAnonymousHeadStringPtrOnlyOmitEmpty", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + *structStringPtrOmitEmpty + }{ + structStringPtrOmitEmpty: &structStringPtrOmitEmpty{A: stringptr("foo")}, + }, + }, + { + name: "PtrAnonymousHeadStringPtrOnlyString", + expected: `{"a":"foo"}`, + indentExpected: ` +{ + "a": "foo" +} +`, + data: struct { + *structStringPtrString + }{ + structStringPtrString: &structStringPtrString{A: stringptr("foo")}, + }, + }, + + // NilPtrAnonymousHeadStringPtrOnly { name: "NilPtrAnonymousHeadStringPtrOnly", expected: `{}`, + indentExpected: ` +{} +`, data: struct { *structStringPtr }{ structStringPtr: nil, }, }, + { + name: "NilPtrAnonymousHeadStringPtrOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structStringPtrOmitEmpty + }{ + structStringPtrOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadStringPtrOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structStringPtrString + }{ + structStringPtrString: nil, + }, + }, } for _, test := range tests { - for _, htmlEscape := range []bool{true, false} { - var buf bytes.Buffer - enc := json.NewEncoder(&buf) - enc.SetEscapeHTML(htmlEscape) - if err := enc.Encode(test.data); err != nil { - t.Fatalf("%s(htmlEscape:%T): %s: %s", test.name, htmlEscape, test.expected, err) - } - if strings.TrimRight(buf.String(), "\n") != test.expected { - t.Fatalf("%s(htmlEscape:%T): expected %q but got %q", test.name, htmlEscape, test.expected, buf.String()) + for _, indent := range []bool{true, false} { + for _, htmlEscape := range []bool{true, false} { + var buf bytes.Buffer + enc := json.NewEncoder(&buf) + enc.SetEscapeHTML(htmlEscape) + if indent { + enc.SetIndent("", " ") + } + if err := enc.Encode(test.data); err != nil { + t.Fatalf("%s(htmlEscape:%T): %s: %s", test.name, htmlEscape, test.expected, err) + } + stdresult := encodeByEncodingJSON(test.data, indent, htmlEscape) + if buf.String() != stdresult { + t.Errorf("%s(htmlEscape:%T): doesn't compatible with encoding/json. expected %q but got %q", test.name, htmlEscape, stdresult, buf.String()) + } } } } diff --git a/encode_vm.go b/encode_vm.go index e0eb98e..01f3fa0 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -6029,6 +6029,50 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagString: + 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...) + s := e.ptrToString(ptr + code.offset) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, s))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrHeadStringOnly, opStructFieldHeadStringOnly: p := load(ctxptr, code.idx) b = append(b, '{') @@ -6036,6 +6080,23 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeNoEscapedString(b, e.ptrToString(p)) b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringOnly, opStructFieldHeadOmitEmptyStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + v := e.ptrToString(p) + if v != "" { + b = append(b, code.key...) + b = encodeNoEscapedString(b, v) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringOnly, opStructFieldHeadStringTagStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.key...) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadStringPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6058,6 +6119,47 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyStringPtr: + 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 = encodeNoEscapedString(b, e.ptrToString(p)) + b = encodeComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadStringPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -6079,6 +6181,67 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtrOnly: + 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 opStructFieldHeadOmitEmptyStringPtrOnly: + b = append(b, '{') + p := load(ctxptr, code.idx) + if p != 0 { + b = append(b, code.key...) + b = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringPtrOnly: + 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 opStructFieldHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.key...) + if p == 0 { + b = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next + case opStructFieldHeadStringNPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '{') + b = append(b, code.key...) + for i := 0; i < code.ptrNum; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadString: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6092,6 +6255,43 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(ptr)))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadStringOnly, opStructFieldAnonymousHeadStringOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -6102,6 +6302,31 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyStringOnly, opStructFieldAnonymousHeadOmitEmptyStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagStringOnly, opStructFieldAnonymousHeadStringTagStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(ptr)))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadStringPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6120,6 +6345,42 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtr: + 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 = encodeNoEscapedString(b, e.ptrToString(p)) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtr: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadStringPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -6138,6 +6399,42 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.key...) + if p == 0 { + b = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadBool: p := load(ctxptr, code.idx) if p == 0 { @@ -6458,51 +6755,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - v := e.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = append(b, code.key...) - b = encodeNoEscapedString(b, v) - b = encodeComma(b) - code = code.next - } - } - case opStructFieldPtrAnonymousHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - v := e.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = append(b, code.key...) - b = encodeNoEscapedString(b, v) - b = encodeComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -6785,43 +7037,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, ptr+code.offset) } - case opStructFieldPtrHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagString: - 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...) - s := e.ptrToString(ptr + code.offset) - b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, s))) - b = encodeComma(b) - code = code.next - } - case opStructFieldPtrAnonymousHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - b = append(b, code.key...) - s := string(encodeNoEscapedString([]byte{}, (e.ptrToString(ptr + code.offset)))) - b = encodeNoEscapedString(b, s) - b = encodeComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -8703,6 +8918,44 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = appendStructEnd(b) code = code.next + case opStructEndOmitEmptyStringPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = append(b, code.key...) + b = encodeNoEscapedString(b, e.ptrToString(p)) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagStringPtr: + b = append(b, code.key...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = encodeNull(b) + } else { + v := e.ptrToString(p) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, v))) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringNPtr: + b = append(b, code.key...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + for i := 0; i < code.ptrNum-1; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p)) + } + b = appendStructEnd(b) + code = code.next case opStructEndBool: ptr := load(ctxptr, code.headIdx) b = append(b, code.key...) diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index 5eca5b2..0345338 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -5996,6 +5996,50 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagString: + 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...) + s := e.ptrToString(ptr + code.offset) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, s))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrHeadStringOnly, opStructFieldHeadStringOnly: p := load(ctxptr, code.idx) b = append(b, '{') @@ -6003,6 +6047,23 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeEscapedString(b, e.ptrToString(p+code.offset)) b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringOnly, opStructFieldHeadOmitEmptyStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + v := e.ptrToString(p) + if v != "" { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, v) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringOnly, opStructFieldHeadStringTagStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadStringPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6025,6 +6086,47 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(p)) + b = encodeComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadStringPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -6046,6 +6148,67 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtrOnly: + 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 opStructFieldHeadOmitEmptyStringPtrOnly: + b = append(b, '{') + p := load(ctxptr, code.idx) + if p != 0 { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringPtrOnly: + 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 opStructFieldHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + b = append(b, code.escapedKey...) + if p == 0 { + b = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next + case opStructFieldHeadStringNPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '{') + b = append(b, code.escapedKey...) + for i := 0; i < code.ptrNum; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p+code.offset)) + } + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadString: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6059,6 +6222,43 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(ptr)))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadStringOnly, opStructFieldAnonymousHeadStringOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -6069,6 +6269,31 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyStringOnly, opStructFieldAnonymousHeadOmitEmptyStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, v) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagStringOnly, opStructFieldAnonymousHeadStringTagStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(ptr)))) + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadStringPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6087,6 +6312,42 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(p)) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtr: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadStringPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -6105,6 +6366,42 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.escapedKey...) + if p == 0 { + b = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadBool: p := load(ctxptr, code.idx) if p == 0 { @@ -6425,51 +6722,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - v := e.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - b = encodeEscapedString(b, v) - b = encodeComma(b) - code = code.next - } - } - case opStructFieldPtrAnonymousHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - v := e.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - b = encodeEscapedString(b, v) - b = encodeComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -6752,43 +7004,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, ptr+code.offset) } - case opStructFieldPtrHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagString: - 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...) - s := e.ptrToString(ptr + code.offset) - b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, s))) - b = encodeComma(b) - code = code.next - } - case opStructFieldPtrAnonymousHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - b = append(b, code.escapedKey...) - s := string(encodeEscapedString([]byte{}, e.ptrToString(ptr+code.offset))) - b = encodeEscapedString(b, s) - b = encodeComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -8689,6 +8904,44 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = appendStructEnd(b) code = code.next + case opStructEndOmitEmptyStringPtr: + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p != 0 { + b = append(b, code.escapedKey...) + b = encodeEscapedString(b, e.ptrToString(p)) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringTagStringPtr: + b = append(b, code.escapedKey...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + if p == 0 { + b = encodeNull(b) + } else { + v := e.ptrToString(p) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, v))) + } + b = appendStructEnd(b) + code = code.next + case opStructEndStringNPtr: + b = append(b, code.escapedKey...) + ptr := load(ctxptr, code.headIdx) + p := e.ptrToPtr(ptr + code.offset) + for i := 0; i < code.ptrNum-1; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p)) + } + b = appendStructEnd(b) + code = code.next case opStructEndBool: 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 33fade2..785c0a2 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -6519,12 +6519,10 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op case opStructFieldHeadString: 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') b = e.encodeIndent(b, code.indent+1) b = append(b, code.escapedKey...) @@ -6533,6 +6531,454 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyString: + 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.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = encodeEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagString: + 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, ' ') + v := e.ptrToString(ptr + code.offset) + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, v))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrHeadStringOnly, opStructFieldHeadStringOnly: + 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 = encodeEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringOnly, opStructFieldHeadOmitEmptyStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + v := e.ptrToString(p) + if v != "" { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = encodeEscapedString(b, v) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringOnly, opStructFieldHeadStringTagStringOnly: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringPtr: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p)) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadStringPtrOnly: + 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 opStructFieldHeadStringPtrOnly: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtrOnly: + 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 opStructFieldHeadOmitEmptyStringPtrOnly: + 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 = encodeEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringPtrOnly: + 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 opStructFieldHeadStringTagStringPtrOnly: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldHeadStringNPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + for i := 0; i < code.ptrNum; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p+code.offset)) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadString: + 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 = encodeEscapedString(b, e.ptrToString(ptr+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadOmitEmptyString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = encodeEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagString: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(ptr+code.offset)))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringOnly, opStructFieldAnonymousHeadStringOnly: + 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 = encodeEscapedString(b, e.ptrToString(ptr+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadOmitEmptyStringOnly, opStructFieldAnonymousHeadOmitEmptyStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = encodeEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagStringOnly, opStructFieldAnonymousHeadStringTagStringOnly: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(ptr+code.offset)))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtr: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringPtrOnly: + 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 = encodeEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtrOnly: + 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 = encodeEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtrOnly: + 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 = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadBool: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6573,34 +7019,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyString: - 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.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.escapedKey...) - b = append(b, ' ') - b = encodeEscapedString(b, v) - b = encodeIndentComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -6678,29 +7096,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op code = code.next store(ctxptr, code.idx, p) } - case opStructFieldPtrHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagString: - 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, ' ') - s := e.ptrToString(ptr + code.offset) - b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, s))) - b = encodeIndentComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -8494,8 +8889,17 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, code.escapedKey...) b = append(b, ' ') b = encodeEscapedString(b, 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) } - b = e.appendStructEndIndent(b, code.indent-1) code = code.next case opStructEndStringTagString: ptr := load(ctxptr, code.headIdx) @@ -8506,6 +8910,52 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, s))) b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndStringPtr: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, e.ptrToString(p)) + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next + case opStructEndOmitEmptyStringPtr: + 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 = encodeEscapedString(b, e.ptrToString(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 opStructEndStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeEscapedString(b, string(encodeEscapedString([]byte{}, e.ptrToString(p)))) + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndBool: b = e.encodeIndent(b, code.indent) b = append(b, code.escapedKey...) diff --git a/encode_vm_indent.go b/encode_vm_indent.go index c46942f..3507a46 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -6519,12 +6519,10 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( case opStructFieldHeadString: 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') b = e.encodeIndent(b, code.indent+1) b = append(b, code.key...) @@ -6533,6 +6531,454 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmptyString: + 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.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = encodeNoEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrHeadStringTagString: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadStringTagString: + 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, ' ') + v := e.ptrToString(ptr + code.offset) + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, v))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrHeadStringOnly, opStructFieldHeadStringOnly: + 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 = encodeNoEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringOnly, opStructFieldHeadOmitEmptyStringOnly: + p := load(ctxptr, code.idx) + b = append(b, '{', '\n') + v := e.ptrToString(p) + if v != "" { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + b = encodeNoEscapedString(b, v) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringOnly, opStructFieldHeadStringTagStringOnly: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringPtr: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p)) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadOmitEmptyStringPtr: + 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.key...) + b = append(b, ' ') + b = encodeNoEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + } + code = code.next + } + case opStructFieldPtrHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldHeadStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadStringPtrOnly: + 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 opStructFieldHeadStringPtrOnly: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrHeadOmitEmptyStringPtrOnly: + 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 opStructFieldHeadOmitEmptyStringPtrOnly: + 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 = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeIndentComma(b) + } + code = code.next + case opStructFieldPtrHeadStringTagStringPtrOnly: + 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 opStructFieldHeadStringTagStringPtrOnly: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldHeadStringNPtr: + p := load(ctxptr, code.idx) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '{', '\n') + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + for i := 0; i < code.ptrNum; i++ { + if p == 0 { + break + } + p = e.ptrToPtr(p) + } + if p == 0 { + b = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + } + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadString: + 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 = encodeNoEscapedString(b, e.ptrToString(ptr+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadOmitEmptyString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyString: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = encodeNoEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagString: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagString: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(ptr+code.offset)))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringOnly, opStructFieldAnonymousHeadStringOnly: + 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 = encodeNoEscapedString(b, e.ptrToString(ptr+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadOmitEmptyStringOnly, opStructFieldAnonymousHeadOmitEmptyStringOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToString(ptr + code.offset) + if v == "" { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = encodeNoEscapedString(b, v) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagStringOnly, opStructFieldAnonymousHeadStringTagStringOnly: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(ptr+code.offset)))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringPtr: + 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 = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtr: + 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 = encodeNoEscapedString(b, e.ptrToString(p)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtr: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringPtrOnly: + 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 = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + } + b = encodeIndentComma(b) + code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyStringPtrOnly: + 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 = encodeNoEscapedString(b, e.ptrToString(p+code.offset)) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagStringPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagStringPtrOnly: + 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 = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p+code.offset)))) + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadBool: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -6573,34 +7019,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmptyString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmptyString: - 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.ptrToString(ptr + code.offset) - if v == "" { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.key...) - b = append(b, ' ') - b = encodeNoEscapedString(b, v) - b = encodeIndentComma(b) - code = code.next - } - } case opStructFieldPtrHeadOmitEmptyBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -6678,29 +7096,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( code = code.next store(ctxptr, code.idx, p) } - case opStructFieldPtrHeadStringTagString: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadStringTagString: - 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, ' ') - s := e.ptrToString(ptr + code.offset) - b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, s))) - b = encodeIndentComma(b) - code = code.next - } case opStructFieldPtrHeadStringTagBool: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -8494,8 +8889,17 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, code.key...) b = append(b, ' ') b = encodeNoEscapedString(b, 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) } - b = e.appendStructEndIndent(b, code.indent-1) code = code.next case opStructEndStringTagString: ptr := load(ctxptr, code.headIdx) @@ -8506,6 +8910,52 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, s))) b = e.appendStructEndIndent(b, code.indent-1) code = code.next + case opStructEndStringPtr: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, e.ptrToString(p)) + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next + case opStructEndOmitEmptyStringPtr: + 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 = encodeNoEscapedString(b, e.ptrToString(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 opStructEndStringTagStringPtr: + 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 = encodeNull(b) + } else { + b = encodeNoEscapedString(b, string(encodeNoEscapedString([]byte{}, e.ptrToString(p)))) + } + b = e.appendStructEndIndent(b, code.indent-1) + code = code.next case opStructEndBool: b = e.encodeIndent(b, code.indent) b = append(b, code.key...)