123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- package exchange
- import (
- "errors"
- "fmt"
- "math"
- "reflect"
- "strconv"
- "strings"
- "gorm.io/gorm"
- )
- func setValueFromString(v reflect.Value, strVal string) error {
- if strVal == "" {
- v.Set(reflect.Zero(v.Type()))
- return nil
- }
- switch v.Kind() {
- case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
- val, err := strconv.ParseInt(strVal, 0, 64)
- if err != nil {
- return err
- }
- if v.OverflowInt(val) {
- return errors.New("Int value too big: " + strVal)
- }
- v.SetInt(val)
- case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
- val, err := strconv.ParseUint(strVal, 0, 64)
- if err != nil {
- return err
- }
- if v.OverflowUint(val) {
- return errors.New("UInt value too big: " + strVal)
- }
- v.SetUint(val)
- case reflect.Float32:
- val, err := strconv.ParseFloat(strVal, 32)
- if err != nil {
- return err
- }
- v.SetFloat(val)
- case reflect.Float64:
- val, err := strconv.ParseFloat(strVal, 64)
- if err != nil {
- return err
- }
- v.SetFloat(val)
- case reflect.String:
- v.SetString(strVal)
- case reflect.Bool:
- val, err := strconv.ParseBool(strVal)
- if err != nil {
- return err
- }
- v.SetBool(val)
- case reflect.Ptr:
- v.Set(reflect.New(v.Type().Elem()))
- return setValueFromString(v.Elem(), strVal)
- default:
- return errors.New("Unsupported kind: " + v.Kind().String())
- }
- return nil
- }
- func validateResourceAndMetas(r interface{}, metas []*Meta) error {
- if r == nil {
- return errors.New("resource is nil")
- }
- rt := reflect.TypeOf(r)
- if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Struct {
- return errors.New("resource is not ptr to struct")
- }
- if len(metas) == 0 {
- return errors.New("no metas")
- }
- ret := rt.Elem()
- for i, _ := range metas {
- m := metas[i]
- if m.field == "" {
- return errors.New("field name is empty")
- }
- if m.setter == nil && m.valuer == nil {
- _, ok := ret.FieldByName(m.field)
- if !ok {
- return fmt.Errorf("field %s not found", m.field)
- }
- }
- if m.columnHeader == "" {
- return errors.New("header is empty")
- }
- if m.primaryKey && (m.setter != nil || m.valuer != nil) {
- return fmt.Errorf("can not set setter/valuer on primaryKey meta")
- }
- }
- return nil
- }
- func preloadDB(db *gorm.DB, associations []string) *gorm.DB {
- if len(associations) == 0 {
- return db
- }
- ndb := db.Preload(associations[0])
- for i := 1; i < len(associations); i++ {
- ndb = ndb.Preload(associations[i])
- }
- return ndb
- }
- func getIndirect(v reflect.Value) reflect.Value {
- if v.Kind() != reflect.Ptr {
- return v
- }
- return getIndirect(reflect.Indirect(v))
- }
- func getIndirectStruct(t reflect.Type) reflect.Type {
- if t.Kind() == reflect.Struct {
- return t
- }
- return getIndirectStruct(t.Elem())
- }
- func clearPrimaryKeyValue(v reflect.Value) {
- t := v.Type()
- if idf, ok := t.FieldByName("ID"); ok {
- if strings.Contains(idf.Tag.Get("gorm"), "primarykey") {
- v.FieldByName("ID").SetUint(0)
- }
- }
- for i := 0; i < t.NumField(); i++ {
- ft := t.Field(i)
- if !strings.Contains(ft.Tag.Get("gorm"), "primarykey") {
- continue
- }
- v.Field(i).Set(reflect.New(ft.Type).Elem())
- }
- }
- func getParamsNumbers(n *int, t reflect.Type, associations []string) {
- for i := 0; i < t.NumField(); i++ {
- ft := t.Field(i)
- isAssociation := false
- for _, a := range associations {
- if ft.Name == a {
- isAssociation = true
- break
- }
- }
- if isAssociation {
- continue
- }
- if ft.Type.Kind() == reflect.Struct && ft.Anonymous {
- getParamsNumbers(n, ft.Type, nil)
- continue
- }
- *n++
- }
- }
- func splitStringSliceSlice(s [][]string, size int) [][][]string {
- groupsLen := int(math.Ceil(float64(len(s)) / float64(size)))
- groups := make([][][]string, groupsLen)
- idx := 0
- for i := 0; i < groupsLen; i++ {
- idx = i * size
- if i != groupsLen-1 {
- groups[i] = s[idx : idx+size]
- } else {
- groups[i] = s[idx:]
- }
- }
- return groups
- }
- func splitInterfaceSlice(s []interface{}, size int) [][]interface{} {
- groupsLen := int(math.Ceil(float64(len(s)) / float64(size)))
- groups := make([][]interface{}, groupsLen)
- idx := 0
- for i := 0; i < groupsLen; i++ {
- idx = i * size
- if i != groupsLen-1 {
- groups[i] = s[idx : idx+size]
- } else {
- groups[i] = s[idx:]
- }
- }
- return groups
- }
- func splitReflectSliceValue(s reflect.Value, size int) []reflect.Value {
- groupsLen := int(math.Ceil(float64(s.Len()) / float64(size)))
- groups := make([]reflect.Value, 0, groupsLen)
- idx := 0
- for i := 0; i < groupsLen; i++ {
- idx = i * size
- endIdx := idx + size
- if i == groupsLen-1 {
- endIdx = s.Len()
- }
- vs := reflect.New(reflect.SliceOf(s.Type().Elem())).Elem()
- for j := idx; j < endIdx; j++ {
- vs = reflect.Append(vs, s.Index(j))
- }
- groups = append(groups, vs)
- }
- return groups
- }
|