]> Cypherpunks.ru repositories - gostls13.git/commitdiff
reflect: add Value.{CanInt, CanUint, CanFloat, CanComplex}
authorFabio Falzoi <fabio.falzoi84@gmail.com>
Sat, 25 Sep 2021 16:44:24 +0000 (18:44 +0200)
committerIan Lance Taylor <iant@golang.org>
Mon, 27 Sep 2021 21:31:14 +0000 (21:31 +0000)
As discussed in #47658, Value already has CanAddr and CanInterface to
test if a call to Addr or Inteface, respectively, does not result in a
panic.
Therefore we add CanInt, CanUint, CanFloat and CanComplex to ease the
test for a possible panic in calling, respectively, Int, Uint, Float and
Complex.

Fixes #47658

Change-Id: I58b77d77e6eec9f34234e985f631eab72b5b935e
Reviewed-on: https://go-review.googlesource.com/c/go/+/352131
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: David Chase <drchase@google.com>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/test/inl_test.go
src/reflect/all_test.go
src/reflect/value.go

index 89247fbabf177dec428e6b4e003fa0f9020c0870..5fa6411ae472bf70d3c29ac194a48f35aaea489e 100644 (file)
@@ -127,6 +127,10 @@ func TestIntendedInlining(t *testing.T) {
                        "ValidRune",
                },
                "reflect": {
+                       "Value.CanInt",
+                       "Value.CanUint",
+                       "Value.CanFloat",
+                       "Value.CanComplex",
                        "Value.CanAddr",
                        "Value.CanSet",
                        "Value.CanInterface",
index 22885c548f5ddef19f7dca810513cf5b98ef686b..5e10cc7a633dbd2ff12c9df12c7a8f42a822f494 100644 (file)
@@ -376,6 +376,75 @@ func TestMapIterSet(t *testing.T) {
        }
 }
 
+func TestCanIntUintFloatComplex(t *testing.T) {
+       type integer int
+       type uinteger uint
+       type float float64
+       type complex complex128
+
+       var ops = [...]string{"CanInt", "CanUint", "CanFloat", "CanComplex"}
+
+       var testCases = []struct {
+               i    interface{}
+               want [4]bool
+       }{
+               // signed integer
+               {132, [...]bool{true, false, false, false}},
+               {int8(8), [...]bool{true, false, false, false}},
+               {int16(16), [...]bool{true, false, false, false}},
+               {int32(32), [...]bool{true, false, false, false}},
+               {int64(64), [...]bool{true, false, false, false}},
+               // unsigned integer
+               {uint(132), [...]bool{false, true, false, false}},
+               {uint8(8), [...]bool{false, true, false, false}},
+               {uint16(16), [...]bool{false, true, false, false}},
+               {uint32(32), [...]bool{false, true, false, false}},
+               {uint64(64), [...]bool{false, true, false, false}},
+               {uintptr(0xABCD), [...]bool{false, true, false, false}},
+               // floating-point
+               {float32(256.25), [...]bool{false, false, true, false}},
+               {float64(512.125), [...]bool{false, false, true, false}},
+               // complex
+               {complex64(532.125 + 10i), [...]bool{false, false, false, true}},
+               {complex128(564.25 + 1i), [...]bool{false, false, false, true}},
+               // underlying
+               {integer(-132), [...]bool{true, false, false, false}},
+               {uinteger(132), [...]bool{false, true, false, false}},
+               {float(256.25), [...]bool{false, false, true, false}},
+               {complex(532.125 + 10i), [...]bool{false, false, false, true}},
+               // not-acceptable
+               {"hello world", [...]bool{false, false, false, false}},
+               {new(int), [...]bool{false, false, false, false}},
+               {new(uint), [...]bool{false, false, false, false}},
+               {new(float64), [...]bool{false, false, false, false}},
+               {new(complex64), [...]bool{false, false, false, false}},
+               {new([5]int), [...]bool{false, false, false, false}},
+               {new(integer), [...]bool{false, false, false, false}},
+               {new(map[int]int), [...]bool{false, false, false, false}},
+               {new(chan<- int), [...]bool{false, false, false, false}},
+               {new(func(a int8)), [...]bool{false, false, false, false}},
+               {new(struct{ i int }), [...]bool{false, false, false, false}},
+       }
+
+       for i, tc := range testCases {
+               v := ValueOf(tc.i)
+               got := [...]bool{v.CanInt(), v.CanUint(), v.CanFloat(), v.CanComplex()}
+
+               for j := range tc.want {
+                       if got[j] != tc.want[j] {
+                               t.Errorf(
+                                       "#%d: v.%s() returned %t for type %T, want %t",
+                                       i,
+                                       ops[j],
+                                       got[j],
+                                       tc.i,
+                                       tc.want[j],
+                               )
+                       }
+               }
+       }
+}
+
 func TestCanSetField(t *testing.T) {
        type embed struct{ x, X int }
        type Embed struct{ x, X int }
index 786c494166d09a046fcb0c626a8fab6a0ade9a40..39b82a8c01fbe5634483a69a3af6001a493504b3 100644 (file)
@@ -1122,6 +1122,16 @@ func (v Value) Close() {
        chanclose(v.pointer())
 }
 
+// CanComplex reports whether Complex can be used without panicking.
+func (v Value) CanComplex() bool {
+       switch v.kind() {
+       case Complex64, Complex128:
+               return true
+       default:
+               return false
+       }
+}
+
 // Complex returns v's underlying value, as a complex128.
 // It panics if v's Kind is not Complex64 or Complex128
 func (v Value) Complex() complex128 {
@@ -1249,6 +1259,16 @@ func (v Value) FieldByNameFunc(match func(string) bool) Value {
        return Value{}
 }
 
+// CanFloat reports whether Float can be used without panicking.
+func (v Value) CanFloat() bool {
+       switch v.kind() {
+       case Float32, Float64:
+               return true
+       default:
+               return false
+       }
+}
+
 // Float returns v's underlying value, as a float64.
 // It panics if v's Kind is not Float32 or Float64
 func (v Value) Float() float64 {
@@ -1310,6 +1330,16 @@ func (v Value) Index(i int) Value {
        panic(&ValueError{"reflect.Value.Index", v.kind()})
 }
 
+// CanInt reports whether Int can be used without panicking.
+func (v Value) CanInt() bool {
+       switch v.kind() {
+       case Int, Int8, Int16, Int32, Int64:
+               return true
+       default:
+               return false
+       }
+}
+
 // Int returns v's underlying value, as an int64.
 // It panics if v's Kind is not Int, Int8, Int16, Int32, or Int64.
 func (v Value) Int() int64 {
@@ -2391,6 +2421,16 @@ func (v Value) Type() Type {
        return v.typ.typeOff(m.mtyp)
 }
 
+// CanUint reports whether Uint can be used without panicking.
+func (v Value) CanUint() bool {
+       switch v.kind() {
+       case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr:
+               return true
+       default:
+               return false
+       }
+}
+
 // Uint returns v's underlying value, as a uint64.
 // It panics if v's Kind is not Uint, Uintptr, Uint8, Uint16, Uint32, or Uint64.
 func (v Value) Uint() uint64 {