diff --git a/v2/isbn.go b/v2/isbn.go new file mode 100644 index 0000000..84cf832 --- /dev/null +++ b/v2/isbn.go @@ -0,0 +1,43 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2 + +import ( + "reflect" + "regexp" +) + +const ( + // nameISBN is the name of the ISBN check. + nameISBN = "isbn" +) + +var ( + // ErrNotISBN indicates that the given value is not a valid ISBN. + ErrNotISBN = NewCheckError("ISBN") + + // isbnRegex is the regular expression for validating ISBN-10 and ISBN-13. + isbnRegex = regexp.MustCompile(`^(97(8|9))?\d{9}(\d|X)$`) +) + +// IsISBN checks if the value is a valid ISBN-10 or ISBN-13. +func IsISBN(value string) (string, error) { + if !isbnRegex.MatchString(value) { + return value, ErrNotISBN + } + return value, nil +} + +// checkISBN checks if the value is a valid ISBN-10 or ISBN-13. +func checkISBN(value reflect.Value) (reflect.Value, error) { + _, err := IsISBN(value.Interface().(string)) + return value, err +} + +// makeISBN makes a checker function for the ISBN checker. +func makeISBN(_ string) CheckFunc[reflect.Value] { + return checkISBN +} diff --git a/v2/isbn_test.go b/v2/isbn_test.go new file mode 100644 index 0000000..2f763cf --- /dev/null +++ b/v2/isbn_test.go @@ -0,0 +1,76 @@ +// Copyright (c) 2023-2024 Onur Cinar. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. +// https://github.com/cinar/checker + +package v2_test + +import ( + "fmt" + "testing" + + v2 "github.com/cinar/checker/v2" +) + +func ExampleIsISBN() { + _, err := v2.IsISBN("9783161484100") + if err != nil { + fmt.Println(err) + } +} + +func TestIsISBNInvalid(t *testing.T) { + _, err := v2.IsISBN("invalid-isbn") + if err == nil { + t.Fatal("expected error") + } +} + +func TestIsISBNValid(t *testing.T) { + _, err := v2.IsISBN("9783161484100") + if err != nil { + t.Fatal(err) + } +} + +func TestCheckISBNNonString(t *testing.T) { + defer FailIfNoPanic(t, "expected panic") + + type Book struct { + ISBN int `checkers:"isbn"` + } + + book := &Book{} + + v2.CheckStruct(book) +} + +func TestCheckISBNInvalid(t *testing.T) { + type Book struct { + ISBN string `checkers:"isbn"` + } + + book := &Book{ + ISBN: "invalid-isbn", + } + + _, ok := v2.CheckStruct(book) + if ok { + t.Fatal("expected error") + } +} + +func TestCheckISBNValid(t *testing.T) { + type Book struct { + ISBN string `checkers:"isbn"` + } + + book := &Book{ + ISBN: "9783161484100", + } + + _, ok := v2.CheckStruct(book) + if !ok { + t.Fatal("expected valid") + } +} diff --git a/v2/maker.go b/v2/maker.go index f5ff1b8..5943eef 100644 --- a/v2/maker.go +++ b/v2/maker.go @@ -25,6 +25,7 @@ var makers = map[string]MakeCheckFunc{ nameIP: makeIP, nameIPv4: makeIPv4, nameIPv6: makeIPv6, + nameISBN: makeISBN, nameMaxLen: makeMaxLen, nameMinLen: makeMinLen, nameRequired: makeRequired,