github.com/viant/toolbox@v0.34.5/types.go (about) 1 package toolbox 2 3 import ( 4 "fmt" 5 "reflect" 6 "time" 7 ) 8 9 //Zeroable represents object that can call IsZero 10 type Zeroable interface { 11 //IsZero returns true, if value of object was zeroed. 12 IsZero() bool 13 } 14 15 //IsInt returns true if input is an int 16 func IsInt(input interface{}) bool { 17 switch input.(type) { 18 case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: 19 return true 20 } 21 return false 22 } 23 24 //IsNumber returns true if type is either float or int 25 func IsNumber(input interface{}) bool { 26 return IsFloat(input) || IsInt(input) 27 } 28 29 //IsFloat returns true if input is a float 30 func IsFloat(input interface{}) bool { 31 switch input.(type) { 32 case float32, float64: 33 return true 34 } 35 return false 36 } 37 38 //IsBool returns true if input is a boolean 39 func IsBool(input interface{}) bool { 40 switch input.(type) { 41 case bool: 42 return true 43 } 44 return false 45 } 46 47 //IsString returns true if input is a string 48 func IsString(input interface{}) bool { 49 switch input.(type) { 50 case string: 51 return true 52 } 53 return false 54 } 55 56 //CanConvertToString checks if input can be converted to string 57 func CanConvertToString(input interface{}) bool { 58 return reflect.TypeOf(input).AssignableTo(reflect.TypeOf("")) 59 } 60 61 //IsTime returns true if input is a time 62 func IsTime(input interface{}) bool { 63 switch input.(type) { 64 case time.Time: 65 return true 66 case *time.Time: 67 return true 68 } 69 return false 70 } 71 72 //IsMap returns true if input is a map 73 func IsMap(input interface{}) bool { 74 switch input.(type) { 75 case map[string]interface{}: 76 return true 77 } 78 candidateType := DereferenceType(reflect.TypeOf(input)) 79 return candidateType.Kind() == reflect.Map 80 } 81 82 //IsStruct returns true if input is a map 83 func IsStruct(input interface{}) bool { 84 if input == nil { 85 return false 86 } 87 inputType := DereferenceType(input) 88 return inputType.Kind() == reflect.Struct 89 } 90 91 //IsSlice returns true if input is a map 92 func IsSlice(input interface{}) bool { 93 switch input.(type) { 94 case []interface{}: 95 return true 96 case []string: 97 return true 98 } 99 candidateType := DereferenceType(reflect.TypeOf(input)) 100 return candidateType.Kind() == reflect.Slice 101 } 102 103 //IsFunc returns true if input is a funct 104 func IsFunc(input interface{}) bool { 105 candidateType := DereferenceType(reflect.TypeOf(input)) 106 return candidateType.Kind() == reflect.Func 107 } 108 109 //IsZero returns true if input is a zeroable 110 func IsZero(input interface{}) bool { 111 if zeroable, ok := input.(Zeroable); ok { 112 return zeroable.IsZero() 113 } 114 return false 115 } 116 117 //IsPointer returns true if input is a pointer 118 func IsPointer(input interface{}) bool { 119 if reflectType, ok := input.(reflect.Type); ok { 120 return reflectType.Kind() == reflect.Ptr 121 } 122 return reflect.TypeOf(input).Kind() == reflect.Ptr 123 } 124 125 //AssertPointerKind checks if input is a pointer of the passed in kind, if not it panic with message including name 126 func AssertPointerKind(input interface{}, kind reflect.Kind, name string) { 127 AssertTypeKind(reflect.TypeOf(input), reflect.Ptr, name) 128 AssertTypeKind(reflect.TypeOf(input).Elem(), kind, name) 129 } 130 131 //AssertKind checks if input is of the passed in kind, if not it panic with message including name 132 func AssertKind(input interface{}, kind reflect.Kind, name string) { 133 AssertTypeKind(reflect.TypeOf(input), kind, name) 134 } 135 136 //AssertTypeKind checks if dataType is of the passed in kind, if not it panic with message including name 137 func AssertTypeKind(dataType reflect.Type, kind reflect.Kind, name string) { 138 if dataType.Kind() != kind { 139 panic(fmt.Sprintf("failed to check: %v - expected kind: %v but found %v (%v)", name, kind.String(), dataType.Kind(), dataType.String())) 140 } 141 } 142 143 //DiscoverValueByKind returns unwrapped input that matches expected kind, or panic if this is not possible 144 func DiscoverValueByKind(input interface{}, expected reflect.Kind) reflect.Value { 145 result, err := TryDiscoverValueByKind(input, expected) 146 if err == nil { 147 return result 148 } 149 panic(err) 150 } 151 152 //TryDiscoverValueByKind returns unwrapped input that matches expected kind, or panic if this is not possible 153 func TryDiscoverValueByKind(input interface{}, expected reflect.Kind) (reflect.Value, error) { 154 value, ok := input.(reflect.Value) 155 if !ok { 156 value = reflect.ValueOf(input) 157 } 158 if value.Kind() == expected { 159 return value, nil 160 } else if value.Kind() == reflect.Ptr { 161 return TryDiscoverValueByKind(value.Elem(), expected) 162 } else if value.Kind() == reflect.Interface { 163 return TryDiscoverValueByKind(value.Elem(), expected) 164 } 165 return value, fmt.Errorf("failed to discover value by kind expected: %v, actual:%T on %v:", expected.String(), value.Type(), value) 166 } 167 168 //IsValueOfKind returns true if passed in input is of supplied kind. 169 func IsValueOfKind(input interface{}, kind reflect.Kind) bool { 170 value, ok := input.(reflect.Value) 171 if !ok { 172 value = reflect.ValueOf(input) 173 } 174 if value.Kind() == kind { 175 return true 176 } else if value.Kind() == reflect.Ptr { 177 return IsValueOfKind(value.Elem(), kind) 178 } else if value.Kind() == reflect.Interface { 179 return IsValueOfKind(value.Elem(), kind) 180 } 181 return false 182 } 183 184 //DiscoverTypeByKind returns unwrapped input type that matches expected kind, or panic if this is not possible 185 func DiscoverTypeByKind(input interface{}, expected reflect.Kind) reflect.Type { 186 result, err := TryDiscoverTypeByKind(input, expected) 187 if err != nil { 188 panic(err) 189 } 190 return result 191 } 192 193 //TryDiscoverTypeByKind returns unwrapped input type that matches expected kind, or error 194 func TryDiscoverTypeByKind(input interface{}, expected reflect.Kind) (reflect.Type, error) { 195 value, ok := input.(reflect.Type) 196 if !ok { 197 value = reflect.TypeOf(input) 198 } 199 if value.Kind() == expected { 200 return value, nil 201 } else if value.Kind() == reflect.Ptr || value.Kind() == reflect.Slice { 202 return TryDiscoverTypeByKind(value.Elem(), expected) 203 } 204 return nil, fmt.Errorf("failed to discover type by kind %v, on %v:", expected.String(), value) 205 } 206 207 //DiscoverComponentType returns type unwrapped from pointer, slice or map 208 func DiscoverComponentType(input interface{}) reflect.Type { 209 valueType, ok := input.(reflect.Type) 210 if !ok { 211 valueType = reflect.TypeOf(input) 212 } 213 if valueType.Kind() == reflect.Ptr { 214 return DiscoverComponentType(valueType.Elem()) 215 } else if valueType.Kind() == reflect.Slice { 216 return valueType.Elem() 217 } else if valueType.Kind() == reflect.Map { 218 return valueType.Elem() 219 } 220 return valueType 221 }