70 lines
1.4 KiB
Go
70 lines
1.4 KiB
Go
package patient
|
|
|
|
import (
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
func SetPatient(dst, src interface{}, preserve map[string]bool) {
|
|
dv := reflect.ValueOf(dst).Elem()
|
|
sv := reflect.ValueOf(src).Elem()
|
|
|
|
for i := 0; i < dv.NumField(); i++ {
|
|
f := dv.Type().Field(i)
|
|
fieldName := f.Name
|
|
|
|
// skip preserved fields
|
|
if preserve[fieldName] {
|
|
continue
|
|
}
|
|
|
|
df := dv.Field(i)
|
|
sf := sv.Field(i)
|
|
if !df.CanSet() {
|
|
// skip unexported skip
|
|
continue
|
|
}
|
|
|
|
switch df.Kind() {
|
|
|
|
case reflect.Struct:
|
|
nestedPreserve := map[string]bool{}
|
|
|
|
for key := range preserve {
|
|
if strings.HasPrefix(key, fieldName+".") {
|
|
nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true
|
|
}
|
|
}
|
|
|
|
SetPatient(df.Addr().Interface(), sf.Addr().Interface(), nestedPreserve)
|
|
case reflect.Pointer:
|
|
// Check if pointer points to a struct
|
|
if df.Type().Elem().Kind() == reflect.Struct {
|
|
if sf.IsNil() {
|
|
break
|
|
}
|
|
|
|
// If dest pointer is nil, allocate it
|
|
if df.IsNil() {
|
|
df.Set(reflect.New(df.Type().Elem()))
|
|
}
|
|
|
|
// Recurse into struct via Elem()
|
|
nestedPreserve := map[string]bool{}
|
|
for key := range preserve {
|
|
if strings.HasPrefix(key, fieldName+".") {
|
|
nestedPreserve[strings.TrimPrefix(key, fieldName+".")] = true
|
|
}
|
|
}
|
|
|
|
SetPatient(df.Elem().Addr().Interface(), sf.Elem().Addr().Interface(), nestedPreserve)
|
|
}
|
|
default:
|
|
// Overwrite only when src has non-zero value
|
|
if !sf.IsZero() {
|
|
df.Set(sf)
|
|
}
|
|
}
|
|
}
|
|
}
|