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

Add "clearomitted" directive #373

Merged
merged 2 commits into from
Oct 22, 2024

Conversation

klauspost
Copy link
Collaborator

@klauspost klauspost commented Oct 21, 2024

Adds //msgp:clearomitted directive.

This will cause all omitempty and omitzero fields to be set to the zero value on Unmarshal and Decode, and the field wasn't present in the marshalled data.

This can be useful when de-serializing into reused objects, that can have values set for these, and we want to avoid clearing all fields, but also don't want existing fields to leak through.

Fields are tracked through a bit mask, and zeroed after the unmarshal loop, if no value has been written.

This does not affect marshaling.

DecodeMsg Example
// DecodeMsg implements msgp.Decodable
func (z *NamedStructCO) DecodeMsg(dc *msgp.Reader) (err error) {
	var field []byte
	_ = field
	var zb0001 uint32
	zb0001, err = dc.ReadMapHeader()
	if err != nil {
		err = msgp.WrapError(err)
		return
	}
	var zb0001Mask uint8 /* 2 bits */
	_ = zb0001Mask
	for zb0001 > 0 {
		zb0001--
		field, err = dc.ReadMapKeyPtr()
		if err != nil {
			err = msgp.WrapError(err)
			return
		}
		switch msgp.UnsafeString(field) {
		case "a":
			z.A, err = dc.ReadString()
			if err != nil {
				err = msgp.WrapError(err, "A")
				return
			}
			zb0001Mask |= 0x1
		case "b":
			z.B, err = dc.ReadString()
			if err != nil {
				err = msgp.WrapError(err, "B")
				return
			}
			zb0001Mask |= 0x2
		default:
			err = dc.Skip()
			if err != nil {
				err = msgp.WrapError(err)
				return
			}
		}
	}
	// Clear omitted fields.
	if zb0001Mask != 0x3 {
		if (zb0001Mask & 0x1) == 0 {
			z.A = ""
		}
		if (zb0001Mask & 0x2) == 0 {
			z.B = ""
		}
	}
	return
}
UnmarshalMsg Example
// UnmarshalMsg implements msgp.Unmarshaler
func (z *NamedStructCO) UnmarshalMsg(bts []byte) (o []byte, err error) {
	var field []byte
	_ = field
	var zb0001 uint32
	zb0001, bts, err = msgp.ReadMapHeaderBytes(bts)
	if err != nil {
		err = msgp.WrapError(err)
		return
	}
	var zb0001Mask uint8 /* 2 bits */
	_ = zb0001Mask
	for zb0001 > 0 {
		zb0001--
		field, bts, err = msgp.ReadMapKeyZC(bts)
		if err != nil {
			err = msgp.WrapError(err)
			return
		}
		switch msgp.UnsafeString(field) {
		case "a":
			z.A, bts, err = msgp.ReadStringBytes(bts)
			if err != nil {
				err = msgp.WrapError(err, "A")
				return
			}
			zb0001Mask |= 0x1
		case "b":
			z.B, bts, err = msgp.ReadStringBytes(bts)
			if err != nil {
				err = msgp.WrapError(err, "B")
				return
			}
			zb0001Mask |= 0x2
		default:
			bts, err = msgp.Skip(bts)
			if err != nil {
				err = msgp.WrapError(err)
				return
			}
		}
	}
	// Clear omitted fields.
	if zb0001Mask != 0x3 {
		if (zb0001Mask & 0x1) == 0 {
			z.A = ""
		}
		if (zb0001Mask & 0x2) == 0 {
			z.B = ""
		}
	}
	o = bts
	return
}

Adds `//msgp:clearomitted` directive.

This will cause all `omitempty` and `omitzero` fields to be set to the zero value on Unmarshal and Decode, and the field wasn't present in the marshalled data.

This can be useful when de-serializing into reused objects, that can have values set for these, and we want to avoid clearing all fields, but also don't want existing fields to leak through.

Fields are tracked through a bit mask, and zeroed after the unmarshal loop, if no value has been written.

This does not affect marshaling.
@klauspost klauspost requested a review from philhofer October 21, 2024 12:29
@klauspost
Copy link
Collaborator Author

Merging, but not publishing a release.

@klauspost klauspost merged commit 6da1c88 into tinylib:master Oct 22, 2024
4 checks passed
@klauspost klauspost deleted the add-clearomitted-directive branch October 22, 2024 08:43
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.

2 participants