github.com/easysoft/zendata@v0.0.0-20240513203326-705bd5a7fd67/cmd/test/others/func/proto/defaults/defaults.go (about)

     1  package defaults
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"log"
     8  	"reflect"
     9  	"strconv"
    10  	"time"
    11  
    12  	"github.com/easysoft/zendata/internal/pkg/model"
    13  	"github.com/easysoft/zendata/pkg/utils/vari"
    14  )
    15  
    16  var (
    17  	errInvalidType = errors.New("not a struct pointer")
    18  )
    19  
    20  const (
    21  	fieldName = "default"
    22  )
    23  
    24  // Set initializes members in a struct referenced by a pointer.
    25  // Maps and slices are initialized by `make` and other primitive types are set with default values.
    26  // `ptr` should be a struct pointer
    27  func Set(ptr interface{}, fld *model.DefField) error {
    28  	if reflect.TypeOf(ptr).Kind() != reflect.Ptr {
    29  		return errInvalidType
    30  	}
    31  
    32  	v := reflect.ValueOf(ptr).Elem()
    33  	t := v.Type()
    34  
    35  	if t.Kind() != reflect.Struct {
    36  		return errInvalidType
    37  	}
    38  
    39  	if vari.Verbose {
    40  		log.Println(fmt.Sprintf("1. struct '%s'", v.String()))
    41  	}
    42  
    43  	if t == nil {
    44  		log.Println("")
    45  	}
    46  	fld.Field = t.Name()
    47  	fld.Range = "-"
    48  
    49  	for i := 0; i < t.NumField(); i++ {
    50  		childFld := model.DefField{}
    51  		childFld.Field = t.Field(i).Name
    52  		childFld.Range = "-"
    53  		fld.Fields = append(fld.Fields, childFld)
    54  
    55  		defaultVal := t.Field(i).Tag.Get(fieldName)
    56  		if defaultVal != "-" {
    57  			if err := setField(v.Field(i), defaultVal, &childFld); err != nil {
    58  				return err
    59  			}
    60  		}
    61  	}
    62  	callSetter(ptr)
    63  	return nil
    64  }
    65  
    66  // MustSet function is a wrapper of Set function
    67  // It will call Set and panic if err not equals nil.
    68  func MustSet(ptr interface{}) {
    69  	if err := Set(ptr, nil); err != nil {
    70  		panic(err)
    71  	}
    72  }
    73  
    74  func setField(field reflect.Value, defaultVal string, fld *model.DefField) error {
    75  	if !field.CanSet() {
    76  		return nil
    77  	}
    78  
    79  	if vari.Verbose {
    80  		log.Println(fmt.Sprintf("2. set value '%s'", field.String()))
    81  	}
    82  
    83  	//if !shouldInitializeField(field, defaultVal) {
    84  	//	return nil
    85  	//}
    86  
    87  	if isInitialValue(field) {
    88  		kind := field.Kind()
    89  
    90  		switch kind {
    91  		case reflect.Bool:
    92  			if val, err := strconv.ParseBool(defaultVal); err == nil {
    93  				field.Set(reflect.ValueOf(val).Convert(field.Type()))
    94  			}
    95  		case reflect.Int:
    96  			if val, err := strconv.ParseInt(defaultVal, 0, strconv.IntSize); err == nil {
    97  				field.Set(reflect.ValueOf(int(val)).Convert(field.Type()))
    98  			}
    99  		case reflect.Int8:
   100  			if val, err := strconv.ParseInt(defaultVal, 0, 8); err == nil {
   101  				field.Set(reflect.ValueOf(int8(val)).Convert(field.Type()))
   102  			}
   103  		case reflect.Int16:
   104  			if val, err := strconv.ParseInt(defaultVal, 0, 16); err == nil {
   105  				field.Set(reflect.ValueOf(int16(val)).Convert(field.Type()))
   106  			}
   107  		case reflect.Int32:
   108  			if val, err := strconv.ParseInt(defaultVal, 0, 32); err == nil {
   109  				field.Set(reflect.ValueOf(int32(val)).Convert(field.Type()))
   110  			}
   111  		case reflect.Int64:
   112  			if val, err := time.ParseDuration(defaultVal); err == nil {
   113  				field.Set(reflect.ValueOf(val).Convert(field.Type()))
   114  			} else if val, err := strconv.ParseInt(defaultVal, 0, 64); err == nil {
   115  				field.Set(reflect.ValueOf(val).Convert(field.Type()))
   116  			}
   117  		case reflect.Uint:
   118  			if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil {
   119  				field.Set(reflect.ValueOf(uint(val)).Convert(field.Type()))
   120  			}
   121  		case reflect.Uint8:
   122  			if val, err := strconv.ParseUint(defaultVal, 0, 8); err == nil {
   123  				field.Set(reflect.ValueOf(uint8(val)).Convert(field.Type()))
   124  			}
   125  		case reflect.Uint16:
   126  			if val, err := strconv.ParseUint(defaultVal, 0, 16); err == nil {
   127  				field.Set(reflect.ValueOf(uint16(val)).Convert(field.Type()))
   128  			}
   129  		case reflect.Uint32:
   130  			if val, err := strconv.ParseUint(defaultVal, 0, 32); err == nil {
   131  				field.Set(reflect.ValueOf(uint32(val)).Convert(field.Type()))
   132  			}
   133  		case reflect.Uint64:
   134  			if val, err := strconv.ParseUint(defaultVal, 0, 64); err == nil {
   135  				field.Set(reflect.ValueOf(val).Convert(field.Type()))
   136  			}
   137  		case reflect.Uintptr:
   138  			if val, err := strconv.ParseUint(defaultVal, 0, strconv.IntSize); err == nil {
   139  				field.Set(reflect.ValueOf(uintptr(val)).Convert(field.Type()))
   140  			}
   141  		case reflect.Float32:
   142  			if val, err := strconv.ParseFloat(defaultVal, 32); err == nil {
   143  				field.Set(reflect.ValueOf(float32(val)).Convert(field.Type()))
   144  			}
   145  		case reflect.Float64:
   146  			if val, err := strconv.ParseFloat(defaultVal, 64); err == nil {
   147  				field.Set(reflect.ValueOf(val).Convert(field.Type()))
   148  			}
   149  		case reflect.String:
   150  			field.Set(reflect.ValueOf(defaultVal).Convert(field.Type()))
   151  
   152  		case reflect.Slice:
   153  			ref := reflect.New(field.Type())
   154  			ref.Elem().Set(reflect.MakeSlice(field.Type(), 0, 0))
   155  			if defaultVal != "" && defaultVal != "[]" {
   156  				if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil {
   157  					return err
   158  				}
   159  			}
   160  			field.Set(ref.Elem().Convert(field.Type()))
   161  		case reflect.Map:
   162  			ref := reflect.New(field.Type())
   163  			ref.Elem().Set(reflect.MakeMap(field.Type()))
   164  			if defaultVal != "" && defaultVal != "{}" {
   165  				if err := json.Unmarshal([]byte(defaultVal), ref.Interface()); err != nil {
   166  					return err
   167  				}
   168  			}
   169  			field.Set(ref.Elem().Convert(field.Type()))
   170  		case reflect.Struct:
   171  			if defaultVal != "" && defaultVal != "{}" {
   172  				if err := json.Unmarshal([]byte(defaultVal), field.Addr().Interface()); err != nil {
   173  					return err
   174  				}
   175  			}
   176  		case reflect.Ptr:
   177  			v := reflect.New(field.Type().Elem())
   178  			field.Set(v)
   179  		}
   180  	}
   181  
   182  	switch field.Kind() {
   183  	case reflect.Ptr:
   184  		setField(field.Elem(), defaultVal, fld)
   185  		callSetter(field.Interface())
   186  	case reflect.Struct:
   187  		if err := Set(field.Addr().Interface(), fld); err != nil {
   188  			return err
   189  		}
   190  	case reflect.Slice:
   191  		for j := 0; j < field.Len(); j++ {
   192  			if err := setField(field.Index(j), defaultVal, &model.DefField{}); err != nil {
   193  				return err
   194  			}
   195  		}
   196  	}
   197  
   198  	return nil
   199  }
   200  
   201  func isInitialValue(field reflect.Value) bool {
   202  	return reflect.DeepEqual(reflect.Zero(field.Type()).Interface(), field.Interface())
   203  }
   204  
   205  func shouldInitializeField(field reflect.Value, tag string) bool {
   206  	kind := field.Kind()
   207  
   208  	switch kind {
   209  	case reflect.Struct:
   210  		return true
   211  	case reflect.Ptr:
   212  		if !field.IsNil() && field.Elem().Kind() == reflect.Struct {
   213  			return true
   214  		}
   215  	case reflect.Slice:
   216  		return field.Len() > 0 || tag != ""
   217  	}
   218  
   219  	return tag != ""
   220  }
   221  
   222  // CanUpdate returns true when the given value is an initial value of its type
   223  func CanUpdate(v interface{}) bool {
   224  	return isInitialValue(reflect.ValueOf(v))
   225  }