istio

Форк
0
/
reflect.go 
316 строк · 8.6 Кб
1
// Copyright Istio Authors
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//     http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14

15
package util
16

17
import (
18
	"fmt"
19
	"reflect"
20
)
21

22
// kindOf returns the reflection Kind that represents the dynamic type of value.
23
// If value is a nil interface value, kindOf returns reflect.Invalid.
24
func kindOf(value any) reflect.Kind {
25
	if value == nil {
26
		return reflect.Invalid
27
	}
28
	return reflect.TypeOf(value).Kind()
29
}
30

31
// IsString reports whether value is a string type.
32
func IsString(value any) bool {
33
	return kindOf(value) == reflect.String
34
}
35

36
// IsPtr reports whether value is a ptr type.
37
func IsPtr(value any) bool {
38
	return kindOf(value) == reflect.Ptr
39
}
40

41
// IsMap reports whether value is a map type.
42
func IsMap(value any) bool {
43
	return kindOf(value) == reflect.Map
44
}
45

46
// IsMapPtr reports whether v is a map ptr type.
47
func IsMapPtr(v any) bool {
48
	t := reflect.TypeOf(v)
49
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Map
50
}
51

52
// IsSlice reports whether value is a slice type.
53
func IsSlice(value any) bool {
54
	return kindOf(value) == reflect.Slice
55
}
56

57
// IsStruct reports whether value is a struct type
58
func IsStruct(value any) bool {
59
	return kindOf(value) == reflect.Struct
60
}
61

62
// IsSlicePtr reports whether v is a slice ptr type.
63
func IsSlicePtr(v any) bool {
64
	return kindOf(v) == reflect.Ptr && reflect.TypeOf(v).Elem().Kind() == reflect.Slice
65
}
66

67
// IsSliceInterfacePtr reports whether v is a slice ptr type.
68
func IsSliceInterfacePtr(v any) bool {
69
	// Must use ValueOf because Elem().Elem() type resolves dynamically.
70
	vv := reflect.ValueOf(v)
71
	return vv.Kind() == reflect.Ptr && vv.Elem().Kind() == reflect.Interface && vv.Elem().Elem().Kind() == reflect.Slice
72
}
73

74
// IsTypeStructPtr reports whether v is a struct ptr type.
75
func IsTypeStructPtr(t reflect.Type) bool {
76
	if t == reflect.TypeOf(nil) {
77
		return false
78
	}
79
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Struct
80
}
81

82
// IsTypeSlicePtr reports whether v is a slice ptr type.
83
func IsTypeSlicePtr(t reflect.Type) bool {
84
	if t == reflect.TypeOf(nil) {
85
		return false
86
	}
87
	return t.Kind() == reflect.Ptr && t.Elem().Kind() == reflect.Slice
88
}
89

90
// IsTypeMap reports whether v is a map type.
91
func IsTypeMap(t reflect.Type) bool {
92
	if t == reflect.TypeOf(nil) {
93
		return false
94
	}
95
	return t.Kind() == reflect.Map
96
}
97

98
// IsTypeInterface reports whether v is an interface.
99
func IsTypeInterface(t reflect.Type) bool {
100
	if t == reflect.TypeOf(nil) {
101
		return false
102
	}
103
	return t.Kind() == reflect.Interface
104
}
105

106
// IsTypeSliceOfInterface reports whether v is a slice of interface.
107
func IsTypeSliceOfInterface(t reflect.Type) bool {
108
	if t == reflect.TypeOf(nil) {
109
		return false
110
	}
111
	return t.Kind() == reflect.Slice && t.Elem().Kind() == reflect.Interface
112
}
113

114
// IsNilOrInvalidValue reports whether v is nil or reflect.Zero.
115
func IsNilOrInvalidValue(v reflect.Value) bool {
116
	return !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) || IsValueNil(v.Interface())
117
}
118

119
// IsValueNil returns true if either value is nil, or has dynamic type {ptr,
120
// map, slice} with value nil.
121
func IsValueNil(value any) bool {
122
	if value == nil {
123
		return true
124
	}
125
	switch kindOf(value) {
126
	case reflect.Slice, reflect.Ptr, reflect.Map:
127
		return reflect.ValueOf(value).IsNil()
128
	}
129
	return false
130
}
131

132
// IsValueNilOrDefault returns true if either IsValueNil(value) or the default
133
// value for the type.
134
func IsValueNilOrDefault(value any) bool {
135
	if IsValueNil(value) {
136
		return true
137
	}
138
	if !IsValueScalar(reflect.ValueOf(value)) {
139
		// Default value is nil for non-scalar types.
140
		return false
141
	}
142
	return value == reflect.New(reflect.TypeOf(value)).Elem().Interface()
143
}
144

145
// IsValuePtr reports whether v is a ptr type.
146
func IsValuePtr(v reflect.Value) bool {
147
	return v.Kind() == reflect.Ptr
148
}
149

150
// IsValueInterface reports whether v is an interface type.
151
func IsValueInterface(v reflect.Value) bool {
152
	return v.Kind() == reflect.Interface
153
}
154

155
// IsValueStruct reports whether v is a struct type.
156
func IsValueStruct(v reflect.Value) bool {
157
	return v.Kind() == reflect.Struct
158
}
159

160
// IsValueStructPtr reports whether v is a struct ptr type.
161
func IsValueStructPtr(v reflect.Value) bool {
162
	return v.Kind() == reflect.Ptr && IsValueStruct(v.Elem())
163
}
164

165
// IsValueMap reports whether v is a map type.
166
func IsValueMap(v reflect.Value) bool {
167
	return v.Kind() == reflect.Map
168
}
169

170
// IsValueSlice reports whether v is a slice type.
171
func IsValueSlice(v reflect.Value) bool {
172
	return v.Kind() == reflect.Slice
173
}
174

175
// IsValueScalar reports whether v is a scalar type.
176
func IsValueScalar(v reflect.Value) bool {
177
	if IsNilOrInvalidValue(v) {
178
		return false
179
	}
180
	if IsValuePtr(v) {
181
		if v.IsNil() {
182
			return false
183
		}
184
		v = v.Elem()
185
	}
186
	return !IsValueStruct(v) && !IsValueMap(v) && !IsValueSlice(v)
187
}
188

189
// ValuesAreSameType returns true if v1 and v2 has the same reflect.Type,
190
// otherwise it returns false.
191
func ValuesAreSameType(v1 reflect.Value, v2 reflect.Value) bool {
192
	return v1.Type() == v2.Type()
193
}
194

195
// IsEmptyString returns true if value is an empty string.
196
func IsEmptyString(value any) bool {
197
	if value == nil {
198
		return true
199
	}
200
	switch kindOf(value) {
201
	case reflect.String:
202
		if _, ok := value.(string); ok {
203
			return value.(string) == ""
204
		}
205
	}
206
	return false
207
}
208

209
// DeleteFromSlicePtr deletes an entry at index from the parent, which must be a slice ptr.
210
func DeleteFromSlicePtr(parentSlice any, index int) error {
211
	scope.Debugf("DeleteFromSlicePtr index=%d, slice=\n%v", index, parentSlice)
212
	pv := reflect.ValueOf(parentSlice)
213

214
	if !IsSliceInterfacePtr(parentSlice) {
215
		return fmt.Errorf("deleteFromSlicePtr parent type is %T, must be *[]interface{}", parentSlice)
216
	}
217

218
	pvv := pv.Elem()
219
	if pvv.Kind() == reflect.Interface {
220
		pvv = pvv.Elem()
221
	}
222

223
	pv.Elem().Set(reflect.AppendSlice(pvv.Slice(0, index), pvv.Slice(index+1, pvv.Len())))
224

225
	return nil
226
}
227

228
// UpdateSlicePtr updates an entry at index in the parent, which must be a slice ptr, with the given value.
229
func UpdateSlicePtr(parentSlice any, index int, value any) error {
230
	scope.Debugf("UpdateSlicePtr parent=\n%v\n, index=%d, value=\n%v", parentSlice, index, value)
231
	pv := reflect.ValueOf(parentSlice)
232
	v := reflect.ValueOf(value)
233

234
	if !IsSliceInterfacePtr(parentSlice) {
235
		return fmt.Errorf("updateSlicePtr parent type is %T, must be *[]interface{}", parentSlice)
236
	}
237

238
	pvv := pv.Elem()
239
	if pvv.Kind() == reflect.Interface {
240
		pv.Elem().Elem().Index(index).Set(v)
241
		return nil
242
	}
243
	pv.Elem().Index(index).Set(v)
244

245
	return nil
246
}
247

248
// InsertIntoMap inserts value with key into parent which must be a map, map ptr, or interface to map.
249
func InsertIntoMap(parentMap any, key any, value any) error {
250
	scope.Debugf("InsertIntoMap key=%v, value=%v, map=\n%v", key, value, parentMap)
251
	v := reflect.ValueOf(parentMap)
252
	kv := reflect.ValueOf(key)
253
	vv := reflect.ValueOf(value)
254

255
	if v.Type().Kind() == reflect.Ptr {
256
		v = v.Elem()
257
	}
258
	if v.Type().Kind() == reflect.Interface {
259
		v = v.Elem()
260
	}
261

262
	if v.Type().Kind() != reflect.Map {
263
		scope.Debugf("error %v", v.Type().Kind())
264
		return fmt.Errorf("insertIntoMap parent type is %T, must be map", parentMap)
265
	}
266

267
	v.SetMapIndex(kv, vv)
268

269
	return nil
270
}
271

272
// DeleteFromMap deletes an entry with the given key parent, which must be a map.
273
func DeleteFromMap(parentMap any, key any) error {
274
	scope.Debugf("DeleteFromMap key=%s, parent:\n%v\n", key, parentMap)
275
	pv := reflect.ValueOf(parentMap)
276

277
	if !IsMap(parentMap) {
278
		return fmt.Errorf("deleteFromMap parent type is %T, must be map", parentMap)
279
	}
280
	pv.SetMapIndex(reflect.ValueOf(key), reflect.Value{})
281

282
	return nil
283
}
284

285
// ToIntValue returns 0, false if val is not a number type, otherwise it returns the int value of val.
286
func ToIntValue(val any) (int, bool) {
287
	if IsValueNil(val) {
288
		return 0, false
289
	}
290
	v := reflect.ValueOf(val)
291
	switch {
292
	case IsIntKind(v.Kind()):
293
		return int(v.Int()), true
294
	case IsUintKind(v.Kind()):
295
		return int(v.Uint()), true
296
	}
297
	return 0, false
298
}
299

300
// IsIntKind reports whether k is an integer kind of any size.
301
func IsIntKind(k reflect.Kind) bool {
302
	switch k {
303
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
304
		return true
305
	}
306
	return false
307
}
308

309
// IsUintKind reports whether k is an unsigned integer kind of any size.
310
func IsUintKind(k reflect.Kind) bool {
311
	switch k {
312
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
313
		return true
314
	}
315
	return false
316
}
317

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.