blob: 349fc06ed9f75c3323a9d65c2e519713a9b33e7e [file] [log] [blame]
Damien Neil4a0a2b32022-09-22 10:43:26 -07001// Copyright 2022 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package errors
6
Jes Cok26fc4aa2023-06-06 23:25:42 +00007import (
8 "unsafe"
9)
10
Damien Neil4a0a2b32022-09-22 10:43:26 -070011// Join returns an error that wraps the given errors.
12// Any nil error values are discarded.
David Bendoryf53a95f2023-03-17 14:04:01 +000013// Join returns nil if every value in errs is nil.
Damien Neil4a0a2b32022-09-22 10:43:26 -070014// The error formats as the concatenation of the strings obtained
15// by calling the Error method of each element of errs, with a newline
16// between each string.
Daniel Nephinc0fd7f72023-03-30 16:00:15 +000017//
18// A non-nil error returned by Join implements the Unwrap() []error method.
Damien Neil4a0a2b32022-09-22 10:43:26 -070019func Join(errs ...error) error {
20 n := 0
21 for _, err := range errs {
22 if err != nil {
23 n++
24 }
25 }
26 if n == 0 {
27 return nil
28 }
29 e := &joinError{
30 errs: make([]error, 0, n),
31 }
32 for _, err := range errs {
33 if err != nil {
34 e.errs = append(e.errs, err)
35 }
36 }
37 return e
38}
39
40type joinError struct {
41 errs []error
42}
43
44func (e *joinError) Error() string {
Jes Cok26fc4aa2023-06-06 23:25:42 +000045 // Since Join returns nil if every value in errs is nil,
46 // e.errs cannot be empty.
47 if len(e.errs) == 1 {
48 return e.errs[0].Error()
49 }
50
51 b := []byte(e.errs[0].Error())
52 for _, err := range e.errs[1:] {
53 b = append(b, '\n')
Damien Neil4a0a2b32022-09-22 10:43:26 -070054 b = append(b, err.Error()...)
55 }
Jes Cok26fc4aa2023-06-06 23:25:42 +000056 // At this point, b has at least one byte '\n'.
57 return unsafe.String(&b[0], len(b))
Damien Neil4a0a2b32022-09-22 10:43:26 -070058}
59
60func (e *joinError) Unwrap() []error {
61 return e.errs
62}