github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/binding/func.go (about) 1 package binding 2 3 import ( 4 "errors" 5 "fmt" 6 "reflect" 7 "time" 8 ) 9 10 // JSONUnmarshaler is the interface implemented by types 11 // that can unmarshal a JSON description of themselves. 12 type JSONUnmarshaler func(data []byte, v interface{}) error 13 14 var ( 15 jsonUnmarshalFunc func(data []byte, v interface{}) error 16 ) 17 18 // ResetJSONUnmarshaler reset the JSON Unmarshal function. 19 // NOTE: verifyingRequired is true if the required tag is supported. 20 func ResetJSONUnmarshaler(fn JSONUnmarshaler) { 21 jsonUnmarshalFunc = fn 22 } 23 24 var typeUnmarshalFuncs = make(map[reflect.Type]func(string, bool) (reflect.Value, error)) 25 26 // MustRegTypeUnmarshal registers unmarshalor function of type. 27 // NOTE: 28 // panic if exist error. 29 func MustRegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error)) { 30 err := RegTypeUnmarshal(t, fn) 31 if err != nil { 32 panic(err) 33 } 34 } 35 36 // RegTypeUnmarshal registers unmarshalor function of type. 37 func RegTypeUnmarshal(t reflect.Type, fn func(v string, emptyAsZero bool) (reflect.Value, error)) error { 38 // check 39 switch t.Kind() { 40 case reflect.String, reflect.Bool, 41 reflect.Float32, reflect.Float64, 42 reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, 43 reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8: 44 return errors.New("registration type cannot be a basic type") 45 case reflect.Ptr: 46 return errors.New("registration type cannot be a pointer type") 47 } 48 // test 49 vv, err := fn("", true) 50 if err != nil { 51 return fmt.Errorf("test fail: %s", err) 52 } 53 if tt := vv.Type(); tt != t { 54 return fmt.Errorf("test fail: expect return value type is %s, but got %s", t.String(), tt.String()) 55 } 56 57 typeUnmarshalFuncs[t] = fn 58 return nil 59 } 60 61 func init() { 62 MustRegTypeUnmarshal(reflect.TypeOf(time.Time{}), func(v string, emptyAsZero bool) (reflect.Value, error) { 63 if v == "" && emptyAsZero { 64 return reflect.ValueOf(time.Time{}), nil 65 } 66 t, err := time.Parse(time.RFC3339, v) 67 if err != nil { 68 return reflect.Value{}, err 69 } 70 return reflect.ValueOf(t), nil 71 }) 72 }