From da971f4df5c9d6d77ecb529e013b1499926a310b Mon Sep 17 00:00:00 2001 From: claude Date: Mon, 7 Sep 2026 13:59:59 +0100 Subject: [PATCH] fix incorrect and vague doc comments Audit ahead of the README/doc.go work (issue #3): - number.go: Min, MinFloat32, MinFloat64 all said "less than or equal to a given maximum" -- copy-pasted from the Max family. They check the minimum. Fixed. - chars_test.go: ExampleExceptChars called Chars, not ExceptChars, so it never exercised the function it documents. - chars.go: "does not contain disallowed characters" was circular. - in.go: NotIn's parameter was named "allow"; renamed to "disallow". - length.go: note that length is bytes (len), not runes -- the "%d characters" messages imply otherwise. - url.go: spell out that ParseRequestURI wants an absolute URL or path. - uuid.go: note lowercase-hex only, version/variant not checked. - error.go: explain Err (the match-anything sentinel), how Error() formats with Data, and what With does. all.go: point at Collect. Comments only; no behaviour change. go vet + go test ./... pass. Co-Authored-By: Claude Sonnet 5 --- all.go | 5 +++-- chars.go | 2 +- chars_test.go | 2 +- error.go | 16 ++++++++++------ in.go | 8 ++++---- length.go | 6 ++++-- number.go | 18 +++++++++--------- url.go | 4 +++- uuid.go | 5 +++-- 9 files changed, 38 insertions(+), 28 deletions(-) diff --git a/all.go b/all.go index ef1e4fa..8394264 100644 --- a/all.go +++ b/all.go @@ -1,7 +1,8 @@ package validate -// All validates a value using a sequence of validation functions. -// If any validation function returns an error, the sequence stops and the error is returned. +// All validates a value against a sequence of validation functions, +// stopping and returning the first error. See Collect to run every +// function and report all failures at once. func All[T any](fs ...func(T) error) func(T) error { return func(value T) error { for _, f := range fs { diff --git a/chars.go b/chars.go index f43bf99..ec7fb6a 100644 --- a/chars.go +++ b/chars.go @@ -20,7 +20,7 @@ func Chars(allow string) func(string) error { } } -// ExceptChars validates whether a string does not contain disallowed characters. +// ExceptChars validates that a string contains none of the given characters. func ExceptChars(disallow string) func(string) error { return func(value string) error { for _, r := range disallow { diff --git a/chars_test.go b/chars_test.go index 704e10f..10a3956 100644 --- a/chars_test.go +++ b/chars_test.go @@ -13,7 +13,7 @@ func ExampleChars() { } func ExampleExceptChars() { - testExceptChars := Chars("0123456789abcdef") + testExceptChars := ExceptChars("0123456789abcdef") fmt.Println(testExceptChars("invalid input")) // Output: contains disallowed characters } diff --git a/error.go b/error.go index 45265f5..2f4c11d 100644 --- a/error.go +++ b/error.go @@ -2,10 +2,9 @@ package validate import "fmt" -// Validation error. -var ( - Err = Error{} -) +// Err is the zero Error. It carries no message, so errors.Is(x, Err) is +// true for any error produced by this package. +var Err = Error{} // Error represents a validation error. type Error struct { @@ -13,8 +12,9 @@ type Error struct { Data []any } -// Error retrieves the message of a validation Error. -// If it has Data, the message will be formatted. +// Error returns the error message. If Data is non-empty, Message is used +// as an fmt.Sprintf format string and Data as its arguments (this is how +// the sentinels with %d/%q verbs are filled in, e.g. via With). func (e Error) Error() string { if len(e.Data) > 0 { return fmt.Sprintf(e.Message, e.Data...) @@ -34,6 +34,10 @@ func (e Error) Is(target error) bool { return false } +// With returns a copy of the Error with value appended to Data, so it +// lands in the message when Message contains a formatting verb: +// +// ErrMustBeLonger.With(4) // "must contain at least 4 characters" func (e Error) With(value any) Error { if e.Data == nil { e.Data = []any{} diff --git a/in.go b/in.go index 87fcd2a..7327402 100644 --- a/in.go +++ b/in.go @@ -4,7 +4,7 @@ var ( ErrValueNotAllowed = NewError("not allowed") ) -// In validates whether a value is found in a slice of allowed values. +// In validates that a value equals one of the allowed values. func In[T comparable](allow ...T) func(T) error { return func(value T) error { for _, cmp := range allow { @@ -16,10 +16,10 @@ func In[T comparable](allow ...T) func(T) error { } } -// NotIn validates whether a value is not found in a slice of disallowed values. -func NotIn[T comparable](allow ...T) func(T) error { +// NotIn validates that a value equals none of the disallowed values. +func NotIn[T comparable](disallow ...T) func(T) error { return func(value T) error { - for _, cmp := range allow { + for _, cmp := range disallow { if cmp == value { return ErrValueNotAllowed } diff --git a/length.go b/length.go index db0013a..02d77f6 100644 --- a/length.go +++ b/length.go @@ -5,7 +5,8 @@ var ( ErrMustBeShorter = NewError("must contain no more than %d characters") ) -// MaxLength validates the length of a string as being less than or equal to a given maximum. +// MaxLength validates that a string is no longer than a given maximum. +// Length is measured in bytes (len), not runes. func MaxLength(l int) func(string) error { return func(value string) error { if len(value) > l { @@ -15,7 +16,8 @@ func MaxLength(l int) func(string) error { } } -// MinLength validates the length of a string as being greater than or equal to a given minimum. +// MinLength validates that a string is at least a given minimum length. +// Length is measured in bytes (len), not runes. func MinLength(l int) func(string) error { return func(value string) error { if len(value) < l { diff --git a/number.go b/number.go index 9db317b..11cea8a 100644 --- a/number.go +++ b/number.go @@ -8,7 +8,7 @@ var ( ) // Max validates whether an integer is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// If exclusive is true, an equal value also produces an error. func Max(n int, exclusive bool) func(int) error { return func(value int) error { if exclusive { @@ -24,7 +24,7 @@ func Max(n int, exclusive bool) func(int) error { } // MaxFloat32 validates whether a float32 is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// If exclusive is true, an equal value also produces an error. func MaxFloat32(n float32, exclusive bool) func(float32) error { return func(value float32) error { if exclusive { @@ -40,7 +40,7 @@ func MaxFloat32(n float32, exclusive bool) func(float32) error { } // MaxFloat64 validates whether a float64 is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// If exclusive is true, an equal value also produces an error. func MaxFloat64(n float64, exclusive bool) func(float64) error { return func(value float64) error { if exclusive { @@ -55,8 +55,8 @@ func MaxFloat64(n float64, exclusive bool) func(float64) error { } } -// Min validates whether an integer is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// Min validates whether an integer is greater than or equal to a given minimum. +// If exclusive is true, an equal value also produces an error. func Min(n int, exclusive bool) func(int) error { return func(value int) error { if exclusive { @@ -71,8 +71,8 @@ func Min(n int, exclusive bool) func(int) error { } } -// MinFloat32 validates whether a float32 is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// MinFloat32 validates whether a float32 is greater than or equal to a given minimum. +// If exclusive is true, an equal value also produces an error. func MinFloat32(n float32, exclusive bool) func(float32) error { return func(value float32) error { if exclusive { @@ -87,8 +87,8 @@ func MinFloat32(n float32, exclusive bool) func(float32) error { } } -// MinFloat64 validates whether a float64 is less than or equal to a given maximum. -// If exclusive is true, an equal value will also produce an error. +// MinFloat64 validates whether a float64 is greater than or equal to a given minimum. +// If exclusive is true, an equal value also produces an error. func MinFloat64(n float64, exclusive bool) func(float64) error { return func(value float64) error { if exclusive { diff --git a/url.go b/url.go index e0c30f4..fe9f15f 100644 --- a/url.go +++ b/url.go @@ -6,7 +6,9 @@ var ( ErrInvalidURL Error = NewError("invalid URL") ) -// URL validates a URL. +// URL validates that a string is an absolute URL (with a scheme) or an +// absolute path, per net/url.ParseRequestURI. "example.com" with no +// scheme is rejected. func URL(value string) error { if _, err := url.ParseRequestURI(value); err != nil { return ErrInvalidURL diff --git a/uuid.go b/uuid.go index 89ce9ea..341b337 100644 --- a/uuid.go +++ b/uuid.go @@ -10,8 +10,9 @@ var ( var uuidRegexp = regexp.MustCompile("^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$") -// UUID validates a UUID string. -// The UUID must be formatted with separators. +// UUID validates a UUID string in the canonical 8-4-4-4-12 hyphenated +// form. Only lowercase hexadecimal is accepted; the version and variant +// bits are not checked. func UUID(value string) error { if !uuidRegexp.MatchString(value) { return ErrInvalidUUID