github.com/haraldrudell/parl@v0.4.176/perrors/publics.go (about)

     1  /*
     2  © 2021–present Harald Rudell <harald.rudell@gmail.com> (https://haraldrudell.github.io/haraldrudell/)
     3  ISC License
     4  */
     5  
     6  package perrors
     7  
     8  import (
     9  	"strings"
    10  
    11  	"github.com/haraldrudell/parl/perrors/errorglue"
    12  	"github.com/haraldrudell/parl/pruntime"
    13  )
    14  
    15  // error116.Warning indicates that err is a problem of less severity than error.
    16  // It is uesed for errors that are not to terminate the thread.
    17  // A Warning can be detected using error116.IsWarning().
    18  func Warning(err error) error {
    19  	return Stack(errorglue.NewWarning(err))
    20  }
    21  
    22  // error116.AddKeyValue attaches a string value to err.
    23  // The values can be trrioeved using error116.ErrorData().
    24  // if key is non-empty valiue is returned in a map where last key wins.
    25  // if key is empty, valuse is returned in s string slice.
    26  // err can be nil.
    27  func AddKeyValue(err error, key, value string) (e error) {
    28  	return errorglue.NewErrorData(err, key, value)
    29  }
    30  
    31  // AppendError associates an additional error with err.
    32  //   - return value is nil if and only if both err and err2 are nil
    33  //   - if either err or err2 is nil, return value is the non-nil argument
    34  //   - if both err and err2 are non-nil, the return value is err with err2 associated
    35  //   - associated error instances can be retrieved using:
    36  //   - — perrors.AllErrors,
    37  //   - — perros.ErrorList or
    38  //   - — by rich error printing of perrors package: perrors.Long or
    39  //   - — “%+v”
    40  func AppendError(err error, err2 error) (e error) {
    41  	if err2 == nil {
    42  		e = err // err2 is nil, return is err, possibly nil
    43  	} else if err == nil {
    44  		e = err2 // err is nil, return is non-nil err2
    45  	} else {
    46  		e = errorglue.NewRelatedError(err, err2) // both non-nil
    47  	}
    48  	return
    49  }
    50  
    51  // AppendErrorDefer aggregates error sources into errp.
    52  //   - AppendErrorDefer is deferrable
    53  //   - errp cannot be nil
    54  //   - errp2 is a pointer to a second error variable used as source.
    55  //     If errp2 is nil or *errp2 is nil, no action is taken
    56  //   - fn is a function returning a possible error.
    57  //     If fn is nil or fn returns nil, no action is taken
    58  //   - AppendErrorDefer uses AppendError to aggregate error values into *errp
    59  func AppendErrorDefer(errp, errp2 *error, fn func() (err error)) {
    60  	if errp == nil {
    61  		panic(NewPF("errp cannot be nil"))
    62  	}
    63  	if errp2 != nil {
    64  		if err := *errp2; err != nil {
    65  			*errp = AppendError(*errp, err)
    66  		}
    67  	}
    68  	if fn != nil {
    69  		if err := fn(); err != nil {
    70  			*errp = AppendError(*errp, err)
    71  		}
    72  	}
    73  }
    74  
    75  func TagErr(e error, tags ...string) (err error) {
    76  	var frames = 1 // count TagErr frame
    77  
    78  	// ensure error has stack
    79  	if !HasStack(e) {
    80  		e = Stackn(e, frames)
    81  	}
    82  
    83  	// values to print
    84  	s := pruntime.NewCodeLocation(frames).PackFunc()
    85  	if tagString := strings.Join(tags, "\x20"); tagString != "" {
    86  		s += "\x20" + tagString
    87  	}
    88  
    89  	return Errorf("%s: %w", s, e)
    90  }
    91  
    92  // InvokeIfError invokes errFn with *errp if *errp is non-nil
    93  //   - used as a deferred conditional error storer
    94  //   - deferrable, thread-safe
    95  //
    96  // Usage:
    97  //
    98  //	func someFunc() {
    99  //	  var err error
   100  //	  defer perrors.InvokeIfError(&err, addError)
   101  func InvokeIfError(errp *error, errFn func(err error)) {
   102  	var err error
   103  	if errp != nil {
   104  		err = *errp
   105  	} else {
   106  		err = New("perrors.InvokeIfError errp nil")
   107  	}
   108  	if err != nil {
   109  		errFn(err)
   110  	}
   111  }