diff --git a/error.go b/error.go new file mode 100644 index 0000000..02f450d --- /dev/null +++ b/error.go @@ -0,0 +1,37 @@ +package version + +import "fmt" + +// Error represents a version error. +type Error struct { + Message string + Version string +} + +// Version error. +var ( + ErrInvalidVersion = Error{Message: "invalid version %q"} +) + +// Error retrieves the message of a REST API error. +func (e Error) Error() string { + return fmt.Sprintf(e.Message, e.Version) +} + +// Is determines whether the Error is an instance of the target. +// https://pkg.go.dev/errors#Is +// +// This implementation does not compare versions. +func (e Error) Is(target error) bool { + if t, ok := target.(Error); ok { + return t.Message == e.Message + } + return false +} + +func invalid(version string) Error { + return Error{ + Message: ErrInvalidVersion.Message, + Version: version, + } +} diff --git a/errors.go b/errors.go deleted file mode 100644 index f88fc74..0000000 --- a/errors.go +++ /dev/null @@ -1,7 +0,0 @@ -package version - -import "errors" - -var ( - ErrInvalidVersion = errors.New("invalid version") -) diff --git a/parse.go b/parse.go index a378679..0bc465e 100644 --- a/parse.go +++ b/parse.go @@ -24,7 +24,7 @@ func Parse(str string) (*Version, error) { v := &Version{Text: string(str)} if len(str) == 0 { - return nil, ErrInvalidVersion + return nil, invalid(str) } section := sectionMajor @@ -32,13 +32,13 @@ func Parse(str string) (*Version, error) { commit := func() error { if len(chars) == 0 { - return ErrInvalidVersion + return invalid(str) } if section < sectionExtension { n, err := strconv.Atoi(string(chars)) if err != nil { - return ErrInvalidVersion + return invalid(str) } switch section { diff --git a/parse_test.go b/parse_test.go index 0d4fb18..734fa60 100644 --- a/parse_test.go +++ b/parse_test.go @@ -35,14 +35,14 @@ func TestVersion_Parse(t *testing.T) { if testCase.Err != nil { if err == nil { - t.Errorf("test %d failed (expected error %v, actual nil)", i, testCase.Err) + t.Errorf("test %d failed (expected error %s, actual nil)", i, testCase.Err) } else if !errors.Is(err, testCase.Err) { - t.Errorf("test %d failed (expected error %q, actual error %q)", i, testCase.Err, err) + t.Errorf("test %d failed (expected error %s, actual error %s)", i, testCase.Err, err) } else { - t.Logf("test %d passed with error %q for %q\n", i, testCase.Err, testCase.Input) + t.Logf("test %d passed with error %s for %q\n", i, err, testCase.Input) } } else if err != nil { - t.Errorf("test %d failed (expected error nil, actual error %q)", i, err) + t.Errorf("test %d failed (expected error nil, actual error %s)", i, err) } else if actual.Major != testCase.Expected.Major || actual.Minor != testCase.Expected.Minor || actual.Patch != testCase.Expected.Patch || actual.Text != testCase.Expected.Text { t.Errorf("test %d failed (expected %v, actual %v)", i, testCase.Expected, actual) } else {