You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
stardb/reflect.go

163 lines
3.9 KiB
Go

package stardb
import (
"errors"
"reflect"
)
func (star *StarRows) setAllRefValue(stc interface{}, skey string, rows int) error {
t := reflect.TypeOf(stc)
v := reflect.ValueOf(stc).Elem()
if t.Kind() != reflect.Ptr || !v.CanSet() {
return errors.New("interface{} is not writable")
}
if v.Kind() != reflect.Struct {
return errors.New("interface{} is not a struct")
}
t = t.Elem()
for i := 0; i < t.NumField(); i++ {
tp := t.Field(i)
seg := tp.Tag.Get(skey)
if seg == "" {
continue
}
if _, ok := star.Row(rows).columnref[seg]; !ok {
continue
}
myInt64 := star.Row(rows).MustInt64(seg)
myUint64 := uint64(star.Row(rows).MustInt64(seg))
switch v.Field(i).Kind() {
case reflect.String:
v.Field(i).SetString(star.Row(rows).MustString(seg))
case reflect.Int64:
v.Field(i).SetInt(myInt64)
case reflect.Int32:
v.Field(i).SetInt(int64(star.Row(rows).MustInt32(seg)))
case reflect.Int16:
v.Field(i).SetInt(int64(int16(myInt64)))
case reflect.Int8:
v.Field(i).SetInt(int64(int8(myInt64)))
case reflect.Uint64:
v.Field(i).SetUint(myUint64)
case reflect.Uint32:
v.Field(i).SetUint(uint64(uint32(myUint64)))
case reflect.Uint16:
v.Field(i).SetUint(uint64(uint16(myUint64)))
case reflect.Uint8:
v.Field(i).SetUint(uint64(uint8(myUint64)))
case reflect.Bool:
v.Field(i).SetBool(star.Row(rows).MustBool(seg))
case reflect.Float64:
v.Field(i).SetFloat(star.Row(rows).MustFloat64(seg))
case reflect.Float32:
v.Field(i).SetFloat(float64(star.Row(rows).MustFloat32(seg)))
default:
}
}
return nil
}
func setAllRefValue(stc interface{}, skey string, kv map[string]interface{}) error {
t := reflect.TypeOf(stc)
v := reflect.ValueOf(stc).Elem()
if t.Kind() != reflect.Ptr || !v.CanSet() {
return errors.New("interface{} is not writable")
}
if v.Kind() != reflect.Struct {
return errors.New("interface{} is not a struct")
}
t = t.Elem()
for i := 0; i < t.NumField(); i++ {
tp := t.Field(i)
seg := tp.Tag.Get(skey)
if seg == "" {
continue
}
if _, ok := kv[seg]; !ok {
continue
}
v.Field(i).Set(reflect.ValueOf(kv[seg]))
}
return nil
}
func setRefValue(stc interface{}, skey, key string, value interface{}) error {
t := reflect.TypeOf(stc)
v := reflect.ValueOf(stc).Elem()
if t.Kind() != reflect.Ptr || !v.CanSet() {
return errors.New("interface{} is not writable")
}
if v.Kind() != reflect.Struct {
return errors.New("interface{} is not a struct")
}
t = t.Elem()
for i := 0; i < t.NumField(); i++ {
tp := t.Field(i)
seg := tp.Tag.Get(skey)
if seg == "" || key != seg {
continue
}
v.Field(i).Set(reflect.ValueOf(value))
}
return nil
}
func getAllRefValue(stc interface{}, skey string) (map[string]interface{}, error) {
result := make(map[string]interface{})
t := reflect.TypeOf(stc)
v := reflect.ValueOf(stc)
if v.Kind() != reflect.Struct {
return nil, errors.New("interface{} is not a struct")
}
if t.Kind() == reflect.Ptr {
t = t.Elem()
v = v.Elem()
}
for i := 0; i < t.NumField(); i++ {
tp := t.Field(i)
seg := tp.Tag.Get(skey)
if seg == "" {
continue
}
value := v.Field(i)
if !value.CanInterface() {
continue
}
result[seg] = value.Interface()
}
return result, nil
}
func getAllRefKey(stc interface{}, skey string) ([]string, error) {
var result []string
_, isStruct := isWritableStruct(stc)
if !isStruct {
return []string{}, errors.New("interface{} is not a struct")
}
t := reflect.TypeOf(stc)
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
for i := 0; i < t.NumField(); i++ {
profile := t.Field(i)
seg := profile.Tag.Get(skey)
if seg != "" {
result = append(result, seg)
}
}
return result, nil
}
func isWritableStruct(stc interface{}) (isWritable bool, isStruct bool) {
t := reflect.TypeOf(stc)
v := reflect.ValueOf(stc)
if t.Kind() == reflect.Ptr && v.Elem().CanSet() {
isWritable = true
}
if v.Kind() == reflect.Struct {
isStruct = true
}
return
}