Skip to content

Commit

Permalink
Convert error codes to error messages.
Browse files Browse the repository at this point in the history
  • Loading branch information
cinar committed Oct 29, 2024
1 parent dd6eb0b commit 4dd1e4b
Show file tree
Hide file tree
Showing 60 changed files with 394 additions and 402 deletions.
13 changes: 7 additions & 6 deletions alphanumeric.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@
package checker

import (
"errors"
"reflect"
"unicode"
)

// CheckerAlphanumeric is the name of the checker.
const CheckerAlphanumeric = "alphanumeric"

// ResultNotAlphanumeric indicates that the given string contains non-alphanumeric characters.
const ResultNotAlphanumeric = "NOT_ALPHANUMERIC"
// ErrNotAlphanumeric indicates that the given string contains non-alphanumeric characters.
var ErrNotAlphanumeric = errors.New("please use only letters and numbers")

// IsAlphanumeric checks if the given string consists of only alphanumeric characters.
func IsAlphanumeric(value string) Result {
func IsAlphanumeric(value string) error {
for _, c := range value {
if !unicode.IsDigit(c) && !unicode.IsLetter(c) {
return ResultNotAlphanumeric
return ErrNotAlphanumeric
}
}

return ResultValid
return nil
}

// makeAlphanumeric makes a checker function for the alphanumeric checker.
Expand All @@ -33,7 +34,7 @@ func makeAlphanumeric(_ string) CheckFunc {
}

// checkAlphanumeric checks if the given string consists of only alphanumeric characters.
func checkAlphanumeric(value, _ reflect.Value) Result {
func checkAlphanumeric(value, _ reflect.Value) error {
if value.Kind() != reflect.String {
panic("string expected")
}
Expand Down
9 changes: 4 additions & 5 deletions alphanumeric_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ import (
)

func ExampleIsAlphanumeric() {
result := checker.IsAlphanumeric("ABcd1234")

if result != checker.ResultValid {
err := checker.IsAlphanumeric("ABcd1234")
if err != nil {
// Send the mistakes back to the user
}
}

func TestIsAlphanumericInvalid(t *testing.T) {
if checker.IsAlphanumeric("-/") == checker.ResultValid {
if checker.IsAlphanumeric("-/") == nil {
t.Fail()
}
}

func TestIsAlphanumericValid(t *testing.T) {
if checker.IsAlphanumeric("ABcd1234") != checker.ResultValid {
if checker.IsAlphanumeric("ABcd1234") != nil {
t.Fail()
}
}
Expand Down
13 changes: 7 additions & 6 deletions ascii.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@
package checker

import (
"errors"
"reflect"
"unicode"
)

// CheckerASCII is the name of the checker.
const CheckerASCII = "ascii"

// ResultNotASCII indicates that the given string contains non-ASCII characters.
const ResultNotASCII = "NOT_ASCII"
// ErrNotASCII indicates that the given string contains non-ASCII characters.
var ErrNotASCII = errors.New("please use standard English characters only")

// IsASCII checks if the given string consists of only ASCII characters.
func IsASCII(value string) Result {
func IsASCII(value string) error {
for _, c := range value {
if c > unicode.MaxASCII {
return ResultNotASCII
return ErrNotASCII
}
}

return ResultValid
return nil
}

// makeASCII makes a checker function for the ASCII checker.
Expand All @@ -33,7 +34,7 @@ func makeASCII(_ string) CheckFunc {
}

// checkASCII checks if the given string consists of only ASCII characters.
func checkASCII(value, _ reflect.Value) Result {
func checkASCII(value, _ reflect.Value) error {
if value.Kind() != reflect.String {
panic("string expected")
}
Expand Down
9 changes: 4 additions & 5 deletions ascii_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ import (
)

func ExampleIsASCII() {
result := checker.IsASCII("Checker")

if result != checker.ResultValid {
err := checker.IsASCII("Checker")
if err != nil {
// Send the mistakes back to the user
}
}

func TestIsASCIIInvalid(t *testing.T) {
if checker.IsASCII("𝄞 Music!") == checker.ResultValid {
if checker.IsASCII("𝄞 Music!") == nil {
t.Fail()
}
}

func TestIsASCIIValid(t *testing.T) {
if checker.IsASCII("Checker") != checker.ResultValid {
if checker.IsASCII("Checker") != nil {
t.Fail()
}
}
Expand Down
30 changes: 12 additions & 18 deletions checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,14 @@ import (
"strings"
)

// Result is a unique textual identifier for the mistake.
type Result string
// CheckFunc defines the signature for the checker functions.
type CheckFunc func(value, parent reflect.Value) error

// CheckFunc defines the checker function.
type CheckFunc func(value, parent reflect.Value) Result

// MakeFunc defines the maker function.
// MakeFunc defines the signature for the checker maker functions.
type MakeFunc func(params string) CheckFunc

// Mistakes provides mapping to checker result for the invalid fields.
type Mistakes map[string]Result
// Errors provides a mapping of the checker errors keyed by the field names.
type Errors map[string]error

type checkerJob struct {
Parent reflect.Value
Expand All @@ -31,10 +28,7 @@ type checkerJob struct {
Config string
}

// ResultValid result indicates that the user input is valid.
const ResultValid Result = "VALID"

// makers provides mapping to maker function for the checkers.
// makers provides a mapping of the maker functions keyed by the respective checker names.
var makers = map[string]MakeFunc{
CheckerAlphanumeric: makeAlphanumeric,
CheckerASCII: makeASCII,
Expand Down Expand Up @@ -74,14 +68,14 @@ func Register(name string, maker MakeFunc) {
makers[name] = maker
}

// Check checks the given struct based on the checkers listed in each field's strcut tag named checkers.
func Check(s interface{}) (Mistakes, bool) {
// Check function checks the given struct based on the checkers listed in field tag names.
func Check(s interface{}) (Errors, bool) {
root := reflect.Indirect(reflect.ValueOf(s))
if root.Kind() != reflect.Struct {
panic("expecting struct")
}

mistakes := Mistakes{}
errors := Errors{}

jobs := []checkerJob{
{
Expand Down Expand Up @@ -123,15 +117,15 @@ func Check(s interface{}) (Mistakes, bool) {
}
} else {
for _, checker := range initCheckers(job.Config) {
if result := checker(job.Value, job.Parent); result != ResultValid {
mistakes[job.Name] = result
if err := checker(job.Value, job.Parent); err != nil {
errors[job.Name] = err
break
}
}
}
}

return mistakes, len(mistakes) == 0
return errors, len(errors) == 0
}

// initCheckers initializes the checkers provided in the config.
Expand Down
10 changes: 5 additions & 5 deletions checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ func TestInitCheckersKnwon(t *testing.T) {
}

func TestRegister(t *testing.T) {
var checker CheckFunc = func(_, _ reflect.Value) Result {
return ResultValid
var checker CheckFunc = func(_, _ reflect.Value) error {
return nil
}

var maker MakeFunc = func(_ string) CheckFunc {
Expand Down Expand Up @@ -69,7 +69,7 @@ func TestCheckInvalid(t *testing.T) {
t.Fail()
}

if mistakes["Name"] != ResultRequired {
if mistakes["Name"] != ErrRequired {
t.Fail()
}
}
Expand Down Expand Up @@ -121,11 +121,11 @@ func TestCheckNestedStruct(t *testing.T) {
t.Fail()
}

if mistakes["Name"] != ResultRequired {
if mistakes["Name"] != ErrRequired {
t.Fail()
}

if mistakes["Home.Street"] != ResultRequired {
if mistakes["Home.Street"] != ErrRequired {
t.Fail()
}
}
Expand Down
13 changes: 7 additions & 6 deletions cidr.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,24 +6,25 @@
package checker

import (
"errors"
"net"
"reflect"
)

// CheckerCidr is the name of the checker.
const CheckerCidr = "cidr"

// ResultNotCidr indicates that the given value is not a valid CIDR.
const ResultNotCidr = "NOT_CIDR"
// ErrNotCidr indicates that the given value is not a valid CIDR.
var ErrNotCidr = errors.New("please enter a valid CIDR")

// IsCidr checker checks if the value is a valid CIDR notation IP address and prefix length.
func IsCidr(value string) Result {
func IsCidr(value string) error {
_, _, err := net.ParseCIDR(value)
if err != nil {
return ResultNotCidr
return ErrNotCidr
}

return ResultValid
return nil
}

// makeCidr makes a checker function for the ip checker.
Expand All @@ -32,7 +33,7 @@ func makeCidr(_ string) CheckFunc {
}

// checkCidr checker checks if the value is a valid CIDR notation IP address and prefix length.
func checkCidr(value, _ reflect.Value) Result {
func checkCidr(value, _ reflect.Value) error {
if value.Kind() != reflect.String {
panic("string expected")
}
Expand Down
9 changes: 4 additions & 5 deletions cidr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,20 @@ import (
)

func ExampleIsCidr() {
result := checker.IsCidr("2001:db8::/32")

if result != checker.ResultValid {
err := checker.IsCidr("2001:db8::/32")
if err != nil {
// Send the mistakes back to the user
}
}

func TestIsCidrInvalid(t *testing.T) {
if checker.IsCidr("900.800.200.100//24") == checker.ResultValid {
if checker.IsCidr("900.800.200.100//24") == nil {
t.Fail()
}
}

func TestIsCidrValid(t *testing.T) {
if checker.IsCidr("2001:db8::/32") != checker.ResultValid {
if checker.IsCidr("2001:db8::/32") != nil {
t.Fail()
}
}
Expand Down
Loading

0 comments on commit 4dd1e4b

Please sign in to comment.