add Scalar type enumeration
This commit is contained in:
parent
5363818043
commit
cfa9b6e6f7
6
field.go
6
field.go
@ -65,7 +65,8 @@ func fields(t reflect.Type) []Field {
|
|||||||
if acceptsScalar(tfi.Type) {
|
if acceptsScalar(tfi.Type) {
|
||||||
var fi Field
|
var fi Field
|
||||||
ft := unpackType(tfi.Type, pointer|slice)
|
ft := unpackType(tfi.Type, pointer|slice)
|
||||||
fi.isBool = ft.Kind() == reflect.Bool
|
fi.typ = scalarType(ft.Kind())
|
||||||
|
fi.size = scalarSize(ft.Kind())
|
||||||
fi.list = acceptsList(tfi.Type)
|
fi.list = acceptsList(tfi.Type)
|
||||||
fi.name = strcase.ToKebab(tfi.Name)
|
fi.name = strcase.ToKebab(tfi.Name)
|
||||||
fi.path = []string{tfi.Name}
|
fi.path = []string{tfi.Name}
|
||||||
@ -104,7 +105,8 @@ func fields(t reflect.Type) []Field {
|
|||||||
func fieldFromValue(v reflect.Value) Field {
|
func fieldFromValue(v reflect.Value) Field {
|
||||||
var fi Field
|
var fi Field
|
||||||
fi.value = v.Interface()
|
fi.value = v.Interface()
|
||||||
fi.isBool = v.Kind() == reflect.Bool
|
fi.typ = scalarType(v.Kind())
|
||||||
|
fi.size = valueSize(v)
|
||||||
return fi
|
return fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -60,7 +60,7 @@ func TestField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
que := m["que"]
|
que := m["que"]
|
||||||
if !slices.Equal(que.Path(), []string{"Que"}) || !que.Bool() {
|
if !slices.Equal(que.Path(), []string{"Que"}) || que.Type() != bind.Bool {
|
||||||
t.Fatal(que.Name())
|
t.Fatal(que.Name())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,8 +184,8 @@ func TestField(t *testing.T) {
|
|||||||
v := s{Foo: 42, Bar: true}
|
v := s{Foo: 42, Bar: true}
|
||||||
f := bind.FieldValues(v)
|
f := bind.FieldValues(v)
|
||||||
if len(f) != 2 ||
|
if len(f) != 2 ||
|
||||||
f[0].Name() != "foo" || !slices.Equal(f[0].Path(), []string{"Foo"}) || f[0].Value() != 42 || f[0].Bool() ||
|
f[0].Name() != "foo" || !slices.Equal(f[0].Path(), []string{"Foo"}) || f[0].Value() != 42 || f[0].Type() == bind.Bool ||
|
||||||
f[1].Name() != "bar" || !slices.Equal(f[1].Path(), []string{"Bar"}) || f[1].Value() != true || !f[1.].Bool() {
|
f[1].Name() != "bar" || !slices.Equal(f[1].Path(), []string{"Bar"}) || f[1].Value() != true || f[1.].Type() != bind.Bool {
|
||||||
t.Fatal()
|
t.Fatal()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
18
lib.go
18
lib.go
@ -2,13 +2,26 @@
|
|||||||
// circular type structures not supported
|
// circular type structures not supported
|
||||||
// it handles scalar fields
|
// it handles scalar fields
|
||||||
// primary use cases by design are: command line options, environment variables, ini file fields, URL query parameters, HTTP form values
|
// primary use cases by design are: command line options, environment variables, ini file fields, URL query parameters, HTTP form values
|
||||||
|
// traverses pointers, slices, wrapper interfaces
|
||||||
package bind
|
package bind
|
||||||
|
|
||||||
|
type Scalar int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Any Scalar = iota
|
||||||
|
Bool
|
||||||
|
Int
|
||||||
|
Uint
|
||||||
|
Float
|
||||||
|
String
|
||||||
|
)
|
||||||
|
|
||||||
type Field struct {
|
type Field struct {
|
||||||
path []string
|
path []string
|
||||||
name string
|
name string
|
||||||
list bool
|
list bool
|
||||||
isBool bool
|
typ Scalar
|
||||||
|
size int
|
||||||
free bool
|
free bool
|
||||||
value any
|
value any
|
||||||
}
|
}
|
||||||
@ -45,7 +58,8 @@ func (f Field) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f Field) List() bool { return f.list }
|
func (f Field) List() bool { return f.list }
|
||||||
func (f Field) Bool() bool { return f.isBool }
|
func (f Field) Type() Scalar { return f.typ }
|
||||||
|
func (f Field) Size() int { return f.size }
|
||||||
func (f Field) Free() bool { return f.free }
|
func (f Field) Free() bool { return f.free }
|
||||||
func (f Field) Value() any { return f.value }
|
func (f Field) Value() any { return f.value }
|
||||||
|
|
||||||
|
|||||||
@ -1 +1,7 @@
|
|||||||
|
add the kind to the field type but with time and duration support. Simplified for ints, uints and floats, with bit size. Skipping the unused ones. With different name, e.g. ScalarType
|
||||||
track down the cases when reflect can panic
|
track down the cases when reflect can panic
|
||||||
|
documentation:
|
||||||
|
- give a short description for every exported symbol
|
||||||
|
- start from collecting the docs from the test cases
|
||||||
|
- extrace the common doc items from the function doc items
|
||||||
|
doc/test/code triangle
|
||||||
|
|||||||
63
type.go
63
type.go
@ -20,6 +20,69 @@ func (f unpackFlag) has(v unpackFlag) bool {
|
|||||||
return f&v > 0
|
return f&v > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func scalarType(k reflect.Kind) Scalar {
|
||||||
|
switch k {
|
||||||
|
case reflect.Bool:
|
||||||
|
return Bool
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return Int
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||||
|
return Uint
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return Float
|
||||||
|
case reflect.String:
|
||||||
|
return String
|
||||||
|
default:
|
||||||
|
return Any
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func scalarSize(k reflect.Kind) int {
|
||||||
|
switch k {
|
||||||
|
case reflect.Bool:
|
||||||
|
return 1
|
||||||
|
case reflect.Int:
|
||||||
|
return int(reflect.TypeFor[int]().Size()) * 8
|
||||||
|
case reflect.Int8:
|
||||||
|
return 8
|
||||||
|
case reflect.Int16:
|
||||||
|
return 16
|
||||||
|
case reflect.Int32:
|
||||||
|
return 32
|
||||||
|
case reflect.Int64:
|
||||||
|
return 64
|
||||||
|
case reflect.Uint:
|
||||||
|
return int(reflect.TypeFor[uint]().Size()) * 8
|
||||||
|
case reflect.Uint8:
|
||||||
|
return 8
|
||||||
|
case reflect.Uint16:
|
||||||
|
return 16
|
||||||
|
case reflect.Uint32:
|
||||||
|
return 32
|
||||||
|
case reflect.Uint64:
|
||||||
|
return 64
|
||||||
|
case reflect.Float32:
|
||||||
|
return 32
|
||||||
|
case reflect.Float64:
|
||||||
|
return 64
|
||||||
|
case reflect.String:
|
||||||
|
return -1
|
||||||
|
default:
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func valueSize(v reflect.Value) int {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.String:
|
||||||
|
return v.Len() * 8
|
||||||
|
case reflect.Interface:
|
||||||
|
return valueSize(unpackValue(v, pointer|slice|iface|anytype))
|
||||||
|
default:
|
||||||
|
return scalarSize(v.Kind())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func setVisited[T comparable](visited map[T]bool, k T) map[T]bool {
|
func setVisited[T comparable](visited map[T]bool, k T) map[T]bool {
|
||||||
s := make(map[T]bool)
|
s := make(map[T]bool)
|
||||||
for v := range visited {
|
for v := range visited {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user