github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/accounts/abi/reflect.go (about) 1 // This file is part of the go-sberex library. The go-sberex library is 2 // free software: you can redistribute it and/or modify it under the terms 3 // of the GNU Lesser General Public License as published by the Free 4 // Software Foundation, either version 3 of the License, or (at your option) 5 // any later version. 6 // 7 // The go-sberex library is distributed in the hope that it will be useful, 8 // but WITHOUT ANY WARRANTY; without even the implied warranty of 9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 10 // General Public License <http://www.gnu.org/licenses/> for more details. 11 12 package abi 13 14 import ( 15 "fmt" 16 "reflect" 17 ) 18 19 // indirect recursively dereferences the value until it either gets the value 20 // or finds a big.Int 21 func indirect(v reflect.Value) reflect.Value { 22 if v.Kind() == reflect.Ptr && v.Elem().Type() != derefbig_t { 23 return indirect(v.Elem()) 24 } 25 return v 26 } 27 28 // reflectIntKind returns the reflect using the given size and 29 // unsignedness. 30 func reflectIntKindAndType(unsigned bool, size int) (reflect.Kind, reflect.Type) { 31 switch size { 32 case 8: 33 if unsigned { 34 return reflect.Uint8, uint8_t 35 } 36 return reflect.Int8, int8_t 37 case 16: 38 if unsigned { 39 return reflect.Uint16, uint16_t 40 } 41 return reflect.Int16, int16_t 42 case 32: 43 if unsigned { 44 return reflect.Uint32, uint32_t 45 } 46 return reflect.Int32, int32_t 47 case 64: 48 if unsigned { 49 return reflect.Uint64, uint64_t 50 } 51 return reflect.Int64, int64_t 52 } 53 return reflect.Ptr, big_t 54 } 55 56 // mustArrayToBytesSlice creates a new byte slice with the exact same size as value 57 // and copies the bytes in value to the new slice. 58 func mustArrayToByteSlice(value reflect.Value) reflect.Value { 59 slice := reflect.MakeSlice(reflect.TypeOf([]byte{}), value.Len(), value.Len()) 60 reflect.Copy(slice, value) 61 return slice 62 } 63 64 // set attempts to assign src to dst by either setting, copying or otherwise. 65 // 66 // set is a bit more lenient when it comes to assignment and doesn't force an as 67 // strict ruleset as bare `reflect` does. 68 func set(dst, src reflect.Value, output Argument) error { 69 dstType := dst.Type() 70 srcType := src.Type() 71 switch { 72 case dstType.AssignableTo(srcType): 73 dst.Set(src) 74 case dstType.Kind() == reflect.Interface: 75 dst.Set(src) 76 case dstType.Kind() == reflect.Ptr: 77 return set(dst.Elem(), src, output) 78 default: 79 return fmt.Errorf("abi: cannot unmarshal %v in to %v", src.Type(), dst.Type()) 80 } 81 return nil 82 } 83 84 // requireAssignable assures that `dest` is a pointer and it's not an interface. 85 func requireAssignable(dst, src reflect.Value) error { 86 if dst.Kind() != reflect.Ptr && dst.Kind() != reflect.Interface { 87 return fmt.Errorf("abi: cannot unmarshal %v into %v", src.Type(), dst.Type()) 88 } 89 return nil 90 } 91 92 // requireUnpackKind verifies preconditions for unpacking `args` into `kind` 93 func requireUnpackKind(v reflect.Value, t reflect.Type, k reflect.Kind, 94 args Arguments) error { 95 96 switch k { 97 case reflect.Struct: 98 case reflect.Slice, reflect.Array: 99 if minLen := args.LengthNonIndexed(); v.Len() < minLen { 100 return fmt.Errorf("abi: insufficient number of elements in the list/array for unpack, want %d, got %d", 101 minLen, v.Len()) 102 } 103 default: 104 return fmt.Errorf("abi: cannot unmarshal tuple into %v", t) 105 } 106 return nil 107 }