Files
kubevpn/vendor/github.com/expr-lang/expr/checker/nature/utils.go
2025-04-19 10:06:56 +08:00

77 lines
1.5 KiB
Go

package nature
import (
"reflect"
"github.com/expr-lang/expr/internal/deref"
)
func fieldName(field reflect.StructField) string {
if taggedName := field.Tag.Get("expr"); taggedName != "" {
return taggedName
}
return field.Name
}
func fetchField(t reflect.Type, name string) (reflect.StructField, bool) {
// First check all structs fields.
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
// Search all fields, even embedded structs.
if fieldName(field) == name {
return field, true
}
}
// Second check fields of embedded structs.
for i := 0; i < t.NumField(); i++ {
anon := t.Field(i)
if anon.Anonymous {
anonType := anon.Type
if anonType.Kind() == reflect.Pointer {
anonType = anonType.Elem()
}
if field, ok := fetchField(anonType, name); ok {
field.Index = append(anon.Index, field.Index...)
return field, true
}
}
}
return reflect.StructField{}, false
}
func StructFields(t reflect.Type) map[string]Nature {
table := make(map[string]Nature)
t = deref.Type(t)
if t == nil {
return table
}
switch t.Kind() {
case reflect.Struct:
for i := 0; i < t.NumField(); i++ {
f := t.Field(i)
if f.Anonymous {
for name, typ := range StructFields(f.Type) {
if _, ok := table[name]; ok {
continue
}
typ.FieldIndex = append(f.Index, typ.FieldIndex...)
table[name] = typ
}
}
table[fieldName(f)] = Nature{
Type: f.Type,
FieldIndex: f.Index,
}
}
}
return table
}