github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/depends/kit/validator/validator__string.go (about) 1 package validator 2 3 import ( 4 "context" 5 "fmt" 6 "reflect" 7 "regexp" 8 9 "github.com/machinefi/w3bstream/pkg/depends/kit/validator/errors" 10 "github.com/machinefi/w3bstream/pkg/depends/kit/validator/rules" 11 ) 12 13 var ( 14 TargetStringLength = "string length" 15 TargetStringValue = "string value" 16 ) 17 18 type String struct { 19 Enums map[string]string 20 Pattern *regexp.Regexp 21 LenMode StrLenMode 22 23 MinLength uint64 24 MaxLength *uint64 25 } 26 27 func init() { DefaultFactory.Register(&String{}) } 28 29 func (String) Names() []string { return []string{"string", "char"} } 30 31 func (vs *String) Validate(v interface{}) error { 32 rv, ok := v.(reflect.Value) 33 if !ok { 34 rv = reflect.ValueOf(v) 35 } 36 37 _t := reflect.TypeOf("") 38 39 if !rv.Type().ConvertibleTo(_t) { 40 return errors.NewUnsupportedTypeError(rv.Type().String(), vs.String()) 41 } 42 43 s := rv.Convert(_t).String() 44 45 if vs.Enums != nil { 46 if _, ok := vs.Enums[s]; !ok { 47 values := make([]interface{}, 0) 48 for _, v := range vs.Enums { 49 values = append(values, v) 50 } 51 52 return &errors.NotInEnumError{ 53 Target: TargetStringValue, 54 Current: v, 55 Enums: values, 56 } 57 } 58 return nil 59 } 60 61 if vs.Pattern != nil { 62 if !vs.Pattern.MatchString(s) { 63 return &errors.NotMatchError{ 64 Target: TargetStringLength, 65 Pattern: vs.Pattern, 66 Current: v, 67 } 68 } 69 return nil 70 } 71 72 length := StrLenModes[vs.LenMode](s) 73 74 if length < vs.MinLength { 75 return &errors.OutOfRangeError{ 76 Target: TargetStringLength, 77 Current: length, 78 Minimum: vs.MinLength, 79 } 80 } 81 82 if vs.MaxLength != nil && length > *vs.MaxLength { 83 return &errors.OutOfRangeError{ 84 Target: TargetStringLength, 85 Current: length, 86 Maximum: vs.MaxLength, 87 } 88 } 89 return nil 90 } 91 92 func (String) New(ctx context.Context, r *Rule) (Validator, error) { 93 vs := &String{} 94 95 if r.ExclusiveMin || r.ExclusiveMax { 96 return nil, errors.NewSyntaxError( 97 "range mark of %s should not be `(` or `)`", vs.Names()[0], 98 ) 99 } 100 101 mode, err := StringRuleParam(r) 102 if err != nil { 103 return nil, err 104 } 105 vs.LenMode = mode 106 107 if r.Pattern != nil { 108 vs.Pattern = r.Pattern 109 return vs, vs.TypeCheck(r) 110 } 111 112 min, max, err := UintRuleRange(r, fmt.Sprintf("%s of string", vs.LenMode), 64) 113 if err != nil { 114 return nil, err 115 } 116 vs.MinLength = min 117 vs.MaxLength = max 118 119 vs.Enums = StringRuleValues(r) 120 121 return vs, vs.TypeCheck(r) 122 } 123 124 func (vs *String) TypeCheck(r *Rule) error { 125 if r.Type.Kind() == reflect.String { 126 return nil 127 } 128 return errors.NewUnsupportedTypeError(r.String(), vs.String()) 129 } 130 131 func (vs *String) String() string { 132 r := rules.NewRule(vs.Names()[0]) 133 134 if vs.Enums != nil { 135 ruleValues := make([]*rules.Lit, 0) 136 for _, e := range vs.Enums { 137 ruleValues = append(ruleValues, rules.NewLiteral([]byte(e))) 138 } 139 r.ValueMatrix = [][]*rules.Lit{ruleValues} 140 } 141 142 r.Params = []rules.Node{ 143 rules.NewLiteral([]byte(vs.LenMode.String())), 144 } 145 146 if vs.Pattern != nil { 147 r.Pattern = vs.Pattern 148 } 149 150 r.Range = RangeFromUint(vs.MinLength, vs.MaxLength) 151 152 return string(r.Bytes()) 153 }