diff --git a/coverage_test.go b/coverage_test.go index 66a168a..8180886 100644 --- a/coverage_test.go +++ b/coverage_test.go @@ -24,9 +24,22 @@ func TestCoverStructHeadInt(t *testing.T) { type structInt struct { A int `json:"a"` } + type structIntOmitEmpty struct { + A int `json:"a,omitempty"` + } + type structIntString struct { + A int `json:"a,string"` + } + type structIntPtr struct { A *int `json:"a"` } + type structIntPtrOmitEmpty struct { + A *int `json:"a,omitempty"` + } + type structIntPtrString struct { + A *int `json:"a,string"` + } tests := []struct { name string @@ -171,10 +184,10 @@ func TestCoverStructHeadInt(t *testing.T) { }, { name: "HeadIntPtrNilString", - expected: `{"a":""}`, + expected: `{"a":null}`, indentExpected: ` { - "a": "" + "a": null } `, data: struct { @@ -319,10 +332,10 @@ func TestCoverStructHeadInt(t *testing.T) { }, { name: "PtrHeadIntPtrNilString", - expected: `{"a":""}`, + expected: `{"a":null}`, indentExpected: ` { - "a": "" + "a": null } `, data: &struct { @@ -519,11 +532,11 @@ null }, { name: "HeadIntPtrNilMultiFieldsString", - expected: `{"a":"","b":""}`, + expected: `{"a":null,"b":null}`, indentExpected: ` { - "a": "", - "b": "" + "a": null, + "b": null } `, data: struct { @@ -689,11 +702,11 @@ null }, { name: "PtrHeadIntPtrNilMultiFieldsString", - expected: `{"a":"","b":""}`, + expected: `{"a":null,"b":null}`, indentExpected: ` { - "a": "", - "b": "" + "a": null, + "b": null } `, data: &struct { @@ -860,6 +873,44 @@ null A *int `json:"a"` }{intptr(1)}}, }, + { + name: "HeadIntPtrNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{intptr(1)}}, + }, + { + name: "HeadIntPtrNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{intptr(1)}}, + }, + + // HeadIntPtrNilNotRoot { name: "HeadIntPtrNilNotRoot", expected: `{"A":{"a":null}}`, @@ -876,6 +927,38 @@ null } }{}, }, + { + name: "HeadIntPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + }{}, + }, + { + name: "HeadIntPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + }{}, + }, + + // PtrHeadIntZeroNotRoot { name: "PtrHeadIntZeroNotRoot", expected: `{"A":{"a":0}}`, @@ -894,6 +977,42 @@ null A int `json:"a"` })}, }, + { + name: "PtrHeadIntZeroNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A int `json:"a,omitempty"` + } + }{A: new(struct { + A int `json:"a,omitempty"` + })}, + }, + { + name: "PtrHeadIntZeroNotRootString", + expected: `{"A":{"a":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + } +} +`, + data: struct { + A *struct { + A int `json:"a,string"` + } + }{A: new(struct { + A int `json:"a,string"` + })}, + }, + + // PtrHeadIntNotRoot { name: "PtrHeadIntNotRoot", expected: `{"A":{"a":1}}`, @@ -912,6 +1031,44 @@ null A int `json:"a"` }{A: 1})}, }, + { + name: "PtrHeadIntNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A *struct { + A int `json:"a,omitempty"` + } + }{A: &(struct { + A int `json:"a,omitempty"` + }{A: 1})}, + }, + { + name: "PtrHeadIntNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A *struct { + A int `json:"a,string"` + } + }{A: &(struct { + A int `json:"a,string"` + }{A: 1})}, + }, + + // PtrHeadIntPtrNotRoot { name: "PtrHeadIntPtrNotRoot", expected: `{"A":{"a":1}}`, @@ -930,6 +1087,44 @@ null A *int `json:"a"` }{A: intptr(1)})}, }, + { + name: "PtrHeadIntPtrNotRootOmitEmpty", + expected: `{"A":{"a":1}}`, + indentExpected: ` +{ + "A": { + "a": 1 + } +} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)})}, + }, + { + name: "PtrHeadIntPtrNotRootString", + expected: `{"A":{"a":"1"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + } +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: intptr(1)})}, + }, + + // PtrHeadIntPtrNilNotRoot { name: "PtrHeadIntPtrNilNotRoot", expected: `{"A":{"a":null}}`, @@ -948,6 +1143,42 @@ null A *int `json:"a"` }{A: nil})}, }, + { + name: "PtrHeadIntPtrNilNotRootOmitEmpty", + expected: `{"A":{}}`, + indentExpected: ` +{ + "A": {} +} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: nil})}, + }, + { + name: "PtrHeadIntPtrNilNotRootString", + expected: `{"A":{"a":null}}`, + indentExpected: ` +{ + "A": { + "a": null + } +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: nil})}, + }, + + // PtrHeadIntNilNotRoot { name: "PtrHeadIntNilNotRoot", expected: `{"A":null}`, @@ -962,6 +1193,34 @@ null } }{A: nil}, }, + { + name: "PtrHeadIntNilNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + A *struct { + A *int `json:"a,omitempty"` + } `json:",omitempty"` + }{A: nil}, + }, + { + name: "PtrHeadIntNilNotRootString", + expected: `{"A":null}`, + indentExpected: ` +{ + "A": null +} +`, + data: struct { + A *struct { + A *int `json:"a,string"` + } `json:",string"` + }{A: nil}, + }, + + // HeadIntZeroMultiFieldsNotRoot { name: "HeadIntZeroMultiFieldsNotRoot", expected: `{"A":{"a":0},"B":{"b":0}}`, @@ -984,6 +1243,48 @@ null } }{}, }, + { + name: "HeadIntZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{}, + }, + { + name: "HeadIntZeroMultiFieldsNotRootString", + expected: `{"A":{"a":"0"},"B":{"b":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + }, + "B": { + "b": "0" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{}, + }, + + // HeadIntMultiFieldsNotRoot { name: "HeadIntMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1010,6 +1311,60 @@ null B int `json:"b"` }{B: 2}}, }, + { + name: "HeadIntMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{A: struct { + A int `json:"a,omitempty"` + }{A: 1}, B: struct { + B int `json:"b,omitempty"` + }{B: 2}}, + }, + { + name: "HeadIntMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{A: struct { + A int `json:"a,string"` + }{A: 1}, B: struct { + B int `json:"b,string"` + }{B: 2}}, + }, + + // HeadIntPtrMultiFieldsNotRoot { name: "HeadIntPtrMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1036,6 +1391,60 @@ null B *int `json:"b"` }{B: intptr(2)}}, }, + { + name: "HeadIntPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + B struct { + B *int `json:"b,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}, B: struct { + B *int `json:"b,omitempty"` + }{B: intptr(2)}}, + }, + { + name: "HeadIntPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + B struct { + B *int `json:"b,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{A: intptr(1)}, B: struct { + B *int `json:"b,string"` + }{B: intptr(2)}}, + }, + + // HeadIntPtrNilMultiFieldsNotRoot { name: "HeadIntPtrNilMultiFieldsNotRoot", expected: `{"A":{"a":null},"B":{"b":null}}`, @@ -1062,6 +1471,56 @@ null B *int `json:"b"` }{B: nil}}, }, + { + name: "HeadIntPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: struct { + A struct { + A *int `json:"a,omitempty"` + } + B struct { + B *int `json:"b,omitempty"` + } + }{A: struct { + A *int `json:"a,omitempty"` + }{A: nil}, B: struct { + B *int `json:"b,omitempty"` + }{B: nil}}, + }, + { + name: "HeadIntPtrNilMultiFieldsNotRootString", + expected: `{"A":{"a":null},"B":{"b":null}}`, + indentExpected: ` +{ + "A": { + "a": null + }, + "B": { + "b": null + } +} +`, + data: struct { + A struct { + A *int `json:"a,string"` + } + B struct { + B *int `json:"b,string"` + } + }{A: struct { + A *int `json:"a,string"` + }{A: nil}, B: struct { + B *int `json:"b,string"` + }{B: nil}}, + }, + + // PtrHeadIntZeroMultiFieldsNotRoot { name: "PtrHeadIntZeroMultiFieldsNotRoot", expected: `{"A":{"a":0},"B":{"b":0}}`, @@ -1084,6 +1543,48 @@ null } }{}, }, + { + name: "PtrHeadIntZeroMultiFieldsNotRootOmitEmpty", + expected: `{"A":{},"B":{}}`, + indentExpected: ` +{ + "A": {}, + "B": {} +} +`, + data: &struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{}, + }, + { + name: "PtrHeadIntZeroMultiFieldsNotRootString", + expected: `{"A":{"a":"0"},"B":{"b":"0"}}`, + indentExpected: ` +{ + "A": { + "a": "0" + }, + "B": { + "b": "0" + } +} +`, + data: &struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{}, + }, + + // PtrHeadIntMultiFieldsNotRoot { name: "PtrHeadIntMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1110,6 +1611,60 @@ null B int `json:"b"` }{B: 2}}, }, + { + name: "PtrHeadIntMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: &struct { + A struct { + A int `json:"a,omitempty"` + } + B struct { + B int `json:"b,omitempty"` + } + }{A: struct { + A int `json:"a,omitempty"` + }{A: 1}, B: struct { + B int `json:"b,omitempty"` + }{B: 2}}, + }, + { + name: "PtrHeadIntMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: &struct { + A struct { + A int `json:"a,string"` + } + B struct { + B int `json:"b,string"` + } + }{A: struct { + A int `json:"a,string"` + }{A: 1}, B: struct { + B int `json:"b,string"` + }{B: 2}}, + }, + + // PtrHeadIntPtrMultiFieldsNotRoot { name: "PtrHeadIntPtrMultiFieldsNotRoot", expected: `{"A":{"a":1},"B":{"b":2}}`, @@ -1136,6 +1691,60 @@ null B *int `json:"b"` }{B: intptr(2)})}, }, + { + name: "PtrHeadIntPtrMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1},"B":{"b":2}}`, + indentExpected: ` +{ + "A": { + "a": 1 + }, + "B": { + "b": 2 + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + } + B *struct { + B *int `json:"b,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + }{A: intptr(1)}), B: &(struct { + B *int `json:"b,omitempty"` + }{B: intptr(2)})}, + }, + { + name: "PtrHeadIntPtrMultiFieldsNotRootString", + expected: `{"A":{"a":"1"},"B":{"b":"2"}}`, + indentExpected: ` +{ + "A": { + "a": "1" + }, + "B": { + "b": "2" + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + } + B *struct { + B *int `json:"b,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + }{A: intptr(1)}), B: &(struct { + B *int `json:"b,string"` + }{B: intptr(2)})}, + }, + + // PtrHeadIntPtrNilMultiFieldsNotRoot { name: "PtrHeadIntPtrNilMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1154,6 +1763,41 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntPtrNilMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + } `json:",omitempty"` + B *struct { + B *int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntPtrNilMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + } `json:",string"` + B *struct { + B *int `json:"b,string"` + } `json:",string"` + }{A: nil, B: nil}, + }, + + // PtrHeadIntNilMultiFieldsNotRoot { name: "PtrHeadIntNilMultiFieldsNotRoot", expected: `null`, @@ -1169,6 +1813,38 @@ null } })(nil), }, + { + name: "PtrHeadIntNilMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,omitempty"` + } + B *struct { + B *int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntNilMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,string"` + } + B *struct { + B *int `json:"b,string"` + } + })(nil), + }, + + // PtrHeadIntDoubleMultiFieldsNotRoot { name: "PtrHeadIntDoubleMultiFieldsNotRoot", expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, @@ -1201,6 +1877,72 @@ null B int `json:"b"` }{A: 3, B: 4})}, }, + { + name: "PtrHeadIntDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, + indentExpected: ` +{ + "A": { + "a": 1, + "b": 2 + }, + "B": { + "a": 3, + "b": 4 + } +} +`, + data: &struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + }{A: &(struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 1, B: 2}), B: &(struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + }{A: 3, B: 4})}, + }, + { + name: "PtrHeadIntDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"1","b":"2"},"B":{"a":"3","b":"4"}}`, + indentExpected: ` +{ + "A": { + "a": "1", + "b": "2" + }, + "B": { + "a": "3", + "b": "4" + } +} +`, + data: &struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + }{A: &(struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 1, B: 2}), B: &(struct { + A int `json:"a,string"` + B int `json:"b,string"` + }{A: 3, B: 4})}, + }, + + // PtrHeadIntNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1221,6 +1963,45 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } `json:",omitempty"` + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadIntNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntNilDoubleMultiFieldsNotRoot", expected: `null`, @@ -1238,6 +2019,42 @@ null } })(nil), }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + B *struct { + A int `json:"a,omitempty"` + B int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + B *struct { + A int `json:"a,string"` + B int `json:"b,string"` + } + })(nil), + }, + + // PtrHeadIntPtrDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrDoubleMultiFieldsNotRoot", expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, @@ -1270,6 +2087,72 @@ null B *int `json:"b"` }{A: intptr(3), B: intptr(4)})}, }, + { + name: "PtrHeadIntPtrDoubleMultiFieldsNotRootOmitEmpty", + expected: `{"A":{"a":1,"b":2},"B":{"a":3,"b":4}}`, + indentExpected: ` +{ + "A": { + "a": 1, + "b": 2 + }, + "B": { + "a": 3, + "b": 4 + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + }{A: &(struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(1), B: intptr(2)}), B: &(struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + }{A: intptr(3), B: intptr(4)})}, + }, + { + name: "PtrHeadIntPtrDoubleMultiFieldsNotRootString", + expected: `{"A":{"a":"1","b":"2"},"B":{"a":"3","b":"4"}}`, + indentExpected: ` +{ + "A": { + "a": "1", + "b": "2" + }, + "B": { + "a": "3", + "b": "4" + } +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + }{A: &(struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(1), B: intptr(2)}), B: &(struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + }{A: intptr(3), B: intptr(4)})}, + }, + + // PtrHeadIntPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRoot", expected: `{"A":null,"B":null}`, @@ -1290,6 +2173,45 @@ null } }{A: nil, B: nil}, }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: &struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } `json:",omitempty"` + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } `json:",omitempty"` + }{A: nil, B: nil}, + }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootString", + expected: `{"A":null,"B":null}`, + indentExpected: ` +{ + "A": null, + "B": null +} +`, + data: &struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + }{A: nil, B: nil}, + }, + + // PtrHeadIntPtrNilDoubleMultiFieldsNotRoot { name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRoot", expected: `null`, @@ -1307,6 +2229,42 @@ null } })(nil), }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootOmitEmpty", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + B *struct { + A *int `json:"a,omitempty"` + B *int `json:"b,omitempty"` + } + })(nil), + }, + { + name: "PtrHeadIntPtrNilDoubleMultiFieldsNotRootString", + expected: `null`, + indentExpected: ` +null +`, + data: (*struct { + A *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + B *struct { + A *int `json:"a,string"` + B *int `json:"b,string"` + } + })(nil), + }, + + // AnonymousHeadInt { name: "AnonymousHeadInt", expected: `{"a":1,"b":2}`, @@ -1324,6 +2282,42 @@ null B: 2, }, }, + { + name: "AnonymousHeadIntOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: structIntOmitEmpty{A: 1}, + B: 2, + }, + }, + { + name: "AnonymousHeadIntString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + structIntString + B int `json:"b,string"` + }{ + structIntString: structIntString{A: 1}, + B: 2, + }, + }, + + // PtrAnonymousHeadInt { name: "PtrAnonymousHeadInt", expected: `{"a":1,"b":2}`, @@ -1341,6 +2335,42 @@ null B: 2, }, }, + { + name: "PtrAnonymousHeadIntOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + *structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: &structIntOmitEmpty{A: 1}, + B: 2, + }, + }, + { + name: "PtrAnonymousHeadIntString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + *structIntString + B int `json:"b,string"` + }{ + structIntString: &structIntString{A: 1}, + B: 2, + }, + }, + + // NilPtrAnonymousHeadInt { name: "NilPtrAnonymousHeadInt", expected: `{"b":2}`, @@ -1357,6 +2387,40 @@ null B: 2, }, }, + { + name: "NilPtrAnonymousHeadIntOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + *structIntOmitEmpty + B int `json:"b,omitempty"` + }{ + structIntOmitEmpty: nil, + B: 2, + }, + }, + { + name: "NilPtrAnonymousHeadIntString", + expected: `{"b":"2"}`, + indentExpected: ` +{ + "b": "2" +} +`, + data: struct { + *structIntString + B int `json:"b,string"` + }{ + structIntString: nil, + B: 2, + }, + }, + + // AnonymousHeadIntPtr { name: "AnonymousHeadIntPtr", expected: `{"a":1,"b":2}`, @@ -1374,6 +2438,42 @@ null B: intptr(2), }, }, + { + name: "AnonymousHeadIntPtrOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: intptr(1)}, + B: intptr(2), + }, + }, + { + name: "AnonymousHeadIntPtrString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: structIntPtrString{A: intptr(1)}, + B: intptr(2), + }, + }, + + // AnonymousHeadIntPtrNil { name: "AnonymousHeadIntPtrNil", expected: `{"a":null,"b":2}`, @@ -1391,6 +2491,41 @@ null B: intptr(2), }, }, + { + name: "AnonymousHeadIntPtrNilOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: nil}, + B: intptr(2), + }, + }, + { + name: "AnonymousHeadIntPtrNilString", + expected: `{"a":null,"b":"2"}`, + indentExpected: ` +{ + "a": null, + "b": "2" +} +`, + data: struct { + structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: structIntPtrString{A: nil}, + B: intptr(2), + }, + }, + + // PtrAnonymousHeadIntPtr { name: "PtrAnonymousHeadIntPtr", expected: `{"a":1,"b":2}`, @@ -1408,6 +2543,42 @@ null B: intptr(2), }, }, + { + name: "PtrAnonymousHeadIntPtrOmitEmpty", + expected: `{"a":1,"b":2}`, + indentExpected: ` +{ + "a": 1, + "b": 2 +} +`, + data: struct { + *structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: &structIntPtrOmitEmpty{A: intptr(1)}, + B: intptr(2), + }, + }, + { + name: "PtrAnonymousHeadIntPtrString", + expected: `{"a":"1","b":"2"}`, + indentExpected: ` +{ + "a": "1", + "b": "2" +} +`, + data: struct { + *structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: &structIntPtrString{A: intptr(1)}, + B: intptr(2), + }, + }, + + // NilPtrAnonymousHeadIntPtr { name: "NilPtrAnonymousHeadIntPtr", expected: `{"b":2}`, @@ -1424,6 +2595,40 @@ null B: intptr(2), }, }, + { + name: "NilPtrAnonymousHeadIntPtrOmitEmpty", + expected: `{"b":2}`, + indentExpected: ` +{ + "b": 2 +} +`, + data: struct { + *structIntPtrOmitEmpty + B *int `json:"b,omitempty"` + }{ + structIntPtrOmitEmpty: nil, + B: intptr(2), + }, + }, + { + name: "NilPtrAnonymousHeadIntPtrString", + expected: `{"b":"2"}`, + indentExpected: ` +{ + "b": "2" +} +`, + data: struct { + *structIntPtrString + B *int `json:"b,string"` + }{ + structIntPtrString: nil, + B: intptr(2), + }, + }, + + // AnonymousHeadIntOnly { name: "AnonymousHeadIntOnly", expected: `{"a":1}`, @@ -1438,6 +2643,36 @@ null structInt: structInt{A: 1}, }, }, + { + name: "AnonymousHeadIntOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + structIntOmitEmpty + }{ + structIntOmitEmpty: structIntOmitEmpty{A: 1}, + }, + }, + { + name: "AnonymousHeadIntOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + structIntString + }{ + structIntString: structIntString{A: 1}, + }, + }, + + // PtrAnonymousHeadIntOnly { name: "PtrAnonymousHeadIntOnly", expected: `{"a":1}`, @@ -1452,6 +2687,36 @@ null structInt: &structInt{A: 1}, }, }, + { + name: "PtrAnonymousHeadIntOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + *structIntOmitEmpty + }{ + structIntOmitEmpty: &structIntOmitEmpty{A: 1}, + }, + }, + { + name: "PtrAnonymousHeadIntOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + *structIntString + }{ + structIntString: &structIntString{A: 1}, + }, + }, + + // NilPtrAnonymousHeadIntOnly { name: "NilPtrAnonymousHeadIntOnly", expected: `{}`, @@ -1464,6 +2729,32 @@ null structInt: nil, }, }, + { + name: "NilPtrAnonymousHeadIntOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntOmitEmpty + }{ + structIntOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadIntOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntString + }{ + structIntString: nil, + }, + }, + + // AnonymousHeadIntPtrOnly { name: "AnonymousHeadIntPtrOnly", expected: `{"a":1}`, @@ -1478,6 +2769,36 @@ null structIntPtr: structIntPtr{A: intptr(1)}, }, }, + { + name: "AnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: intptr(1)}, + }, + }, + { + name: "AnonymousHeadIntPtrOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + structIntPtrString + }{ + structIntPtrString: structIntPtrString{A: intptr(1)}, + }, + }, + + // AnonymousHeadIntPtrNilOnly { name: "AnonymousHeadIntPtrNilOnly", expected: `{"a":null}`, @@ -1492,6 +2813,34 @@ null structIntPtr: structIntPtr{A: nil}, }, }, + { + name: "AnonymousHeadIntPtrNilOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: structIntPtrOmitEmpty{A: nil}, + }, + }, + { + name: "AnonymousHeadIntPtrNilOnlyString", + expected: `{"a":null}`, + indentExpected: ` +{ + "a": null +} +`, + data: struct { + structIntPtrString + }{ + structIntPtrString: structIntPtrString{A: nil}, + }, + }, + + // PtrAnonymousHeadIntPtrOnly { name: "PtrAnonymousHeadIntPtrOnly", expected: `{"a":1}`, @@ -1506,6 +2855,36 @@ null structIntPtr: &structIntPtr{A: intptr(1)}, }, }, + { + name: "PtrAnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{"a":1}`, + indentExpected: ` +{ + "a": 1 +} +`, + data: struct { + *structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: &structIntPtrOmitEmpty{A: intptr(1)}, + }, + }, + { + name: "PtrAnonymousHeadIntPtrOnlyString", + expected: `{"a":"1"}`, + indentExpected: ` +{ + "a": "1" +} +`, + data: struct { + *structIntPtrString + }{ + structIntPtrString: &structIntPtrString{A: intptr(1)}, + }, + }, + + // NilPtrAnonymousHeadIntPtrOnly { name: "NilPtrAnonymousHeadIntPtrOnly", expected: `{}`, @@ -1518,6 +2897,30 @@ null structIntPtr: nil, }, }, + { + name: "NilPtrAnonymousHeadIntPtrOnlyOmitEmpty", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntPtrOmitEmpty + }{ + structIntPtrOmitEmpty: nil, + }, + }, + { + name: "NilPtrAnonymousHeadIntPtrOnlyString", + expected: `{}`, + indentExpected: ` +{} +`, + data: struct { + *structIntPtrString + }{ + structIntPtrString: nil, + }, + }, } for _, test := range tests { for _, indent := range []bool{true, false} { diff --git a/encode_compile.go b/encode_compile.go index dbbb806..cece1e9 100644 --- a/encode_compile.go +++ b/encode_compile.go @@ -105,7 +105,17 @@ func (e *Encoder) convertHeadOnlyCode(c *opcode, isPtrHead bool) { } c.op = opStructFieldHeadOnly case opStructFieldHeadOmitEmpty: - return + e.convertHeadOnlyCode(c.next, false) + if !strings.Contains(c.next.op.String(), "Only") { + return + } + c.op = opStructFieldHeadOmitEmptyOnly + case opStructFieldHeadStringTag: + e.convertHeadOnlyCode(c.next, false) + if !strings.Contains(c.next.op.String(), "Only") { + return + } + c.op = opStructFieldHeadStringTagOnly case opStructFieldPtrHead: } diff --git a/encode_vm.go b/encode_vm.go index 88f6e85..58956ff 100644 --- a/encode_vm.go +++ b/encode_vm.go @@ -615,7 +615,30 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{') if !code.anonymousKey { @@ -624,6 +647,19 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{') + if !code.anonymousKey { + if ptr != 0 { + b = append(b, code.key...) + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } + } case opStructFieldAnonymousHead: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -632,6 +668,26 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte code = code.next store(ctxptr, code.idx, ptr) } + case opStructFieldPtrAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + code = code.next + store(ctxptr, code.idx, p) + } + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -775,7 +831,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = append(b, code.key...) p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -839,7 +895,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = append(b, '{') b = append(b, code.key...) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -930,6 +986,33 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.key...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -948,6 +1031,44 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = append(b, code.key...) + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -966,6 +1087,44 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.key...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.key...) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2839,49 +2998,6 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - code = code.next - store(ctxptr, code.idx, p) - } - } - case opStructFieldPtrAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.key...) - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -5175,7 +5291,7 @@ func (e *Encoder) run(ctx *encodeRuntimeContext, b []byte, code *opcode) ([]byte ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_escaped.go b/encode_vm_escaped.go index 64cc918..e08fde6 100644 --- a/encode_vm_escaped.go +++ b/encode_vm_escaped.go @@ -577,15 +577,49 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = encodeNull(b) + b = encodeComma(b) + code = code.end.next + } else { + b = append(b, '{') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: + p := load(ctxptr, code.idx) b = append(b, '{') if !code.anonymousKey { b = append(b, code.escapedKey...) } - p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + p := load(ctxptr, code.idx) + b = append(b, '{') + if !code.anonymousKey { + if p != 0 { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } + } case opStructFieldAnonymousHead: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -594,6 +628,26 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) code = code.next store(ctxptr, code.idx, ptr) } + case opStructFieldPtrAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldAnonymousHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + code = code.next + store(ctxptr, code.idx, p) + } + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -737,7 +791,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = append(b, code.escapedKey...) p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -801,7 +855,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = append(b, '{') b = append(b, code.escapedKey...) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -892,6 +946,33 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(v)) + b = encodeComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = append(b, code.escapedKey...) + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -910,6 +991,44 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = append(b, code.escapedKey...) + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -928,6 +1047,44 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) } b = encodeComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = append(b, code.escapedKey...) + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = append(b, code.escapedKey...) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2808,49 +2965,6 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) b = encodeComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = encodeNull(b) - b = encodeComma(b) - code = code.end.next - } else { - b = append(b, '{') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - code = code.next - store(ctxptr, code.idx, p) - } - } - case opStructFieldPtrAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldAnonymousHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - code = code.end.next - } else { - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = append(b, code.escapedKey...) - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -5203,7 +5317,7 @@ func (e *Encoder) runEscaped(ctx *encodeRuntimeContext, b []byte, code *opcode) ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_escaped_indent.go b/encode_vm_escaped_indent.go index adc3c29..1194054 100644 --- a/encode_vm_escaped_indent.go +++ b/encode_vm_escaped_indent.go @@ -617,7 +617,34 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = e.encodeIndent(b, code.indent) + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, '{', '\n') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{', '\n') if !code.anonymousKey { @@ -628,6 +655,19 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if !code.anonymousKey && ptr != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.escapedKey...) + b = append(b, ' ') + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -787,7 +827,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, ' ') p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -857,7 +897,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = append(b, code.escapedKey...) b = append(b, ' ') if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -903,6 +943,43 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -915,6 +992,37 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -935,6 +1043,48 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -955,6 +1105,48 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2855,33 +3047,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.escapedKey...) - b = append(b, ' ') - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3286,7 +3451,6 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op case opStructFieldHeadStringTag: ptr := load(ctxptr, code.idx) if ptr == 0 { - b = e.encodeIndent(b, code.indent) b = encodeNull(b) b = encodeIndentComma(b) code = code.end.next @@ -4390,7 +4554,7 @@ func (e *Encoder) runEscapedIndent(ctx *encodeRuntimeContext, b []byte, code *op ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p))) diff --git a/encode_vm_indent.go b/encode_vm_indent.go index c5d5e8a..5e2976d 100644 --- a/encode_vm_indent.go +++ b/encode_vm_indent.go @@ -617,7 +617,34 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( code = code.next store(ctxptr, code.idx, p) } - case opStructFieldHeadOnly: + case opStructFieldPtrHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr != 0 { + store(ctxptr, code.idx, e.ptrToPtr(ptr)) + } + fallthrough + case opStructFieldHeadOmitEmpty: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + b = e.encodeIndent(b, code.indent) + b = encodeNull(b) + b = encodeIndentComma(b) + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, '{', '\n') + p := ptr + code.offset + if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + code = code.next + store(ctxptr, code.idx, p) + } + } + case opStructFieldHeadOnly, opStructFieldHeadStringTagOnly: ptr := load(ctxptr, code.idx) b = append(b, '{', '\n') if !code.anonymousKey { @@ -628,6 +655,19 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( p := ptr + code.offset code = code.next store(ctxptr, code.idx, p) + case opStructFieldHeadOmitEmptyOnly: + ptr := load(ctxptr, code.idx) + b = append(b, '{', '\n') + if !code.anonymousKey && ptr != 0 { + b = e.encodeIndent(b, code.indent+1) + b = append(b, code.key...) + b = append(b, ' ') + p := ptr + code.offset + code = code.next + store(ctxptr, code.idx, p) + } else { + code = code.nextField + } case opStructFieldPtrHeadInt: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -787,7 +827,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, ' ') p = e.ptrToPtr(p) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -857,7 +897,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = append(b, code.key...) b = append(b, ' ') if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p+code.offset))) @@ -903,6 +943,43 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagInt: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagInt: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.escapedKey...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntOnly, opStructFieldAnonymousHeadIntOnly: ptr := load(ctxptr, code.idx) if ptr == 0 { @@ -915,6 +992,37 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } + case opStructFieldPtrAnonymousHeadOmitEmptyIntOnly, opStructFieldAnonymousHeadOmitEmptyIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + v := e.ptrToInt(ptr + code.offset) + if v == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(v)) + b = encodeIndentComma(b) + code = code.next + } + } + case opStructFieldPtrAnonymousHeadStringTagIntOnly, opStructFieldAnonymousHeadStringTagIntOnly: + ptr := load(ctxptr, code.idx) + if ptr == 0 { + code = code.end.next + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(ptr+code.offset))) + b = append(b, '"') + b = encodeIndentComma(b) + code = code.next + } case opStructFieldPtrAnonymousHeadIntPtr: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -935,6 +1043,48 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + p = e.ptrToPtr(p) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtr: + store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtr: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + p = e.ptrToPtr(p) + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrAnonymousHeadIntPtrOnly: p := load(ctxptr, code.idx) if p == 0 { @@ -955,6 +1105,48 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( } b = encodeIndentComma(b) code = code.next + case opStructFieldPtrAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadOmitEmptyIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.nextField + } else { + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = encodeIndentComma(b) + code = code.next + } + case opStructFieldPtrAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + if p == 0 { + code = code.end.next + break + } + store(ctxptr, code.idx, e.ptrToPtr(p)) + fallthrough + case opStructFieldAnonymousHeadStringTagIntPtrOnly: + p := load(ctxptr, code.idx) + b = e.encodeIndent(b, code.indent) + b = append(b, code.key...) + b = append(b, ' ') + if p == 0 { + b = encodeNull(b) + } else { + b = append(b, '"') + b = appendInt(b, int64(e.ptrToInt(p+code.offset))) + b = append(b, '"') + } + b = encodeIndentComma(b) + code = code.next case opStructFieldPtrHeadInt8: store(ctxptr, code.idx, e.ptrToPtr(load(ctxptr, code.idx))) fallthrough @@ -2855,33 +3047,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( b = encodeIndentComma(b) code = code.next } - case opStructFieldPtrHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr != 0 { - store(ctxptr, code.idx, e.ptrToPtr(ptr)) - } - fallthrough - case opStructFieldHeadOmitEmpty: - ptr := load(ctxptr, code.idx) - if ptr == 0 { - b = e.encodeIndent(b, code.indent) - b = encodeNull(b) - b = encodeIndentComma(b) - code = code.end.next - } else { - b = e.encodeIndent(b, code.indent) - b = append(b, '{', '\n') - p := ptr + code.offset - if p == 0 || *(*uintptr)(*(*unsafe.Pointer)(unsafe.Pointer(&p))) == 0 { - code = code.nextField - } else { - b = e.encodeIndent(b, code.indent+1) - b = append(b, code.key...) - b = append(b, ' ') - code = code.next - store(ctxptr, code.idx, p) - } - } case opStructFieldPtrHeadOmitEmptyInt8: ptr := load(ctxptr, code.idx) if ptr != 0 { @@ -3286,7 +3451,6 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( case opStructFieldHeadStringTag: ptr := load(ctxptr, code.idx) if ptr == 0 { - b = e.encodeIndent(b, code.indent) b = encodeNull(b) b = encodeIndentComma(b) code = code.end.next @@ -4390,7 +4554,7 @@ func (e *Encoder) runIndent(ctx *encodeRuntimeContext, b []byte, code *opcode) ( ptr := load(ctxptr, code.headIdx) p := e.ptrToPtr(ptr + code.offset) if p == 0 { - b = append(b, `""`...) + b = encodeNull(b) } else { b = append(b, '"') b = appendInt(b, int64(e.ptrToInt(p)))