github.com/bazelbuild/remote-apis-sdks@v0.0.0-20240425170053-8a36686a6350/go/pkg/errors/errors.go (about)

     1  // Package errors provides the ability to wrap multiple errors while maintaining API compatibility with the standard package.
     2  // This functionality is a drop-in replacement from go1.20. Remove this package once the SDK is updated to g1.20.
     3  package errors
     4  
     5  import "errors"
     6  
     7  type joinError struct {
     8  	errs []error
     9  }
    10  
    11  // Error joins the texts of the wrapped errors using newline as the delimiter.
    12  func (e *joinError) Error() string {
    13  	var b []byte
    14  	for i, err := range e.errs {
    15  		if i > 0 {
    16  			b = append(b, '\n')
    17  		}
    18  		b = append(b, err.Error()...)
    19  	}
    20  	return string(b)
    21  }
    22  
    23  // Join wraps the specified errors into one error that prints the entire list using newline as the delimiter.
    24  func Join(errs ...error) error {
    25  	n := 0
    26  	for _, err := range errs {
    27  		if err != nil {
    28  			n++
    29  		}
    30  	}
    31  
    32  	if n == 0 {
    33  		return nil
    34  	}
    35  
    36  	// Unlike go1.20, this allows for efficient and convenient wrapping of errors without additional guards.
    37  	// E.g. the following code returns err as is without any allocations if errClose is nil:
    38  	// errClose := f.Close(); err = errors.Join(errClose, err)
    39  	if n == 1 {
    40  		for _, err := range errs {
    41  			if err != nil {
    42  				return err
    43  			}
    44  		}
    45  	}
    46  
    47  	e := &joinError{
    48  		errs: make([]error, 0, n),
    49  	}
    50  	for _, err := range errs {
    51  		if err != nil {
    52  			e.errs = append(e.errs, err)
    53  		}
    54  	}
    55  	return e
    56  }
    57  
    58  // Is implements the corresponding interface allowing the joinError type to be compatible with
    59  // errors.Is(error) bool of the standard package without having to override it.
    60  func (e *joinError) Is(target error) bool {
    61  	if target == nil || e == nil {
    62  		return e == target
    63  	}
    64  
    65  	for _, e := range e.errs {
    66  		if errors.Is(e, target) {
    67  			return true
    68  		}
    69  	}
    70  	return false
    71  }
    72  
    73  // Is delegates to the standard package.
    74  func Is(err, target error) bool {
    75  	return errors.Is(err, target)
    76  }
    77  
    78  // New delegates to the standard package.
    79  func New(text string) error {
    80  	return errors.New(text)
    81  }