Misc number fixes

* Allow strings/json.Number with just zeroes after the decmial point to be converted to integer`
* Allow nil in ToFloat*
* Remove some test duplication
* replace testify with quicktest
* Enable integer and float conversion of time.Weekday values

Fixes #139
Fixes #141
This commit is contained in:
Bjørn Erik Pedersen 2022-05-11 10:35:17 +02:00
parent 36a7d5b5b8
commit 2b0eb0f724
5 changed files with 507 additions and 838 deletions

View File

@ -10,7 +10,7 @@ jobs:
build: build:
strategy: strategy:
matrix: matrix:
go-version: [1.17.x, 1.18.x] go-version: [1.16.x, 1.17.x, 1.18.x]
os: [ubuntu-latest, windows-latest] os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
steps: steps:

File diff suppressed because it is too large Load Diff

305
caste.go
View File

@ -35,7 +35,7 @@ func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.
case string: case string:
return StringToDateInDefaultLocation(v, location) return StringToDateInDefaultLocation(v, location)
case json.Number: case json.Number:
s, err1 := v.Int64() s, err1 := ToInt64E(v)
if err1 != nil { if err1 != nil {
return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i) return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i)
} }
@ -105,7 +105,7 @@ func ToBoolE(i interface{}) (bool, error) {
case string: case string:
return strconv.ParseBool(i.(string)) return strconv.ParseBool(i.(string))
case json.Number: case json.Number:
v, err := b.Int64() v, err := ToInt64E(b)
if err == nil { if err == nil {
return v != 0, nil return v != 0, nil
} }
@ -119,13 +119,16 @@ func ToBoolE(i interface{}) (bool, error) {
func ToFloat64E(i interface{}) (float64, error) { func ToFloat64E(i interface{}) (float64, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return float64(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case float64: case float64:
return s, nil return s, nil
case float32: case float32:
return float64(s), nil return float64(s), nil
case int:
return float64(s), nil
case int64: case int64:
return float64(s), nil return float64(s), nil
case int32: case int32:
@ -161,6 +164,8 @@ func ToFloat64E(i interface{}) (float64, error) {
return 1, nil return 1, nil
} }
return 0, nil return 0, nil
case nil:
return 0, nil
default: default:
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
} }
@ -170,13 +175,16 @@ func ToFloat64E(i interface{}) (float64, error) {
func ToFloat32E(i interface{}) (float32, error) { func ToFloat32E(i interface{}) (float32, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return float32(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case float64: case float64:
return float32(s), nil return float32(s), nil
case float32: case float32:
return s, nil return s, nil
case int:
return float32(s), nil
case int64: case int64:
return float32(s), nil return float32(s), nil
case int32: case int32:
@ -212,6 +220,8 @@ func ToFloat32E(i interface{}) (float32, error) {
return 1, nil return 1, nil
} }
return 0, nil return 0, nil
case nil:
return 0, nil
default: default:
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
} }
@ -221,9 +231,12 @@ func ToFloat32E(i interface{}) (float32, error) {
func ToInt64E(i interface{}) (int64, error) { func ToInt64E(i interface{}) (int64, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return int64(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case int:
return int64(s), nil
case int64: case int64:
return s, nil return s, nil
case int32: case int32:
@ -247,17 +260,13 @@ func ToInt64E(i interface{}) (int64, error) {
case float32: case float32:
return int64(s), nil return int64(s), nil
case string: case string:
v, err := strconv.ParseInt(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil { if err == nil {
return v, nil return v, nil
} }
return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i)
case json.Number: case json.Number:
v, err := s.Int64() return ToInt64E(string(s))
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i)
case bool: case bool:
if s { if s {
return 1, nil return 1, nil
@ -274,9 +283,12 @@ func ToInt64E(i interface{}) (int64, error) {
func ToInt32E(i interface{}) (int32, error) { func ToInt32E(i interface{}) (int32, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return int32(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case int:
return int32(s), nil
case int64: case int64:
return int32(s), nil return int32(s), nil
case int32: case int32:
@ -300,17 +312,13 @@ func ToInt32E(i interface{}) (int32, error) {
case float32: case float32:
return int32(s), nil return int32(s), nil
case string: case string:
v, err := strconv.ParseInt(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil { if err == nil {
return int32(v), nil return int32(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i)
case json.Number: case json.Number:
v, err := s.Int64() return ToInt32E(string(s))
if err == nil {
return int32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i)
case bool: case bool:
if s { if s {
return 1, nil return 1, nil
@ -327,9 +335,12 @@ func ToInt32E(i interface{}) (int32, error) {
func ToInt16E(i interface{}) (int16, error) { func ToInt16E(i interface{}) (int16, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return int16(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case int:
return int16(s), nil
case int64: case int64:
return int16(s), nil return int16(s), nil
case int32: case int32:
@ -353,17 +364,13 @@ func ToInt16E(i interface{}) (int16, error) {
case float32: case float32:
return int16(s), nil return int16(s), nil
case string: case string:
v, err := strconv.ParseInt(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil { if err == nil {
return int16(v), nil return int16(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i)
case json.Number: case json.Number:
v, err := s.Int64() return ToInt16E(string(s))
if err == nil {
return int16(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i)
case bool: case bool:
if s { if s {
return 1, nil return 1, nil
@ -380,9 +387,12 @@ func ToInt16E(i interface{}) (int16, error) {
func ToInt8E(i interface{}) (int8, error) { func ToInt8E(i interface{}) (int8, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return int8(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case int:
return int8(s), nil
case int64: case int64:
return int8(s), nil return int8(s), nil
case int32: case int32:
@ -406,17 +416,13 @@ func ToInt8E(i interface{}) (int8, error) {
case float32: case float32:
return int8(s), nil return int8(s), nil
case string: case string:
v, err := strconv.ParseInt(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil { if err == nil {
return int8(v), nil return int8(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i)
case json.Number: case json.Number:
v, err := s.Int64() return ToInt8E(string(s))
if err == nil {
return int8(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i)
case bool: case bool:
if s { if s {
return 1, nil return 1, nil
@ -433,9 +439,12 @@ func ToInt8E(i interface{}) (int8, error) {
func ToIntE(i interface{}) (int, error) { func ToIntE(i interface{}) (int, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
return intv, nil
}
switch s := i.(type) { switch s := i.(type) {
case int:
return s, nil
case int64: case int64:
return int(s), nil return int(s), nil
case int32: case int32:
@ -459,17 +468,13 @@ func ToIntE(i interface{}) (int, error) {
case float32: case float32:
return int(s), nil return int(s), nil
case string: case string:
v, err := strconv.ParseInt(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil { if err == nil {
return int(v), nil return int(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i) return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i)
case json.Number: case json.Number:
v, err := s.Int64() return ToIntE(string(s))
if err == nil {
return int(v), nil
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i)
case bool: case bool:
if s { if s {
return 1, nil return 1, nil
@ -486,27 +491,26 @@ func ToIntE(i interface{}) (int, error) {
func ToUintE(i interface{}) (uint, error) { func ToUintE(i interface{}) (uint, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
if intv < 0 {
return 0, errNegativeNotAllowed
}
return uint(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case string: case string:
v, err := strconv.ParseUint(s, 0, 0) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil {
return uint(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err)
case json.Number:
v, err := s.Int64()
if err == nil { if err == nil {
if v < 0 { if v < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
} }
return uint(v), nil return uint(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v to uint: %s", i, err) return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i)
case int: case json.Number:
if s < 0 { return ToUintE(string(s))
return 0, errNegativeNotAllowed
}
return uint(s), nil
case int64: case int64:
if s < 0 { if s < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
@ -563,27 +567,26 @@ func ToUintE(i interface{}) (uint, error) {
func ToUint64E(i interface{}) (uint64, error) { func ToUint64E(i interface{}) (uint64, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
if intv < 0 {
return 0, errNegativeNotAllowed
}
return uint64(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case string: case string:
v, err := strconv.ParseUint(s, 0, 64) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil {
return v, nil
}
return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err)
case json.Number:
v, err := s.Int64()
if err == nil { if err == nil {
if v < 0 { if v < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
} }
return uint64(v), nil return uint64(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v to uint64: %s", i, err) return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
case int: case json.Number:
if s < 0 { return ToUint64E(string(s))
return 0, errNegativeNotAllowed
}
return uint64(s), nil
case int64: case int64:
if s < 0 { if s < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
@ -640,27 +643,26 @@ func ToUint64E(i interface{}) (uint64, error) {
func ToUint32E(i interface{}) (uint32, error) { func ToUint32E(i interface{}) (uint32, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
if intv < 0 {
return 0, errNegativeNotAllowed
}
return uint32(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case string: case string:
v, err := strconv.ParseUint(s, 0, 32) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil {
return uint32(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err)
case json.Number:
v, err := s.Int64()
if err == nil { if err == nil {
if v < 0 { if v < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
} }
return uint32(v), nil return uint32(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v to uint32: %s", i, err) return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i)
case int: case json.Number:
if s < 0 { return ToUint32E(string(s))
return 0, errNegativeNotAllowed
}
return uint32(s), nil
case int64: case int64:
if s < 0 { if s < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
@ -717,27 +719,26 @@ func ToUint32E(i interface{}) (uint32, error) {
func ToUint16E(i interface{}) (uint16, error) { func ToUint16E(i interface{}) (uint16, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
if intv < 0 {
return 0, errNegativeNotAllowed
}
return uint16(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case string: case string:
v, err := strconv.ParseUint(s, 0, 16) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil {
return uint16(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err)
case json.Number:
v, err := s.Int64()
if err == nil { if err == nil {
if v < 0 { if v < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
} }
return uint16(v), nil return uint16(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v to uint16: %s", i, err) return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i)
case int: case json.Number:
if s < 0 { return ToUint16E(string(s))
return 0, errNegativeNotAllowed
}
return uint16(s), nil
case int64: case int64:
if s < 0 { if s < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
@ -794,27 +795,26 @@ func ToUint16E(i interface{}) (uint16, error) {
func ToUint8E(i interface{}) (uint8, error) { func ToUint8E(i interface{}) (uint8, error) {
i = indirect(i) i = indirect(i)
intv, ok := toInt(i)
if ok {
if intv < 0 {
return 0, errNegativeNotAllowed
}
return uint8(intv), nil
}
switch s := i.(type) { switch s := i.(type) {
case string: case string:
v, err := strconv.ParseUint(s, 0, 8) v, err := strconv.ParseInt(trimZeroDecimal(s), 0, 0)
if err == nil {
return uint8(v), nil
}
return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err)
case json.Number:
v, err := s.Int64()
if err == nil { if err == nil {
if v < 0 { if v < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
} }
return uint8(v), nil return uint8(v), nil
} }
return 0, fmt.Errorf("unable to cast %#v to uint8: %s", i, err) return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i)
case int: case json.Number:
if s < 0 { return ToUint8E(string(s))
return 0, errNegativeNotAllowed
}
return uint8(s), nil
case int64: case int64:
if s < 0 { if s < 0 {
return 0, errNegativeNotAllowed return 0, errNegativeNotAllowed
@ -1385,30 +1385,30 @@ func (f timeFormat) hasTimezone() bool {
var ( var (
timeFormats = []timeFormat{ timeFormats = []timeFormat{
timeFormat{time.RFC3339, timeFormatNumericTimezone}, {time.RFC3339, timeFormatNumericTimezone},
timeFormat{"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone
timeFormat{time.RFC1123Z, timeFormatNumericTimezone}, {time.RFC1123Z, timeFormatNumericTimezone},
timeFormat{time.RFC1123, timeFormatNamedTimezone}, {time.RFC1123, timeFormatNamedTimezone},
timeFormat{time.RFC822Z, timeFormatNumericTimezone}, {time.RFC822Z, timeFormatNumericTimezone},
timeFormat{time.RFC822, timeFormatNamedTimezone}, {time.RFC822, timeFormatNamedTimezone},
timeFormat{time.RFC850, timeFormatNamedTimezone}, {time.RFC850, timeFormatNamedTimezone},
timeFormat{"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String() {"2006-01-02 15:04:05.999999999 -0700 MST", timeFormatNumericAndNamedTimezone}, // Time.String()
timeFormat{"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon {"2006-01-02T15:04:05-0700", timeFormatNumericTimezone}, // RFC3339 without timezone hh:mm colon
timeFormat{"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon {"2006-01-02 15:04:05Z0700", timeFormatNumericTimezone}, // RFC3339 without T or timezone hh:mm colon
timeFormat{"2006-01-02 15:04:05", timeFormatNoTimezone}, {"2006-01-02 15:04:05", timeFormatNoTimezone},
timeFormat{time.ANSIC, timeFormatNoTimezone}, {time.ANSIC, timeFormatNoTimezone},
timeFormat{time.UnixDate, timeFormatNamedTimezone}, {time.UnixDate, timeFormatNamedTimezone},
timeFormat{time.RubyDate, timeFormatNumericTimezone}, {time.RubyDate, timeFormatNumericTimezone},
timeFormat{"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone},
timeFormat{"2006-01-02", timeFormatNoTimezone}, {"2006-01-02", timeFormatNoTimezone},
timeFormat{"02 Jan 2006", timeFormatNoTimezone}, {"02 Jan 2006", timeFormatNoTimezone},
timeFormat{"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone},
timeFormat{"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone},
timeFormat{time.Kitchen, timeFormatTimeOnly}, {time.Kitchen, timeFormatTimeOnly},
timeFormat{time.Stamp, timeFormatTimeOnly}, {time.Stamp, timeFormatTimeOnly},
timeFormat{time.StampMilli, timeFormatTimeOnly}, {time.StampMilli, timeFormatTimeOnly},
timeFormat{time.StampMicro, timeFormatTimeOnly}, {time.StampMicro, timeFormatTimeOnly},
timeFormat{time.StampNano, timeFormatTimeOnly}, {time.StampNano, timeFormatTimeOnly},
} }
) )
@ -1441,3 +1441,36 @@ func jsonStringToObject(s string, v interface{}) error {
data := []byte(s) data := []byte(s)
return json.Unmarshal(data, v) return json.Unmarshal(data, v)
} }
// toInt returns the int value of v if v or v's underlying type
// is an int.
// Note that this will return false for int64 etc. types.
func toInt(v interface{}) (int, bool) {
switch v := v.(type) {
case int:
return v, true
case time.Weekday:
return int(v), true
case time.Month:
return int(v), true
default:
return 0, false
}
}
func trimZeroDecimal(s string) string {
var foundZero bool
for i := len(s); i > 0; i-- {
switch s[i-1] {
case '.':
if foundZero {
return s[:i-1]
}
case '0':
foundZero = true
default:
return s
}
}
return s
}

12
go.mod
View File

@ -1,7 +1,13 @@
module github.com/spf13/cast module github.com/spf13/cast
go 1.18
require github.com/frankban/quicktest v1.14.3
require ( require (
github.com/davecgh/go-spew v1.1.1 // indirect github.com/google/go-cmp v0.5.7 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/kr/pretty v0.3.0 // indirect
github.com/stretchr/testify v1.2.2 github.com/kr/text v0.2.0 // indirect
github.com/rogpeppe/go-internal v1.6.1 // indirect
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 // indirect
) )

24
go.sum
View File

@ -1,6 +1,18 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=