Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
put the new functionality behind an opt
Browse files Browse the repository at this point in the history
  • Loading branch information
jpalawaga committed Oct 3, 2022
1 parent d3e61bc commit 8412676
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 20 deletions.
43 changes: 26 additions & 17 deletions hashstructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type HashOptions struct {
// precedence (meaning that if the type doesn't implement fmt.Stringer, we
// panic)
UseStringer bool

// StringIgnoredStructs will attempt to .String() a struct if all of the
// members of the struct are ignored for the purposes of hashing.
StringIgnoredStructs bool
}

// Format specifies the hashing process used. Different formats typically
Expand Down Expand Up @@ -116,25 +120,27 @@ func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) {

// Create our walker and walk the structure
w := &walker{
format: format,
h: opts.Hasher,
tag: opts.TagName,
zeronil: opts.ZeroNil,
ignorezerovalue: opts.IgnoreZeroValue,
sets: opts.SlicesAsSets,
stringer: opts.UseStringer,
format: format,
h: opts.Hasher,
tag: opts.TagName,
zeronil: opts.ZeroNil,
ignorezerovalue: opts.IgnoreZeroValue,
sets: opts.SlicesAsSets,
stringer: opts.UseStringer,
stringignoredstructs: opts.StringIgnoredStructs,
}
return w.visit(reflect.ValueOf(v), nil)
}

type walker struct {
format Format
h hash.Hash64
tag string
zeronil bool
ignorezerovalue bool
sets bool
stringer bool
format Format
h hash.Hash64
tag string
zeronil bool
ignorezerovalue bool
sets bool
stringer bool
stringignoredstructs bool
}

type visitOpts struct {
Expand Down Expand Up @@ -385,11 +391,14 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
}
}
// no fields involved in the hash! try and string instead.
if unhashedfields == l {
if impl, ok := v.Interface().(fmt.Stringer); ok {
if unhashedfields == l && w.stringignoredstructs {
if impl, ok := parent.(fmt.Stringer); ok {
w.h.Reset()
_, err := w.h.Write([]byte(impl.String()))
return w.h.Sum64(), err
if err != nil {
return 0, err
}
return w.h.Sum64(), nil
}
}

Expand Down
6 changes: 3 additions & 3 deletions hashstructure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -738,7 +738,7 @@ func (u Unexported) String() string {
return fmt.Sprintf("%d", u.n)
}

func TestHash_unexported_stringable(t *testing.T) {
func TestHash_StringIgnoredStructs(t *testing.T) {
cases := []struct {
One, Two interface{}
Match bool
Expand Down Expand Up @@ -784,7 +784,7 @@ func TestHash_unexported_stringable(t *testing.T) {

for i, tc := range cases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
one, err := Hash(tc.One, testFormat, &HashOptions{})
one, err := Hash(tc.One, testFormat, &HashOptions{StringIgnoredStructs: true})
if tc.Err != "" {
if err == nil {
t.Fatal("expected error")
Expand All @@ -800,7 +800,7 @@ func TestHash_unexported_stringable(t *testing.T) {
t.Fatalf("Failed to hash %#v: %s", tc.One, err)
}

two, err := Hash(tc.Two, testFormat, nil)
two, err := Hash(tc.Two, testFormat, &HashOptions{StringIgnoredStructs: true})
if err != nil {
t.Fatalf("Failed to hash %#v: %s", tc.Two, err)
}
Expand Down

0 comments on commit 8412676

Please sign in to comment.