github.com/profzone/eden-framework@v1.0.10/pkg/strings/stringifier.go (about) 1 package str 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "strconv" 8 "strings" 9 ) 10 11 var ( 12 UnSupportTypeError = errors.New("un support type") 13 ) 14 15 type StringUnmarshal func(s string, v reflect.Value) (bool, error) 16 17 type Stringifier struct { 18 stringUnmarshalList []StringUnmarshal 19 } 20 21 func (stringifier *Stringifier) Register(stringUnmarshalList ...StringUnmarshal) { 22 stringifier.stringUnmarshalList = append(stringifier.stringUnmarshalList, stringUnmarshalList...) 23 } 24 25 func (stringifier Stringifier) Unmarshal(str string, rv reflect.Value) error { 26 rv = reflect.Indirect(rv) 27 for _, stringUnmarshal := range stringifier.stringUnmarshalList { 28 matched, err := stringUnmarshal(str, rv) 29 if matched { 30 if err != nil { 31 return fmt.Errorf("unmarshal failed for %v: %s", stringUnmarshal, err.Error()) 32 } 33 return nil 34 } 35 } 36 return stringifier.UnmarshalBuiltIn(str, rv) 37 } 38 39 func (stringifier Stringifier) UnmarshalBuiltIn(str string, rv reflect.Value) error { 40 switch rv.Kind() { 41 case reflect.String: 42 rv.SetString(str) 43 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 44 intV, err := strconv.ParseInt(str, 10, getBitSize(rv)) 45 if err != nil { 46 return err 47 } 48 rv.Set(reflect.ValueOf(intV).Convert(rv.Type())) 49 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 50 uintV, err := strconv.ParseUint(str, 10, getBitSize(rv)) 51 if err != nil { 52 return err 53 } 54 rv.Set(reflect.ValueOf(uintV).Convert(rv.Type())) 55 case reflect.Float32, reflect.Float64: 56 bitSize := getBitSize(rv) 57 floatV, err := strconv.ParseFloat(str, bitSize) 58 if err != nil { 59 return err 60 } 61 rv.Set(reflect.ValueOf(floatV).Convert(rv.Type())) 62 case reflect.Bool: 63 boolV, err := strconv.ParseBool(str) 64 if err != nil { 65 return err 66 } 67 rv.SetBool(boolV) 68 case reflect.Slice, reflect.Array: 69 if str != "" { 70 subStrValues := strings.Split(str, ",") 71 elemType := rv.Type().Elem() 72 tmpSlice := reflect.MakeSlice(reflect.SliceOf(elemType), 0, 0) 73 for _, subStrValue := range subStrValues { 74 elemValue := reflect.New(elemType) 75 err := stringifier.Unmarshal(subStrValue, elemValue) 76 if err != nil { 77 return err 78 } 79 tmpSlice = reflect.Append(tmpSlice, elemValue.Elem()) 80 } 81 rv.Set(tmpSlice) 82 } 83 default: 84 return UnSupportTypeError 85 } 86 return nil 87 } 88 89 func getBitSize(v reflect.Value) int { 90 switch v.Kind() { 91 case reflect.Int, reflect.Uint: 92 return 32 93 case reflect.Int8, reflect.Uint8: 94 return 8 95 case reflect.Int16, reflect.Uint16: 96 return 16 97 case reflect.Int32, reflect.Uint32, reflect.Float32: 98 return 32 99 case reflect.Int64, reflect.Uint64, reflect.Float64: 100 return 64 101 default: 102 panic("only int, uint and float can support getBitSize") 103 } 104 }