initial commit
This commit is contained in:
104
error.go
Normal file
104
error.go
Normal file
@ -0,0 +1,104 @@
|
||||
package adverr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Error is a wrapper for error with stack trace
|
||||
type Error struct {
|
||||
msg string
|
||||
callTrace *CallTrace
|
||||
tmpl *ErrTmpl
|
||||
cause error
|
||||
}
|
||||
|
||||
// New returns a new Error with the given message
|
||||
func New(msg string) *Error {
|
||||
return &Error{
|
||||
msg: msg,
|
||||
cause: nil,
|
||||
tmpl: nil,
|
||||
callTrace: Trace(2),
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap returns a new Error with the given message which is caused by cause
|
||||
func Wrap(msg string, cause error) *Error {
|
||||
return &Error{
|
||||
msg: msg,
|
||||
cause: cause,
|
||||
callTrace: Trace(2),
|
||||
}
|
||||
}
|
||||
|
||||
func errtype(err error) string {
|
||||
if e, ok := err.(*Error); ok && e.tmpl != nil {
|
||||
return errtype(e.tmpl)
|
||||
} else if tmpl, ok := err.(*ErrTmpl); ok {
|
||||
t := reflect.TypeOf(tmpl)
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t.PkgPath() + "." + tmpl.name
|
||||
}
|
||||
|
||||
t := reflect.TypeOf(err)
|
||||
for t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
return t.PkgPath() + "." + t.Name()
|
||||
}
|
||||
|
||||
func (e *Error) Unwrap() error {
|
||||
return e.cause
|
||||
}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
b := new(strings.Builder)
|
||||
printErr(e, b)
|
||||
return b.String()
|
||||
}
|
||||
|
||||
// Is implements the error equality function used by errors.Is()
|
||||
// It returns true if the error is the same instance or is created using the same ErrTmpl
|
||||
func (e *Error) Is(target error) bool {
|
||||
// same error instance
|
||||
if target == e {
|
||||
return true
|
||||
}
|
||||
|
||||
// no template used, therefore no equality possible
|
||||
if e.tmpl == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// same template, therefore errors are equal to another
|
||||
if tErr, ok := target.(*Error); ok {
|
||||
return tErr.tmpl == e.tmpl
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func printErr(err error, b *strings.Builder) {
|
||||
if e, ok := err.(*Error); ok {
|
||||
b.WriteString(errtype(e))
|
||||
b.WriteString(": ")
|
||||
b.WriteString(e.msg)
|
||||
b.WriteString("\n")
|
||||
b.WriteString(e.callTrace.String())
|
||||
} else {
|
||||
b.WriteString(errtype(err))
|
||||
b.WriteString(": ")
|
||||
b.WriteString(err.Error())
|
||||
b.WriteString("\n")
|
||||
}
|
||||
|
||||
cause := errors.Unwrap(err)
|
||||
if cause != nil {
|
||||
b.WriteString("Caused by ")
|
||||
printErr(cause, b)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user