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 <noreply@anthropic.com>
This commit is contained in:
2026-09-07 13:59:59 +01:00
co-authored by Claude Sonnet 5
parent 7ea26f9c88
commit da971f4df5
9 changed files with 38 additions and 28 deletions
+3 -2
View File
@@ -1,7 +1,8 @@
package validate package validate
// All validates a value using a sequence of validation functions. // All validates a value against a sequence of validation functions,
// If any validation function returns an error, the sequence stops and the error is returned. // 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 { func All[T any](fs ...func(T) error) func(T) error {
return func(value T) error { return func(value T) error {
for _, f := range fs { for _, f := range fs {
+1 -1
View File
@@ -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 { func ExceptChars(disallow string) func(string) error {
return func(value string) error { return func(value string) error {
for _, r := range disallow { for _, r := range disallow {
+1 -1
View File
@@ -13,7 +13,7 @@ func ExampleChars() {
} }
func ExampleExceptChars() { func ExampleExceptChars() {
testExceptChars := Chars("0123456789abcdef") testExceptChars := ExceptChars("0123456789abcdef")
fmt.Println(testExceptChars("invalid input")) fmt.Println(testExceptChars("invalid input"))
// Output: contains disallowed characters // Output: contains disallowed characters
} }
+10 -6
View File
@@ -2,10 +2,9 @@ package validate
import "fmt" import "fmt"
// Validation error. // Err is the zero Error. It carries no message, so errors.Is(x, Err) is
var ( // true for any error produced by this package.
Err = Error{} var Err = Error{}
)
// Error represents a validation error. // Error represents a validation error.
type Error struct { type Error struct {
@@ -13,8 +12,9 @@ type Error struct {
Data []any Data []any
} }
// Error retrieves the message of a validation Error. // Error returns the error message. If Data is non-empty, Message is used
// If it has Data, the message will be formatted. // 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 { func (e Error) Error() string {
if len(e.Data) > 0 { if len(e.Data) > 0 {
return fmt.Sprintf(e.Message, e.Data...) return fmt.Sprintf(e.Message, e.Data...)
@@ -34,6 +34,10 @@ func (e Error) Is(target error) bool {
return false 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 { func (e Error) With(value any) Error {
if e.Data == nil { if e.Data == nil {
e.Data = []any{} e.Data = []any{}
+4 -4
View File
@@ -4,7 +4,7 @@ var (
ErrValueNotAllowed = NewError("not allowed") 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 { func In[T comparable](allow ...T) func(T) error {
return func(value T) error { return func(value T) error {
for _, cmp := range allow { 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. // NotIn validates that a value equals none of the disallowed values.
func NotIn[T comparable](allow ...T) func(T) error { func NotIn[T comparable](disallow ...T) func(T) error {
return func(value T) error { return func(value T) error {
for _, cmp := range allow { for _, cmp := range disallow {
if cmp == value { if cmp == value {
return ErrValueNotAllowed return ErrValueNotAllowed
} }
+4 -2
View File
@@ -5,7 +5,8 @@ var (
ErrMustBeShorter = NewError("must contain no more than %d characters") 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 { func MaxLength(l int) func(string) error {
return func(value string) error { return func(value string) error {
if len(value) > l { 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 { func MinLength(l int) func(string) error {
return func(value string) error { return func(value string) error {
if len(value) < l { if len(value) < l {
+9 -9
View File
@@ -8,7 +8,7 @@ var (
) )
// Max validates whether an integer is less than or equal to a given maximum. // 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 { func Max(n int, exclusive bool) func(int) error {
return func(value int) error { return func(value int) error {
if exclusive { 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. // 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 { func MaxFloat32(n float32, exclusive bool) func(float32) error {
return func(value float32) error { return func(value float32) error {
if exclusive { 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. // 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 { func MaxFloat64(n float64, exclusive bool) func(float64) error {
return func(value float64) error { return func(value float64) error {
if exclusive { 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. // Min validates whether an integer is greater than or equal to a given minimum.
// If exclusive is true, an equal value will also produce an error. // If exclusive is true, an equal value also produces an error.
func Min(n int, exclusive bool) func(int) error { func Min(n int, exclusive bool) func(int) error {
return func(value int) error { return func(value int) error {
if exclusive { 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. // MinFloat32 validates whether a float32 is greater than or equal to a given minimum.
// If exclusive is true, an equal value will also produce an error. // If exclusive is true, an equal value also produces an error.
func MinFloat32(n float32, exclusive bool) func(float32) error { func MinFloat32(n float32, exclusive bool) func(float32) error {
return func(value float32) error { return func(value float32) error {
if exclusive { 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. // MinFloat64 validates whether a float64 is greater than or equal to a given minimum.
// If exclusive is true, an equal value will also produce an error. // If exclusive is true, an equal value also produces an error.
func MinFloat64(n float64, exclusive bool) func(float64) error { func MinFloat64(n float64, exclusive bool) func(float64) error {
return func(value float64) error { return func(value float64) error {
if exclusive { if exclusive {
+3 -1
View File
@@ -6,7 +6,9 @@ var (
ErrInvalidURL Error = NewError("invalid URL") 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 { func URL(value string) error {
if _, err := url.ParseRequestURI(value); err != nil { if _, err := url.ParseRequestURI(value); err != nil {
return ErrInvalidURL return ErrInvalidURL
+3 -2
View File
@@ -10,8 +10,9 @@ var (
var uuidRegexp = regexp.MustCompile("^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$") var uuidRegexp = regexp.MustCompile("^[a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12}$")
// UUID validates a UUID string. // UUID validates a UUID string in the canonical 8-4-4-4-12 hyphenated
// The UUID must be formatted with separators. // form. Only lowercase hexadecimal is accepted; the version and variant
// bits are not checked.
func UUID(value string) error { func UUID(value string) error {
if !uuidRegexp.MatchString(value) { if !uuidRegexp.MatchString(value) {
return ErrInvalidUUID return ErrInvalidUUID