// Package errors is a drop-in replacement for Golang lib 'errors'. package errors import ( "fmt" "strings" "v2ray.com/core/common/serial" ) type Severity int const ( SeverityDebug Severity = iota SeverityInfo SeverityWarning SeverityError ) type hasInnerError interface { // Inner returns the underlying error of this one. Inner() error } type hasSeverity interface { Severity() Severity } // Error is an error object with underlying error. type Error struct { format string message []interface{} inner error severity Severity path []string } func (v *Error) formMessage() string { if len(v.format) == 0 { return serial.Concat(v.message...) } return fmt.Sprintf(v.format, v.message...) } // Error implements error.Error(). func (v *Error) Error() string { msg := v.formMessage() if v.inner != nil { msg += " > " + v.inner.Error() } if len(v.path) > 0 { msg = strings.Join(v.path, "|") + ": " + msg } return msg } // Inner implements hasInnerError.Inner() func (v *Error) Inner() error { if v.inner == nil { return nil } return v.inner } func (v *Error) Base(err error) *Error { v.inner = err return v } func (v *Error) atSeverity(s Severity) *Error { v.severity = s return v } func (v *Error) Severity() Severity { if v.inner == nil { return v.severity } if s, ok := v.inner.(hasSeverity); ok { as := s.Severity() if as > v.severity { return as } } return v.severity } func (v *Error) AtDebug() *Error { return v.atSeverity(SeverityDebug) } func (v *Error) AtInfo() *Error { return v.atSeverity(SeverityInfo) } func (v *Error) AtWarning() *Error { return v.atSeverity(SeverityWarning) } func (v *Error) AtError() *Error { return v.atSeverity(SeverityError) } func (v *Error) Path(path ...string) *Error { v.path = path return v } // New returns a new error object with message formed from given arguments. func New(msg ...interface{}) *Error { return &Error{ message: msg, severity: SeverityInfo, } } func Format(format string, values ...interface{}) *Error { return &Error{ format: format, message: values, severity: SeverityInfo, } } // Cause returns the root cause of this error. func Cause(err error) error { if err == nil { return nil } for { inner, ok := err.(hasInnerError) if !ok || inner.Inner() == nil { break } err = inner.Inner() } return err } func GetSeverity(err error) Severity { if s, ok := err.(hasSeverity); ok { return s.Severity() } return SeverityInfo }