go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/errutil/append.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package errutil
     9  
    10  // Append appends errors together, creating a multi-error.
    11  //
    12  // Errors that are already multi-errors will be appended
    13  // as is, creating a jagged error list.
    14  //
    15  // To have a one-dimensional resulting error list, use `AppendFlat(...)`.
    16  func Append(err error, errs ...error) error {
    17  	if err == nil && len(errs) == 0 {
    18  		return nil
    19  	}
    20  	var output Multi
    21  	switch typedErr := err.(type) {
    22  	case Multi:
    23  		output = typedErr
    24  	default:
    25  		if typedErr != nil {
    26  			output = Multi{typedErr}
    27  		}
    28  	}
    29  	for _, e := range errs {
    30  		if e == nil {
    31  			continue
    32  		}
    33  		output = append(output, e)
    34  	}
    35  	if len(output) > 0 {
    36  		return output
    37  	}
    38  	return nil
    39  }
    40  
    41  // AppendFlat appends errors together, creating a multi-error.
    42  //
    43  // It differs from `Append(...)` in that it will flatten errors in the
    44  // list that are already `Multi` errors, creating a one dimensional
    45  // return list instead of a jagged return list.
    46  func AppendFlat(err error, errs ...error) error {
    47  	if err == nil && len(errs) == 0 {
    48  		return nil
    49  	}
    50  	var output Multi
    51  	switch typedErr := err.(type) {
    52  	case Multi:
    53  		output = typedErr
    54  	default:
    55  		if typedErr != nil {
    56  			output = Multi{typedErr}
    57  		}
    58  	}
    59  	for _, e := range errs {
    60  		if e == nil {
    61  			continue
    62  		}
    63  		output = append(output, flatten(e)...)
    64  	}
    65  
    66  	if len(output) > 0 {
    67  		return output
    68  	}
    69  	return nil
    70  }
    71  
    72  // flatten takes _any_ error of any mishapen form
    73  // and returns a single level error for it.
    74  func flatten(err error) Multi {
    75  	var output Multi
    76  	switch typedErr := err.(type) {
    77  	case Multi:
    78  		for _, inner := range typedErr {
    79  			output = append(output, flatten(inner)...)
    80  		}
    81  	default:
    82  		if typedErr != nil {
    83  			output = Multi{typedErr}
    84  		}
    85  	}
    86  	return output
    87  }