vendor: github.com/mitchellh/hashstructure v1.0.0
This commit is contained in:
parent
e0841f73b3
commit
12ac212611
2
go.mod
2
go.mod
|
@ -100,7 +100,7 @@ require (
|
||||||
github.com/mitchellh/go-homedir v1.0.0
|
github.com/mitchellh/go-homedir v1.0.0
|
||||||
github.com/mitchellh/go-linereader v0.0.0-20141013185533-07bab5fdd958
|
github.com/mitchellh/go-linereader v0.0.0-20141013185533-07bab5fdd958
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0
|
github.com/mitchellh/go-wordwrap v1.0.0
|
||||||
github.com/mitchellh/hashstructure v0.0.0-20160209213820-6b17d669fac5
|
github.com/mitchellh/hashstructure v1.0.0
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49
|
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49
|
||||||
github.com/mitchellh/panicwrap v0.0.0-20161208170302-ba9e1a65e0f7
|
github.com/mitchellh/panicwrap v0.0.0-20161208170302-ba9e1a65e0f7
|
||||||
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
|
github.com/mitchellh/prefixedio v0.0.0-20151214002211-6e6954073784
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -239,8 +239,8 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.
|
||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
|
||||||
github.com/mitchellh/hashstructure v0.0.0-20160209213820-6b17d669fac5 h1:h+4fp6yIoLPf/K2egDK3kvYM2zqb28gJIWWMiDzBdKM=
|
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
|
||||||
github.com/mitchellh/hashstructure v0.0.0-20160209213820-6b17d669fac5/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49 h1:kaWdlw4YogwkDl8CG+/VxhXkrL9uz3n1D9QBC2pEGLE=
|
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49 h1:kaWdlw4YogwkDl8CG+/VxhXkrL9uz3n1D9QBC2pEGLE=
|
||||||
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/mitchellh/panicwrap v0.0.0-20161208170302-ba9e1a65e0f7 h1:+PBI9A4rLQJlch3eQI/RkTY2HzX+bl2lPUf3goenBxs=
|
github.com/mitchellh/panicwrap v0.0.0-20161208170302-ba9e1a65e0f7 h1:+PBI9A4rLQJlch3eQI/RkTY2HzX+bl2lPUf3goenBxs=
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# hashstructure
|
# hashstructure [![GoDoc](https://godoc.org/github.com/mitchellh/hashstructure?status.svg)](https://godoc.org/github.com/mitchellh/hashstructure)
|
||||||
|
|
||||||
hashstructure is a Go library for creating a unique hash value
|
hashstructure is a Go library for creating a unique hash value
|
||||||
for arbitrary values in Go.
|
for arbitrary values in Go.
|
||||||
|
@ -20,6 +20,9 @@ sending data across the network, caching values locally (de-dup), and so on.
|
||||||
* Optionally specify a custom hash function to optimize for speed, collision
|
* Optionally specify a custom hash function to optimize for speed, collision
|
||||||
avoidance for your data set, etc.
|
avoidance for your data set, etc.
|
||||||
|
|
||||||
|
* Optionally hash the output of `.String()` on structs that implement fmt.Stringer,
|
||||||
|
allowing effective hashing of time.Time
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Standard `go get`:
|
Standard `go get`:
|
||||||
|
@ -34,28 +37,29 @@ For usage and examples see the [Godoc](http://godoc.org/github.com/mitchellh/has
|
||||||
|
|
||||||
A quick code example is shown below:
|
A quick code example is shown below:
|
||||||
|
|
||||||
|
```go
|
||||||
|
type ComplexStruct struct {
|
||||||
|
Name string
|
||||||
|
Age uint
|
||||||
|
Metadata map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
type ComplexStruct struct {
|
v := ComplexStruct{
|
||||||
Name string
|
Name: "mitchellh",
|
||||||
Age uint
|
Age: 64,
|
||||||
Metadata map[string]interface{}
|
Metadata: map[string]interface{}{
|
||||||
}
|
"car": true,
|
||||||
|
"location": "California",
|
||||||
|
"siblings": []string{"Bob", "John"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
v := ComplexStruct{
|
hash, err := hashstructure.Hash(v, nil)
|
||||||
Name: "mitchellh",
|
if err != nil {
|
||||||
Age: 64,
|
panic(err)
|
||||||
Metadata: map[string]interface{}{
|
}
|
||||||
"car": true,
|
|
||||||
"location": "California",
|
|
||||||
"siblings": []string{"Bob", "John"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
hash, err := hashstructure.Hash(v, nil)
|
fmt.Printf("%d", hash)
|
||||||
if err != nil {
|
// Output:
|
||||||
panic(err)
|
// 2307517237273902113
|
||||||
}
|
```
|
||||||
|
|
||||||
fmt.Printf("%d", hash)
|
|
||||||
// Output:
|
|
||||||
// 2307517237273902113
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
module github.com/mitchellh/hashstructure
|
|
@ -8,6 +8,16 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// ErrNotStringer is returned when there's an error with hash:"string"
|
||||||
|
type ErrNotStringer struct {
|
||||||
|
Field string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error implements error for ErrNotStringer
|
||||||
|
func (ens *ErrNotStringer) Error() string {
|
||||||
|
return fmt.Sprintf("hashstructure: %s has hash:\"string\" set, but does not implement fmt.Stringer", ens.Field)
|
||||||
|
}
|
||||||
|
|
||||||
// HashOptions are options that are available for hashing.
|
// HashOptions are options that are available for hashing.
|
||||||
type HashOptions struct {
|
type HashOptions struct {
|
||||||
// Hasher is the hash function to use. If this isn't set, it will
|
// Hasher is the hash function to use. If this isn't set, it will
|
||||||
|
@ -17,12 +27,18 @@ type HashOptions struct {
|
||||||
// TagName is the struct tag to look at when hashing the structure.
|
// TagName is the struct tag to look at when hashing the structure.
|
||||||
// By default this is "hash".
|
// By default this is "hash".
|
||||||
TagName string
|
TagName string
|
||||||
|
|
||||||
|
// ZeroNil is flag determining if nil pointer should be treated equal
|
||||||
|
// to a zero value of pointed type. By default this is false.
|
||||||
|
ZeroNil bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hash returns the hash value of an arbitrary value.
|
// Hash returns the hash value of an arbitrary value.
|
||||||
//
|
//
|
||||||
// If opts is nil, then default options will be used. See HashOptions
|
// If opts is nil, then default options will be used. See HashOptions
|
||||||
// for the default values.
|
// for the default values. The same *HashOptions value cannot be used
|
||||||
|
// concurrently. None of the values within a *HashOptions struct are
|
||||||
|
// safe to read/write while hashing is being done.
|
||||||
//
|
//
|
||||||
// Notes on the value:
|
// Notes on the value:
|
||||||
//
|
//
|
||||||
|
@ -41,11 +57,14 @@ type HashOptions struct {
|
||||||
//
|
//
|
||||||
// The available tag values are:
|
// The available tag values are:
|
||||||
//
|
//
|
||||||
// * "ignore" - The field will be ignored and not affect the hash code.
|
// * "ignore" or "-" - The field will be ignored and not affect the hash code.
|
||||||
//
|
//
|
||||||
// * "set" - The field will be treated as a set, where ordering doesn't
|
// * "set" - The field will be treated as a set, where ordering doesn't
|
||||||
// affect the hash code. This only works for slices.
|
// affect the hash code. This only works for slices.
|
||||||
//
|
//
|
||||||
|
// * "string" - The field will be hashed as a string, only works when the
|
||||||
|
// field implements fmt.Stringer
|
||||||
|
//
|
||||||
func Hash(v interface{}, opts *HashOptions) (uint64, error) {
|
func Hash(v interface{}, opts *HashOptions) (uint64, error) {
|
||||||
// Create default options
|
// Create default options
|
||||||
if opts == nil {
|
if opts == nil {
|
||||||
|
@ -63,15 +82,17 @@ func Hash(v interface{}, opts *HashOptions) (uint64, error) {
|
||||||
|
|
||||||
// Create our walker and walk the structure
|
// Create our walker and walk the structure
|
||||||
w := &walker{
|
w := &walker{
|
||||||
h: opts.Hasher,
|
h: opts.Hasher,
|
||||||
tag: opts.TagName,
|
tag: opts.TagName,
|
||||||
|
zeronil: opts.ZeroNil,
|
||||||
}
|
}
|
||||||
return w.visit(reflect.ValueOf(v), nil)
|
return w.visit(reflect.ValueOf(v), nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type walker struct {
|
type walker struct {
|
||||||
h hash.Hash64
|
h hash.Hash64
|
||||||
tag string
|
tag string
|
||||||
|
zeronil bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type visitOpts struct {
|
type visitOpts struct {
|
||||||
|
@ -84,6 +105,8 @@ type visitOpts struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
|
t := reflect.TypeOf(0)
|
||||||
|
|
||||||
// Loop since these can be wrapped in multiple layers of pointers
|
// Loop since these can be wrapped in multiple layers of pointers
|
||||||
// and interfaces.
|
// and interfaces.
|
||||||
for {
|
for {
|
||||||
|
@ -96,6 +119,9 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if v.Kind() == reflect.Ptr {
|
if v.Kind() == reflect.Ptr {
|
||||||
|
if w.zeronil {
|
||||||
|
t = v.Type().Elem()
|
||||||
|
}
|
||||||
v = reflect.Indirect(v)
|
v = reflect.Indirect(v)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -105,8 +131,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
|
|
||||||
// If it is nil, treat it like a zero.
|
// If it is nil, treat it like a zero.
|
||||||
if !v.IsValid() {
|
if !v.IsValid() {
|
||||||
var tmp int8
|
v = reflect.Zero(t)
|
||||||
v = reflect.ValueOf(tmp)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Binary writing can use raw ints, we have to convert to
|
// Binary writing can use raw ints, we have to convert to
|
||||||
|
@ -189,8 +214,8 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
return h, nil
|
return h, nil
|
||||||
|
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
var include Includable
|
|
||||||
parent := v.Interface()
|
parent := v.Interface()
|
||||||
|
var include Includable
|
||||||
if impl, ok := parent.(Includable); ok {
|
if impl, ok := parent.(Includable); ok {
|
||||||
include = impl
|
include = impl
|
||||||
}
|
}
|
||||||
|
@ -203,7 +228,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
|
|
||||||
l := v.NumField()
|
l := v.NumField()
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
if v := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
if innerV := v.Field(i); v.CanSet() || t.Field(i).Name != "_" {
|
||||||
var f visitFlag
|
var f visitFlag
|
||||||
fieldType := t.Field(i)
|
fieldType := t.Field(i)
|
||||||
if fieldType.PkgPath != "" {
|
if fieldType.PkgPath != "" {
|
||||||
|
@ -212,14 +237,25 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tag := fieldType.Tag.Get(w.tag)
|
tag := fieldType.Tag.Get(w.tag)
|
||||||
if tag == "ignore" {
|
if tag == "ignore" || tag == "-" {
|
||||||
// Ignore this field
|
// Ignore this field
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if string is set, use the string value
|
||||||
|
if tag == "string" {
|
||||||
|
if impl, ok := innerV.Interface().(fmt.Stringer); ok {
|
||||||
|
innerV = reflect.ValueOf(impl.String())
|
||||||
|
} else {
|
||||||
|
return 0, &ErrNotStringer{
|
||||||
|
Field: v.Type().Field(i).Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check if we implement includable and check it
|
// Check if we implement includable and check it
|
||||||
if include != nil {
|
if include != nil {
|
||||||
incl, err := include.HashInclude(fieldType.Name, v)
|
incl, err := include.HashInclude(fieldType.Name, innerV)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
@ -238,7 +274,7 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vh, err := w.visit(v, &visitOpts{
|
vh, err := w.visit(innerV, &visitOpts{
|
||||||
Flags: f,
|
Flags: f,
|
||||||
Struct: parent,
|
Struct: parent,
|
||||||
StructField: fieldType.Name,
|
StructField: fieldType.Name,
|
||||||
|
@ -289,7 +325,6 @@ func (w *walker) visit(v reflect.Value, opts *visitOpts) (uint64, error) {
|
||||||
return 0, fmt.Errorf("unknown kind to hash: %s", k)
|
return 0, fmt.Errorf("unknown kind to hash: %s", k)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 {
|
func hashUpdateOrdered(h hash.Hash64, a, b uint64) uint64 {
|
||||||
|
|
|
@ -473,7 +473,7 @@ github.com/mitchellh/go-linereader
|
||||||
github.com/mitchellh/go-testing-interface
|
github.com/mitchellh/go-testing-interface
|
||||||
# github.com/mitchellh/go-wordwrap v1.0.0
|
# github.com/mitchellh/go-wordwrap v1.0.0
|
||||||
github.com/mitchellh/go-wordwrap
|
github.com/mitchellh/go-wordwrap
|
||||||
# github.com/mitchellh/hashstructure v0.0.0-20160209213820-6b17d669fac5
|
# github.com/mitchellh/hashstructure v1.0.0
|
||||||
github.com/mitchellh/hashstructure
|
github.com/mitchellh/hashstructure
|
||||||
# github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49
|
# github.com/mitchellh/mapstructure v0.0.0-20170307201123-53818660ed49
|
||||||
github.com/mitchellh/mapstructure
|
github.com/mitchellh/mapstructure
|
||||||
|
|
Loading…
Reference in New Issue