(from, i any)
| 19 | } |
| 20 | |
| 21 | func Fetch(from, i any) any { |
| 22 | v := reflect.ValueOf(from) |
| 23 | if v.Kind() == reflect.Invalid { |
| 24 | panic(fmt.Sprintf("cannot fetch %v from %T", i, from)) |
| 25 | } |
| 26 | |
| 27 | // Methods can be defined on any type. |
| 28 | if v.NumMethod() > 0 { |
| 29 | if methodName, ok := i.(string); ok { |
| 30 | method := v.MethodByName(methodName) |
| 31 | if method.IsValid() { |
| 32 | return method.Interface() |
| 33 | } |
| 34 | } |
| 35 | } |
| 36 | |
| 37 | // Structs, maps, and slices can be access through a pointer or through |
| 38 | // a value, when they are accessed through a pointer we don't want to |
| 39 | // copy them to a value. |
| 40 | // De-reference everything if necessary (interface and pointers) |
| 41 | v = deref.Value(v) |
| 42 | |
| 43 | switch v.Kind() { |
| 44 | case reflect.Array, reflect.Slice, reflect.String: |
| 45 | index := ToInt(i) |
| 46 | l := v.Len() |
| 47 | if index < 0 { |
| 48 | index = l + index |
| 49 | } |
| 50 | if index < 0 || index >= l { |
| 51 | panic(fmt.Sprintf("index out of range: %v (array length is %v)", index, l)) |
| 52 | } |
| 53 | value := v.Index(index) |
| 54 | if value.IsValid() { |
| 55 | return value.Interface() |
| 56 | } |
| 57 | |
| 58 | case reflect.Map: |
| 59 | var value reflect.Value |
| 60 | if i == nil { |
| 61 | value = v.MapIndex(reflect.Zero(v.Type().Key())) |
| 62 | } else { |
| 63 | value = v.MapIndex(reflect.ValueOf(i)) |
| 64 | } |
| 65 | if value.IsValid() { |
| 66 | return value.Interface() |
| 67 | } else { |
| 68 | elem := reflect.TypeOf(from).Elem() |
| 69 | return reflect.Zero(elem).Interface() |
| 70 | } |
| 71 | |
| 72 | case reflect.Struct: |
| 73 | fieldName := i.(string) |
| 74 | t := v.Type() |
| 75 | key := fieldCacheKey{ |
| 76 | t: t, |
| 77 | f: fieldName, |
| 78 | } |
no test coverage detected
searching dependent graphs…