1
0
bind/scalar.go

157 lines
2.9 KiB
Go
Raw Normal View History

2025-08-27 21:03:25 +02:00
package bind
2025-09-04 01:48:21 +02:00
import (
"reflect"
"time"
)
2025-08-27 21:03:25 +02:00
func bindScalar(receiver reflect.Value, values []any) bool {
2025-08-31 17:11:09 +02:00
if !receiver.IsValid() || len(values) == 0 {
2025-08-27 21:03:25 +02:00
return false
}
if !acceptsScalar(receiver.Type()) {
return false
}
if len(values) == 1 {
receiver = unpackValue(receiver, pointer|iface|slice)
2025-08-31 17:11:09 +02:00
if !receiver.CanSet() {
return false
}
v := reflect.ValueOf(values[0])
v = unpackValue(v, pointer|iface)
if !v.IsValid() && !isAny(receiver.Type()) {
2025-08-27 21:03:25 +02:00
return false
}
if !v.IsValid() {
2025-08-31 17:11:09 +02:00
receiver.Set(reflect.Zero(receiver.Type()))
return true
}
vv, ok := scan(receiver.Type(), v.Interface())
2025-08-31 17:11:09 +02:00
if !ok {
2025-08-27 21:03:25 +02:00
return false
}
receiver.Set(reflect.ValueOf(vv))
2025-08-27 21:03:25 +02:00
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
}
2025-09-04 00:33:05 +02:00
if hasCircularType(t) {
return reflect.Zero(t), false
}
for _, vi := range values {
if hasCircularReference(reflect.ValueOf(vi)) {
return reflect.Zero(t), false
}
}
2025-08-27 21:03:25 +02:00
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 {
2025-08-28 05:04:06 +02:00
v := reflect.ValueOf(receiver)
2025-08-31 00:40:47 +02:00
if hasCircularReference(v) {
2025-08-28 05:04:06 +02:00
return false
}
for _, vi := range values {
2025-08-31 00:40:47 +02:00
if hasCircularReference(reflect.ValueOf(vi)) {
2025-08-28 05:04:06 +02:00
return false
}
}
return bindScalar(v, values)
2025-08-27 21:03:25 +02:00
}
func bindScalarCreateReflect[T any](values []any) (T, bool) {
2025-08-28 05:04:06 +02:00
t := reflect.TypeFor[T]()
v, ok := bindScalarCreate(t, values)
2025-08-27 21:03:25 +02:00
if !ok {
2025-08-28 05:04:06 +02:00
var tt T
return tt, false
2025-08-27 21:03:25 +02:00
}
return v.Interface().(T), true
}
2025-09-04 01:48:21 +02:00
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)
}