github.com/bytedance/go-tagexpr/v2@v2.9.8/binding/func.go (about) 1 package binding 2 3 import ( 4 jsonpkg "encoding/json" 5 "errors" 6 "fmt" 7 "reflect" 8 "time" 9 10 "github.com/andeya/ameda" 11 "google.golang.org/protobuf/proto" 12 ) 13 14 // JSONUnmarshaler is the interface implemented by types 15 // that can unmarshal a JSON description of themselves. 16 type JSONUnmarshaler func(data []byte, v interface{}) error 17 18 // ResetJSONUnmarshaler reset the JSON Unmarshal function. 19 // NOTE: verifyingRequired is true if the required tag is supported. 20 // 21 // Deprecated: please use: Default().ResetJSONUnmarshaler 22 func ResetJSONUnmarshaler(fn JSONUnmarshaler) { 23 defaultBinding.ResetJSONUnmarshaler(fn) 24 } 25 26 var typeUnmarshalFuncs = make(map[reflect.Type]func(string, bool) (reflect.Value, error)) 27 28 func unsafeUnmarshalValue(v reflect.Value, s string, looseZeroMode bool) error { 29 fn := typeUnmarshalFuncs[v.Type()] 30 if fn != nil { 31 vv, err := fn(s, looseZeroMode) 32 if err == nil { 33 v.Set(vv) 34 } 35 return err 36 } 37 return unmarshal(ameda.UnsafeStringToBytes(s), v.Addr().Interface()) 38 } 39 40 func unsafeUnmarshalSlice(t reflect.Type, a []string, looseZeroMode bool) (reflect.Value, error) { 41 var err error 42 fn := typeUnmarshalFuncs[t] 43 if fn == nil { 44 fn = func(s string, _ bool) (reflect.Value, error) { 45 v := reflect.New(t) 46 i := v.Interface() 47 err = unmarshal(ameda.UnsafeStringToBytes(s), i) 48 return v.Elem(), err 49 } 50 } 51 v := reflect.New(reflect.SliceOf(t)).Elem() 52 for _, s := range a { 53 var vv reflect.Value 54 vv, err = fn(s, looseZeroMode) 55 if err != nil { 56 return v, err 57 } 58 v = reflect.Append(v, vv) 59 } 60 return v, nil 61 } 62 63 func unmarshal(b []byte, i interface{}) error { 64 switch x := i.(type) { 65 case jsonpkg.Unmarshaler: 66 return x.UnmarshalJSON(b) 67 case proto.Message: 68 return proto.Unmarshal(b, x) 69 default: 70 return jsonpkg.Unmarshal(b, i) 71 } 72 } 73 74 // MustRegTypeUnmarshal registers unmarshalor function of type. 75 // NOTE: 76 // 77 // panic if exist error. 78 func MustRegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error)) { 79 err := RegTypeUnmarshal(t, fn) 80 if err != nil { 81 panic(err) 82 } 83 } 84 85 // RegTypeUnmarshal registers unmarshalor function of type. 86 func RegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error)) error { 87 // check 88 switch t.Kind() { 89 case reflect.String, reflect.Bool, 90 reflect.Float32, reflect.Float64, 91 reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, 92 reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8: 93 return errors.New("registration type cannot be a basic type") 94 case reflect.Ptr: 95 return errors.New("registration type cannot be a pointer type") 96 } 97 // test 98 vv, err := fn("", true) 99 if err != nil { 100 return fmt.Errorf("test fail: %s", err) 101 } 102 if tt := vv.Type(); tt != t { 103 return fmt.Errorf("test fail: expect return value type is %s, but got %s", t.String(), tt.String()) 104 } 105 106 typeUnmarshalFuncs[t] = fn 107 return nil 108 } 109 110 func init() { 111 MustRegTypeUnmarshal(reflect.TypeOf(time.Time{}), func(v string, emptyAsZero bool) (reflect.Value, error) { 112 if v == "" && emptyAsZero { 113 return reflect.ValueOf(time.Time{}), nil 114 } 115 t, err := time.Parse(time.RFC3339, v) 116 if err != nil { 117 return reflect.Value{}, err 118 } 119 return reflect.ValueOf(t), nil 120 }) 121 }