lbry.go/extras/errors/errors.go

111 lines
2.2 KiB
Go

package errors
import (
"fmt"
"github.com/go-errors/errors"
)
// interop with pkg/errors
type causer interface {
Cause() error
}
// Err intelligently creates/handles errors, while preserving the stack trace.
// It works with errors from github.com/pkg/errors too.
func Err(err interface{}, fmtParams ...interface{}) error {
if err == nil {
return nil
}
if _, ok := err.(causer); ok {
err = fmt.Errorf("%+v", err)
} else if errString, ok := err.(string); ok && len(fmtParams) > 0 {
err = fmt.Errorf(errString, fmtParams...)
}
return errors.Wrap(err, 1)
}
// Wrap calls errors.Wrap, in case you want to skip a different amount
func Wrap(err interface{}, skip int) *errors.Error {
if err == nil {
return nil
}
if _, ok := err.(causer); ok {
err = fmt.Errorf("%+v", err)
}
return errors.Wrap(err, skip+1)
}
// Unwrap returns the original error that was wrapped
func Unwrap(err error) error {
if err == nil {
return nil
}
deeper := true
for deeper {
deeper = false
if e, ok := err.(*errors.Error); ok {
err = e.Err
deeper = true
}
if c, ok := err.(causer); ok {
err = c.Cause()
deeper = true
}
}
return err
}
// Is compares two wrapped errors to determine if the underlying errors are the same
// It also interops with errors from pkg/errors
func Is(e error, original error) bool {
if c, ok := e.(causer); ok {
e = c.Cause()
}
if c, ok := original.(causer); ok {
original = c.Cause()
}
return errors.Is(e, original)
}
// Prefix prefixes the message of the error with the given string
func Prefix(prefix string, err interface{}) error {
if err == nil {
return nil
}
return errors.WrapPrefix(Err(err), prefix, 0)
}
// Trace returns the stack trace
func Trace(err error) string {
if err == nil {
return ""
}
return string(Err(err).(*errors.Error).Stack())
}
// FullTrace returns the error type, message, and stack trace
func FullTrace(err error) string {
if err == nil {
return ""
}
return Err(err).(*errors.Error).ErrorStack()
}
// Base returns a simple error with no stack trace attached
func Base(format string, a ...interface{}) error {
return fmt.Errorf(format, a...)
}
// HasTrace checks if error has a trace attached
func HasTrace(err error) bool {
_, ok := err.(*errors.Error)
return ok
}