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 }