github.com/bytedance/go-tagexpr@v2.7.5-0.20210114074101-de5b8743ad85+incompatible/validator/func.go (about)

     1  package validator
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"regexp"
     7  
     8  	"github.com/nyaruka/phonenumbers"
     9  
    10  	tagexpr "github.com/bytedance/go-tagexpr"
    11  )
    12  
    13  // ErrInvalidWithoutMsg verification error without error message.
    14  var ErrInvalidWithoutMsg = errors.New("")
    15  
    16  // MustRegFunc registers validator function expression.
    17  // NOTE:
    18  //  panic if exist error;
    19  //  example: phone($) or phone($,'CN');
    20  //  If @force=true, allow to cover the existed same @funcName;
    21  //  The go number types always are float64;
    22  //  The go string types always are string.
    23  func MustRegFunc(funcName string, fn func(args ...interface{}) error, force ...bool) {
    24  	err := RegFunc(funcName, fn, force...)
    25  	if err != nil {
    26  		panic(err)
    27  	}
    28  }
    29  
    30  // RegFunc registers validator function expression.
    31  // NOTE:
    32  //  example: phone($) or phone($,'CN');
    33  //  If @force=true, allow to cover the existed same @funcName;
    34  //  The go number types always are float64;
    35  //  The go string types always are string.
    36  func RegFunc(funcName string, fn func(args ...interface{}) error, force ...bool) error {
    37  	return tagexpr.RegFunc(funcName, func(args ...interface{}) interface{} {
    38  		err := fn(args...)
    39  		if err == nil {
    40  			// nil defaults to false, so returns true
    41  			return true
    42  		}
    43  		return err
    44  	}, force...)
    45  }
    46  
    47  func init() {
    48  	var pattern = "^([A-Za-z0-9_\\-\\.\u4e00-\u9fa5])+\\@([A-Za-z0-9_\\-\\.])+\\.([A-Za-z]{2,8})$"
    49  	emailRegexp := regexp.MustCompile(pattern)
    50  	MustRegFunc("email", func(args ...interface{}) error {
    51  		if len(args) != 1 {
    52  			return errors.New("number of parameters of email function is not one")
    53  		}
    54  		s, ok := args[0].(string)
    55  		if !ok {
    56  			return errors.New("parameter of email function is not string type")
    57  		}
    58  		matched := emailRegexp.MatchString(s)
    59  		if !matched {
    60  			// return ErrInvalidWithoutMsg
    61  			return errors.New("email format is incorrect")
    62  		}
    63  		return nil
    64  	}, true)
    65  }
    66  
    67  func init() {
    68  	// phone: defaultRegion is 'CN'
    69  	MustRegFunc("phone", func(args ...interface{}) error {
    70  		var numberToParse, defaultRegion string
    71  		var ok bool
    72  		switch len(args) {
    73  		default:
    74  			return errors.New("the number of parameters of phone function is not one or two")
    75  		case 2:
    76  			defaultRegion, ok = args[1].(string)
    77  			if !ok {
    78  				return errors.New("the 2nd parameter of phone function is not string type")
    79  			}
    80  			fallthrough
    81  		case 1:
    82  			numberToParse, ok = args[0].(string)
    83  			if !ok {
    84  				return errors.New("the 1st parameter of phone function is not string type")
    85  			}
    86  		}
    87  		if defaultRegion == "" {
    88  			defaultRegion = "CN"
    89  		}
    90  		num, err := phonenumbers.Parse(numberToParse, defaultRegion)
    91  		if err != nil {
    92  			return err
    93  		}
    94  		matched := phonenumbers.IsValidNumber(num)
    95  		if !matched {
    96  			// return ErrInvalidWithoutMsg
    97  			return errors.New("phone format is incorrect")
    98  		}
    99  		return nil
   100  	}, true)
   101  }
   102  
   103  func init() {
   104  	// in: Check if the first parameter is one of the enumerated parameters
   105  	MustRegFunc("in", func(args ...interface{}) error {
   106  		switch len(args) {
   107  		case 0:
   108  			return nil
   109  		case 1:
   110  			return errors.New("input parameters of the in function are at least two")
   111  		default:
   112  			elem := args[0]
   113  			set := args[1:]
   114  			for _, e := range set {
   115  				if elem == e {
   116  					return nil
   117  				}
   118  			}
   119  			return fmt.Errorf("%+v range exceeded", set)
   120  		}
   121  	}, true)
   122  }