github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/common/errors/errors.go (about)

     1  // Package errors is a drop-in replacement for Golang lib 'errors'.
     2  package errors // import "v2ray.com/core/common/errors"
     3  
     4  import (
     5  	"os"
     6  	"reflect"
     7  	"strings"
     8  
     9  	"v2ray.com/core/common/log"
    10  	"v2ray.com/core/common/serial"
    11  )
    12  
    13  type hasInnerError interface {
    14  	// Inner returns the underlying error of this one.
    15  	Inner() error
    16  }
    17  
    18  type hasSeverity interface {
    19  	Severity() log.Severity
    20  }
    21  
    22  // Error is an error object with underlying error.
    23  type Error struct {
    24  	pathObj  interface{}
    25  	prefix   []interface{}
    26  	message  []interface{}
    27  	inner    error
    28  	severity log.Severity
    29  }
    30  
    31  func (err *Error) WithPathObj(obj interface{}) *Error {
    32  	err.pathObj = obj
    33  	return err
    34  }
    35  
    36  func (err *Error) pkgPath() string {
    37  	if err.pathObj == nil {
    38  		return ""
    39  	}
    40  	return reflect.TypeOf(err.pathObj).PkgPath()
    41  }
    42  
    43  // Error implements error.Error().
    44  func (err *Error) Error() string {
    45  	builder := strings.Builder{}
    46  	for _, prefix := range err.prefix {
    47  		builder.WriteByte('[')
    48  		builder.WriteString(serial.ToString(prefix))
    49  		builder.WriteString("] ")
    50  	}
    51  
    52  	path := err.pkgPath()
    53  	if len(path) > 0 {
    54  		builder.WriteString(path)
    55  		builder.WriteString(": ")
    56  	}
    57  
    58  	msg := serial.Concat(err.message...)
    59  	builder.WriteString(msg)
    60  
    61  	if err.inner != nil {
    62  		builder.WriteString(" > ")
    63  		builder.WriteString(err.inner.Error())
    64  	}
    65  
    66  	return builder.String()
    67  }
    68  
    69  // Inner implements hasInnerError.Inner()
    70  func (err *Error) Inner() error {
    71  	if err.inner == nil {
    72  		return nil
    73  	}
    74  	return err.inner
    75  }
    76  
    77  func (err *Error) Base(e error) *Error {
    78  	err.inner = e
    79  	return err
    80  }
    81  
    82  func (err *Error) atSeverity(s log.Severity) *Error {
    83  	err.severity = s
    84  	return err
    85  }
    86  
    87  func (err *Error) Severity() log.Severity {
    88  	if err.inner == nil {
    89  		return err.severity
    90  	}
    91  
    92  	if s, ok := err.inner.(hasSeverity); ok {
    93  		as := s.Severity()
    94  		if as < err.severity {
    95  			return as
    96  		}
    97  	}
    98  
    99  	return err.severity
   100  }
   101  
   102  // AtDebug sets the severity to debug.
   103  func (err *Error) AtDebug() *Error {
   104  	return err.atSeverity(log.Severity_Debug)
   105  }
   106  
   107  // AtInfo sets the severity to info.
   108  func (err *Error) AtInfo() *Error {
   109  	return err.atSeverity(log.Severity_Info)
   110  }
   111  
   112  // AtWarning sets the severity to warning.
   113  func (err *Error) AtWarning() *Error {
   114  	return err.atSeverity(log.Severity_Warning)
   115  }
   116  
   117  // AtError sets the severity to error.
   118  func (err *Error) AtError() *Error {
   119  	return err.atSeverity(log.Severity_Error)
   120  }
   121  
   122  // String returns the string representation of this error.
   123  func (err *Error) String() string {
   124  	return err.Error()
   125  }
   126  
   127  // WriteToLog writes current error into log.
   128  func (err *Error) WriteToLog(opts ...ExportOption) {
   129  	var holder ExportOptionHolder
   130  
   131  	for _, opt := range opts {
   132  		opt(&holder)
   133  	}
   134  
   135  	if holder.SessionID > 0 {
   136  		err.prefix = append(err.prefix, holder.SessionID)
   137  	}
   138  
   139  	log.Record(&log.GeneralMessage{
   140  		Severity: GetSeverity(err),
   141  		Content:  err,
   142  	})
   143  }
   144  
   145  type ExportOptionHolder struct {
   146  	SessionID uint32
   147  }
   148  
   149  type ExportOption func(*ExportOptionHolder)
   150  
   151  // New returns a new error object with message formed from given arguments.
   152  func New(msg ...interface{}) *Error {
   153  	return &Error{
   154  		message:  msg,
   155  		severity: log.Severity_Info,
   156  	}
   157  }
   158  
   159  // Cause returns the root cause of this error.
   160  func Cause(err error) error {
   161  	if err == nil {
   162  		return nil
   163  	}
   164  L:
   165  	for {
   166  		switch inner := err.(type) {
   167  		case hasInnerError:
   168  			if inner.Inner() == nil {
   169  				break L
   170  			}
   171  			err = inner.Inner()
   172  		case *os.PathError:
   173  			if inner.Err == nil {
   174  				break L
   175  			}
   176  			err = inner.Err
   177  		case *os.SyscallError:
   178  			if inner.Err == nil {
   179  				break L
   180  			}
   181  			err = inner.Err
   182  		default:
   183  			break L
   184  		}
   185  	}
   186  	return err
   187  }
   188  
   189  // GetSeverity returns the actual severity of the error, including inner errors.
   190  func GetSeverity(err error) log.Severity {
   191  	if s, ok := err.(hasSeverity); ok {
   192  		return s.Severity()
   193  	}
   194  	return log.Severity_Info
   195  }