1
0
bind/scalar.go
2025-08-31 17:11:09 +02:00

112 lines
2.0 KiB
Go

package bind
import "reflect"
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
}
r := reflect.ValueOf(values[0])
r = unpackValue(r, pointer|iface|slice)
if !r.IsValid() && !isAny(receiver.Type()) {
return false
}
if !r.IsValid() {
receiver.Set(reflect.Zero(receiver.Type()))
return true
}
v, ok := scan(receiver.Type(), r.Interface())
if !ok {
return false
}
receiver.Set(reflect.ValueOf(v))
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 {
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]()
if hasCircularType(t) {
var tt T
return tt, false
}
for _, vi := range values {
if hasCircularReference(reflect.ValueOf(vi)) {
var tt T
return tt, false
}
}
v, ok := bindScalarCreate(t, values)
if !ok {
var tt T
return tt, false
}
return v.Interface().(T), true
}