Skip to content

Commit

Permalink
reorganize code structure
Browse files Browse the repository at this point in the history
  • Loading branch information
shockerli committed Jul 22, 2021
1 parent 8f2948c commit 53e4fc1
Show file tree
Hide file tree
Showing 18 changed files with 2,886 additions and 2,810 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# cvt

[![PkgGoDev](https://pkg.go.dev/badge/github.com/shockerli/cvt)](https://pkg.go.dev/github.com/shockerli/cvt) [![Go Report Card](https://goreportcard.com/badge/github.com/shockerli/cvt)](https://goreportcard.com/report/github.com/shockerli/cvt) [![Build Status](https://travis-ci.com/shockerli/cvt.svg?branch=master)](https://travis-ci.com/shockerli/cvt) ![GitHub top language](https://img.shields.io/github/languages/top/shockerli/cvt) ![GitHub](https://img.shields.io/github/license/shockerli/cvt) [![Sourcegraph](https://sourcegraph.com/github.com/shockerli/cvt/-/badge.svg)](https://sourcegraph.com/github.com/shockerli/cvt?badge)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/shockerli/cvt)](https://pkg.go.dev/github.com/shockerli/cvt) [![Go Report Card](https://goreportcard.com/badge/github.com/shockerli/cvt)](https://goreportcard.com/report/github.com/shockerli/cvt) [![Build Status](https://travis-ci.com/shockerli/cvt.svg?branch=master)](https://travis-ci.com/shockerli/cvt) ![GitHub top language](https://img.shields.io/github/languages/top/shockerli/cvt) ![GitHub](https://img.shields.io/github/license/shockerli/cvt)

> Simple, safe conversion of any type, including custom types.
>
Expand Down Expand Up @@ -60,7 +60,7 @@ cvt.Float("hello", 12.34) // 12.34

### more

> For more examples, see tests [cvt_test.go](cvt_test.go) and [cvte_test.go](cvte_test.go)
> For more examples, see `*_test.go`
## API

Expand Down Expand Up @@ -103,7 +103,6 @@ cvt.Float("hello", 12.34) // 12.34
- Uint8E
- UintE


## License

This project is licensed under the terms of the [MIT](LICENSE) license.
5 changes: 2 additions & 3 deletions README_ZH.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# cvt

[![PkgGoDev](https://pkg.go.dev/badge/github.com/shockerli/cvt)](https://pkg.go.dev/github.com/shockerli/cvt) [![Go Report Card](https://goreportcard.com/badge/github.com/shockerli/cvt)](https://goreportcard.com/report/github.com/shockerli/cvt) [![Build Status](https://travis-ci.com/shockerli/cvt.svg?branch=master)](https://travis-ci.com/shockerli/cvt) ![GitHub top language](https://img.shields.io/github/languages/top/shockerli/cvt) ![GitHub](https://img.shields.io/github/license/shockerli/cvt) [![Sourcegraph](https://sourcegraph.com/github.com/shockerli/cvt/-/badge.svg)](https://sourcegraph.com/github.com/shockerli/cvt?badge)
[![PkgGoDev](https://pkg.go.dev/badge/github.com/shockerli/cvt)](https://pkg.go.dev/github.com/shockerli/cvt) [![Go Report Card](https://goreportcard.com/badge/github.com/shockerli/cvt)](https://goreportcard.com/report/github.com/shockerli/cvt) [![Build Status](https://travis-ci.com/shockerli/cvt.svg?branch=master)](https://travis-ci.com/shockerli/cvt) ![GitHub top language](https://img.shields.io/github/languages/top/shockerli/cvt) ![GitHub](https://img.shields.io/github/license/shockerli/cvt)

> 简单、安全的转换任意类型值,包括自定义类型
Expand Down Expand Up @@ -58,7 +58,7 @@ cvt.Float("hello", 12.34) // 12.34

### more

> 所有示例,可通过单元测试了解:[cvt_test.go](cvt_test.go)[cvte_test.go](cvte_test.go)
> 所有示例,可通过单元测试了解:`*_test.go`

## API
Expand Down Expand Up @@ -102,7 +102,6 @@ cvt.Float("hello", 12.34) // 12.34
- Uint8E
- UintE


## 开源协议

本项目基于 [MIT](LICENSE) 协议开放源代码。
68 changes: 68 additions & 0 deletions bool.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package cvt

import (
"reflect"
"strconv"
"strings"
)

// Bool convert an interface to a bool type, with default value
func Bool(v interface{}, def ...bool) bool {
if v, err := BoolE(v); err == nil {
return v
}

if len(def) > 0 {
return def[0]
}

return false
}

// BoolE convert an interface to a bool type
func BoolE(val interface{}) (bool, error) {
v, rk, rv := indirect(val)

switch vv := v.(type) {
case bool:
return vv, nil
case int, int8, int16, int32, int64:
return rv.Int() != 0, nil
case uint, uint8, uint16, uint32, uint64:
return rv.Uint() != 0, nil
case float32, float64:
return rv.Float() != 0, nil
case []byte:
return str2bool(string(vv))
case string:
return str2bool(vv)
case nil:
return false, nil
}

switch rk.Kind() {
// by elem length
case reflect.Array, reflect.Slice, reflect.Map:
return rv.Len() > 0, nil
}

return false, newErr(val, "bool")
}

// returns the boolean value represented by the string
func str2bool(str string) (bool, error) {
if val, err := strconv.ParseBool(str); err == nil {
return val, nil
} else if val, err := strconv.ParseFloat(str, 64); err == nil {
return val != 0, nil
}

switch strings.ToLower(strings.TrimSpace(str)) {
case "on":
return true, nil
case "off":
return false, nil
default:
return false, newErr(str, "bool")
}
}
209 changes: 209 additions & 0 deletions bool_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
package cvt_test

import (
"fmt"
"testing"

"github.com/shockerli/cvt"
"github.com/stretchr/testify/assert"
)

func TestBool_HasDefault(t *testing.T) {
tests := []struct {
input interface{}
def bool
expect bool
}{
// supported value, def is not used, def != expect
{0, true, false},
{float64(0.00), true, false},
{int(0.00), true, false},
{int64(0.00), true, false},
{uint(0.00), true, false},
{uint64(0.00), true, false},
{uint8(0.00), true, false},
{nil, true, false},
{"false", true, false},
{"FALSE", true, false},
{"False", true, false},
{"f", true, false},
{"F", true, false},
{false, true, false},
{"off", true, false},
{"Off", true, false},
{[]byte("Off"), true, false},
{aliasTypeInt_0, true, false},
{&aliasTypeInt_0, true, false},
{aliasTypeString_0, true, false},
{&aliasTypeString_0, true, false},
{aliasTypeString_off, true, false},
{&aliasTypeString_off, true, false},

{[]int{}, true, false},
{[]string{}, true, false},
{[...]string{}, true, false},
{map[int]int{}, true, false},
{map[string]string{}, true, false},

{"true", false, true},
{"TRUE", false, true},
{"True", false, true},
{"t", false, true},
{"T", false, true},
{1, false, true},
{true, false, true},
{-1, false, true},
{"on", false, true},
{"On", false, true},
{0.01, false, true},
{aliasTypeInt_1, false, true},
{&aliasTypeInt_1, false, true},
{aliasTypeString_1, false, true},
{&aliasTypeString_1, false, true},
{aliasTypeString_on, false, true},
{&aliasTypeString_on, false, true},

{[]int{1, 2, 3}, false, true},
{[]string{"a", "b", "c"}, false, true},
{[...]string{"a", "b", "c"}, false, true},
{map[int]int{1: 111, 2: 222}, false, true},
{map[string]string{"a": "aaa"}, false, true},

// unsupported value, def == expect
{"hello", true, true},
{"hello", false, false},
{testing.T{}, true, true},
{testing.T{}, false, false},
{&testing.T{}, true, true},
{&testing.T{}, false, false},
}

for i, tt := range tests {
msg := fmt.Sprintf("i = %d, input[%+v], def[%+v], expect[%+v]", i, tt.input, tt.def, tt.expect)

v := cvt.Bool(tt.input, tt.def)
assert.Equal(t, tt.expect, v, msg)
}
}

func TestBool_BaseLine(t *testing.T) {
tests := []struct {
input interface{}
expect bool
}{
{testing.T{}, false},
{&testing.T{}, false},
{[]int{}, false},
{[]int{1, 2, 3}, true},
{[]string{}, false},
{[]string{"a", "b", "c"}, true},
{[...]string{}, false},
{map[int]string{}, false},
{aliasTypeString_8d15_minus, true},
{&aliasTypeString_8d15_minus, true},
}

for i, tt := range tests {
msg := fmt.Sprintf("i = %d, input[%+v], expect[%+v]", i, tt.input, tt.expect)

v := cvt.Bool(tt.input)
assert.Equal(t, tt.expect, v, msg)
}
}

func TestBoolE(t *testing.T) {
tests := []struct {
input interface{}
expect bool
isErr bool
}{
// false/scale
{0, false, false},
{float64(0.00), false, false},
{int(0.00), false, false},
{int64(0.00), false, false},
{uint(0.00), false, false},
{uint64(0.00), false, false},
{uint8(0.00), false, false},
{nil, false, false},
{false, false, false},
{"false", false, false},
{"FALSE", false, false},
{"False", false, false},
{"f", false, false},
{"F", false, false},
{"off", false, false},
{"Off", false, false},
{"0", false, false},
{"0.00", false, false},
{[]byte("false"), false, false},
{[]byte("Off"), false, false},
{aliasTypeInt_0, false, false},
{&aliasTypeInt_0, false, false},
{aliasTypeString_0, false, false},
{&aliasTypeString_0, false, false},
{aliasTypeString_off, false, false},
{&aliasTypeString_off, false, false},
{aliasTypeBool_false, false, false},
{&aliasTypeBool_false, false, false},

// false/slice/array/map
{[]int{}, false, false},
{[]string{}, false, false},
{[...]string{}, false, false},
{map[int]int{}, false, false},
{map[string]string{}, false, false},

// true/scale
{true, true, false},
{"true", true, false},
{"TRUE", true, false},
{"True", true, false},
{"t", true, false},
{"T", true, false},
{1, true, false},
{-1, true, false},
{"on", true, false},
{"On", true, false},
{0.01, true, false},
{"0.01", true, false},
{[]byte("true"), true, false},
{aliasTypeInt_1, true, false},
{&aliasTypeInt_1, true, false},
{aliasTypeString_1, true, false},
{&aliasTypeString_1, true, false},
{aliasTypeString_on, true, false},
{&aliasTypeString_on, true, false},
{aliasTypeBool_true, true, false},
{&aliasTypeBool_true, true, false},

// true/slice/array/map
{[]int{1, 2, 3}, true, false},
{[]string{"a", "b", "c"}, true, false},
{[...]string{"a", "b", "c"}, true, false},
{map[int]int{1: 111, 2: 222}, true, false},
{map[string]string{"a": "aaa"}, true, false},

// errors
{"hello", false, true},
{testing.T{}, false, true},
{&testing.T{}, false, true},
}

for i, tt := range tests {
msg := fmt.Sprintf("i = %d, input[%+v], expect[%+v], isErr[%+v]", i, tt.input, tt.expect, tt.isErr)

v, err := cvt.BoolE(tt.input)
if tt.isErr {
assert.Error(t, err, msg)
continue
}

assert.NoError(t, err, msg)
assert.Equal(t, tt.expect, v, msg)

// Non-E test with no default value:
v = cvt.Bool(tt.input)
assert.Equal(t, tt.expect, v, msg)
}
}
Loading

0 comments on commit 53e4fc1

Please sign in to comment.