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 hash calculation based on proto.Struct #1318

Merged
merged 5 commits into from
Sep 10, 2019
Merged

Conversation

krhubert
Copy link
Contributor

@krhubert krhubert commented Sep 9, 2019

close #1315

@krhubert krhubert added the bug Something isn't working label Sep 9, 2019
@krhubert krhubert added this to the next milestone Sep 9, 2019
@krhubert krhubert self-assigned this Sep 9, 2019
Co-Authored-By: Nicolas Mahé <nicolas@mesg.com>
// NOTE: structhash will allow to process all interface types.
// gogo/protobuf is not able to set tags for directly oneof interface.
// see: https://github.com/gogo/protobuf/issues/623
{
Copy link
Member

@NicolasMahe NicolasMahe Sep 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another problem, the following is returning {a:{b:1}}:

Suggested change
{
{
struct {
a interface{}
}{
struct {
b interface{}
}{
b: 1,
},
},
"{a:{}}",
},
{

Copy link
Member

@NicolasMahe NicolasMahe Sep 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solution, replace in structhash.go line 105 by:

- if to.name == "" && reflect.Zero(sf.Type).Kind() == reflect.Interface {
+ if to.name == "" && v.Field(i).Kind() == reflect.Interface && v.Field(i).Elem().Kind() == reflect.Struct {

It will only continue if the field is defined as type interface and has as "real" type Struct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is how it interface works. It's not a bug, it done design.
So let's break it down:

a struct is passed with a interface{] fileds which has no tag.

A struct is serialized and a field is serialized because it's an interface.

Then interface{} has struct inside. That struct is serialized because it's not a field of any struct, but rather the object (interface value). The struct contains b fields which is an interface so it's serialized and interface value contains an integer. So the final output should be {a:{b:1}}

Copy link
Member

@NicolasMahe NicolasMahe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test line 60 is wrong:

		{
			struct {
				a int `hash:"omitempty"`
			}{1},
			"{}",
		},

it should returns {a:1}

Solution:
Replace hash:"omitempty" by hash:"name:a,omitempty"

So any field without an explicit hash name is discarded?

@krhubert
Copy link
Contributor Author

krhubert commented Sep 10, 2019

Test line 60 is wrong:

It's not. Field a has no name in the tag, only omitempty and a is not an interface so serialize should return an empty struct.

@NicolasMahe NicolasMahe mentioned this pull request Sep 11, 2019
@NicolasMahe NicolasMahe added the release:fix Pull requests that fix something label Sep 11, 2019
@NicolasMahe NicolasMahe changed the title Fix hash calculation based on proto.Structs Fix hash calculation based on proto.Struct Sep 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working release:fix Pull requests that fix something
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Hash calculation based on proto.Structs
3 participants