Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
Jamess-Lucass committed Jan 26, 2024
1 parent 5ca6f64 commit 389d586
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 130 deletions.
10 changes: 6 additions & 4 deletions examples/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
type User struct {
Firstname string
Lastname string
Age int
}

func main() {
Expand All @@ -30,19 +31,20 @@ func main() {
validator.Required(),
validator.Min(3),
).WithName("lastname"),
validator.RuleFor(user.Age, validator.Min(0)),

Check failure on line 34 in examples/main.go

View workflow job for this annotation

GitHub Actions / test (1.20.x)

type *validator.RuleConfig[string] of validator.Min(0) does not match inferred type *validator.RuleConfig[int] for *validator.RuleConfig[T]

Check failure on line 34 in examples/main.go

View workflow job for this annotation

GitHub Actions / test (1.21.x)

type *validator.RuleConfig[string] of validator.Min(0) does not match inferred type *validator.RuleConfig[int] for *validator.RuleConfig[T]
)

validationResult := rules.Validate()

fmt.Printf("valid: %t with errors: %v\n", validationResult.IsValid(), validationResult.Errors)
}

func Custom() *validator.RuleConfig {
return &validator.RuleConfig{
MessageFunc: func(r validator.RuleConfig) string {
func Custom[T any]() *validator.RuleConfig[T] {
return &validator.RuleConfig[T]{
MessageFunc: func(r validator.RuleConfig[T]) string {
return fmt.Sprintf("'%s' must equal 'jane'", r.Value)
},
ValidateFunc: func(r validator.RuleConfig) bool {
ValidateFunc: func(r validator.RuleConfig[T]) bool {
val, ok := r.Value.(string)

Check failure on line 48 in examples/main.go

View workflow job for this annotation

GitHub Actions / test (1.20.x)

invalid operation: cannot use type assertion on type parameter value r.Value (variable of type T constrained by any)

Check failure on line 48 in examples/main.go

View workflow job for this annotation

GitHub Actions / test (1.21.x)

invalid operation: cannot use type assertion on type parameter value r.Value (variable of type T constrained by any)
if !ok {
return false
Expand Down
70 changes: 35 additions & 35 deletions rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,67 @@ package validator

import "fmt"

type RuleConfig struct {
Value any
MessageFunc func(RuleConfig) string
ValidateFunc func(RuleConfig) bool
type RuleConfig[T any] struct {
Value T
MessageFunc func(RuleConfig[T]) string
ValidateFunc func(RuleConfig[T]) bool
}

func Min(min int) *RuleConfig {
return &RuleConfig{
MessageFunc: func(r RuleConfig) string {
func Min[T string](min int) *RuleConfig[T] {
return &RuleConfig[T]{
MessageFunc: func(r RuleConfig[T]) string {
return fmt.Sprintf("'%s' does not meet the minimum length of %d", r.Value, min)
},
ValidateFunc: func(r RuleConfig) bool {
val, ok := r.Value.(string)
if !ok {
return false
}

return len(val) >= min
ValidateFunc: func(r RuleConfig[T]) bool {
return len(r.Value) >= min
},
}
}

func Max(max int) *RuleConfig {
return &RuleConfig{
MessageFunc: func(r RuleConfig) string {
func Max[T string](max int) *RuleConfig[T] {
return &RuleConfig[T]{
MessageFunc: func(r RuleConfig[T]) string {
return fmt.Sprintf("'%s' exceeds the maximum length of %d", r.Value, max)
},
ValidateFunc: func(r RuleConfig) bool {
val, ok := r.Value.(string)
if !ok {
return false
}

return len(val) <= max
ValidateFunc: func(r RuleConfig[T]) bool {
return len(r.Value) <= max
},
}
}

func Must(predicate func() bool) *RuleConfig {
return &RuleConfig{
MessageFunc: func(r RuleConfig) string {
func Must[T any](predicate func() bool) *RuleConfig[T] {
return &RuleConfig[T]{
MessageFunc: func(r RuleConfig[T]) string {
return "Validation failed"
},
ValidateFunc: func(r RuleConfig) bool {
ValidateFunc: func(r RuleConfig[T]) bool {
return predicate()
},
}
}

func Required() *RuleConfig {
return &RuleConfig{
MessageFunc: func(r RuleConfig) string {
func Required[T string]() *RuleConfig[T] {
return &RuleConfig[T]{
MessageFunc: func(r RuleConfig[T]) string {
return "Required"
},
ValidateFunc: func(r RuleConfig) bool {
val, ok := r.Value.(string)
ValidateFunc: func(r RuleConfig[T]) bool {
return len(r.Value) > 0
},
}
}

func GreaterThan[T int](min int) *RuleConfig[T] {
return &RuleConfig[T]{
MessageFunc: func(r RuleConfig[T]) string {
return fmt.Sprintf("%d must be greater than %d", r.Value, min)
},
ValidateFunc: func(r RuleConfig[T]) bool {
val, ok := interface{}(r.Value).(int)
if !ok {
return false
}

return len(val) > 0
return val > min
},
}
}
26 changes: 13 additions & 13 deletions validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,31 +17,31 @@ func (m *ValidationError) Error() string {
return m.errorMessage
}

func (r *RuleConfig) WithMessage(message string) *RuleConfig {
r.MessageFunc = func(r RuleConfig) string {
func (r *RuleConfig[T]) WithMessage(message string) *RuleConfig[T] {
r.MessageFunc = func(r RuleConfig[T]) string {
return message
}

return r
}

type Rule struct {
value any
type Rule[T any] struct {
value T
name string
rules []*RuleConfig
rules []*RuleConfig[T]
}

func RuleFor(value any, options ...*RuleConfig) *Rule {
return &Rule{value: value, rules: options}
func RuleFor[T any](value T, options ...*RuleConfig[T]) *Rule[T] {
return &Rule[T]{value: value, rules: options}
}

func (r *Rule) WithName(name string) *Rule {
func (r *Rule[T]) WithName(name string) *Rule[T] {
r.name = name

return r
}

func (r *Rule) Validate() *ValidationResult {
func (r *Rule[T]) Validate() *ValidationResult {
res := &ValidationResult{}

for _, rule := range r.rules {
Expand All @@ -60,10 +60,10 @@ func (r *Rule) Validate() *ValidationResult {
return res
}

type MultipleRules []Rule
type MultipleRules[T any] []Rule[T]

func Rules(options ...*Rule) *MultipleRules {
multipleRules := make(MultipleRules, len(options))
func Rules[T any](options ...*Rule[T]) *MultipleRules[T] {
multipleRules := make(MultipleRules[T], len(options))

for i, opt := range options {
multipleRules[i] = *opt
Expand All @@ -72,7 +72,7 @@ func Rules(options ...*Rule) *MultipleRules {
return &multipleRules
}

func (r *MultipleRules) Validate() *ValidationResult {
func (r *MultipleRules[T]) Validate() *ValidationResult {
res := &ValidationResult{}

for _, rule := range *r {
Expand Down
181 changes: 103 additions & 78 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,89 +10,114 @@ import (
type User struct {
Firstname string
Lastname string
Age int
}

func Test_MinWithValidLength_ReturnsTrue(t *testing.T) {
user := User{
Firstname: "john",
}
// func Test_MinWithValidLength_ReturnsTrue(t *testing.T) {
// user := User{
// Firstname: "john",
// }

// rule := validator.RuleFor(
// user.Firstname,
// validator.Min(4),
// )

// res := rule.Validate()

// assert.Equal(t, true, res.IsValid())
// }

// func Test_MinWithInvalidLength_ReturnsFalse(t *testing.T) {
// user := User{
// Firstname: "john",
// }

// rule := validator.RuleFor(
// user.Firstname,
// validator.Min(100),
// )

// assert.Equal(t, false, rule.Validate().IsValid())
// }

// func Test_MultipleMinWithInValidLength_ReturnsFalse(t *testing.T) {
// user := User{
// Firstname: "john",
// }

// rules := validator.Rules(
// validator.RuleFor(
// user.Firstname,
// validator.Min(4),
// ),
// validator.RuleFor(
// user.Lastname,
// validator.Min(4),
// ),
// )

// assert.Equal(t, false, rules.Validate().IsValid())
// }

// func Test_MaxWithValidLength_ReturnsTrue(t *testing.T) {
// user := User{
// Firstname: "john",
// }

// rule := validator.RuleFor(
// user.Firstname,
// validator.Max(5),
// )

// assert.Equal(t, true, rule.Validate().IsValid())
// }

// func Test_MaxWithInvalidLength_ReturnsFalse(t *testing.T) {
// user := User{
// Firstname: "john",
// }

// rule := validator.RuleFor(
// user.Firstname,
// validator.Max(2),
// )

// assert.Equal(t, false, rule.Validate().IsValid())
// }

// func Test_RequiredWithNoValue_ReturnsFalse(t *testing.T) {
// user := User{}

// rule := validator.RuleFor(
// user.Firstname,
// validator.Required(),
// validator.Min(2),
// )

// assert.Equal(t, false, rule.Validate().IsValid())
// }

// func Test_GreaterThanInvalid_ReturnsFalse(t *testing.T) {
// user := User{Age: 17}

// rule := validator.RuleFor(
// user.Age,
// validator.Required(),
// validator.GreaterThan(17),
// )

// assert.Equal(t, false, rule.Validate().IsValid())
// }

func Test_GreaterThanValid_ReturnsTrue(t *testing.T) {
user := User{Age: 18}

rule := validator.RuleFor(
user.Firstname,
validator.Min(4),
)

res := rule.Validate()

assert.Equal(t, true, res.IsValid())
}

func Test_MinWithInvalidLength_ReturnsFalse(t *testing.T) {
user := User{
Firstname: "john",
}

rule := validator.RuleFor(
user.Firstname,
validator.Min(100),
)

assert.Equal(t, false, rule.Validate().IsValid())
}

func Test_MultipleMinWithInValidLength_ReturnsFalse(t *testing.T) {
user := User{
Firstname: "john",
}

rules := validator.Rules(
validator.RuleFor(
user.Firstname,
validator.Min(4),
),
validator.RuleFor(
user.Lastname,
validator.Min(4),
),
)

assert.Equal(t, false, rules.Validate().IsValid())
}

func Test_MaxWithValidLength_ReturnsTrue(t *testing.T) {
user := User{
Firstname: "john",
}

rule := validator.RuleFor(
user.Firstname,
validator.Max(5),
)

assert.Equal(t, true, rule.Validate().IsValid())
}

func Test_MaxWithInvalidLength_ReturnsFalse(t *testing.T) {
user := User{
Firstname: "john",
}

rule := validator.RuleFor(
user.Firstname,
validator.Max(2),
)

assert.Equal(t, false, rule.Validate().IsValid())
}

func Test_RequiredWithNoValue_ReturnsFalse(t *testing.T) {
user := User{}

rule := validator.RuleFor(
user.Firstname,
user.Age,
validator.Required(),

Check failure on line 118 in validator_test.go

View workflow job for this annotation

GitHub Actions / test (1.20.x)

type *validator.RuleConfig[string] of validator.Required() does not match inferred type *validator.RuleConfig[int] for *validator.RuleConfig[T]

Check failure on line 118 in validator_test.go

View workflow job for this annotation

GitHub Actions / test (1.21.x)

type *validator.RuleConfig[string] of validator.Required() does not match inferred type *validator.RuleConfig[int] for *validator.RuleConfig[T]
validator.Min(2),
validator.GreaterThan(17),
)

assert.Equal(t, false, rule.Validate().IsValid())
assert.Equal(t, true, rule.Validate().IsValid())
}

0 comments on commit 389d586

Please sign in to comment.