157 lines
2.9 KiB
Go
157 lines
2.9 KiB
Go
package bind
|
|
|
|
import (
|
|
"reflect"
|
|
"time"
|
|
)
|
|
|
|
func bindScalar(receiver reflect.Value, values []any) bool {
|
|
if !receiver.IsValid() || len(values) == 0 {
|
|
return false
|
|
}
|
|
|
|
if !acceptsScalar(receiver.Type()) {
|
|
return false
|
|
}
|
|
|
|
if len(values) == 1 {
|
|
receiver = unpackValue(receiver, pointer|iface|slice)
|
|
if !receiver.CanSet() {
|
|
return false
|
|
}
|
|
|
|
v := reflect.ValueOf(values[0])
|
|
v = unpackValue(v, pointer|iface)
|
|
if !v.IsValid() && !isAny(receiver.Type()) {
|
|
return false
|
|
}
|
|
|
|
if !v.IsValid() {
|
|
receiver.Set(reflect.Zero(receiver.Type()))
|
|
return true
|
|
}
|
|
|
|
vv, ok := scan(receiver.Type(), v.Interface())
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
receiver.Set(reflect.ValueOf(vv))
|
|
return true
|
|
}
|
|
|
|
receiver = unpackValue(receiver, pointer|iface|anytype)
|
|
if receiver.Kind() != reflect.Slice || receiver.Len() < len(values) {
|
|
return false
|
|
}
|
|
|
|
for i := range values {
|
|
if !bindScalar(receiver.Index(i), []any{values[i]}) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func bindScalarCreate(t reflect.Type, values []any) (reflect.Value, bool) {
|
|
if len(values) == 0 {
|
|
return reflect.Zero(t), false
|
|
}
|
|
|
|
if hasCircularType(t) {
|
|
return reflect.Zero(t), false
|
|
}
|
|
|
|
for _, vi := range values {
|
|
if hasCircularReference(reflect.ValueOf(vi)) {
|
|
return reflect.Zero(t), false
|
|
}
|
|
}
|
|
|
|
if !acceptsScalar(t) {
|
|
return reflect.Zero(t), false
|
|
}
|
|
|
|
receiver, ok := allocate(t, len(values))
|
|
if !ok {
|
|
return reflect.Zero(t), false
|
|
}
|
|
|
|
if !bindScalar(receiver, values) {
|
|
return reflect.Zero(t), false
|
|
}
|
|
|
|
return receiver, true
|
|
}
|
|
|
|
func bindScalarReflect(receiver any, values []any) bool {
|
|
v := reflect.ValueOf(receiver)
|
|
if hasCircularReference(v) {
|
|
return false
|
|
}
|
|
|
|
for _, vi := range values {
|
|
if hasCircularReference(reflect.ValueOf(vi)) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return bindScalar(v, values)
|
|
}
|
|
|
|
func bindScalarCreateReflect[T any](values []any) (T, bool) {
|
|
t := reflect.TypeFor[T]()
|
|
v, ok := bindScalarCreate(t, values)
|
|
if !ok {
|
|
var tt T
|
|
return tt, false
|
|
}
|
|
|
|
return v.Interface().(T), true
|
|
}
|
|
|
|
func bindScalarCreateFieldType(t FieldType, values []any) (reflect.Value, bool) {
|
|
var r reflect.Type
|
|
switch t {
|
|
case Bool:
|
|
r = reflect.TypeFor[bool]()
|
|
case Int:
|
|
r = reflect.TypeFor[int]()
|
|
case Int8:
|
|
r = reflect.TypeFor[int8]()
|
|
case Int16:
|
|
r = reflect.TypeFor[int16]()
|
|
case Int32:
|
|
r = reflect.TypeFor[int32]()
|
|
case Int64:
|
|
r = reflect.TypeFor[int64]()
|
|
case Uint:
|
|
r = reflect.TypeFor[uint]()
|
|
case Uint8:
|
|
r = reflect.TypeFor[uint8]()
|
|
case Uint16:
|
|
r = reflect.TypeFor[uint16]()
|
|
case Uint32:
|
|
r = reflect.TypeFor[uint32]()
|
|
case Uint64:
|
|
r = reflect.TypeFor[uint64]()
|
|
case Float32:
|
|
r = reflect.TypeFor[float32]()
|
|
case Float64:
|
|
r = reflect.TypeFor[float64]()
|
|
case String:
|
|
r = reflect.TypeFor[string]()
|
|
case Any:
|
|
r = reflect.TypeFor[any]()
|
|
case Duration:
|
|
r = reflect.TypeFor[time.Duration]()
|
|
case Time:
|
|
r = reflect.TypeFor[time.Time]()
|
|
default:
|
|
return reflect.Value{}, false
|
|
}
|
|
|
|
return bindScalarCreate(r, values)
|
|
}
|