Skip to content

Commit

Permalink
improve direct type performance for uint*
Browse files Browse the repository at this point in the history
  • Loading branch information
shockerli committed Oct 7, 2021
1 parent 263dfc1 commit a1119ba
Show file tree
Hide file tree
Showing 2 changed files with 217 additions and 3 deletions.
70 changes: 67 additions & 3 deletions int.go
Original file line number Diff line number Diff line change
Expand Up @@ -263,11 +263,75 @@ func IntE(val interface{}) (int, error) {

// convert any value to uint64
func convUint64(val interface{}) (uint64, error) {
v, _, rv := indirect(val)

switch vv := v.(type) {
// direct type(for improve performance)
switch vv := val.(type) {
case int:
if vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case int64:
if vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case int32:
if vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case int16:
if vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case int8:
if vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case uint:
return uint64(vv), nil
case uint64:
return vv, nil
case uint32:
return uint64(vv), nil
case uint16:
return uint64(vv), nil
case uint8:
return uint64(vv), nil
case float64:
if vv > math.MaxUint64 || vv < 0 {
return 0, errConvFail
}
return uint64(math.Trunc(vv)), nil
case float32:
if vv > math.MaxUint64 || vv < 0 {
return 0, errConvFail
}
return uint64(vv), nil
case nil:
return 0, nil
case bool:
if vv {
return 1, nil
}
return 0, nil
case string:
vvv, err := strconv.ParseFloat(vv, 64)
if err == nil && vvv >= 0 && vvv <= math.MaxUint64 {
return uint64(math.Trunc(vvv)), nil
}
case []byte:
vvv, err := strconv.ParseFloat(string(vv), 64)
if err == nil && vvv >= 0 && vvv <= math.MaxUint64 {
return uint64(math.Trunc(vvv)), nil
}
}

// indirect type
v, _, rv := indirect(val)
switch vv := v.(type) {
case bool:
if vv {
return 1, nil
Expand Down
150 changes: 150 additions & 0 deletions int_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,24 @@ func TestUint64E(t *testing.T) {
{&aliasTypeInt_0, 0, false},
{aliasTypeInt_1, 1, false},
{&aliasTypeInt_1, 1, false},
{AliasTypeInt8(1), 1, false},
{AliasTypeInt16(1), 1, false},
{AliasTypeInt32(1), 1, false},
{AliasTypeInt64(1), 1, false},
{aliasTypeUint_0, 0, false},
{&aliasTypeUint_0, 0, false},
{aliasTypeUint_1, 1, false},
{&aliasTypeUint_1, 1, false},
{AliasTypeUint8(1), 1, false},
{AliasTypeUint16(1), 1, false},
{AliasTypeUint32(1), 1, false},
{AliasTypeUint64(1), 1, false},
{AliasTypeFloat32(1), 1, false},
{AliasTypeFloat32(0), 0, false},
{AliasTypeFloat32(1.01), 1, false},
{AliasTypeFloat64(0), 0, false},
{AliasTypeFloat64(1), 1, false},
{AliasTypeFloat64(1.01), 1, false},
{aliasTypeString_0, 0, false},
{&aliasTypeString_0, 0, false},
{aliasTypeString_1, 1, false},
Expand All @@ -996,6 +1014,9 @@ func TestUint64E(t *testing.T) {
{&aliasTypeBool_true, 1, false},
{aliasTypeBool_false, 0, false},
{&aliasTypeBool_false, 0, false},
{AliasTypeBytes("0"), 0, false},
{AliasTypeBytes("10.98"), 10, false},
{json.Number("1"), 1, false},

// errors
{int(-8), 0, true},
Expand All @@ -1014,6 +1035,8 @@ func TestUint64E(t *testing.T) {
{"4873546382743564386435354655456575456754356765546554643456", 0, true},
{float64(4873546382743564386435354655456575456754356765546554643456), 0, true},
{"hello", 0, true},
{[]byte("hello"), 0, true},
{json.Number("hello"), 0, true},
{testing.T{}, 0, true},
{&testing.T{}, 0, true},
{[]int{}, 0, true},
Expand All @@ -1022,6 +1045,13 @@ func TestUint64E(t *testing.T) {
{map[int]string{}, 0, true},
{aliasTypeString_8d15_minus, 0, true},
{&aliasTypeString_8d15_minus, 0, true},
{AliasTypeInt(-1), 0, true},
{AliasTypeInt8(-1), 0, true},
{AliasTypeInt16(-1), 0, true},
{AliasTypeInt32(-1), 0, true},
{AliasTypeInt64(-1), 0, true},
{AliasTypeFloat32(-1.01), 0, true},
{AliasTypeFloat64(-1.01), 0, true},
}

for i, tt := range tests {
Expand Down Expand Up @@ -1072,12 +1102,33 @@ func TestUint32E(t *testing.T) {
{&aliasTypeInt_0, 0, false},
{aliasTypeInt_1, 1, false},
{&aliasTypeInt_1, 1, false},
{AliasTypeInt8(1), 1, false},
{AliasTypeInt16(1), 1, false},
{AliasTypeInt32(1), 1, false},
{AliasTypeInt64(1), 1, false},
{aliasTypeUint_0, 0, false},
{&aliasTypeUint_0, 0, false},
{aliasTypeUint_1, 1, false},
{&aliasTypeUint_1, 1, false},
{AliasTypeUint8(1), 1, false},
{AliasTypeUint16(1), 1, false},
{AliasTypeUint32(1), 1, false},
{AliasTypeUint64(1), 1, false},
{AliasTypeFloat32(1), 1, false},
{AliasTypeFloat32(0), 0, false},
{AliasTypeFloat32(1.01), 1, false},
{AliasTypeFloat64(0), 0, false},
{AliasTypeFloat64(1), 1, false},
{AliasTypeFloat64(1.01), 1, false},
{aliasTypeString_0, 0, false},
{&aliasTypeString_0, 0, false},
{aliasTypeString_1, 1, false},
{&aliasTypeString_1, 1, false},
{aliasTypeString_8d15, 8, false},
{&aliasTypeString_8d15, 8, false},
{AliasTypeBytes("0"), 0, false},
{AliasTypeBytes("10.98"), 10, false},
{json.Number("1"), 1, false},

// errors
{int(-8), 0, true},
Expand All @@ -1099,6 +1150,8 @@ func TestUint32E(t *testing.T) {
{int64(1487354638276643554), 0, true},
{uint64(1487354638276643554), 0, true},
{"hello", 0, true},
{[]byte("hello"), 0, true},
{json.Number("hello"), 0, true},
{testing.T{}, 0, true},
{&testing.T{}, 0, true},
{[]int{}, 0, true},
Expand All @@ -1107,6 +1160,13 @@ func TestUint32E(t *testing.T) {
{map[int]string{}, 0, true},
{aliasTypeString_8d15_minus, 0, true},
{&aliasTypeString_8d15_minus, 0, true},
{AliasTypeInt(-1), 0, true},
{AliasTypeInt8(-1), 0, true},
{AliasTypeInt16(-1), 0, true},
{AliasTypeInt32(-1), 0, true},
{AliasTypeInt64(-1), 0, true},
{AliasTypeFloat32(-1.01), 0, true},
{AliasTypeFloat64(-1.01), 0, true},
}

for i, tt := range tests {
Expand Down Expand Up @@ -1155,12 +1215,33 @@ func TestUint16E(t *testing.T) {
{&aliasTypeInt_0, 0, false},
{aliasTypeInt_1, 1, false},
{&aliasTypeInt_1, 1, false},
{AliasTypeInt8(1), 1, false},
{AliasTypeInt16(1), 1, false},
{AliasTypeInt32(1), 1, false},
{AliasTypeInt64(1), 1, false},
{aliasTypeUint_0, 0, false},
{&aliasTypeUint_0, 0, false},
{aliasTypeUint_1, 1, false},
{&aliasTypeUint_1, 1, false},
{AliasTypeUint8(1), 1, false},
{AliasTypeUint16(1), 1, false},
{AliasTypeUint32(1), 1, false},
{AliasTypeUint64(1), 1, false},
{AliasTypeFloat32(1), 1, false},
{AliasTypeFloat32(0), 0, false},
{AliasTypeFloat32(1.01), 1, false},
{AliasTypeFloat64(0), 0, false},
{AliasTypeFloat64(1), 1, false},
{AliasTypeFloat64(1.01), 1, false},
{aliasTypeString_0, 0, false},
{&aliasTypeString_0, 0, false},
{aliasTypeString_1, 1, false},
{&aliasTypeString_1, 1, false},
{aliasTypeString_8d15, 8, false},
{&aliasTypeString_8d15, 8, false},
{AliasTypeBytes("0"), 0, false},
{AliasTypeBytes("10.98"), 10, false},
{json.Number("1"), 1, false},

// errors
{int(-8), 0, true},
Expand All @@ -1184,6 +1265,8 @@ func TestUint16E(t *testing.T) {
{uint(math.MaxUint32), 0, true},
{uint32(math.MaxUint32), 0, true},
{"hello", 0, true},
{[]byte("hello"), 0, true},
{json.Number("hello"), 0, true},
{testing.T{}, 0, true},
{&testing.T{}, 0, true},
{[]int{}, 0, true},
Expand All @@ -1192,6 +1275,13 @@ func TestUint16E(t *testing.T) {
{map[int]string{}, 0, true},
{aliasTypeString_8d15_minus, 0, true},
{&aliasTypeString_8d15_minus, 0, true},
{AliasTypeInt(-1), 0, true},
{AliasTypeInt8(-1), 0, true},
{AliasTypeInt16(-1), 0, true},
{AliasTypeInt32(-1), 0, true},
{AliasTypeInt64(-1), 0, true},
{AliasTypeFloat32(-1.01), 0, true},
{AliasTypeFloat64(-1.01), 0, true},
}

for i, tt := range tests {
Expand Down Expand Up @@ -1240,12 +1330,33 @@ func TestUint8E(t *testing.T) {
{&aliasTypeInt_0, 0, false},
{aliasTypeInt_1, 1, false},
{&aliasTypeInt_1, 1, false},
{AliasTypeInt8(1), 1, false},
{AliasTypeInt16(1), 1, false},
{AliasTypeInt32(1), 1, false},
{AliasTypeInt64(1), 1, false},
{aliasTypeUint_0, 0, false},
{&aliasTypeUint_0, 0, false},
{aliasTypeUint_1, 1, false},
{&aliasTypeUint_1, 1, false},
{AliasTypeUint8(1), 1, false},
{AliasTypeUint16(1), 1, false},
{AliasTypeUint32(1), 1, false},
{AliasTypeUint64(1), 1, false},
{AliasTypeFloat32(1), 1, false},
{AliasTypeFloat32(0), 0, false},
{AliasTypeFloat32(1.01), 1, false},
{AliasTypeFloat64(0), 0, false},
{AliasTypeFloat64(1), 1, false},
{AliasTypeFloat64(1.01), 1, false},
{aliasTypeString_0, 0, false},
{&aliasTypeString_0, 0, false},
{aliasTypeString_1, 1, false},
{&aliasTypeString_1, 1, false},
{aliasTypeString_8d15, 8, false},
{&aliasTypeString_8d15, 8, false},
{AliasTypeBytes("0"), 0, false},
{AliasTypeBytes("10.98"), 10, false},
{json.Number("1"), 1, false},

// errors
{int(-8), 0, true},
Expand All @@ -1269,6 +1380,8 @@ func TestUint8E(t *testing.T) {
{uint(math.MaxUint32), 0, true},
{uint32(math.MaxUint32), 0, true},
{"hello", 0, true},
{[]byte("hello"), 0, true},
{json.Number("hello"), 0, true},
{testing.T{}, 0, true},
{&testing.T{}, 0, true},
{[]int{}, 0, true},
Expand All @@ -1277,6 +1390,13 @@ func TestUint8E(t *testing.T) {
{map[int]string{}, 0, true},
{aliasTypeString_8d15_minus, 0, true},
{&aliasTypeString_8d15_minus, 0, true},
{AliasTypeInt(-1), 0, true},
{AliasTypeInt8(-1), 0, true},
{AliasTypeInt16(-1), 0, true},
{AliasTypeInt32(-1), 0, true},
{AliasTypeInt64(-1), 0, true},
{AliasTypeFloat32(-1.01), 0, true},
{AliasTypeFloat64(-1.01), 0, true},
}

for i, tt := range tests {
Expand Down Expand Up @@ -1327,12 +1447,33 @@ func TestUintE(t *testing.T) {
{&aliasTypeInt_0, 0, false},
{aliasTypeInt_1, 1, false},
{&aliasTypeInt_1, 1, false},
{AliasTypeInt8(1), 1, false},
{AliasTypeInt16(1), 1, false},
{AliasTypeInt32(1), 1, false},
{AliasTypeInt64(1), 1, false},
{aliasTypeUint_0, 0, false},
{&aliasTypeUint_0, 0, false},
{aliasTypeUint_1, 1, false},
{&aliasTypeUint_1, 1, false},
{AliasTypeUint8(1), 1, false},
{AliasTypeUint16(1), 1, false},
{AliasTypeUint32(1), 1, false},
{AliasTypeUint64(1), 1, false},
{AliasTypeFloat32(1), 1, false},
{AliasTypeFloat32(0), 0, false},
{AliasTypeFloat32(1.01), 1, false},
{AliasTypeFloat64(0), 0, false},
{AliasTypeFloat64(1), 1, false},
{AliasTypeFloat64(1.01), 1, false},
{aliasTypeString_0, 0, false},
{&aliasTypeString_0, 0, false},
{aliasTypeString_1, 1, false},
{&aliasTypeString_1, 1, false},
{aliasTypeString_8d15, 8, false},
{&aliasTypeString_8d15, 8, false},
{AliasTypeBytes("0"), 0, false},
{AliasTypeBytes("10.98"), 10, false},
{json.Number("1"), 1, false},

// errors
{int(-8), 0, true},
Expand All @@ -1351,6 +1492,8 @@ func TestUintE(t *testing.T) {
{"4873546382743564386435354655456575456754356765546554643456", 0, true},
{float64(4873546382743564386435354655456575456754356765546554643456), 0, true},
{"hello", 0, true},
{[]byte("hello"), 0, true},
{json.Number("hello"), 0, true},
{testing.T{}, 0, true},
{&testing.T{}, 0, true},
{[]int{}, 0, true},
Expand All @@ -1359,6 +1502,13 @@ func TestUintE(t *testing.T) {
{map[int]string{}, 0, true},
{aliasTypeString_8d15_minus, 0, true},
{&aliasTypeString_8d15_minus, 0, true},
{AliasTypeInt(-1), 0, true},
{AliasTypeInt8(-1), 0, true},
{AliasTypeInt16(-1), 0, true},
{AliasTypeInt32(-1), 0, true},
{AliasTypeInt64(-1), 0, true},
{AliasTypeFloat32(-1.01), 0, true},
{AliasTypeFloat64(-1.01), 0, true},
}

for i, tt := range tests {
Expand Down

0 comments on commit a1119ba

Please sign in to comment.