github.com/sohaha/zlsgo@v1.7.13-0.20240501141223-10dd1a906f76/zerror/error.go (about)

     1  package zerror
     2  
     3  import (
     4  	"errors"
     5  
     6  	"github.com/sohaha/zlsgo/zutil"
     7  )
     8  
     9  type (
    10  	// ErrCode error code type
    11  	ErrCode int32
    12  	// Error wraps err with code
    13  	Error struct {
    14  		err     error
    15  		wrapErr error
    16  		errText *string
    17  		stack   zutil.Stack
    18  		code    ErrCode
    19  		inner   bool
    20  	}
    21  
    22  	External func(err error) error
    23  )
    24  
    25  var (
    26  	goROOT = zutil.GOROOT()
    27  )
    28  
    29  func New(code ErrCode, text string, w ...External) error {
    30  	var err error = &Error{
    31  		code:    code,
    32  		stack:   zutil.Callers(3),
    33  		errText: &(&[1]string{text})[0],
    34  	}
    35  
    36  	for i := range w {
    37  		err = w[i](err)
    38  	}
    39  
    40  	return err
    41  }
    42  
    43  // Reuse the error
    44  func Reuse(err error) error {
    45  	if err == nil {
    46  		return nil
    47  	}
    48  	if e, ok := err.(*Error); ok {
    49  		return e
    50  	}
    51  	return &Error{
    52  		err:   err,
    53  		stack: zutil.Callers(3),
    54  	}
    55  }
    56  
    57  // Wrap wraps err with code
    58  func Wrap(err error, code ErrCode, text string, w ...External) error {
    59  	if err == nil {
    60  		return nil
    61  	}
    62  
    63  	for i := range w {
    64  		err = w[i](err)
    65  	}
    66  
    67  	return &Error{
    68  		wrapErr: err,
    69  		code:    code,
    70  		stack:   zutil.Callers(3),
    71  		errText: &(&[1]string{text})[0],
    72  	}
    73  }
    74  
    75  // Deprecated: please use zerror.With
    76  // SupText returns the error text
    77  func SupText(err error, text string) error {
    78  	return With(err, text)
    79  }
    80  
    81  // With returns the inner error's text
    82  func With(err error, text string, w ...External) error {
    83  	if err == nil {
    84  		return &Error{
    85  			stack:   zutil.Callers(3),
    86  			errText: &(&[1]string{text})[0],
    87  		}
    88  	}
    89  
    90  	for i := range w {
    91  		err = w[i](err)
    92  	}
    93  
    94  	return &Error{
    95  		wrapErr: err,
    96  		inner:   true,
    97  		stack:   zutil.Callers(3),
    98  		errText: &(&[1]string{text})[0],
    99  	}
   100  }
   101  
   102  // Unwrap returns if err is Error and its code == code
   103  func Unwrap(err error, code ErrCode) (error, bool) {
   104  	for {
   105  		if err == nil {
   106  			return nil, false
   107  		}
   108  
   109  		e, ok := err.(*Error)
   110  		if !ok {
   111  			return err, false
   112  		}
   113  
   114  		if e.code == code {
   115  			if e.errText != nil {
   116  				return errors.New(*e.errText), true
   117  			}
   118  
   119  			return e.err, true
   120  		}
   121  
   122  		err = e.Unwrap()
   123  	}
   124  }
   125  
   126  // Is returns if err is Error and its code == code
   127  func Is(err error, code ...ErrCode) bool {
   128  	for i := range code {
   129  		_, ok := Unwrap(err, code[i])
   130  		if ok {
   131  			return true
   132  		}
   133  	}
   134  
   135  	return false
   136  }
   137  
   138  // UnwrapCode Returns the current error code
   139  func UnwrapCode(err error) (ErrCode, bool) {
   140  	if err == nil {
   141  		return 0, false
   142  	}
   143  
   144  	e, ok := err.(*Error)
   145  	if !ok {
   146  		return 0, false
   147  	}
   148  
   149  	if e.code == 0 {
   150  		return UnwrapCode(e.wrapErr)
   151  	}
   152  
   153  	return e.code, true
   154  }
   155  
   156  // UnwrapCodes Returns the current all error code
   157  func UnwrapCodes(err error) (codes []ErrCode) {
   158  	for {
   159  		if err == nil {
   160  			return
   161  		}
   162  
   163  		e, ok := err.(*Error)
   164  		if !ok {
   165  			return
   166  		}
   167  
   168  		codes = append(codes, e.code)
   169  
   170  		err = e.Unwrap()
   171  	}
   172  }
   173  
   174  // UnwrapErrors Returns the current all error text
   175  func UnwrapErrors(err error) (errs []string) {
   176  	for {
   177  		if err == nil {
   178  			return
   179  		}
   180  
   181  		e, ok := err.(*Error)
   182  		if !ok {
   183  			errs = append(errs, err.Error())
   184  			return
   185  		}
   186  
   187  		if e.errText != nil {
   188  			errs = append(errs, *e.errText)
   189  		} else {
   190  			errs = append(errs, e.err.Error())
   191  		}
   192  
   193  		err = e.Unwrap()
   194  	}
   195  }
   196  
   197  func UnwrapFirst(err error) (ferr error) {
   198  	for {
   199  		if err == nil {
   200  			return
   201  		}
   202  
   203  		e, ok := err.(*Error)
   204  		if !ok {
   205  			return err
   206  		}
   207  
   208  		if e.errText != nil {
   209  			ferr = errors.New(*e.errText)
   210  		} else {
   211  			ferr = e.err
   212  		}
   213  
   214  		err = e.Unwrap()
   215  	}
   216  }
   217  
   218  func UnwrapFirstCode(err error) (code ErrCode) {
   219  	for {
   220  		if err == nil {
   221  			return
   222  		}
   223  
   224  		e, ok := err.(*Error)
   225  		if !ok {
   226  			return
   227  		}
   228  
   229  		code = e.code
   230  
   231  		err = e.Unwrap()
   232  	}
   233  }