minireader/internal/pkg/errx/details.go
2024-08-10 11:01:50 +07:00

67 lines
1.3 KiB
Go

package errx
// Package `errx` named like this to not confuse with built-in `errors` package.
import "errors"
type detailedError struct {
error
details []any
}
func (e *detailedError) Unwrap() error {
return e.error
}
func (e *detailedError) Details() []any {
return e.details
}
// WithDetails creates new error value with embedded details
func WithDetails(err error, details ...any) error {
derr := &detailedError{}
if errors.As(err, &derr) {
derr.details = append(derr.details, details...)
return err
}
return &detailedError{
error: err,
details: details,
}
}
// Details will extract details array from error
func Details(err error) []any {
if err == nil {
return nil
}
// detailedError on top level of errors chain
if derr, ok := err.(interface{ Details() []any }); ok {
return derr.Details()
}
// detailed error were wrapped into another error, and we need to dig it up
derr := &detailedError{}
if errors.As(err, &derr) {
return derr.Details()
}
return nil
}
// LookupDetails will find some specific details by its type
// NOTE: I'm not sure it's good idea or expected behaviour for function named Lookup
func LookupDetails[T any](err error) T {
var empty T
for _, d := range Details(err) {
if v, ok := d.(T); ok {
return v
}
}
return empty
}