diff --git a/.github/.editorconfig b/.github/.editorconfig new file mode 100644 index 0000000..0902c6a --- /dev/null +++ b/.github/.editorconfig @@ -0,0 +1,2 @@ +[{*.yml,*.yaml}] +indent_size = 2 diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..5153b81 --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,16 @@ +version: 2 + +updates: + - package-ecosystem: gomod + directory: / + labels: + - dependencies + schedule: + interval: daily + + - package-ecosystem: github-actions + directory: / + labels: + - dependencies + schedule: + interval: daily diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..e3501b2 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,34 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + +jobs: + build: + name: Build + runs-on: ${{ matrix.os }} + strategy: + # Fail fast is disabled because there are Go version specific features and tests + # that should be able to fail independently. + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest] + go-version: ['1.16', '1.17', '1.18', '1.19', '1.20'] + + steps: + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go }} + + - name: Checkout code + uses: actions/checkout@v3 + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -race -v ./... diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml deleted file mode 100644 index c4f0f68..0000000 --- a/.github/workflows/go.yml +++ /dev/null @@ -1,28 +0,0 @@ -name: Go - -on: - push: - branches: [ master ] - pull_request: - branches: [ master ] - -jobs: - build: - strategy: - matrix: - go-version: [1.16.x, 1.17.x, 1.18.x] - os: [ubuntu-latest, windows-latest] - runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v2 - - - name: Set up Go - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} - - - name: Build - run: go build -v ./... - - - name: Test - run: go test -race -v ./... diff --git a/README.md b/README.md index 120a573..58141f0 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ -cast -==== -[![GoDoc](https://godoc.org/github.com/spf13/cast?status.svg)](https://godoc.org/github.com/spf13/cast) -[![Build Status](https://github.com/spf13/cast/actions/workflows/go.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/go.yml) +# cast + +[![Build Status](https://github.com/spf13/cast/actions/workflows/ci.yml/badge.svg)](https://github.com/spf13/cast/actions/workflows/ci.yml) +[![PkgGoDev](https://pkg.go.dev/badge/mod/github.com/spf13/cast)](https://pkg.go.dev/mod/github.com/spf13/cast) +![Go Version](https://img.shields.io/badge/go%20version-%3E=1.16-61CFDD.svg?style=flat-square) [![Go Report Card](https://goreportcard.com/badge/github.com/spf13/cast)](https://goreportcard.com/report/github.com/spf13/cast) Easy and safe casting from one type to another in Go @@ -17,7 +18,7 @@ interface into a bool, etc. Cast does this intelligently when an obvious conversion is possible. It doesn’t make any attempts to guess what you meant, for example you can only convert a string to an int when it is a string representation of an int such as “8”. Cast was developed for use in -[Hugo](http://hugo.spf13.com), a website engine which uses YAML, TOML or JSON +[Hugo](https://gohugo.io), a website engine which uses YAML, TOML or JSON for meta data. ## Why use Cast? @@ -72,4 +73,3 @@ the code for a complete set. var eight interface{} = 8 cast.ToInt(eight) // 8 cast.ToInt(nil) // 0 - diff --git a/cast_test.go b/cast_test.go index 2a51854..db839a6 100644 --- a/cast_test.go +++ b/cast_test.go @@ -797,6 +797,18 @@ func TestToBoolE(t *testing.T) { iserr bool }{ {0, false, false}, + {int64(0), false, false}, + {int32(0), false, false}, + {int16(0), false, false}, + {int8(0), false, false}, + {uint(0), false, false}, + {uint64(0), false, false}, + {uint32(0), false, false}, + {uint16(0), false, false}, + {uint8(0), false, false}, + {float64(0), false, false}, + {float32(0), false, false}, + {time.Duration(0), false, false}, {jf, false, false}, {nil, false, false}, {"false", false, false}, @@ -812,10 +824,26 @@ func TestToBoolE(t *testing.T) { {"t", true, false}, {"T", true, false}, {1, true, false}, + {int64(1), true, false}, + {int32(1), true, false}, + {int16(1), true, false}, + {int8(1), true, false}, + {uint(1), true, false}, + {uint64(1), true, false}, + {uint32(1), true, false}, + {uint16(1), true, false}, + {uint8(1), true, false}, + {float64(1), true, false}, + {float32(1), true, false}, + {time.Duration(1), true, false}, {jt, true, false}, {je, true, false}, {true, true, false}, {-1, true, false}, + {int64(-1), true, false}, + {int32(-1), true, false}, + {int16(-1), true, false}, + {int8(-1), true, false}, // errors {"test", false, true}, @@ -870,6 +898,17 @@ func BenchmarkTrimZeroDecimal(b *testing.B) { } } +func BenchmarkCommonTimeLayouts(b *testing.B) { + for i := 0; i < b.N; i++ { + for _, commonLayout := range []string{"2019-04-29", "2017-05-30T00:00:00Z"} { + _, err := StringToDateInDefaultLocation(commonLayout, time.UTC) + if err != nil { + b.Fatal(err) + } + } + } +} + func TestIndirectPointers(t *testing.T) { c := qt.New(t) diff --git a/caste.go b/caste.go index 15ba78a..c523abb 100644 --- a/caste.go +++ b/caste.go @@ -98,10 +98,31 @@ func ToBoolE(i interface{}) (bool, error) { case nil: return false, nil case int: - if i.(int) != 0 { - return true, nil - } - return false, nil + return b != 0, nil + case int64: + return b != 0, nil + case int32: + return b != 0, nil + case int16: + return b != 0, nil + case int8: + return b != 0, nil + case uint: + return b != 0, nil + case uint64: + return b != 0, nil + case uint32: + return b != 0, nil + case uint16: + return b != 0, nil + case uint8: + return b != 0, nil + case float64: + return b != 0, nil + case float32: + return b != 0, nil + case time.Duration: + return b != 0, nil case string: return strconv.ParseBool(i.(string)) case json.Number: @@ -1370,6 +1391,8 @@ func (f timeFormat) hasTimezone() bool { var ( timeFormats = []timeFormat{ + // Keep common formats at the top. + {"2006-01-02", timeFormatNoTimezone}, {time.RFC3339, timeFormatNumericTimezone}, {"2006-01-02T15:04:05", timeFormatNoTimezone}, // iso8601 without timezone {time.RFC1123Z, timeFormatNumericTimezone}, @@ -1385,7 +1408,6 @@ var ( {time.UnixDate, timeFormatNamedTimezone}, {time.RubyDate, timeFormatNumericTimezone}, {"2006-01-02 15:04:05Z07:00", timeFormatNumericTimezone}, - {"2006-01-02", timeFormatNoTimezone}, {"02 Jan 2006", timeFormatNoTimezone}, {"2006-01-02 15:04:05 -07:00", timeFormatNumericTimezone}, {"2006-01-02 15:04:05 -0700", timeFormatNumericTimezone}, diff --git a/go.mod b/go.mod index 255e99f..231f764 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,11 @@ module github.com/spf13/cast go 1.18 -require github.com/frankban/quicktest v1.14.3 +require github.com/frankban/quicktest v1.14.4 require ( - github.com/google/go-cmp v0.5.7 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/google/go-cmp v0.5.9 // indirect + github.com/kr/pretty v0.3.1 // indirect 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 + github.com/rogpeppe/go-internal v1.9.0 // indirect ) diff --git a/go.sum b/go.sum index 1dbb1c6..80fb7de 100644 --- a/go.sum +++ b/go.sum @@ -1,18 +1,12 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= -github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 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= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=