Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix omitempty on aliased types #377

Merged
merged 2 commits into from
Oct 29, 2024

Conversation

klauspost
Copy link
Collaborator

@klauspost klauspost commented Oct 29, 2024

Instead of doing return, insert an if block to skip emitting zero fields.

This also allows the check to be inserted at any level.

Fixes #376

Emitted code:

// MarshalMsg implements msgp.Marshaler
func (z TypeSamples) MarshalMsg(b []byte) (o []byte, err error) {
	o = msgp.Require(b, z.Msgsize())
	o = msgp.AppendArrayHeader(o, uint32(len(z)))
	for zb0004 := range z {
		// check for omitted fields
		zb0001Len := uint32(2)
		var zb0001Mask uint8 /* 2 bits */
		_ = zb0001Mask
		if z[zb0004].K == 0 {
			zb0001Len--
			zb0001Mask |= 0x1
		}
		if z[zb0004].V == 0 {
			zb0001Len--
			zb0001Mask |= 0x2
		}
		// variable map header, size zb0001Len
		o = append(o, 0x80|uint8(zb0001Len))

		// skip if no fields are to be emitted
		if zb0001Len != 0 {
			if (zb0001Mask & 0x1) == 0 { // if not omitted
				// string "k"
				o = append(o, 0xa1, 0x6b)
				o = msgp.AppendUint32(o, z[zb0004].K)
			}
			if (zb0001Mask & 0x2) == 0 { // if not omitted
				// string "v"
				o = append(o, 0xa1, 0x76)
				o = msgp.AppendUint32(o, z[zb0004].V)
			}
		}
	}
	return
}

If only 1 field, the check is omitted (and there is similar behavior on clearomitted).

Instead of doing return, insert an if block to skip emitting zero fields.

This also allows the check to be inserted at any level.

Fixes tinylib#376

Emitted code:

```
// MarshalMsg implements msgp.Marshaler
func (z TypeSample) MarshalMsg(b []byte) (o []byte, err error) {
	o = msgp.Require(b, z.Msgsize())
	// check for omitted fields
	zb0001Len := uint32(2)
	var zb0001Mask uint8 /* 2 bits */
	_ = zb0001Mask
	if z.K == 0 {
		zb0001Len--
		zb0001Mask |= 0x1
	}
	if z.V == 0 {
		zb0001Len--
		zb0001Mask |= 0x2
	}
	// variable map header, size zb0001Len
	o = append(o, 0x80|uint8(zb0001Len))
	// Skip if no fields are to be emitted
	if zb0001Len != 0 {
		if (zb0001Mask & 0x1) == 0 { // if not omitted
			// string "k"
			o = append(o, 0xa1, 0x6b)
			o = msgp.AppendUint32(o, z.K)
		}
		if (zb0001Mask & 0x2) == 0 { // if not omitted
			// string "v"
			o = append(o, 0xa1, 0x76)
			o = msgp.AppendUint32(o, z.V)
		}
	}
	return
}
```

If only 1 field, the check is omitted (and there is similar behavior on clearomitted).
@klauspost klauspost merged commit 1de3898 into tinylib:master Oct 29, 2024
4 checks passed
@klauspost klauspost deleted the fix-omitempty-alias branch October 29, 2024 18:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Slice struct with all "omitempty" fields set to zero value ​​will generate wrong data
2 participants