docs: explain what distinguishes validate (+ comment audit) #11
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ func ExampleChars() {
|
||||
}
|
||||
|
||||
func ExampleExceptChars() {
|
||||
testExceptChars := Chars("0123456789abcdef")
|
||||
testExceptChars := ExceptChars("0123456789abcdef")
|
||||
fmt.Println(testExceptChars("invalid input"))
|
||||
// Output: contains disallowed characters
|
||||
}
|
||||
|
||||
@@ -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{}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user
The original intention was to measure text length. Does this make it more correct to measure runes rather than bytes?