codeberg.org/gruf/go-errors/v2@v2.3.1/standard.go (about)

     1  package errors
     2  
     3  import (
     4  	_ "unsafe"
     5  )
     6  
     7  // Is reports whether any error in err's tree matches target.
     8  //
     9  // The tree consists of err itself, followed by the errors obtained by repeatedly
    10  // calling Unwrap. When err wraps multiple errors, Is examines err followed by a
    11  // depth-first traversal of its children.
    12  //
    13  // An error is considered to match a target if it is equal to that target or if
    14  // it implements a method Is(error) bool such that Is(target) returns true.
    15  //
    16  // An error type might provide an Is method so it can be treated as equivalent
    17  // to an existing error. For example, if MyError defines
    18  //
    19  //	func (m MyError) Is(target error) bool { return target == fs.ErrExist }
    20  //
    21  // then Is(MyError{}, fs.ErrExist) returns true. See [syscall.Errno.Is] for
    22  // an example in the standard library. An Is method should only shallowly
    23  // compare err and the target and not call Unwrap on either.
    24  //
    25  //go:linkname Is errors.Is
    26  func Is(err error, target error) bool
    27  
    28  // IsV2 calls Is(err, target) for each target within targets.
    29  func IsV2(err error, targets ...error) bool {
    30  	for _, target := range targets {
    31  		if Is(err, target) {
    32  			return true
    33  		}
    34  	}
    35  	return false
    36  }
    37  
    38  // As finds the first error in err's tree that matches target, and if one is found, sets
    39  // target to that error value and returns true. Otherwise, it returns false.
    40  //
    41  // The tree consists of err itself, followed by the errors obtained by repeatedly
    42  // calling Unwrap. When err wraps multiple errors, As examines err followed by a
    43  // depth-first traversal of its children.
    44  //
    45  // An error matches target if the error's concrete value is assignable to the value
    46  // pointed to by target, or if the error has a method As(interface{}) bool such that
    47  // As(target) returns true. In the latter case, the As method is responsible for
    48  // setting target.
    49  //
    50  // An error type might provide an As method so it can be treated as if it were a
    51  // different error type.
    52  //
    53  // As panics if target is not a non-nil pointer to either a type that implements
    54  // error, or to any interface type.
    55  //
    56  //go:linkname As errors.As
    57  func As(err error, target any) bool
    58  
    59  // AsV2 is functionally similar to As(), instead
    60  // leveraging generics to handle allocation and
    61  // returning of a concrete generic parameter type.
    62  func AsV2[Type any](err error) Type {
    63  	var t Type
    64  	var ok bool
    65  	errs := []error{err}
    66  	for len(errs) > 0 {
    67  		// Pop next error to check.
    68  		err := errs[len(errs)-1]
    69  		errs = errs[:len(errs)-1]
    70  
    71  		// Check direct type.
    72  		t, ok = err.(Type)
    73  		if ok {
    74  			return t
    75  		}
    76  
    77  		// Look for .As() support.
    78  		as, ok := err.(interface {
    79  			As(target any) bool
    80  		})
    81  
    82  		if ok {
    83  			// Attempt .As().
    84  			if as.As(&t) {
    85  				return t
    86  			}
    87  		}
    88  
    89  		// Try unwrap errors.
    90  		switch u := err.(type) {
    91  		case interface{ Unwrap() error }:
    92  			errs = append(errs, u.Unwrap())
    93  		case interface{ Unwrap() []error }:
    94  			errs = append(errs, u.Unwrap()...)
    95  		}
    96  	}
    97  	return t
    98  }
    99  
   100  // Unwrap returns the result of calling the Unwrap method on err, if err's
   101  // type contains an Unwrap method returning error.
   102  // Otherwise, Unwrap returns nil.
   103  //
   104  // Unwrap only calls a method of the form "Unwrap() error".
   105  // In particular Unwrap does not unwrap errors returned by [Join].
   106  //
   107  //go:linkname Unwrap errors.Unwrap
   108  func Unwrap(err error) error
   109  
   110  // UnwrapV2 is functionally similar to Unwrap(), except that
   111  // it also handles the case of interface{ Unwrap() []error }.
   112  func UnwrapV2(err error) []error {
   113  	switch u := err.(type) {
   114  	case interface{ Unwrap() error }:
   115  		if e := u.Unwrap(); err != nil {
   116  			return []error{e}
   117  		}
   118  	case interface{ Unwrap() []error }:
   119  		return u.Unwrap()
   120  	}
   121  	return nil
   122  }
   123  
   124  // Join returns an error that wraps the given errors.
   125  // Any nil error values are discarded.
   126  // Join returns nil if every value in errs is nil.
   127  // The error formats as the concatenation of the strings obtained
   128  // by calling the Error method of each element of errs, with a newline
   129  // between each string.
   130  //
   131  // A non-nil error returned by Join implements the Unwrap() []error method.
   132  //
   133  //go:linkname Join errors.Join
   134  func Join(errs ...error) error