mirror of
https://github.com/mudler/luet.git
synced 2025-09-02 07:45:02 +00:00
update vendor/
This commit is contained in:
185
vendor/github.com/jinzhu/copier/copier.go
generated
vendored
Normal file
185
vendor/github.com/jinzhu/copier/copier.go
generated
vendored
Normal file
@@ -0,0 +1,185 @@
|
||||
package copier
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Copy copy things
|
||||
func Copy(toValue interface{}, fromValue interface{}) (err error) {
|
||||
var (
|
||||
isSlice bool
|
||||
amount = 1
|
||||
from = indirect(reflect.ValueOf(fromValue))
|
||||
to = indirect(reflect.ValueOf(toValue))
|
||||
)
|
||||
|
||||
if !to.CanAddr() {
|
||||
return errors.New("copy to value is unaddressable")
|
||||
}
|
||||
|
||||
// Return is from value is invalid
|
||||
if !from.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
// Just set it if possible to assign
|
||||
if from.Type().AssignableTo(to.Type()) {
|
||||
to.Set(from)
|
||||
return
|
||||
}
|
||||
|
||||
fromType := indirectType(from.Type())
|
||||
toType := indirectType(to.Type())
|
||||
|
||||
if fromType.Kind() != reflect.Struct || toType.Kind() != reflect.Struct {
|
||||
return
|
||||
}
|
||||
|
||||
if to.Kind() == reflect.Slice {
|
||||
isSlice = true
|
||||
if from.Kind() == reflect.Slice {
|
||||
amount = from.Len()
|
||||
}
|
||||
}
|
||||
|
||||
for i := 0; i < amount; i++ {
|
||||
var dest, source reflect.Value
|
||||
|
||||
if isSlice {
|
||||
// source
|
||||
if from.Kind() == reflect.Slice {
|
||||
source = indirect(from.Index(i))
|
||||
} else {
|
||||
source = indirect(from)
|
||||
}
|
||||
|
||||
// dest
|
||||
dest = indirect(reflect.New(toType).Elem())
|
||||
} else {
|
||||
source = indirect(from)
|
||||
dest = indirect(to)
|
||||
}
|
||||
|
||||
// Copy from field to field or method
|
||||
for _, field := range deepFields(fromType) {
|
||||
name := field.Name
|
||||
|
||||
if fromField := source.FieldByName(name); fromField.IsValid() {
|
||||
// has field
|
||||
if toField := dest.FieldByName(name); toField.IsValid() {
|
||||
if toField.CanSet() {
|
||||
if !set(toField, fromField) {
|
||||
if err := Copy(toField.Addr().Interface(), fromField.Interface()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// try to set to method
|
||||
var toMethod reflect.Value
|
||||
if dest.CanAddr() {
|
||||
toMethod = dest.Addr().MethodByName(name)
|
||||
} else {
|
||||
toMethod = dest.MethodByName(name)
|
||||
}
|
||||
|
||||
if toMethod.IsValid() && toMethod.Type().NumIn() == 1 && fromField.Type().AssignableTo(toMethod.Type().In(0)) {
|
||||
toMethod.Call([]reflect.Value{fromField})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy from method to field
|
||||
for _, field := range deepFields(toType) {
|
||||
name := field.Name
|
||||
|
||||
var fromMethod reflect.Value
|
||||
if source.CanAddr() {
|
||||
fromMethod = source.Addr().MethodByName(name)
|
||||
} else {
|
||||
fromMethod = source.MethodByName(name)
|
||||
}
|
||||
|
||||
if fromMethod.IsValid() && fromMethod.Type().NumIn() == 0 && fromMethod.Type().NumOut() == 1 {
|
||||
if toField := dest.FieldByName(name); toField.IsValid() && toField.CanSet() {
|
||||
values := fromMethod.Call([]reflect.Value{})
|
||||
if len(values) >= 1 {
|
||||
set(toField, values[0])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if isSlice {
|
||||
if dest.Addr().Type().AssignableTo(to.Type().Elem()) {
|
||||
to.Set(reflect.Append(to, dest.Addr()))
|
||||
} else if dest.Type().AssignableTo(to.Type().Elem()) {
|
||||
to.Set(reflect.Append(to, dest))
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func deepFields(reflectType reflect.Type) []reflect.StructField {
|
||||
var fields []reflect.StructField
|
||||
|
||||
if reflectType = indirectType(reflectType); reflectType.Kind() == reflect.Struct {
|
||||
for i := 0; i < reflectType.NumField(); i++ {
|
||||
v := reflectType.Field(i)
|
||||
if v.Anonymous {
|
||||
fields = append(fields, deepFields(v.Type)...)
|
||||
} else {
|
||||
fields = append(fields, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
func indirect(reflectValue reflect.Value) reflect.Value {
|
||||
for reflectValue.Kind() == reflect.Ptr {
|
||||
reflectValue = reflectValue.Elem()
|
||||
}
|
||||
return reflectValue
|
||||
}
|
||||
|
||||
func indirectType(reflectType reflect.Type) reflect.Type {
|
||||
for reflectType.Kind() == reflect.Ptr || reflectType.Kind() == reflect.Slice {
|
||||
reflectType = reflectType.Elem()
|
||||
}
|
||||
return reflectType
|
||||
}
|
||||
|
||||
func set(to, from reflect.Value) bool {
|
||||
if from.IsValid() {
|
||||
if to.Kind() == reflect.Ptr {
|
||||
//set `to` to nil if from is nil
|
||||
if from.Kind() == reflect.Ptr && from.IsNil() {
|
||||
to.Set(reflect.Zero(to.Type()))
|
||||
return true
|
||||
} else if to.IsNil() {
|
||||
to.Set(reflect.New(to.Type().Elem()))
|
||||
}
|
||||
to = to.Elem()
|
||||
}
|
||||
|
||||
if from.Type().ConvertibleTo(to.Type()) {
|
||||
to.Set(from.Convert(to.Type()))
|
||||
} else if scanner, ok := to.Addr().Interface().(sql.Scanner); ok {
|
||||
err := scanner.Scan(from.Interface())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
} else if from.Kind() == reflect.Ptr {
|
||||
return set(to, from.Elem())
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
Reference in New Issue
Block a user