-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathreflect.go
300 lines (255 loc) · 9.35 KB
/
reflect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
package typ
import (
"math"
"math/big"
"reflect"
)
var complexFloatMap = map[reflect.Kind]reflect.Kind{
reflect.Complex64: reflect.Float32,
reflect.Complex128: reflect.Float64,
}
var bitSizeMap = map[reflect.Kind]int{
reflect.Int8: 8,
reflect.Int16: 16,
reflect.Int32: 32,
reflect.Int64: 64,
reflect.Int: 64,
reflect.Uint8: 8,
reflect.Uint16: 16,
reflect.Uint32: 32,
reflect.Uint64: 64,
reflect.Uint: 64,
reflect.Float32: 32,
reflect.Float64: 64,
reflect.Complex64: 32,
reflect.Complex128: 64,
}
// Determine whether a value can safely convert between float
func isSafeFloat(from float64, floatBitSize int) bool {
if math.IsInf(from, 0) || math.IsNaN(from) {
return true
}
if floatBitSize <= 32 && from != 0 {
_, accuracy := big.NewFloat(from).Float32()
return accuracy == big.Exact
}
return true
}
// Determine whether a value can safely convert from float to int
func isSafeFloatToInt(from float64, floatBitSize, intBitSize int) bool {
if math.IsNaN(from) {
return false
}
_, exp := math.Frexp(math.Abs(from))
safeFloat := big.NewFloat(from).IsInt() && ((floatBitSize <= 32 && exp <= 24) || (floatBitSize > 32 && exp <= 53))
return safeFloat && isSafeInt(int64(from), intBitSize)
}
// Determine whether a value can safely convert from float to uint
func isSafeFloatToUint(from float64, floatBitSize, uintBitSize int) bool {
if from < 0 || math.IsNaN(from) {
return false
}
_, exp := math.Frexp(math.Abs(from))
safeFloat := big.NewFloat(from).IsInt() && ((floatBitSize <= 32 && exp <= 24) || (floatBitSize > 32 && exp <= 53))
return safeFloat && isSafeUint(uint64(from), uintBitSize)
}
// Determine whether a value can safely convert between complex
func isSafeComplex(from complex128, floatBitSize int) bool {
return isSafeFloat(real(from), floatBitSize) && isSafeFloat(imag(from), floatBitSize)
}
// Determine whether a value can safely convert from complex to float
func isSafeComplexToFloat(from complex128, floatBitSize int) bool {
return isSafeFloat(real(from), floatBitSize) && imag(from) == 0
}
// Determine whether a value can safely convert from complex to int
func isSafeComplexToInt(from complex128, floatBitSize, intBitSize int) bool {
return isSafeFloatToInt(real(from), floatBitSize, intBitSize) && imag(from) == 0
}
// Determine whether a value can safely convert from complex to uint
func isSafeComplexToUint(from complex128, floatBitSize, uintBitSize int) bool {
return isSafeFloatToUint(real(from), floatBitSize, uintBitSize) && imag(from) == 0
}
// Determine whether a value can safely convert between int
func isSafeInt(from int64, intBitSize int) bool {
maxValue := int64(1<<uint(intBitSize-1) - 1)
return from >= ^maxValue && from <= maxValue
}
// Determine whether a value can safely convert from int to float
func isSafeIntToFloat(from int64, floatBitSize int) bool {
floatValue := float64(from)
_, exp := math.Frexp(math.Abs(floatValue))
return ((floatBitSize <= 32 && exp <= 24) || (floatBitSize > 32 && exp <= 53)) && isSafeInt(from, floatBitSize)
}
// Determine whether a value can safely convert from int to uint
func isSafeIntToUint(from int64, uintBitSize int) bool {
return from >= 0 && uint64(from) <= uint64(1<<uint(uintBitSize)-1)
}
// Determine whether a value can safely convert between uint
func isSafeUint(from uint64, uintBitSize int) bool {
maxValue := uint64(1<<uint(uintBitSize) - 1)
return from <= maxValue
}
// Determine whether a value can safely convert from uint to float
func isSafeUintToFloat(from uint64, floatBitSize int) bool {
floatValue := float64(from)
_, exp := math.Frexp(math.Abs(floatValue))
return ((floatBitSize <= 32 && exp <= 24) || (floatBitSize > 32 && exp <= 53)) && isSafeUint(from, floatBitSize)
}
// Determine whether a value can safely convert from uint to int
func isSafeUintToInt(from uint64, intBitSize int) bool {
return from <= uint64(1<<uint(intBitSize-1)-1)
}
// Determine whether a reflect type is primitives type (int, uint, float, complex, bool)
func isPrimitives(kind reflect.Kind) bool {
return isNumeric(kind) || kind == reflect.Bool
}
// Determine whether a reflect type is composite type (array, slice, map)
func isComposite(kind reflect.Kind) bool {
return kind == reflect.Array || kind == reflect.Slice || kind == reflect.Map
}
// Determine whether a reflect type is signed integer type
func isInt(kind reflect.Kind) bool {
switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return true
}
return false
}
// Determine whether a reflect type is unsigned integer type
func isUint(kind reflect.Kind) bool {
switch kind {
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return true
}
return false
}
// Determine whether a reflect type is float type
func isFloat(kind reflect.Kind) bool {
switch kind {
case reflect.Float32, reflect.Float64:
return true
}
return false
}
// Determine whether a reflect type is complex type
func isComplex(kind reflect.Kind) bool {
switch kind {
case reflect.Complex64, reflect.Complex128:
return true
}
return false
}
// Determine whether a reflect type is numeric type (int, uint, float, complex)
func isNumeric(kind reflect.Kind) bool {
return isInt(kind) || isUint(kind) || isFloat(kind) || isComplex(kind)
}
// Determine whether a reflect type is pointer type
func isPointer(kind reflect.Kind) bool {
switch kind {
case reflect.Ptr, reflect.Uintptr, reflect.UnsafePointer:
return true
}
return false
}
// Determine whether a value is bool type
func isBool(kind reflect.Kind) bool {
return kind == reflect.Bool
}
// Determine whether a value is string type
func isString(kind reflect.Kind) bool {
return kind == reflect.String
}
// Determine whether a value is float32 type
func isFloat32(kind reflect.Kind) bool {
return kind == reflect.Float32
}
// Determine whether a value is float64 type
func isFloat64(kind reflect.Kind) bool {
return kind == reflect.Float64
}
// Determine whether a value is complex64 type
func isComplex64(kind reflect.Kind) bool {
return kind == reflect.Complex64
}
// Determine whether a value is complex128 type
func isComplex128(kind reflect.Kind) bool {
return kind == reflect.Complex128
}
// IsPrimitives determine whether a value is primitives type (int, uint, float, complex, bool)
// If indirect argument specified, real reflect type returned
func (t *Type) IsPrimitives(indirect ...bool) bool {
return isPrimitives(t.Kind(indirect...))
}
// IsComposite determine whether a value is composite type (array, slice, map)
// If indirect argument specified, real reflect type returned
func (t *Type) IsComposite(indirect ...bool) bool {
return isComposite(t.Kind(indirect...))
}
// IsInt determine whether a value is signed integer type
// If indirect argument specified, real reflect type returned
func (t *Type) IsInt(indirect ...bool) bool {
return isInt(t.Kind(indirect...))
}
// IsUint determine whether a value is unsigned integer type
// If indirect argument specified, real reflect type returned
func (t *Type) IsUint(indirect ...bool) bool {
return isUint(t.Kind(indirect...))
}
// IsFloat determine whether a value is float type
// If indirect argument specified, real reflect type returned
func (t *Type) IsFloat(indirect ...bool) bool {
return isFloat(t.Kind(indirect...))
}
// IsComplex determine whether a value is complex type
// If indirect argument specified, real reflect type returned
func (t *Type) IsComplex(indirect ...bool) bool {
return isComplex(t.Kind(indirect...))
}
// IsNumeric determine whether a value is numeric type (int, uint, float, complex)
// If indirect argument specified, real reflect type returned
func (t *Type) IsNumeric(indirect ...bool) bool {
return isNumeric(t.Kind(indirect...))
}
// IsPointer determine whether a value is pointer type (Ptr, UnsafePointer, Uintptr)
// If indirect argument specified, real reflect type returned
func (t *Type) IsPointer(indirect ...bool) bool {
return isPointer(t.Kind(indirect...))
}
// IsBool determine whether a value is boolean type
// If indirect argument specified, real reflect type returned
func (t *Type) IsBool(indirect ...bool) bool {
return isBool(t.Kind(indirect...))
}
// IsString determine whether a value is string type
// If indirect argument specified, real reflect type returned
func (t *Type) IsString(indirect ...bool) bool {
return isString(t.Kind(indirect...))
}
// IsFloat32 determine whether a value is float32 type
// If indirect argument specified, real reflect type returned
func (t *Type) IsFloat32(indirect ...bool) bool {
return isFloat32(t.Kind(indirect...))
}
// IsFloat64 determine whether a value is float64 type
// If indirect argument specified, real reflect type returned
func (t *Type) IsFloat64(indirect ...bool) bool {
return isFloat64(t.Kind(indirect...))
}
// IsComplex64 determine whether a value is complex64 type
// If indirect argument specified, real reflect type returned
func (t *Type) IsComplex64(indirect ...bool) bool {
return isComplex64(t.Kind(indirect...))
}
// IsComplex128 determine whether a value is complex128 type
// If indirect argument specified, real reflect type returned
func (t *Type) IsComplex128(indirect ...bool) bool {
return isComplex128(t.Kind(indirect...))
}
// Kind returns reflect type
// If indirect argument specified, real reflect type returned
func (t *Type) Kind(indirect ...bool) reflect.Kind {
if len(indirect) > 0 && indirect[0] {
return t.rv.Kind()
}
return t.kind
}