From 7c8cdd1a9a8b1b327c4519c23ae99db59a1c619a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Tue, 30 Jul 2024 12:07:27 +0200 Subject: [PATCH] Remove the FormatV1/FormatV2 option This is a new fork so we can start fresh. --- README.md | 11 +-------- hashstructure.go | 43 +++++----------------------------- hashstructure_examples_test.go | 29 +---------------------- hashstructure_test.go | 38 ++++++++++++++---------------- 4 files changed, 26 insertions(+), 95 deletions(-) diff --git a/README.md b/README.md index 5e50639..054586a 100644 --- a/README.md +++ b/README.md @@ -33,15 +33,6 @@ Standard `go get`: $ go get github.com/gohugoio/hashstructure ``` -**Note on v2:** It is highly recommended you use the "v2" release since this -fixes some significant hash collisions issues from v1. In practice, we used -v1 for many years in real projects at HashiCorp and never had issues, but it -is highly dependent on the shape of the data you're hashing and how you use -those hashes. - -When using v2+, you can still generate weaker v1 hashes by using the -`FormatV1` format when calling `Hash`. - ## Usage & Example For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/hashstructure). @@ -65,7 +56,7 @@ v := ComplexStruct{ }, } -hash, err := hashstructure.Hash(v, hashstructure.FormatV2, nil) +hash, err := hashstructure.Hash(v, nil) if err != nil { panic(err) } diff --git a/hashstructure.go b/hashstructure.go index a734ed6..651f840 100644 --- a/hashstructure.go +++ b/hashstructure.go @@ -39,25 +39,6 @@ type HashOptions struct { UseStringer bool } -// Format specifies the hashing process used. Different formats typically -// generate different hashes for the same value and have different properties. -type Format uint - -const ( - // To disallow the zero value - formatInvalid Format = iota - - // FormatV1 is the format used in v1.x of this library. This has the - // downsides noted in issue #18 but allows simultaneous v1/v2 usage. - FormatV1 - - // FormatV2 is the current recommended format and fixes the issues - // noted in FormatV1. - FormatV2 - - formatMax // so we can easily find the end -) - // Hash returns the hash value of an arbitrary value. // // If opts is nil, then default options will be used. See HashOptions @@ -94,12 +75,7 @@ const ( // // - "string" - The field will be hashed as a string, only works when the // field implements fmt.Stringer -func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) { - // Validate our format - if format <= formatInvalid || format >= formatMax { - return 0, &ErrFormat{} - } - +func Hash(v interface{}, opts *HashOptions) (uint64, error) { // Create default options if opts == nil { opts = &HashOptions{} @@ -116,7 +92,6 @@ 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, @@ -128,7 +103,6 @@ func Hash(v interface{}, format Format, opts *HashOptions) (uint64, error) { } type walker struct { - format Format h hash.Hash64 tag string zeronil bool @@ -267,10 +241,8 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { h = hashUpdateUnordered(h, fieldHash) } - if w.format != FormatV1 { - // Important: read the docs for hashFinishUnordered - h = hashFinishUnordered(w.h, h) - } + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) return h, nil @@ -373,11 +345,8 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { fieldHash := hashUpdateOrdered(w.h, kh, vh) h = hashUpdateUnordered(h, fieldHash) } - - if w.format != FormatV1 { - // Important: read the docs for hashFinishUnordered - h = hashFinishUnordered(w.h, h) - } + // Important: read the docs for hashFinishUnordered + h = hashFinishUnordered(w.h, h) } return h, nil @@ -405,7 +374,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) { } } - if set && w.format != FormatV1 { + if set { // Important: read the docs for hashFinishUnordered h = hashFinishUnordered(w.h, h) } diff --git a/hashstructure_examples_test.go b/hashstructure_examples_test.go index b598df1..3ae925a 100644 --- a/hashstructure_examples_test.go +++ b/hashstructure_examples_test.go @@ -21,7 +21,7 @@ func ExampleHash() { }, } - hash, err := Hash(v, FormatV2, nil) + hash, err := Hash(v, nil) if err != nil { panic(err) } @@ -30,30 +30,3 @@ func ExampleHash() { // Output: // 1839806922502695369 } - -func ExampleHash_v1() { - type ComplexStruct struct { - Name string - Age uint - Metadata map[string]interface{} - } - - v := ComplexStruct{ - Name: "mitchellh", - Age: 64, - Metadata: map[string]interface{}{ - "car": true, - "location": "California", - "siblings": []string{"Bob", "John"}, - }, - } - - hash, err := Hash(v, FormatV1, nil) - if err != nil { - panic(err) - } - - fmt.Printf("%d", hash) - // Output: - // 6691276962590150517 -} diff --git a/hashstructure_test.go b/hashstructure_test.go index e0607a8..0b35af2 100644 --- a/hashstructure_test.go +++ b/hashstructure_test.go @@ -7,8 +7,6 @@ import ( "time" ) -var testFormat = FormatV2 - func TestHash_identity(t *testing.T) { cases := []interface{}{ nil, @@ -42,7 +40,7 @@ func TestHash_identity(t *testing.T) { // in the runtime in terms of ordering. valuelist := make([]uint64, 100) for i := range valuelist { - v, err := Hash(tc, testFormat, nil) + v, err := Hash(tc, nil) if err != nil { t.Fatalf("Error: %s\n\n%#v", err, tc) } @@ -171,13 +169,13 @@ func TestHash_equal(t *testing.T) { for i, tc := range cases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { t.Logf("Hashing: %#v", tc.One) - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) t.Logf("Result: %d", one) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } t.Logf("Hashing: %#v", tc.Two) - two, err := Hash(tc.Two, testFormat, nil) + two, err := Hash(tc.Two, nil) t.Logf("Result: %d", two) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) @@ -271,11 +269,11 @@ func TestHash_equalIgnore(t *testing.T) { } for _, tc := range cases { - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } - two, err := Hash(tc.Two, testFormat, nil) + two, err := Hash(tc.Two, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) } @@ -327,7 +325,7 @@ func TestHash_stringTagError(t *testing.T) { } for _, tc := range cases { - _, err := Hash(tc.Test, testFormat, nil) + _, err := Hash(tc.Test, nil) if err != nil { if ens, ok := err.(*ErrNotStringer); ok { if ens.Field != tc.Field { @@ -400,11 +398,11 @@ func TestHash_equalNil(t *testing.T) { } for _, tc := range cases { - one, err := Hash(tc.One, testFormat, &HashOptions{ZeroNil: tc.ZeroNil}) + one, err := Hash(tc.One, &HashOptions{ZeroNil: tc.ZeroNil}) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } - two, err := Hash(tc.Two, testFormat, &HashOptions{ZeroNil: tc.ZeroNil}) + two, err := Hash(tc.Two, &HashOptions{ZeroNil: tc.ZeroNil}) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) } @@ -445,11 +443,11 @@ func TestHash_equalSet(t *testing.T) { } for _, tc := range cases { - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } - two, err := Hash(tc.Two, testFormat, nil) + two, err := Hash(tc.Two, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) } @@ -491,11 +489,11 @@ func TestHash_includable(t *testing.T) { } for _, tc := range cases { - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } - two, err := Hash(tc.Two, testFormat, nil) + two, err := Hash(tc.Two, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) } @@ -542,11 +540,11 @@ func TestHash_ignoreZeroValue(t *testing.T) { } for _, tc := range cases { - hashA, err := Hash(structA, testFormat, &HashOptions{IgnoreZeroValue: tc.IgnoreZeroValue}) + hashA, err := Hash(structA, &HashOptions{IgnoreZeroValue: tc.IgnoreZeroValue}) if err != nil { t.Fatalf("Failed to hash %#v: %s", structA, err) } - hashB, err := Hash(structB, testFormat, &HashOptions{IgnoreZeroValue: tc.IgnoreZeroValue}) + hashB, err := Hash(structB, &HashOptions{IgnoreZeroValue: tc.IgnoreZeroValue}) if err != nil { t.Fatalf("Failed to hash %#v: %s", structB, err) } @@ -581,11 +579,11 @@ func TestHash_includableMap(t *testing.T) { } for _, tc := range cases { - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.One, err) } - two, err := Hash(tc.Two, testFormat, nil) + two, err := Hash(tc.Two, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) } @@ -643,7 +641,7 @@ func TestHash_hashable(t *testing.T) { for i, tc := range cases { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { - one, err := Hash(tc.One, testFormat, nil) + one, err := Hash(tc.One, nil) if tc.Err != "" { if err == nil { t.Fatal("expected error") @@ -659,7 +657,7 @@ func TestHash_hashable(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, nil) if err != nil { t.Fatalf("Failed to hash %#v: %s", tc.Two, err) }