1
0

create receiver and bind fields

This commit is contained in:
Arpad Ryszka 2025-08-31 01:49:53 +02:00
parent 0a5ab05c88
commit 5363818043
3 changed files with 77 additions and 12 deletions

View File

@ -445,16 +445,7 @@ func groupFields(f []Field) [][]Field {
return groups
}
func bindFieldsReflect(structure any, values []Field) []Field {
receiver := reflect.ValueOf(structure)
if hasCircularReference(receiver) {
return values
}
if !acceptsFields(receiver.Type()) {
return values
}
func bindFields(receiver reflect.Value, values []Field) []Field {
unmatched, try := filterFields(fieldHasCircRef, values)
groups := groupFields(try)
for _, g := range groups {
@ -465,3 +456,42 @@ func bindFieldsReflect(structure any, values []Field) []Field {
return unmatched
}
func bindFieldsReflect(structure any, values []Field) []Field {
receiver := reflect.ValueOf(structure)
if hasCircularReference(receiver) {
return values
}
if !acceptsFields(receiver.Type()) {
return values
}
return bindFields(receiver, values)
}
func bindFieldsCreateReflect[T any](values []Field) (T, []Field) {
t := reflect.TypeFor[T]()
if hasCircularType(t) {
var r T
return r, values
}
if !acceptsFields(t) {
var r T
return r, values
}
receiver, ok := allocate(t, 1)
if !ok {
var r T
return r, values
}
unmatched := bindFields(receiver, values)
if len(unmatched) == len(values) {
receiver = reflect.Zero(t)
}
return receiver.Interface().(T), unmatched
}

View File

@ -701,4 +701,40 @@ func TestField(t *testing.T) {
}
})
})
t.Run("bind fields create", func(t *testing.T) {
t.Run("circular type", func(t *testing.T) {
type s struct {
Foo int
Bar *s
}
_, u := bind.BindFieldsCreate[s](bind.NamedValue("foo", 42))
if len(u) != 1 {
t.Fatal()
}
})
t.Run("type does not accept fields", func(t *testing.T) {
_, u := bind.BindFieldsCreate[[]int](bind.NamedValue("foo", 42))
if len(u) != 1 {
t.Fatal()
}
})
t.Run("zero value when no fields were bound", func(t *testing.T) {
type s struct{ Foo int }
v, u := bind.BindFieldsCreate[*s](bind.NamedValue("bar", 42))
if len(u) != 1 || v != nil {
t.Fatal()
}
})
t.Run("create receiver", func(t *testing.T) {
type s struct{ Foo int }
v, u := bind.BindFieldsCreate[*s](bind.NamedValue("foo", 42))
if len(u) != 0 || v == nil || v.Foo != 42 {
t.Fatal()
}
})
})
}

3
lib.go
View File

@ -65,8 +65,7 @@ func BindFields(structure any, values ...Field) []Field {
}
func BindFieldsCreate[T any](values ...Field) (T, []Field) {
var t T
return t, nil
return bindFieldsCreateReflect[T](values)
}
func AcceptsScalar[T any]() bool {