1
0
bind/scalar.go

112 lines
2.0 KiB
Go
Raw Normal View History

2025-08-27 21:03:25 +02:00
package bind
import "reflect"
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
}
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]()
2025-08-31 00:40:47 +02:00
if hasCircularType(t) {
2025-08-28 05:04:06 +02:00
var tt T
return tt, 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
var tt T
return tt, false
}
}
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
}