github.com/blend/go-sdk@v1.20220411.3/ex/multi.go (about)

     1  /*
     2  
     3  Copyright (c) 2022 - Present. Blend Labs, Inc. All rights reserved
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file.
     5  
     6  */
     7  
     8  package ex
     9  
    10  import (
    11  	"fmt"
    12  	"strings"
    13  )
    14  
    15  // Append appends errors together, creating a multi-error.
    16  func Append(err error, errs ...error) error {
    17  	if len(errs) == 0 {
    18  		return err
    19  	}
    20  	var all []error
    21  	if err != nil {
    22  		all = append(all, NewWithStackDepth(err, DefaultNewStartDepth+1))
    23  	}
    24  	for _, extra := range errs {
    25  		if extra != nil {
    26  			all = append(all, NewWithStackDepth(extra, DefaultNewStartDepth+1))
    27  		}
    28  	}
    29  	if len(all) == 0 {
    30  		return nil
    31  	}
    32  	if len(all) == 1 {
    33  		return all[0]
    34  	}
    35  	return Multi(all)
    36  }
    37  
    38  // Unwrap unwraps multi-errors.
    39  func Unwrap(err error) []error {
    40  	if typed, ok := err.(Multi); ok {
    41  		return []error(typed)
    42  	}
    43  	return []error{err}
    44  }
    45  
    46  // Multi represents an array of errors.
    47  type Multi []error
    48  
    49  // Error implements error.
    50  func (m Multi) Error() string {
    51  	if len(m) == 0 {
    52  		return ""
    53  	}
    54  	if len(m) == 1 {
    55  		return fmt.Sprintf("1 error occurred:\n\t* %v\n\n", m[0])
    56  	}
    57  
    58  	points := make([]string, len(m))
    59  	for i, err := range m {
    60  		points[i] = fmt.Sprintf("* %v", err)
    61  	}
    62  
    63  	return fmt.Sprintf(
    64  		"%d errors occurred:\n\t%s\n\n",
    65  		len(m), strings.Join(points, "\n\t"))
    66  }
    67  
    68  // WrappedErrors implements something in errors.
    69  func (m Multi) WrappedErrors() []error {
    70  	return m
    71  }
    72  
    73  // Unwrap returns an error from Error (or nil if there are no errors).
    74  // This error returned will further support Unwrap to get the next error,
    75  // etc.
    76  //
    77  // The resulting error supports errors.As/Is/Unwrap so you can continue
    78  // to use the stdlib errors package to introspect further.
    79  //
    80  // This will perform a shallow copy of the errors slice. Any errors appended
    81  // to this error after calling Unwrap will not be available until a new
    82  // Unwrap is called on the multierror.Error.
    83  func (m Multi) Unwrap() error {
    84  	if m == nil || len(m) == 0 {
    85  		return nil
    86  	}
    87  	if len(m) == 1 {
    88  		return m[0]
    89  	}
    90  	errs := make([]error, len(m))
    91  	copy(errs, m)
    92  	return Nest(errs...)
    93  }