Regexp checker is added. Fixes #48 (#67)

* Regexp checker is added. Fixes #48

* Fix the struct tag.
This commit is contained in:
Onur Cinar 2023-06-18 21:23:37 -07:00 committed by GitHub
commit 5dd65585ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 171 additions and 1 deletions

View file

@ -84,6 +84,7 @@ This package currently provides the following checkers:
- [max-length](doc/checkers/maxlength.md) checks if the length of the given value is less than the given maximum length.
- [min](doc/checkers/min.md) checks if the given value is greather than the given minimum.
- [min-length](doc/checkers/minlength.md) checks if the length of the given value is greather than the given minimum length.
- [regexp](doc/checkers/regexp.md) checks if the given string matches the regexp pattern.
- [required](doc/checkers/required.md) checks if the required value is provided.
- [same](doc/checkers/same.md) checks if the given value is equal to the value of the field with the given name.

View file

@ -45,6 +45,7 @@ var makers = map[string]MakeFunc{
CheckerMaxLength: makeMaxLength,
CheckerMin: makeMin,
CheckerMinLength: makeMinLength,
CheckerRegexp: makeRegexp,
CheckerRequired: makeRequired,
CheckerSame: makeSame,
NormalizerLower: makeLower,

48
doc/checkers/regexp.md Normal file
View file

@ -0,0 +1,48 @@
# Regexp Checker
The ```regexp``` checker checks if the given string matches the given regexp. If the given string does not match, the checker will return the ```NOT_MATCH``` result. Here is an example:
```golang
type User struct {
Username string `checkers:"regexp:^[A-Za-z]+$"`
}
user := &User{
Username: "abcd",
}
_, valid := Check(user)
if !valid {
// Send the mistakes back to the user
}
```
The ```regexp``` checker can be used to build other checkers for other regexp patterns. In order to do that, you can use the ```MakeRegexpChecker``` function. The function takes an expression and a result to return when the the given string is not a match. Here is an example:
```golang
checkHex := MakeRegexpChecker("^[A-Fa-f0-9]+$", "NOT_HEX")
result := checkHex(reflect.ValueOf("f0f0f0"), reflect.ValueOf(nil))
if result != ResultValid {
// Send the mistakes back to the user
}
```
To register the new regexp checker to validate user input in struct, you ```MakeRegexpChecker``` function can be used. Here is an example:
```golang
Register("hex", MakeRegexpMaker("^[A-Fa-f0-9]+$", "NOT_HEX"))
type Theme struct {
Color string `checkers:hex`
}
theme := &Theme{
Color: "f0f0f0",
}
_, valid := Check(theme)
if !valid {
// Send the mistakes back to the user
}
```

View file

@ -9,7 +9,7 @@ import (
// CheckerEmail is the name of the checker.
const CheckerEmail = "email"
// ResultNotFqdn indicates that the given string is not a valid email.
// ResultNotEmail indicates that the given string is not a valid email.
const ResultNotEmail = "NOT_EMAIL"
// ipV6Prefix is the IPv6 prefix for the domain.

46
regexp.go Normal file
View file

@ -0,0 +1,46 @@
package checker
import (
"reflect"
"regexp"
)
// CheckerRegexp is the name of the checker.
const CheckerRegexp = "regexp"
// ResultNotMatch indicates that the given string does not match the regexp pattern.
const ResultNotMatch = "NOT_MATCH"
// MakeRegexpMaker makes a regexp checker maker for the given regexp expression with the given invalid result.
func MakeRegexpMaker(expression string, invalidResult Result) MakeFunc {
return func(_ string) CheckFunc {
return MakeRegexpChecker(expression, invalidResult)
}
}
// MakeRegexpChecker makes a regexp checker for the given regexp expression with the given invalid result.
func MakeRegexpChecker(expression string, invalidResult Result) CheckFunc {
pattern := regexp.MustCompile(expression)
return func(value, parent reflect.Value) Result {
return checkRegexp(value, pattern, invalidResult)
}
}
// makeRegexp makes a checker function for the regexp.
func makeRegexp(config string) CheckFunc {
return MakeRegexpChecker(config, ResultNotMatch)
}
// checkRegexp checks if the given string matches the regexp pattern.
func checkRegexp(value reflect.Value, pattern *regexp.Regexp, invalidResult Result) Result {
if value.Kind() != reflect.String {
panic("string expected")
}
if !pattern.MatchString(value.String()) {
return invalidResult
}
return ResultValid
}

74
regexp_test.go Normal file
View file

@ -0,0 +1,74 @@
package checker
import (
"reflect"
"testing"
)
func TestCheckRegexpNonString(t *testing.T) {
defer FailIfNoPanic(t)
type User struct {
Username int `checkers:"regexp:^[A-Za-z]$"`
}
user := &User{}
Check(user)
}
func TestCheckRegexpInvalid(t *testing.T) {
type User struct {
Username string `checkers:"regexp:^[A-Za-z]+$"`
}
user := &User{
Username: "abcd1234",
}
_, valid := Check(user)
if valid {
t.Fail()
}
}
func TestCheckRegexpValid(t *testing.T) {
type User struct {
Username string `checkers:"regexp:^[A-Za-z]+$"`
}
user := &User{
Username: "abcd",
}
_, valid := Check(user)
if !valid {
t.Fail()
}
}
func TestMakeRegexpChecker(t *testing.T) {
checkHex := MakeRegexpChecker("^[A-Fa-f0-9]+$", "NOT_HEX")
result := checkHex(reflect.ValueOf("f0f0f0"), reflect.ValueOf(nil))
if result != ResultValid {
t.Fail()
}
}
func TestMakeRegexpMaker(t *testing.T) {
Register("hex", MakeRegexpMaker("^[A-Fa-f0-9]+$", "NOT_HEX"))
type Theme struct {
Color string `checkers:"hex"`
}
theme := &Theme{
Color: "f0f0f0",
}
_, valid := Check(theme)
if !valid {
t.Fail()
}
}