diff --git a/vendor/yunion.io/x/pkg/util/reflectutils/reflectutils.go b/vendor/yunion.io/x/pkg/util/reflectutils/reflectutils.go index 55d9019d8e..7c4bfca7e9 100644 --- a/vendor/yunion.io/x/pkg/util/reflectutils/reflectutils.go +++ b/vendor/yunion.io/x/pkg/util/reflectutils/reflectutils.go @@ -1,6 +1,7 @@ package reflectutils import ( + "fmt" "reflect" "strings" @@ -174,3 +175,37 @@ func ExpandInterface(val interface{}) []interface{} { return []interface{}{val} } } + +// tagetType must not be a pointer +func getAnonymouStructPointer(structValue reflect.Value, targetType reflect.Type) interface{} { + structType := structValue.Type() + for i := 0; i < structValue.NumField(); i += 1 { + fieldType := structType.Field(i) + if fieldType.Type == targetType { + val := structValue.Field(i) // val is not a pointer + return val.Addr().Interface() + } + if fieldType.Anonymous && fieldType.Type.Kind() == reflect.Struct { + ptr := getAnonymouStructPointer(structValue.Field(i), targetType) + if ptr != nil { + return ptr + } + } + } + return nil +} + +func FindAnonymouStructPointer(data interface{}, targetPtr interface{}) error { + targetValue := reflect.ValueOf(targetPtr).Elem() + if targetValue.Kind() != reflect.Ptr { + return fmt.Errorf("target must be a pointer to pointer") + } + targetType := targetValue.Type().Elem() + structValue := reflect.Indirect(reflect.ValueOf(data)) + ptr := getAnonymouStructPointer(structValue, targetType) + if ptr == nil { + return fmt.Errorf("no anonymous struct found") + } + targetValue.Set(reflect.ValueOf(ptr)) + return nil +}