Skip to content

Fix hash calculation based on proto.Struct#1318

Merged
NicolasMahe merged 5 commits intodevfrom
fix/struct-hash-calc
Sep 10, 2019
Merged

Fix hash calculation based on proto.Struct#1318
NicolasMahe merged 5 commits intodevfrom
fix/struct-hash-calc

Conversation

@krhubert
Copy link
Copy Markdown
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
@krhubert krhubert force-pushed the fix/struct-hash-calc branch from 0919511 to c47da2f Compare September 9, 2019 13:03
Comment thread hash/structhash/structhash.go
Comment thread protobuf/types/struct.proto
Comment thread protobuf/types/struct.proto
Comment thread hash/structhash/structhash_test.go
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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
Copy Markdown
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