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 }