refactor/rename
This commit is contained in:
parent
c27b9c2daa
commit
8683d8ba40
35
field.go
35
field.go
@ -427,6 +427,18 @@ func fieldsReflect[T any]() []Field {
|
|||||||
return fields(t)
|
return fields(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fieldsOf(t reflect.Type) []Field {
|
||||||
|
if t == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if hasCircularType(t) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields(t)
|
||||||
|
}
|
||||||
|
|
||||||
func fieldValuesReflect(structure any) []Field {
|
func fieldValuesReflect(structure any) []Field {
|
||||||
v := reflect.ValueOf(structure)
|
v := reflect.ValueOf(structure)
|
||||||
if hasCircularReference(v) {
|
if hasCircularReference(v) {
|
||||||
@ -499,22 +511,18 @@ func bindFieldsReflect(structure any, values []Field) []Field {
|
|||||||
return bindFields(receiver, values)
|
return bindFields(receiver, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
func bindFieldsCreateReflect[T any](values []Field) (T, []Field) {
|
func bindFieldsCreate(t reflect.Type, values []Field) (reflect.Value, []Field) {
|
||||||
t := reflect.TypeFor[T]()
|
|
||||||
if hasCircularType(t) {
|
if hasCircularType(t) {
|
||||||
var r T
|
return reflect.Zero(t), values
|
||||||
return r, values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !acceptsFields(t) {
|
if !acceptsFields(t) {
|
||||||
var r T
|
return reflect.Zero(t), values
|
||||||
return r, values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver, ok := allocate(t, 1)
|
receiver, ok := allocate(t, 1)
|
||||||
if !ok {
|
if !ok {
|
||||||
var r T
|
return reflect.Zero(t), values
|
||||||
return r, values
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unmatched := bindFields(receiver, values)
|
unmatched := bindFields(receiver, values)
|
||||||
@ -522,5 +530,16 @@ func bindFieldsCreateReflect[T any](values []Field) (T, []Field) {
|
|||||||
receiver = reflect.Zero(t)
|
receiver = reflect.Zero(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return receiver, unmatched
|
||||||
|
}
|
||||||
|
|
||||||
|
func bindFieldsCreateReflect[T any](values []Field) (T, []Field) {
|
||||||
|
t := reflect.TypeFor[T]()
|
||||||
|
receiver, unmatched := bindFieldsCreate(t, values)
|
||||||
|
if len(unmatched) == len(values) {
|
||||||
|
var t T
|
||||||
|
return t, unmatched
|
||||||
|
}
|
||||||
|
|
||||||
return receiver.Interface().(T), unmatched
|
return receiver.Interface().(T), unmatched
|
||||||
}
|
}
|
||||||
|
|||||||
137
field_test.go
137
field_test.go
@ -3,12 +3,13 @@ package bind_test
|
|||||||
import (
|
import (
|
||||||
"code.squareroundforest.org/arpio/bind"
|
"code.squareroundforest.org/arpio/bind"
|
||||||
"code.squareroundforest.org/arpio/notation"
|
"code.squareroundforest.org/arpio/notation"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"fmt"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestField(t *testing.T) {
|
func TestField(t *testing.T) {
|
||||||
@ -132,7 +133,7 @@ func TestField(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("list of struct", func(t *testing.T) {
|
t.Run("list of struct", func(t *testing.T) {
|
||||||
type s struct{Foo []struct{Bar int}}
|
type s struct{ Foo []struct{ Bar int } }
|
||||||
f := bind.Fields[s]()
|
f := bind.Fields[s]()
|
||||||
if len(f) != 1 || f[0].Name() != "foo-bar" || !f[0].List() {
|
if len(f) != 1 || f[0].Name() != "foo-bar" || !f[0].List() {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
@ -156,7 +157,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Fatal(notation.Sprint(f))
|
t.Fatal(notation.Sprint(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
check := map[string]bind.FieldType {
|
check := map[string]bind.FieldType{
|
||||||
"b": bind.Bool,
|
"b": bind.Bool,
|
||||||
"i": bind.Int,
|
"i": bind.Int,
|
||||||
"u": bind.Uint,
|
"u": bind.Uint,
|
||||||
@ -173,6 +174,31 @@ func TestField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("fields from reflection type", func(t *testing.T) {
|
||||||
|
t.Run("ok", func(t *testing.T) {
|
||||||
|
type s struct{ Foo int }
|
||||||
|
f := bind.FieldsOf(reflect.TypeFor[s]())
|
||||||
|
if len(f) != 1 || f[0].Name() != "foo" {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("nil type", func(t *testing.T) {
|
||||||
|
f := bind.FieldsOf(nil)
|
||||||
|
if len(f) != 0 {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("circular type", func(t *testing.T) {
|
||||||
|
type p *p
|
||||||
|
f := bind.FieldsOf(reflect.TypeFor[p]())
|
||||||
|
if len(f) != 0 {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("field values", func(t *testing.T) {
|
t.Run("field values", func(t *testing.T) {
|
||||||
@ -405,7 +431,7 @@ func TestField(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("list of struct", func(t *testing.T) {
|
t.Run("list of struct", func(t *testing.T) {
|
||||||
type s struct{Foo []struct{Bar int}}
|
type s struct{ Foo []struct{ Bar int } }
|
||||||
var v s
|
var v s
|
||||||
f := bind.FieldValues(v)
|
f := bind.FieldValues(v)
|
||||||
if len(f) != 1 || f[0].Name() != "foo-bar" || !f[0].List() {
|
if len(f) != 1 || f[0].Name() != "foo-bar" || !f[0].List() {
|
||||||
@ -428,7 +454,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar int
|
Bar int
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
if len(bind.BindFields(&v, bind.NamedValue("bar", 42))) != 1 {
|
if len(bind.Bind(&v, bind.NamedValue("bar", 42))) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -437,7 +463,7 @@ func TestField(t *testing.T) {
|
|||||||
type s struct{ Foo int }
|
type s struct{ Foo int }
|
||||||
type p *p
|
type p *p
|
||||||
var v p
|
var v p
|
||||||
if len(bind.BindFields(&v, bind.NamedValue("foo", 42))) != 1 {
|
if len(bind.Bind(&v, bind.NamedValue("foo", 42))) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -445,7 +471,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("set by name", func(t *testing.T) {
|
t.Run("set by name", func(t *testing.T) {
|
||||||
type s struct{ FooBar int }
|
type s struct{ FooBar int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 0 || v.FooBar != 42 {
|
if len(u) != 0 || v.FooBar != 42 {
|
||||||
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
||||||
}
|
}
|
||||||
@ -454,7 +480,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("set by path", func(t *testing.T) {
|
t.Run("set by path", func(t *testing.T) {
|
||||||
type s struct{ FooBar int }
|
type s struct{ FooBar int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(&v, bind.ValueByPath([]string{"FooBar"}, 42))
|
u := bind.Bind(&v, bind.ValueByPath([]string{"FooBar"}, 42))
|
||||||
if len(u) != 0 || v.FooBar != 42 {
|
if len(u) != 0 || v.FooBar != 42 {
|
||||||
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
||||||
}
|
}
|
||||||
@ -466,7 +492,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar int
|
Bar int
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 21),
|
bind.NamedValue("foo", 21),
|
||||||
bind.NamedValue("baz", 42),
|
bind.NamedValue("baz", 42),
|
||||||
@ -480,7 +506,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("bind list", func(t *testing.T) {
|
t.Run("bind list", func(t *testing.T) {
|
||||||
type s struct{ Foo []int }
|
type s struct{ Foo []int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 21),
|
bind.NamedValue("foo", 21),
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
@ -495,7 +521,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("bind list of structs", func(t *testing.T) {
|
t.Run("bind list of structs", func(t *testing.T) {
|
||||||
type s struct{ Foo []struct{ Bar int } }
|
type s struct{ Foo []struct{ Bar int } }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo-bar", 21),
|
bind.NamedValue("foo-bar", 21),
|
||||||
bind.NamedValue("foo-bar", 42),
|
bind.NamedValue("foo-bar", 42),
|
||||||
@ -510,7 +536,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("bind list in list", func(t *testing.T) {
|
t.Run("bind list in list", func(t *testing.T) {
|
||||||
type s struct{ Foo []struct{ Bar []int } }
|
type s struct{ Foo []struct{ Bar []int } }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo-bar", 21),
|
bind.NamedValue("foo-bar", 21),
|
||||||
bind.NamedValue("foo-bar", 42),
|
bind.NamedValue("foo-bar", 42),
|
||||||
@ -527,7 +553,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("list receiver", func(t *testing.T) {
|
t.Run("list receiver", func(t *testing.T) {
|
||||||
var l []struct{ Foo int }
|
var l []struct{ Foo int }
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&l,
|
&l,
|
||||||
bind.NamedValue("foo", 21),
|
bind.NamedValue("foo", 21),
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
@ -546,7 +572,7 @@ func TestField(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
v := s1{[]s0{{1}, {2}}}
|
v := s1{[]s0{{1}, {2}}}
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
v,
|
v,
|
||||||
bind.NamedValue("foo-bar", 21),
|
bind.NamedValue("foo-bar", 21),
|
||||||
bind.NamedValue("foo-bar", 42),
|
bind.NamedValue("foo-bar", 42),
|
||||||
@ -565,7 +591,7 @@ func TestField(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
v := s1{[]s0{{1}, {2}}}
|
v := s1{[]s0{{1}, {2}}}
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo-bar", 21),
|
bind.NamedValue("foo-bar", 21),
|
||||||
bind.NamedValue("foo-bar", 42),
|
bind.NamedValue("foo-bar", 42),
|
||||||
@ -584,7 +610,7 @@ func TestField(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
v := s1{[]s0{{nil}, {nil}}}
|
v := s1{[]s0{{nil}, {nil}}}
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo-bar", 21),
|
bind.NamedValue("foo-bar", 21),
|
||||||
bind.NamedValue("foo-bar", 42),
|
bind.NamedValue("foo-bar", 42),
|
||||||
@ -598,7 +624,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("bind scalar map", func(t *testing.T) {
|
t.Run("bind scalar map", func(t *testing.T) {
|
||||||
m := make(map[string]int)
|
m := make(map[string]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo-bar", 21), bind.NamedValue("baz-qux", 42))
|
u := bind.Bind(m, bind.NamedValue("foo-bar", 21), bind.NamedValue("baz-qux", 42))
|
||||||
if len(u) != 0 || len(m) != 2 || m["foo-bar"] != 21 || m["baz-qux"] != 42 {
|
if len(u) != 0 || len(m) != 2 || m["foo-bar"] != 21 || m["baz-qux"] != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -607,7 +633,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("scalar map key conversion", func(t *testing.T) {
|
t.Run("scalar map key conversion", func(t *testing.T) {
|
||||||
type key string
|
type key string
|
||||||
m := make(map[key]int)
|
m := make(map[key]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", 42))
|
u := bind.Bind(m, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 0 || len(m) != 1 || m["foo"] != 42 {
|
if len(u) != 0 || len(m) != 1 || m["foo"] != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -615,7 +641,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map pointer key", func(t *testing.T) {
|
t.Run("scalar map pointer key", func(t *testing.T) {
|
||||||
m := make(map[*string]int)
|
m := make(map[*string]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", 42))
|
u := bind.Bind(m, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 0 || len(m) != 1 {
|
if len(u) != 0 || len(m) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -629,7 +655,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map list value", func(t *testing.T) {
|
t.Run("scalar map list value", func(t *testing.T) {
|
||||||
m := make(map[string][]int)
|
m := make(map[string][]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", 21), bind.NamedValue("foo", 42), bind.NamedValue("foo", 84))
|
u := bind.Bind(m, bind.NamedValue("foo", 21), bind.NamedValue("foo", 42), bind.NamedValue("foo", 84))
|
||||||
if len(u) != 0 || len(m) != 1 || !slices.Equal(m["foo"], []int{21, 42, 84}) {
|
if len(u) != 0 || len(m) != 1 || !slices.Equal(m["foo"], []int{21, 42, 84}) {
|
||||||
t.Fatal(notation.Sprint(u), notation.Sprint(m))
|
t.Fatal(notation.Sprint(u), notation.Sprint(m))
|
||||||
}
|
}
|
||||||
@ -637,7 +663,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map pointer value", func(t *testing.T) {
|
t.Run("scalar map pointer value", func(t *testing.T) {
|
||||||
m := make(map[string]*int)
|
m := make(map[string]*int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", 42))
|
u := bind.Bind(m, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 0 || len(m) != 1 {
|
if len(u) != 0 || len(m) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -651,7 +677,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map list pointer value", func(t *testing.T) {
|
t.Run("scalar map list pointer value", func(t *testing.T) {
|
||||||
m := make(map[string]*[]int)
|
m := make(map[string]*[]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", 21), bind.NamedValue("foo", 42), bind.NamedValue("foo", 84))
|
u := bind.Bind(m, bind.NamedValue("foo", 21), bind.NamedValue("foo", 42), bind.NamedValue("foo", 84))
|
||||||
if len(u) != 0 || len(m) != 1 || !slices.Equal(*m["foo"], []int{21, 42, 84}) {
|
if len(u) != 0 || len(m) != 1 || !slices.Equal(*m["foo"], []int{21, 42, 84}) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -660,7 +686,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("allocate scalar map", func(t *testing.T) {
|
t.Run("allocate scalar map", func(t *testing.T) {
|
||||||
type s struct{ Foo map[string]int }
|
type s struct{ Foo map[string]int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 0 || len(v.Foo) != 1 || v.Foo["bar"] != 42 {
|
if len(u) != 0 || len(v.Foo) != 1 || v.Foo["bar"] != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -669,7 +695,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("scalar map addressing via path", func(t *testing.T) {
|
t.Run("scalar map addressing via path", func(t *testing.T) {
|
||||||
type s struct{ Foo map[string]int }
|
type s struct{ Foo map[string]int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(&v, bind.ValueByPath([]string{"Foo", "Bar"}, 42))
|
u := bind.Bind(&v, bind.ValueByPath([]string{"Foo", "Bar"}, 42))
|
||||||
if len(u) != 0 || len(v.Foo) != 1 || v.Foo["Bar"] != 42 {
|
if len(u) != 0 || len(v.Foo) != 1 || v.Foo["Bar"] != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -677,7 +703,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map and too long field path", func(t *testing.T) {
|
t.Run("scalar map and too long field path", func(t *testing.T) {
|
||||||
m := make(map[string]int)
|
m := make(map[string]int)
|
||||||
u := bind.BindFields(m, bind.ValueByPath([]string{"foo", "bar"}, 42))
|
u := bind.Bind(m, bind.ValueByPath([]string{"foo", "bar"}, 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -686,7 +712,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("scalar map cannot be set", func(t *testing.T) {
|
t.Run("scalar map cannot be set", func(t *testing.T) {
|
||||||
type s struct{ Foo map[string]int }
|
type s struct{ Foo map[string]int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -694,7 +720,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map with wrong value type", func(t *testing.T) {
|
t.Run("scalar map with wrong value type", func(t *testing.T) {
|
||||||
m := make(map[string]int)
|
m := make(map[string]int)
|
||||||
u := bind.BindFields(m, bind.NamedValue("foo", "bar"))
|
u := bind.Bind(m, bind.NamedValue("foo", "bar"))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -706,7 +732,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar struct{ Baz string }
|
Bar struct{ Baz string }
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
bind.NamedValue("bar-baz", "qux"),
|
bind.NamedValue("bar-baz", "qux"),
|
||||||
@ -723,7 +749,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar struct{ Baz string }
|
Bar struct{ Baz string }
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
bind.NamedValue("bar-qux", "qux"),
|
bind.NamedValue("bar-qux", "qux"),
|
||||||
@ -740,7 +766,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar struct{ Baz string }
|
Bar struct{ Baz string }
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
bind.NamedValue("bar-baz", "qux"),
|
bind.NamedValue("bar-baz", "qux"),
|
||||||
@ -760,7 +786,7 @@ func TestField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
bind.NamedValue("bar-baz", "qux"),
|
bind.NamedValue("bar-baz", "qux"),
|
||||||
@ -773,9 +799,9 @@ func TestField(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
t.Run("pointer field with invalid value", func(t *testing.T) {
|
t.Run("pointer field with invalid value", func(t *testing.T) {
|
||||||
type s struct {Foo *struct{ Bar int }}
|
type s struct{ Foo *struct{ Bar int } }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo-bar", "baz"),
|
bind.NamedValue("foo-bar", "baz"),
|
||||||
)
|
)
|
||||||
@ -792,7 +818,7 @@ func TestField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.NamedValue("foo", 42),
|
bind.NamedValue("foo", 42),
|
||||||
bind.NamedValue("bar", "qux"),
|
bind.NamedValue("bar", "qux"),
|
||||||
@ -811,7 +837,7 @@ func TestField(t *testing.T) {
|
|||||||
Bar struct{ Baz string }
|
Bar struct{ Baz string }
|
||||||
}
|
}
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(
|
u := bind.Bind(
|
||||||
&v,
|
&v,
|
||||||
bind.ValueByPath([]string{"Foo"}, 42),
|
bind.ValueByPath([]string{"Foo"}, 42),
|
||||||
bind.ValueByPath([]string{"Bar", "Baz"}, "qux"),
|
bind.ValueByPath([]string{"Bar", "Baz"}, "qux"),
|
||||||
@ -825,7 +851,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("cannot set field", func(t *testing.T) {
|
t.Run("cannot set field", func(t *testing.T) {
|
||||||
type s struct{ Foo int }
|
type s struct{ Foo int }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(v, bind.NamedValue("foo", 42))
|
u := bind.Bind(v, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -838,7 +864,7 @@ func TestField(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
var v s1
|
var v s1
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 0 || v.Foo != 42 {
|
if len(u) != 0 || v.Foo != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -847,7 +873,7 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("receiver cannot be set", func(t *testing.T) {
|
t.Run("receiver cannot be set", func(t *testing.T) {
|
||||||
type s struct{ Foo *struct{ Bar int } }
|
type s struct{ Foo *struct{ Bar int } }
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -855,7 +881,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("receiver not supported", func(t *testing.T) {
|
t.Run("receiver not supported", func(t *testing.T) {
|
||||||
v := make(chan int)
|
v := make(chan int)
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -863,7 +889,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("empty receiver", func(t *testing.T) {
|
t.Run("empty receiver", func(t *testing.T) {
|
||||||
var v any
|
var v any
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -872,14 +898,14 @@ func TestField(t *testing.T) {
|
|||||||
t.Run("nil value", func(t *testing.T) {
|
t.Run("nil value", func(t *testing.T) {
|
||||||
type s struct{ Foo any }
|
type s struct{ Foo any }
|
||||||
v := s{42}
|
v := s{42}
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo", nil))
|
u := bind.Bind(&v, bind.NamedValue("foo", nil))
|
||||||
if len(u) != 0 || v.Foo != nil {
|
if len(u) != 0 || v.Foo != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nil receiver", func(t *testing.T) {
|
t.Run("nil receiver", func(t *testing.T) {
|
||||||
u := bind.BindFields(nil, bind.NamedValue("foo", nil))
|
u := bind.Bind(nil, bind.NamedValue("foo", nil))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -892,7 +918,7 @@ func TestField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var v s
|
var v s
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo-bar", 42))
|
u := bind.Bind(&v, bind.NamedValue("foo-bar", 42))
|
||||||
if len(u) != 0 || v.FooBar != 42 || v.Foo.Bar != 42 {
|
if len(u) != 0 || v.FooBar != 42 || v.Foo.Bar != 42 {
|
||||||
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
t.Fatal(notation.Sprint(u), notation.Sprint(v))
|
||||||
}
|
}
|
||||||
@ -900,18 +926,18 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("scalar map with invalid field type", func(t *testing.T) {
|
t.Run("scalar map with invalid field type", func(t *testing.T) {
|
||||||
v := make(map[string]int)
|
v := make(map[string]int)
|
||||||
u := bind.BindFields(v, bind.NamedValue("foo", "bar"))
|
u := bind.Bind(v, bind.NamedValue("foo", "bar"))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unpack interfaces", func(t *testing.T) {
|
t.Run("unpack interfaces", func(t *testing.T) {
|
||||||
type s struct{Foo time.Duration}
|
type s struct{ Foo time.Duration }
|
||||||
var v s
|
var v s
|
||||||
var str fmt.Stringer
|
var str fmt.Stringer
|
||||||
str = time.Second
|
str = time.Second
|
||||||
u := bind.BindFields(&v, bind.NamedValue("foo", &str))
|
u := bind.Bind(&v, bind.NamedValue("foo", &str))
|
||||||
if len(u) != 0 || v.Foo != time.Second {
|
if len(u) != 0 || v.Foo != time.Second {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -924,14 +950,14 @@ func TestField(t *testing.T) {
|
|||||||
Foo int
|
Foo int
|
||||||
Bar *s
|
Bar *s
|
||||||
}
|
}
|
||||||
_, u := bind.BindFieldsCreate[s](bind.NamedValue("foo", 42))
|
_, u := bind.CreateAndBind[s](bind.NamedValue("foo", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("type does not accept fields", func(t *testing.T) {
|
t.Run("type does not accept fields", func(t *testing.T) {
|
||||||
_, u := bind.BindFieldsCreate[[]int](bind.NamedValue("foo", 42))
|
_, u := bind.CreateAndBind[[]int](bind.NamedValue("foo", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -939,7 +965,7 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("zero value when no fields were bound", func(t *testing.T) {
|
t.Run("zero value when no fields were bound", func(t *testing.T) {
|
||||||
type s struct{ Foo int }
|
type s struct{ Foo int }
|
||||||
v, u := bind.BindFieldsCreate[*s](bind.NamedValue("bar", 42))
|
v, u := bind.CreateAndBind[*s](bind.NamedValue("bar", 42))
|
||||||
if len(u) != 1 || v != nil {
|
if len(u) != 1 || v != nil {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -947,17 +973,26 @@ func TestField(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("create receiver", func(t *testing.T) {
|
t.Run("create receiver", func(t *testing.T) {
|
||||||
type s struct{ Foo int }
|
type s struct{ Foo int }
|
||||||
v, u := bind.BindFieldsCreate[*s](bind.NamedValue("foo", 42))
|
v, u := bind.CreateAndBind[*s](bind.NamedValue("foo", 42))
|
||||||
if len(u) != 0 || v == nil || v.Foo != 42 {
|
if len(u) != 0 || v == nil || v.Foo != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("any type", func(t *testing.T) {
|
t.Run("any type", func(t *testing.T) {
|
||||||
_, u := bind.BindFieldsCreate[any](bind.NamedValue("foo", 42))
|
_, u := bind.CreateAndBind[any](bind.NamedValue("foo", 42))
|
||||||
if len(u) != 1 {
|
if len(u) != 1 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("bind fields create with reflection type", func(t *testing.T) {
|
||||||
|
type s struct{ Foo int }
|
||||||
|
typ := reflect.TypeFor[s]()
|
||||||
|
v, u := bind.CreateAndBindFor(typ, bind.NamedValue("foo", 42))
|
||||||
|
if len(u) != 0 || v.Interface().(s).Foo != 42 {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
38
lib.go
38
lib.go
@ -49,13 +49,13 @@ func BindScalar(receiver any, value ...any) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BindScalarCreate is like BindScalar, but it allocates the receiver from the type T.
|
// BindScalarCreate is like BindScalar, but it allocates the receiver from the type T.
|
||||||
func BindScalarCreate[T any](value ...any) (T, bool) {
|
func CreateAndBindScalar[T any](value ...any) (T, bool) {
|
||||||
return bindScalarCreateReflect[T](value)
|
return bindScalarCreateReflect[T](value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindScalarCreate is like BindScalar, but it allocates the receiver from the type t.
|
// BindScalarCreate is like BindScalar, but it allocates the receiver from the type t.
|
||||||
func BindScalarCreateWith(t reflect.Type, value ...any) (reflect.Value, bool) {
|
func CreateAndBindScalarFor(t reflect.Type, value ...any) (reflect.Value, bool) {
|
||||||
return reflect.Value{}, false
|
return bindScalarCreate(t, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValueByPath defines a field for input to BindFields or BindFieldsCreate. It defines the field by its exact
|
// ValueByPath defines a field for input to BindFields or BindFieldsCreate. It defines the field by its exact
|
||||||
@ -119,7 +119,7 @@ func Fields[T any]() []Field {
|
|||||||
|
|
||||||
// Fields of is like Fields but uses type t as the input.
|
// Fields of is like Fields but uses type t as the input.
|
||||||
func FieldsOf(t reflect.Type) []Field {
|
func FieldsOf(t reflect.Type) []Field {
|
||||||
return nil
|
return fieldsOf(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FieldValues returns the fields of a structure value recursively. It traverses through pointers, slices and
|
// FieldValues returns the fields of a structure value recursively. It traverses through pointers, slices and
|
||||||
@ -128,21 +128,21 @@ func FieldValues(structure any) []Field {
|
|||||||
return fieldValuesReflect(structure)
|
return fieldValuesReflect(structure)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindFields sets structure fields recursively. It traverses through poitners, slices and interfaces. It
|
// Bind sets structure fields recursively. It traverses through poitners, slices and interfaces. It returns the
|
||||||
// returns the values for which it is not possible to find a compatible matching field. It supports maps that
|
// values for which it is not possible to find a compatible matching field. It supports maps that have string
|
||||||
// have string keys and scalar values.
|
// keys and scalar values.
|
||||||
func BindFields(structure any, values ...Field) []Field {
|
func Bind(structure any, value ...Field) []Field {
|
||||||
return bindFieldsReflect(structure, values)
|
return bindFieldsReflect(structure, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindFieldsCreate is like BindFields, but it allocates the receiver from type T.
|
// CreateAndBind is like Bind, but it allocates the receiver from type T.
|
||||||
func BindFieldsCreate[T any](values ...Field) (T, []Field) {
|
func CreateAndBind[T any](value ...Field) (T, []Field) {
|
||||||
return bindFieldsCreateReflect[T](values)
|
return bindFieldsCreateReflect[T](value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BindFieldsCreate is like BindFields, but it allocates the receiver from type t.
|
// CreateAndBindFor is like Bind, but it allocates the receiver from type t.
|
||||||
func BindFieldsCreateWith(t reflect.Type, values ...Field) (reflect.Value, []Field) {
|
func CreateAndBindFor(t reflect.Type, value ...Field) (reflect.Value, []Field) {
|
||||||
return reflect.Value{}, nil
|
return bindFieldsCreate(t, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcceptsScalar checks if a type can be used with BindScalarCreate or the values of the type with BindScalar.
|
// AcceptsScalar checks if a type can be used with BindScalarCreate or the values of the type with BindScalar.
|
||||||
@ -152,7 +152,7 @@ func AcceptsScalar[T any]() bool {
|
|||||||
|
|
||||||
// TypeAcceptsScalar is like AcceptsScalar, but uses type t as input.
|
// TypeAcceptsScalar is like AcceptsScalar, but uses type t as input.
|
||||||
func TypeAcceptsScalar(t reflect.Type) bool {
|
func TypeAcceptsScalar(t reflect.Type) bool {
|
||||||
return false
|
return acceptsScalarChecked(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcceptsFields checks if a type can be used with BindFieldsCreate or the values of the type with BindFields.
|
// AcceptsFields checks if a type can be used with BindFieldsCreate or the values of the type with BindFields.
|
||||||
@ -162,7 +162,7 @@ func AcceptsFields[T any]() bool {
|
|||||||
|
|
||||||
// TypeAcceptsFields is like AcceptsFields, but uses type t as input.
|
// TypeAcceptsFields is like AcceptsFields, but uses type t as input.
|
||||||
func TypeAcceptsFields(t reflect.Type) bool {
|
func TypeAcceptsFields(t reflect.Type) bool {
|
||||||
return false
|
return acceptsFieldsChecked(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AcceptsList checks if a type can be used to bind multiple values.
|
// AcceptsList checks if a type can be used to bind multiple values.
|
||||||
@ -172,7 +172,7 @@ func AcceptsList[T any]() bool {
|
|||||||
|
|
||||||
// TypeAcceptsList is like AcceptsList, but uses type t as input.
|
// TypeAcceptsList is like AcceptsList, but uses type t as input.
|
||||||
func TypeAcceptsList(t reflect.Type) bool {
|
func TypeAcceptsList(t reflect.Type) bool {
|
||||||
return false
|
return acceptsListChecked(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bindable is the same as AcceptsScalar[T]() || AcceptsFields[T]().
|
// Bindable is the same as AcceptsScalar[T]() || AcceptsFields[T]().
|
||||||
@ -182,5 +182,5 @@ func Bindable[T any]() bool {
|
|||||||
|
|
||||||
// BindableType is like Bindable, but uses type t as input.
|
// BindableType is like Bindable, but uses type t as input.
|
||||||
func BindableType(t reflect.Type) bool {
|
func BindableType(t reflect.Type) bool {
|
||||||
return false
|
return bindableChecked(t)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,15 +1,15 @@
|
|||||||
package bind_test
|
package bind_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
|
||||||
"code.squareroundforest.org/arpio/bind"
|
"code.squareroundforest.org/arpio/bind"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestLib(t *testing.T) {
|
func TestLib(t *testing.T) {
|
||||||
t.Run("field", func(t *testing.T) {
|
t.Run("field", func(t *testing.T) {
|
||||||
t.Run("type", func(t *testing.T) {
|
t.Run("type", func(t *testing.T) {
|
||||||
t.Run("not from input", func(t *testing.T) {
|
t.Run("not from input", func(t *testing.T) {
|
||||||
v := struct{Foo int}{42}
|
v := struct{ Foo int }{42}
|
||||||
f := bind.FieldValues(v)
|
f := bind.FieldValues(v)
|
||||||
if len(f) != 1 || f[0].Type() != bind.Int {
|
if len(f) != 1 || f[0].Type() != bind.Int {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
|
|||||||
22
scalar.go
22
scalar.go
@ -56,6 +56,16 @@ func bindScalarCreate(t reflect.Type, values []any) (reflect.Value, bool) {
|
|||||||
return reflect.Zero(t), false
|
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) {
|
if !acceptsScalar(t) {
|
||||||
return reflect.Zero(t), false
|
return reflect.Zero(t), false
|
||||||
}
|
}
|
||||||
@ -89,18 +99,6 @@ func bindScalarReflect(receiver any, values []any) bool {
|
|||||||
|
|
||||||
func bindScalarCreateReflect[T any](values []any) (T, bool) {
|
func bindScalarCreateReflect[T any](values []any) (T, bool) {
|
||||||
t := reflect.TypeFor[T]()
|
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)
|
v, ok := bindScalarCreate(t, values)
|
||||||
if !ok {
|
if !ok {
|
||||||
var tt T
|
var tt T
|
||||||
|
|||||||
@ -2,6 +2,7 @@ package bind_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.squareroundforest.org/arpio/bind"
|
"code.squareroundforest.org/arpio/bind"
|
||||||
|
"reflect"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -181,62 +182,62 @@ func TestScalar(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("bind scalar with create", func(t *testing.T) {
|
t.Run("bind scalar with create", func(t *testing.T) {
|
||||||
t.Run("no value", func(t *testing.T) {
|
t.Run("no value", func(t *testing.T) {
|
||||||
if _, ok := bind.BindScalarCreate[int](); ok {
|
if _, ok := bind.CreateAndBindScalar[int](); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("does not accept scalar", func(t *testing.T) {
|
t.Run("does not accept scalar", func(t *testing.T) {
|
||||||
if _, ok := bind.BindScalarCreate[struct{ Foo int }]("42"); ok {
|
if _, ok := bind.CreateAndBindScalar[struct{ Foo int }]("42"); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("empty interface", func(t *testing.T) {
|
t.Run("empty interface", func(t *testing.T) {
|
||||||
if v, ok := bind.BindScalarCreate[any]("42"); !ok || v != "42" {
|
if v, ok := bind.CreateAndBindScalar[any]("42"); !ok || v != "42" {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("scalar", func(t *testing.T) {
|
t.Run("scalar", func(t *testing.T) {
|
||||||
if v, ok := bind.BindScalarCreate[int]("42"); !ok || v != 42 {
|
if v, ok := bind.CreateAndBindScalar[int]("42"); !ok || v != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("slice", func(t *testing.T) {
|
t.Run("slice", func(t *testing.T) {
|
||||||
if v, ok := bind.BindScalarCreate[[]int]("21", "42", "84"); !ok || !slices.Equal(v, []int{21, 42, 84}) {
|
if v, ok := bind.CreateAndBindScalar[[]int]("21", "42", "84"); !ok || !slices.Equal(v, []int{21, 42, 84}) {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("slice with non-scalar type", func(t *testing.T) {
|
t.Run("slice with non-scalar type", func(t *testing.T) {
|
||||||
if _, ok := bind.BindScalarCreate[[]func(int)]("21", "42", "84"); ok {
|
if _, ok := bind.CreateAndBindScalar[[]func(int)]("21", "42", "84"); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("pointer to non-scalar", func(t *testing.T) {
|
t.Run("pointer to non-scalar", func(t *testing.T) {
|
||||||
if _, ok := bind.BindScalarCreate[*func()]("42"); ok {
|
if _, ok := bind.CreateAndBindScalar[*func()]("42"); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("pointer", func(t *testing.T) {
|
t.Run("pointer", func(t *testing.T) {
|
||||||
if v, ok := bind.BindScalarCreate[*int]("42"); !ok || *v != 42 {
|
if v, ok := bind.CreateAndBindScalar[*int]("42"); !ok || *v != 42 {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("unscannable", func(t *testing.T) {
|
t.Run("unscannable", func(t *testing.T) {
|
||||||
if _, ok := bind.BindScalarCreate[int]("foo"); ok {
|
if _, ok := bind.CreateAndBindScalar[int]("foo"); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("receiver has circular type", func(t *testing.T) {
|
t.Run("receiver has circular type", func(t *testing.T) {
|
||||||
type s []s
|
type s []s
|
||||||
if _, ok := bind.BindScalarCreate[s]("foo"); ok {
|
if _, ok := bind.CreateAndBindScalar[s]("foo"); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -245,9 +246,16 @@ func TestScalar(t *testing.T) {
|
|||||||
var v any
|
var v any
|
||||||
p := &v
|
p := &v
|
||||||
*p = p
|
*p = p
|
||||||
if _, ok := bind.BindScalarCreate[any](p); ok {
|
if _, ok := bind.CreateAndBindScalar[any](p); ok {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("bind with reflection type", func(t *testing.T) {
|
||||||
|
v, ok := bind.CreateAndBindScalarFor(reflect.TypeFor[int](), 42)
|
||||||
|
if !ok || v.Interface() != 42 {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
27
type_test.go
27
type_test.go
@ -2,6 +2,7 @@ package bind_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"code.squareroundforest.org/arpio/bind"
|
"code.squareroundforest.org/arpio/bind"
|
||||||
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -274,6 +275,12 @@ func TestTypeChecks(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("with reflection type", func(t *testing.T) {
|
||||||
|
if !bind.BindableType(reflect.TypeFor[int]()) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("circular type", func(t *testing.T) {
|
t.Run("circular type", func(t *testing.T) {
|
||||||
@ -378,11 +385,17 @@ func TestTypeChecks(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("with reflection type", func(t *testing.T) {
|
||||||
|
if !bind.TypeAcceptsScalar(reflect.TypeFor[int]()) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("fields", func(t *testing.T) {
|
t.Run("fields", func(t *testing.T) {
|
||||||
t.Run("yes", func(t *testing.T) {
|
t.Run("yes", func(t *testing.T) {
|
||||||
type s struct{Foo int}
|
type s struct{ Foo int }
|
||||||
if !bind.AcceptsFields[s]() {
|
if !bind.AcceptsFields[s]() {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
@ -400,6 +413,12 @@ func TestTypeChecks(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("with reflection type", func(t *testing.T) {
|
||||||
|
if !bind.TypeAcceptsFields(reflect.TypeFor[struct{ Foo int }]()) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("list", func(t *testing.T) {
|
t.Run("list", func(t *testing.T) {
|
||||||
@ -421,6 +440,12 @@ func TestTypeChecks(t *testing.T) {
|
|||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("with reflection type", func(t *testing.T) {
|
||||||
|
if !bind.TypeAcceptsList(reflect.TypeFor[[]int]()) {
|
||||||
|
t.Fatal()
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user