Hypercode/alex/hypercodePublic

Code

  1. hypercode
  2. validator
  3. rule
  4. rule.go
rule.go190 lines
package rule

import (
	"fmt"
	"regexp"
	"strconv"
)

type Rule interface {
	Validate(field string, value string) (bool, string)
	WithMessage(message string) Rule
}

type requiredRule struct {
	customMessage string
}

func Required() Rule {
	return &requiredRule{}
}

func (r *requiredRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s is required", field)
		}
		return false, msg
	}
	return true, ""
}

func (r *requiredRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}

type emailRule struct {
	customMessage string
}

func Email() Rule {
	return &emailRule{}
}

func (r *emailRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		return true, ""
	}

	emailRegex := regexp.MustCompile(`^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$`)
	if !emailRegex.MatchString(value) {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be a valid email address", field)
		}
		return false, msg
	}
	return true, ""
}

func (r *emailRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}

type minRule struct {
	min           int
	customMessage string
}

func Min(min int) Rule {
	return &minRule{min: min}
}

func (r *minRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		return true, ""
	}

	if len(value) < r.min {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be at least %d characters", field, r.min)
		}
		return false, msg
	}
	return true, ""
}

func (r *minRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}

type maxRule struct {
	max           int
	customMessage string
}

func Max(max int) Rule {
	return &maxRule{max: max}
}

func (r *maxRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		return true, ""
	}

	if len(value) > r.max {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be at most %d characters", field, r.max)
		}
		return false, msg
	}
	return true, ""
}

func (r *maxRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}

type numericRule struct {
	customMessage string
}

func Numeric() Rule {
	return &numericRule{}
}

func (r *numericRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		return true, ""
	}

	if _, err := strconv.ParseFloat(value, 64); err != nil {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be a number", field)
		}
		return false, msg
	}
	return true, ""
}

func (r *numericRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}

type gteRule struct {
	min           int
	customMessage string
}

func Gte(min int) Rule {
	return >eRule{min: min}
}

func (r *gteRule) Validate(field string, value string) (bool, string) {
	if value == "" {
		return true, ""
	}

	num, err := strconv.Atoi(value)
	if err != nil {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be a number", field)
		}
		return false, msg
	}

	if num < r.min {
		msg := r.customMessage
		if msg == "" {
			msg = fmt.Sprintf("%s must be greater than or equal to %d", field, r.min)
		}
		return false, msg
	}
	return true, ""
}

func (r *gteRule) WithMessage(message string) Rule {
	r.customMessage = message
	return r
}