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  }