package merry import ( "fmt" v2 "github.com/ansel1/merry/v2" "io" ) // Error extends the standard golang `error` interface with functions // for attachment additional data to the error type Error interface { error Appendf(format string, args ...interface{}) Error Append(msg string) Error Prepend(msg string) Error Prependf(format string, args ...interface{}) Error WithMessage(msg string) Error WithMessagef(format string, args ...interface{}) Error WithUserMessage(msg string) Error WithUserMessagef(format string, args ...interface{}) Error WithValue(key, value interface{}) Error Here() Error WithStackSkipping(skip int) Error WithHTTPCode(code int) Error WithCause(err error) Error Cause() error fmt.Formatter } // make sure errImpl implements Error var _ Error = (*errImpl)(nil) // WithValue is equivalent to WithValue(e, key, value). func (e *errImpl) WithValue(key, value interface{}) Error { return WrapSkipping(e, 1, v2.WithValue(key, value)) } // Here is equivalent to Here(e). func (e *errImpl) Here() Error { return HereSkipping(e, 1) } // WithStackSkipping is equivalent to HereSkipping(e, i). func (e *errImpl) WithStackSkipping(skip int) Error { return HereSkipping(e, skip+1) } // WithHTTPCode is equivalent to WithHTTPCode(e, code). func (e *errImpl) WithHTTPCode(code int) Error { return WrapSkipping(e, 1, v2.WithHTTPCode(code)) } // WithMessage is equivalent to WithMessage(e, msg). func (e *errImpl) WithMessage(msg string) Error { return WrapSkipping(e, 1, v2.WithMessage(msg)) } // WithMessagef is equivalent to WithMessagef(e, format, args...). func (e *errImpl) WithMessagef(format string, args ...interface{}) Error { return WrapSkipping(e, 1, v2.WithMessagef(format, args...)) } // WithUserMessage is equivalent to WithUserMessage(e, msg). func (e *errImpl) WithUserMessage(msg string) Error { return WrapSkipping(e, 1, v2.WithUserMessage(msg)) } // WithUserMessagef is equivalent to WithUserMessagef(e, format, args...). func (e *errImpl) WithUserMessagef(format string, args ...interface{}) Error { return WrapSkipping(e, 1, v2.WithUserMessagef(format, args...)) } // Append is equivalent to Append(err, msg). func (e *errImpl) Append(msg string) Error { return WrapSkipping(e, 1, v2.AppendMessage(msg)) } // Appendf is equivalent to Appendf(err, format, msg). func (e *errImpl) Appendf(format string, args ...interface{}) Error { return WrapSkipping(e, 1, v2.AppendMessagef(format, args...)) } // Prepend is equivalent to Prepend(err, msg). func (e *errImpl) Prepend(msg string) Error { return WrapSkipping(e, 1, v2.PrependMessage(msg)) } // Prependf is equivalent to Prependf(err, format, args...). func (e *errImpl) Prependf(format string, args ...interface{}) Error { return WrapSkipping(e, 1, v2.PrependMessagef(format, args...)) } // WithCause is equivalent to WithCause(e, err). func (e *errImpl) WithCause(err error) Error { return WrapSkipping(e, 1, v2.WithCause(err)) } // errImpl coerces an error to an Error type errImpl struct { err error } func coerce(err error) Error { if err == nil { return nil } if e, ok := err.(Error); ok { return e } return &errImpl{err} } // Format implements fmt.Formatter. func (e *errImpl) Format(s fmt.State, verb rune) { // the inner err should always be an err produced // by v2 if f, ok := e.err.(fmt.Formatter); ok { f.Format(s, verb) return } // should never happen, but fall back on something switch verb { case 'v': if s.Flag('+') { _, _ = io.WriteString(s, Details(e)) return } fallthrough case 's': _, _ = io.WriteString(s, e.Error()) case 'q': _, _ = fmt.Fprintf(s, "%q", e.Error()) } } // Error implements the error interface. func (e *errImpl) Error() string { return e.err.Error() } // Unwrap returns the next wrapped error. func (e *errImpl) Unwrap() error { return e.err } // Cause implements Error. func (e *errImpl) Cause() error { return Cause(e.err) }