github.com/bobyang007/helper@v1.1.3/reflecth/op-unary.go (about)

     1  package reflecth
     2  
     3  import (
     4  	"go/token"
     5  	"reflect"
     6  )
     7  
     8  // UnaryOp performs unary operation <op><y> as Go language specification describes.
     9  // Supported operations: + - ^ ! & <- .
    10  // If operation cannot be performed then error will be returned.
    11  // Special note for token.AND (&) operation: if passed y is not addressable (reflect.Value.CanAddr) then new variable will be created with the same as y type and value and address of new variable will be returned.
    12  func UnaryOp(op token.Token, y reflect.Value) (r reflect.Value, err error) {
    13  	switch op {
    14  	case token.SUB:
    15  		return unaryOpSub(y)
    16  	case token.XOR:
    17  		return unaryOpXor(y)
    18  	case token.NOT:
    19  		return unaryOpNot(y)
    20  	case token.AND:
    21  		return unaryOpAnd(y)
    22  	case token.ARROW:
    23  		return unaryOpArrow(y)
    24  	case token.ADD:
    25  		if k := y.Kind(); IsAnyInt(k) || IsFloat(k) || IsComplex(k) {
    26  			return y, nil
    27  		}
    28  		fallthrough
    29  	default:
    30  		return reflect.Value{}, unaryOpError(y, op)
    31  	}
    32  }
    33  
    34  func unaryOpAnd(x reflect.Value) (r reflect.Value, err error) {
    35  	if x.CanAddr() {
    36  		return x.Addr(), nil
    37  	}
    38  
    39  	r = reflect.New(x.Type())
    40  	r.Elem().Set(x)
    41  	return
    42  }
    43  
    44  func unaryOpSub(x reflect.Value) (r reflect.Value, err error) {
    45  	r = reflect.New(x.Type()).Elem()
    46  
    47  	switch k := x.Kind(); {
    48  	case IsInt(k):
    49  		r.SetInt(-x.Int()) // looks like overflow correct (see tests)
    50  	case IsFloat(k):
    51  		r.SetFloat(-x.Float())
    52  	case IsComplex(k):
    53  		r.SetComplex(-x.Complex())
    54  	default:
    55  		return reflect.Value{}, unaryOpError(x, token.SUB)
    56  	}
    57  	return
    58  }
    59  
    60  func unaryOpNot(x reflect.Value) (r reflect.Value, err error) {
    61  	if k := x.Kind(); k != reflect.Bool {
    62  		return reflect.Value{}, unaryOpError(x, token.NOT)
    63  	}
    64  
    65  	r = reflect.New(x.Type()).Elem()
    66  	r.SetBool(!x.Bool())
    67  	return
    68  }
    69  
    70  func unaryOpXor(x reflect.Value) (r reflect.Value, err error) {
    71  	r = reflect.New(x.Type()).Elem()
    72  
    73  	switch k := x.Kind(); k {
    74  	case reflect.Int:
    75  		r.SetInt(int64(^int(x.Int())))
    76  	case reflect.Int8:
    77  		r.SetInt(int64(^int8(x.Int())))
    78  	case reflect.Int16:
    79  		r.SetInt(int64(^int16(x.Int())))
    80  	case reflect.Int32:
    81  		r.SetInt(int64(^int32(x.Int())))
    82  	case reflect.Int64:
    83  		r.SetInt(^x.Int())
    84  	case reflect.Uint:
    85  		r.SetUint(uint64(^uint(x.Uint())))
    86  	case reflect.Uint8:
    87  		r.SetUint(uint64(^uint8(x.Uint())))
    88  	case reflect.Uint16:
    89  		r.SetUint(uint64(^uint16(x.Uint())))
    90  	case reflect.Uint32:
    91  		r.SetUint(uint64(^uint32(x.Uint())))
    92  	case reflect.Uint64:
    93  		r.SetUint(^x.Uint())
    94  	default:
    95  		return reflect.Value{}, unaryOpError(x, token.XOR)
    96  	}
    97  
    98  	return
    99  }
   100  
   101  func unaryOpArrow(x reflect.Value) (r reflect.Value, err error) {
   102  	if x.Kind() != reflect.Chan {
   103  		return reflect.Value{}, unaryOpInvalidReceiverError(x, token.ARROW)
   104  	}
   105  	switch dir := x.Type().ChanDir(); dir {
   106  	case reflect.RecvDir, reflect.BothDir:
   107  		// nothing to do
   108  	default:
   109  		return reflect.Value{}, unaryOpReceiveFromSendOnlyError(x, token.ARROW)
   110  	}
   111  	r, _ = x.Recv()
   112  	return
   113  }