Skip to content
Snippets Groups Projects
Select Git revision
  • 4d59a554970de40dabfb4e2d4dca023810529a15
  • main default protected
  • v1.298.0
  • v1.297.0
  • v1.296.0
  • v1.295.0
  • v1.294.0
  • v1.293.0
  • v1.292.0
  • v1.291.0
  • v1.290.0
  • v1.289.0
  • v1.288.0
  • v1.287.0
  • v1.286.0
  • v1.285.0
  • v1.284.0
  • v1.283.0
  • v1.282.0
  • v1.281.0
  • v1.280.0
  • v1.279.0
22 results

type_clone.go

Blame
  • user avatar
    Jan Semmelink authored
    4d59a554
    History
    type_clone.go 1.65 KiB
    package reflection
    
    import (
    	"reflect"
    	"strings"
    
    	"gitlab.com/uafrica/go-utils/errors"
    )
    
    func CloneType(t reflect.Type, replace map[string]reflect.Type) (reflect.Type, error) {
    	return clone("", t, replace)
    }
    
    func clone(name string, t reflect.Type, replace map[string]reflect.Type) (reflect.Type, error) {
    	switch t.Kind() {
    	case reflect.Struct:
    		fields := []reflect.StructField{}
    		for i := 0; i < t.NumField(); i++ {
    			f := t.Field(i)
    			n := strings.SplitN(f.Tag.Get("json"), ",", 2)[0] //exclude ,omitempty...
    			if n == "" {
    				n = f.Name
    			}
    			fieldName := name + "." + n
    			for replaceName, replaceType := range replace {
    				if strings.HasPrefix(replaceName, fieldName) {
    					if replaceName == fieldName {
    						f.Type = replaceType
    					} else {
    						clonedType, err := clone(fieldName, f.Type, replace)
    						if err != nil {
    							return t, errors.Wrapf(err, "failed to clone %s", fieldName)
    						}
    						f.Type = clonedType
    					}
    				}
    			}
    			if newType, ok := replace[fieldName]; ok {
    				f.Type = newType
    			}
    			fields = append(fields, f)
    		}
    		return reflect.StructOf(fields), nil
    
    	case reflect.Slice:
    		for replaceName, replaceType := range replace {
    			if strings.HasPrefix(replaceName, name+"[]") {
    				if replaceName == name+"[]" {
    					//full match
    					return replaceType, nil
    				} else {
    					elemType, err := clone(name+"[]", t.Elem(), replace)
    					if err != nil {
    						return t, errors.Wrapf(err, "failed to clone slice elem type")
    					}
    					return reflect.SliceOf(elemType), nil
    				}
    			} else {
    				return t, nil
    			}
    		}
    
    		return t, errors.Errorf("NYI")
    
    	default:
    	}
    	return t, errors.Errorf("cannot clone %v %s", t.Kind(), t.Name())
    }