github.com/tencent/goom@v1.0.1/arg/value.go (about)

     1  package arg
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"reflect"
     7  	"strings"
     8  	"unsafe"
     9  
    10  	"github.com/tencent/goom/internal/hack"
    11  	"github.com/tencent/goom/internal/iface"
    12  )
    13  
    14  // I2V []interface convert to []reflect.Value 将interface元素类型的数组,转换成reflect.Value元素类型的数组
    15  func I2V(params []interface{}, types []reflect.Type) []reflect.Value {
    16  	if len(params) != len(types) {
    17  		panic(fmt.Sprintf("param lenth mismatch,must: %d, actual: %d", len(types), len(params)))
    18  	}
    19  	values := make([]reflect.Value, len(params))
    20  	for i, a := range params {
    21  		values[i] = toValue(a, types[i])
    22  	}
    23  	return values
    24  }
    25  
    26  // toValue 将interface参数值转化为reflect.Value值
    27  func toValue(r interface{}, out reflect.Type) reflect.Value {
    28  	v := reflect.ValueOf(r)
    29  	if r != nil && v.Type() != out && (out.Kind() == reflect.Struct || out.Kind() == reflect.Ptr) {
    30  		if v.Type().Size() != out.Size() {
    31  			panic(fmt.Sprintf("type mismatch,must: %s, actual: %v", v.Type(), out))
    32  		}
    33  		// 类型强制转换,适用于结构体 fake 场景
    34  		v = cast(v, out)
    35  	}
    36  
    37  	if r == nil && (out.Kind() == reflect.Interface || out.Kind() == reflect.Ptr || out.Kind() == reflect.Slice ||
    38  		out.Kind() == reflect.Map || out.Kind() == reflect.Array || out.Kind() == reflect.Chan) {
    39  		v = reflect.Zero(reflect.SliceOf(out).Elem())
    40  	} else if v.Type().Kind() == reflect.Ptr &&
    41  		v.Type() == reflect.TypeOf(&iface.IContext{}) {
    42  		panic("goom not support Return() API when returns mocked interface type, use Apply() API instead.")
    43  	} else if r != nil && out.Kind() == reflect.Interface {
    44  
    45  		ptr := reflect.New(out)
    46  		ptr.Elem().Set(v)
    47  		v = ptr.Elem()
    48  	}
    49  	return v
    50  }
    51  
    52  // cast 将reflect.Value类型强制转换为执行type类型的reflect.Value
    53  func cast(v reflect.Value, typ reflect.Type) reflect.Value {
    54  	originV := (*hack.Value)(unsafe.Pointer(&v))
    55  	newV := reflect.NewAt(typ, originV.Ptr).Elem()
    56  	newVHack := (*hack.Value)(unsafe.Pointer(&newV))
    57  	v = *(*reflect.Value)(unsafe.Pointer(&hack.Value{
    58  		Typ:  newVHack.Typ,
    59  		Ptr:  originV.Ptr,
    60  		Flag: originV.Flag,
    61  	}))
    62  
    63  	return v
    64  }
    65  
    66  // V2I []reflect.Value convert to []interface 将reflect.Value元素类型的数组,转换成interface元素类型的数组
    67  func V2I(params []reflect.Value, types []reflect.Type) []interface{} {
    68  	values := make([]interface{}, len(params))
    69  	for i, a := range params {
    70  		if (types[i].Kind() == reflect.Interface || types[i].Kind() == reflect.Ptr) && isZero(a) {
    71  			values[i] = nil
    72  		} else {
    73  			values[i] = a.Interface()
    74  		}
    75  	}
    76  	return values
    77  }
    78  
    79  // SprintV []reflect.Value print to string 将[]reflect.Value参数列表转换为string用于打印输出
    80  func SprintV(params []reflect.Value) string {
    81  	s := make([]string, 0, len(params))
    82  	for _, a := range params {
    83  		if (a.Kind() == reflect.Interface || a.Kind() == reflect.Ptr) && isZero(a) {
    84  			s = append(s, "nil")
    85  		} else {
    86  			s = append(s, fmt.Sprintf("%v", a.Interface()))
    87  		}
    88  	}
    89  	return strings.Join(s, ",")
    90  }
    91  
    92  // ToExpr 将[]interface{}参数转换成[]Expr
    93  func ToExpr(params []interface{}, types []reflect.Type) ([]Expr, error) {
    94  	if len(params) != len(types) {
    95  		return nil, fmt.Errorf("param lenth mismatch,must: %d, actual: %d", len(types), len(params))
    96  	}
    97  	// TODO results check
    98  	expressions := make([]Expr, len(params))
    99  	for i, a := range params {
   100  		if expr, ok := a.(Expr); ok {
   101  			expressions[i] = expr
   102  		} else {
   103  			// 默认使用 equals 表达式
   104  			expressions[i] = Equals(a)
   105  		}
   106  		err := expressions[i].Resolve([]reflect.Type{types[i]})
   107  		if err != nil {
   108  			return nil, err
   109  		}
   110  	}
   111  	return expressions, nil
   112  }
   113  
   114  // isZero reports whether v is the zero value for its type.
   115  // It panics if the argument is invalid.
   116  func isZero(v reflect.Value) bool {
   117  	switch v.Kind() {
   118  	case reflect.Bool:
   119  		return !v.Bool()
   120  	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
   121  		return v.Int() == 0
   122  	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
   123  		return v.Uint() == 0
   124  	case reflect.Float32, reflect.Float64:
   125  		return math.Float64bits(v.Float()) == 0
   126  	case reflect.Complex64, reflect.Complex128:
   127  		c := v.Complex()
   128  		return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
   129  	case reflect.Array:
   130  		for i := 0; i < v.Len(); i++ {
   131  			if !isZero(v.Index(i)) {
   132  				return false
   133  			}
   134  		}
   135  		return true
   136  	case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
   137  		return v.IsNil()
   138  	case reflect.String:
   139  		return v.Len() == 0
   140  	case reflect.Struct:
   141  		for i := 0; i < v.NumField(); i++ {
   142  			if !isZero(v.Field(i)) {
   143  				return false
   144  			}
   145  		}
   146  		return true
   147  	default:
   148  		return true
   149  	}
   150  }