Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support type casting for interfaces created from basic types #235

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions cast_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func createNumberTestSteps(zero, one, eight, eightnegative, eightpoint31, eightp
eightpoint31negative_32 = float64(float32(eightpoint31negative.(float64)))
}

type int2 int
type uint2 uint
type float642 float64

return []testStep{
{int(8), eight, false},
{int8(8), eight, false},
Expand Down Expand Up @@ -73,6 +77,9 @@ func createNumberTestSteps(zero, one, eight, eightnegative, eightpoint31, eightp
{jfloateight, eight, false},
{"test", zero, true},
{testing.T{}, zero, true},
{int2(8), eight, false},
{uint2(8), eight, false},
{float642(8.31), eightpoint31, false},
}
}

Expand Down Expand Up @@ -244,6 +251,8 @@ func TestToStringE(t *testing.T) {
}
key := &Key{"foo"}

type string2 string

tests := []struct {
input interface{}
expect string
Expand Down Expand Up @@ -275,6 +284,7 @@ func TestToStringE(t *testing.T) {
// errors
{testing.T{}, "", true},
{key, "", true},
{string2("foo"), "foo", false},
}

for i, test := range tests {
Expand Down Expand Up @@ -796,6 +806,8 @@ func TestToBoolE(t *testing.T) {
_ = json.Unmarshal([]byte("0"), &jf)
_ = json.Unmarshal([]byte("1"), &jt)
_ = json.Unmarshal([]byte("1.0"), &je)

type bool2 bool
tests := []struct {
input interface{}
expect bool
Expand Down Expand Up @@ -853,6 +865,9 @@ func TestToBoolE(t *testing.T) {
// errors
{"test", false, true},
{testing.T{}, false, true},

{bool2(false), false, false},
{bool2(true), true, false},
}

for i, test := range tests {
Expand Down Expand Up @@ -921,9 +936,17 @@ func TestIndirectPointers(t *testing.T) {
y := &x
z := &y

type int1 int
a := int1(14)
pa := &a
ppa := &pa

c.Assert(ToInt(y), qt.Equals, 13)
c.Assert(ToInt(z), qt.Equals, 13)

c.Assert(ToInt(pa), qt.Equals, 14)
c.Assert(ToInt(ppa), qt.Equals, 14)

}

func TestToTime(t *testing.T) {
Expand Down
71 changes: 71 additions & 0 deletions caste.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ func ToTimeInDefaultLocationE(i interface{}, location *time.Location) (tim time.
case uint32:
return time.Unix(int64(v), 0), nil
default:
if iNative, changed := toNative(v); changed {
return ToTimeInDefaultLocationE(iNative, location)
}
return time.Time{}, fmt.Errorf("unable to cast %#v of type %T to Time", i, i)
}
}
Expand Down Expand Up @@ -94,6 +97,10 @@ func ToDurationE(i interface{}) (d time.Duration, err error) {
d = time.Duration(s.Float64())
return
default:
if iNative, changed := toNative(i); changed {
return ToDurationE(iNative)
}

err = fmt.Errorf("unable to cast %#v of type %T to Duration", i, i)
return
}
Expand Down Expand Up @@ -143,6 +150,9 @@ func ToBoolE(i interface{}) (bool, error) {
}
return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i)
default:
if iNative, changed := toNative(i); changed {
return ToBoolE(iNative)
}
return false, fmt.Errorf("unable to cast %#v of type %T to bool", i, i)
}
}
Expand Down Expand Up @@ -201,6 +211,9 @@ func ToFloat64E(i interface{}) (float64, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToFloat64E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float64", i, i)
}
}
Expand Down Expand Up @@ -259,6 +272,9 @@ func ToFloat32E(i interface{}) (float32, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToFloat32E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to float32", i, i)
}
}
Expand Down Expand Up @@ -311,6 +327,9 @@ func ToInt64E(i interface{}) (int64, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToInt64E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int64", i, i)
}
}
Expand Down Expand Up @@ -363,6 +382,9 @@ func ToInt32E(i interface{}) (int32, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToInt32E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int32", i, i)
}
}
Expand Down Expand Up @@ -415,6 +437,9 @@ func ToInt16E(i interface{}) (int16, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToInt16E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int16", i, i)
}
}
Expand Down Expand Up @@ -467,6 +492,9 @@ func ToInt8E(i interface{}) (int8, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToInt8E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int8", i, i)
}
}
Expand Down Expand Up @@ -519,6 +547,9 @@ func ToIntE(i interface{}) (int, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToIntE(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to int", i, i)
}
}
Expand Down Expand Up @@ -595,6 +626,9 @@ func ToUintE(i interface{}) (uint, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToUintE(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint", i, i)
}
}
Expand Down Expand Up @@ -671,6 +705,9 @@ func ToUint64E(i interface{}) (uint64, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToUint64E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint64", i, i)
}
}
Expand Down Expand Up @@ -747,6 +784,9 @@ func ToUint32E(i interface{}) (uint32, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToUint32E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint32", i, i)
}
}
Expand Down Expand Up @@ -823,6 +863,9 @@ func ToUint16E(i interface{}) (uint16, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToUint16E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint16", i, i)
}
}
Expand Down Expand Up @@ -899,6 +942,9 @@ func ToUint8E(i interface{}) (uint8, error) {
case nil:
return 0, nil
default:
if iNative, changed := toNative(i); changed {
return ToUint8E(iNative)
}
return 0, fmt.Errorf("unable to cast %#v of type %T to uint8", i, i)
}
}
Expand Down Expand Up @@ -996,6 +1042,9 @@ func ToStringE(i interface{}) (string, error) {
case error:
return s.Error(), nil
default:
if iNative, changed := toNative(i); changed {
return ToStringE(iNative)
}
return "", fmt.Errorf("unable to cast %#v of type %T to string", i, i)
}
}
Expand Down Expand Up @@ -1508,3 +1557,25 @@ func trimZeroDecimal(s string) string {
}
return s
}

// toNative is called when converting to a basic type (int, int8, int16, int32, int64, uint, uint8, uint16, uint32,
// uint64, float32, float64, bool). If the current interface's type is created from a basic type, toNative will convert
// it to a basic data type.
func toNative(v interface{}) (interface{}, bool) {
var vNative = v
value := reflect.ValueOf(v)
switch {
case value.CanInt():
vNative = value.Int()
case value.CanUint():
vNative = value.Uint()
case value.CanFloat():
vNative = value.Float()
case value.Kind() == reflect.Bool:
vNative = value.Bool()
case value.Kind() == reflect.String:
vNative = value.String()
}

return vNative, reflect.TypeOf(vNative) != reflect.TypeOf(v)
}