Skip to content

Commit

Permalink
validate: add NotNilInterface
Browse files Browse the repository at this point in the history
  • Loading branch information
ainar-g committed Jan 16, 2025
1 parent 776881d commit 408558a
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 19 deletions.
6 changes: 3 additions & 3 deletions contextutil/contextutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ func NewTimeoutConstructor(timeout time.Duration) (c *TimeoutConstructor) {
// type check
var _ Constructor = (*TimeoutConstructor)(nil)

// New implements the [Constructor] interface for
// *TimeoutConstructor. It returns a context with its timeout and the
// corresponding cancelation function.
// New implements the [Constructor] interface for *TimeoutConstructor. It
// returns a context with its timeout and the corresponding cancelation
// function.
func (c *TimeoutConstructor) New(
parent context.Context,
) (ctx context.Context, cancel context.CancelFunc) {
Expand Down
11 changes: 3 additions & 8 deletions service/errorhandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,10 @@ type SlogErrorHandler struct {
// NewSlogErrorHandler returns a new logging error handler. l and lvl must not
// be nil.
func NewSlogErrorHandler(l *slog.Logger, lvl slog.Leveler, msg string) (h *SlogErrorHandler) {
errs := []error{
err := errors.Join(
validate.NotNil("l", l),
}

if lvl == nil {
errs = append(errs, fmt.Errorf("lvl: %w", errors.ErrNoValue))
}

err := errors.Join(errs...)
validate.NotNilInterface("lvl", lvl),
)
if err != nil {
panic(fmt.Errorf("service.NewSlogErrorHandler: %w", err))
}
Expand Down
11 changes: 3 additions & 8 deletions timeutil/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,16 +90,11 @@ func NewRandomizedSchedule(
minAdd time.Duration,
maxAdd time.Duration,
) (s *RandomizedSchedule) {
errs := []error{
err := errors.Join(
validate.NotNilInterface("sched", sched),
validate.NotNil("r", r),
validate.GreaterThan("maxAdd", maxAdd, minAdd),
}

if sched == nil {
errs = append(errs, fmt.Errorf("sched: %w", errors.ErrNoValue))
}

err := errors.Join(errs...)
)
if err != nil {
panic(fmt.Errorf("timeutil.NewRandomizedSchedule: %w", err))
}
Expand Down
19 changes: 19 additions & 0 deletions validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,25 @@ func NotNil[T any](name string, v *T) (err error) {
return nil
}

// NotNilInterface returns an error if v is nil. The underlying error of err is
// [errors.ErrNoValue].
//
// For checking against emptiness (comparing with the zero value), prefer
// [NotEmpty].
//
// NOTE: This function returns an error only if v is a nil interface value.
// This means that if v is an interface value with a type and a nil pointer, err
// is nil.
//
// TODO(a.garipov): Find ways of merging with [NotNil].
func NotNilInterface(name string, v any) (err error) {
if v == nil {
return fmt.Errorf("%s: %w", name, errors.ErrNoValue)
}

return nil
}

// Positive returns an error if v is less than or equal to the zero value of
// type T. The underlying error of err is [errors.ErrNotPositive].
//
Expand Down
18 changes: 18 additions & 0 deletions validate/validate_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,24 @@ func ExampleNotNil() {
// foo: no value
}

func ExampleNotNilInterface() {
var v any
fmt.Println(validate.NotNilInterface("foo", v))

type T struct{}
v = T{}
fmt.Println(validate.NotNilInterface("foo", v))

// NOTE: A typed but nil interface value, be careful!
v = (*T)(nil)
fmt.Println(validate.NotNilInterface("foo", v))

// Output:
// foo: no value
// <nil>
// <nil>
}

func ExamplePositive() {
fmt.Println(validate.Positive("foo", 1))
fmt.Println(validate.Positive("foo", 0))
Expand Down

0 comments on commit 408558a

Please sign in to comment.