github.com/imannamdari/v2ray-core/v5@v5.0.5/common/errors/errors.go (about)

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