Skip to content

Commit

Permalink
add KeysE support
Browse files Browse the repository at this point in the history
* add KeysE()
* TimeE() add tests for fmt.Stringer
* dump type of value, for unsupported type
  • Loading branch information
shockerli committed Mar 24, 2021
1 parent 2da9d1f commit 8e63f20
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 2 deletions.
23 changes: 21 additions & 2 deletions cvte.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ func ColumnsE(val interface{}, field interface{}) (sl []interface{}, err error)
return
}

return nil, fmt.Errorf("unsupported type: %s", rt.Kind())
return nil, fmt.Errorf("unsupported type: %s", rt.Name())
}

func ColumnsIntE(val interface{}, field interface{}) (sl []int, err error) {
Expand Down Expand Up @@ -605,6 +605,25 @@ func ColumnsStringE(val interface{}, field interface{}) (sl []string, err error)
return
}

// KeysE return the keys of map, sorted by asc
func KeysE(val interface{}) (sl []interface{}, err error) {
if val == nil {
return nil, errUnsupportedTypeNil
}

_, rt, rv := indirect(val)

switch rt.Kind() {
case reflect.Map:
for _, key := range sortedMapKeys(rv) {
sl = append(sl, key.Interface())
}
return
}

return nil, fmt.Errorf("unsupported type: %s", rt.Name())
}

// returns the value with base type
func indirect(a interface{}) (val interface{}, rt reflect.Type, rv reflect.Value) {
if a == nil {
Expand Down Expand Up @@ -668,7 +687,7 @@ func newErr(val interface{}, t string) error {
// catching an error and return a new
func catch(t string, val interface{}, e error) error {
if e != nil {
if errors.Is(e, errConvFail) {
if errors.Is(e, errConvFail) || errors.Is(e, errFieldNotFound) || errors.Is(e, errUnsupportedTypeNil) {
return newErr(val, t)
}
return fmt.Errorf(formatExtend, newErr(val, t), e)
Expand Down
49 changes: 49 additions & 0 deletions cvte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,20 @@ type TestStructE struct {
DD *TestStructD
}

type TestTimeStringer struct {
time time.Time
}

func (t TestTimeStringer) String() string {
return t.time.String()
}

func Benchmark(b *testing.B) {
for i := 0; i < b.N; i++ {
cvt.Bool(aliasTypeString_0, true)
}
}

// [function tests]

func TestBoolE(t *testing.T) {
Expand Down Expand Up @@ -1538,6 +1552,7 @@ func TestTimeE(t *testing.T) {
{uint64(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, loc), false},
{uint32(1234567890), time.Date(2009, 2, 13, 23, 31, 30, 0, loc), false},
{time.Date(2009, 2, 13, 23, 31, 30, 0, loc), time.Date(2009, 2, 13, 23, 31, 30, 0, loc), false},
{TestTimeStringer{time.Date(2010, 3, 7, 0, 0, 0, 0, loc)}, time.Date(2010, 3, 7, 0, 0, 0, 0, loc), false},

// errors
{"2006", time.Time{}, true},
Expand Down Expand Up @@ -1718,3 +1733,37 @@ func TestColumnsFloat64E(t *testing.T) {
assert.Equal(t, tt.expect, v, msg)
}
}

func TestKeysE(t *testing.T) {
tests := []struct {
input interface{}
expect []interface{}
isErr bool
}{
{map[int]map[string]interface{}{1: {"1": 111, "DDD": 12.3}, 2: {"2": 222, "DDD": "321"}, 3: {"DDD": nil}}, []interface{}{1, 2, 3}, false},
{map[string]interface{}{"A": 1, "2": 2}, []interface{}{"2", "A"}, false},
{map[float64]TestStructD{1: {11}, 2: {22}}, []interface{}{float64(1), float64(2)}, false},
{map[interface{}]interface{}{1: 1, 2.2: 2.22, "A": "A"}, []interface{}{1, 2.2, "A"}, false},

// errors
{nil, nil, true},
{"Name", nil, true},
{testing.T{}, nil, 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.KeysE(tt.input)
if tt.isErr {
assert.Error(t, err, msg)
continue
}

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

0 comments on commit 8e63f20

Please sign in to comment.