Skip to content

Commit

Permalink
Fix ignored tag directives on unnamed fields (#352)
Browse files Browse the repository at this point in the history
Example:

```
type S struct {
	ABool       bool       `msg:",omitempty"`
}
```

... would ignore the omitempty, since all tags were replaced, resulting in output like:

```
// MarshalMsg implements msgp.Marshaler
func (z S) MarshalMsg(b []byte) (o []byte, err error) {
	o = msgp.Require(b, z.Msgsize())
	// map header, size 1
	// string "ABool"
	o = append(o, 0x81, 0xa5, 0x41, 0x42, 0x6f, 0x6f, 0x6c)
	o = msgp.AppendBool(o, z.ABool)
	return
}

```

Keep remaining tags when filling out the field name.

Code after:

```
// MarshalMsg implements msgp.Marshaler
func (z S) MarshalMsg(b []byte) (o []byte, err error) {
	o = msgp.Require(b, z.Msgsize())
	// check for omitted fields
	zb0001Len := uint32(1)
	var zb0001Mask uint8 /* 1 bits */
	_ = zb0001Mask
	if z.ABool == false {
		zb0001Len--
		zb0001Mask |= 0x1
	}
	// variable map header, size zb0001Len
	o = append(o, 0x80|uint8(zb0001Len))
	if zb0001Len == 0 {
		return
	}
	if (zb0001Mask & 0x1) == 0 { // if not omitted
		// string "ABool"
		o = append(o, 0xa5, 0x41, 0x42, 0x6f, 0x6f, 0x6c)
		o = msgp.AppendBool(o, z.ABool)
	}
	return
}
```

Regression test added.
  • Loading branch information
klauspost authored Jul 2, 2024
1 parent 869874d commit cde6e95
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 1 deletion.
47 changes: 47 additions & 0 deletions _generated/omitempty.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,3 +177,50 @@ type NotOmitEmpty10 struct {
Field08 string `msg:"field08"`
Field09 string `msg:"field09"`
}

type OmitEmptyNoName struct {
ABool bool `msg:",omitempty"`
AInt int `msg:",omitempty"`
AInt8 int8 `msg:",omitempty"`
AInt16 int16 `msg:",omitempty"`
AInt32 int32 `msg:",omitempty"`
AInt64 int64 `msg:",omitempty"`
AUint uint `msg:",omitempty"`
AUint8 uint8 `msg:",omitempty"`
AUint16 uint16 `msg:",omitempty"`
AUint32 uint32 `msg:",omitempty"`
AUint64 uint64 `msg:",omitempty"`
AFloat32 float32 `msg:",omitempty"`
AFloat64 float64 `msg:",omitempty"`
AComplex64 complex64 `msg:",omitempty"`
AComplex128 complex128 `msg:",omitempty"`

ANamedBool bool `msg:",omitempty"`
ANamedInt int `msg:",omitempty"`
ANamedFloat64 float64 `msg:",omitempty"`

AMapStrStr map[string]string `msg:",omitempty"`

APtrNamedStr *NamedString `msg:",omitempty"`

AString string `msg:",omitempty"`
AByteSlice []byte `msg:",omitempty"`

ASliceString []string `msg:",omitempty"`
ASliceNamedString []NamedString `msg:",omitempty"`

ANamedStruct NamedStruct `msg:",omitempty"`
APtrNamedStruct *NamedStruct `msg:",omitempty"`

AUnnamedStruct struct {
A string `msg:",omitempty"`
} `msg:",omitempty"` // omitempty not supported on unnamed struct

EmbeddableStruct `msg:",flatten,omitempty"` // embed flat

EmbeddableStruct2 `msg:",omitempty"` // embed non-flat

AArrayInt [5]int `msg:",omitempty"` // not supported

ATime time.Time `msg:",omitempty"`
}
65 changes: 65 additions & 0 deletions _generated/omitempty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,71 @@ func TestOmitEmpty0(t *testing.T) {
}
}

func TestOmitEmptyNoNames(t *testing.T) {
var s string

var oe0a OmitEmptyNoName

s = mustEncodeToJSON(&oe0a)
if s != `{"AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` {
t.Errorf("wrong result: %s", s)
}

var oe0b OmitEmptyNoName
oe0b.AString = "teststr"
s = mustEncodeToJSON(&oe0b)
if s != `{"AString":"teststr","AUnnamedStruct":{},"AArrayInt":[0,0,0,0,0]}` {
t.Errorf("wrong result: %s", s)
}

// more than 15 fields filled in
var oe0c OmitEmptyNoName
oe0c.ABool = true
oe0c.AInt = 1
oe0c.AInt8 = 1
oe0c.AInt16 = 1
oe0c.AInt32 = 1
oe0c.AInt64 = 1
oe0c.AUint = 1
oe0c.AUint8 = 1
oe0c.AUint16 = 1
oe0c.AUint32 = 1
oe0c.AUint64 = 1
oe0c.AFloat32 = 1
oe0c.AFloat64 = 1
oe0c.AComplex64 = complex(1, 1)
oe0c.AComplex128 = complex(1, 1)
oe0c.AString = "test"
oe0c.ANamedBool = true
oe0c.ANamedInt = 1
oe0c.ANamedFloat64 = 1

var buf bytes.Buffer
en := msgp.NewWriter(&buf)
err := oe0c.EncodeMsg(en)
if err != nil {
t.Fatal(err)
}
en.Flush()
de := msgp.NewReader(&buf)
var oe0d OmitEmptyNoName
err = oe0d.DecodeMsg(de)
if err != nil {
t.Fatal(err)
}

// spot check some fields
if oe0c.AFloat32 != oe0d.AFloat32 {
t.Fail()
}
if oe0c.ANamedBool != oe0d.ANamedBool {
t.Fail()
}
if oe0c.AInt64 != oe0d.AInt64 {
t.Fail()
}
}

// TestOmitEmptyHalfFull tests mixed omitempty and not
func TestOmitEmptyHalfFull(t *testing.T) {
var s string
Expand Down
6 changes: 5 additions & 1 deletion parse/getast.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,11 @@ func (fs *FileSet) getField(f *ast.Field) []gen.StructField {
sf[0].FieldElem = ex
if sf[0].FieldTag == "" {
sf[0].FieldTag = sf[0].FieldName
sf[0].FieldTagParts = []string{sf[0].FieldName}
if len(sf[0].FieldTagParts) <= 1 {
sf[0].FieldTagParts = []string{sf[0].FieldTag}
} else {
sf[0].FieldTagParts = append([]string{sf[0].FieldName}, sf[0].FieldTagParts[1:]...)
}
}

// validate extension
Expand Down

0 comments on commit cde6e95

Please sign in to comment.