mirror of https://github.com/prometheus/prometheus
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
104 lines
2.7 KiB
104 lines
2.7 KiB
// Copyright 2016 The etcd Authors |
|
// |
|
// Licensed under the Apache License, Version 2.0 (the "License"); |
|
// you may not use this file except in compliance with the License. |
|
// You may obtain a copy of the License at |
|
// |
|
// http://www.apache.org/licenses/LICENSE-2.0 |
|
// |
|
// Unless required by applicable law or agreed to in writing, software |
|
// distributed under the License is distributed on an "AS IS" BASIS, |
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
// See the License for the specific language governing permissions and |
|
// limitations under the License. |
|
|
|
package errors |
|
|
|
import ( |
|
"bytes" |
|
"errors" |
|
"fmt" |
|
"io" |
|
) |
|
|
|
// multiError type allows combining multiple errors into one. |
|
type multiError []error |
|
|
|
// NewMulti returns multiError with provided errors added if not nil. |
|
func NewMulti(errs ...error) multiError { //nolint:revive // unexported-return. |
|
m := multiError{} |
|
m.Add(errs...) |
|
return m |
|
} |
|
|
|
// Add adds single or many errors to the error list. Each error is added only if not nil. |
|
// If the error is a nonNilMultiError type, the errors inside nonNilMultiError are added to the main multiError. |
|
func (es *multiError) Add(errs ...error) { |
|
for _, err := range errs { |
|
if err == nil { |
|
continue |
|
} |
|
var merr nonNilMultiError |
|
if errors.As(err, &merr) { |
|
*es = append(*es, merr.errs...) |
|
continue |
|
} |
|
*es = append(*es, err) |
|
} |
|
} |
|
|
|
// Err returns the error list as an error or nil if it is empty. |
|
func (es multiError) Err() error { |
|
if len(es) == 0 { |
|
return nil |
|
} |
|
return nonNilMultiError{errs: es} |
|
} |
|
|
|
// nonNilMultiError implements the error interface, and it represents |
|
// multiError with at least one error inside it. |
|
// This type is needed to make sure that nil is returned when no error is combined in multiError for err != nil |
|
// check to work. |
|
type nonNilMultiError struct { |
|
errs multiError |
|
} |
|
|
|
// Error returns a concatenated string of the contained errors. |
|
func (es nonNilMultiError) Error() string { |
|
var buf bytes.Buffer |
|
|
|
if len(es.errs) > 1 { |
|
fmt.Fprintf(&buf, "%d errors: ", len(es.errs)) |
|
} |
|
|
|
for i, err := range es.errs { |
|
if i != 0 { |
|
buf.WriteString("; ") |
|
} |
|
buf.WriteString(err.Error()) |
|
} |
|
|
|
return buf.String() |
|
} |
|
|
|
// Is attempts to match the provided error against errors in the error list. |
|
// |
|
// This function allows errors.Is to traverse the values stored in the MultiError. |
|
// It returns true if any of the errors in the list match the target. |
|
func (es nonNilMultiError) Is(target error) bool { |
|
for _, err := range es.errs { |
|
if errors.Is(err, target) { |
|
return true |
|
} |
|
} |
|
return false |
|
} |
|
|
|
// CloseAll closes all given closers while recording error in MultiError. |
|
func CloseAll(cs []io.Closer) error { |
|
errs := NewMulti() |
|
for _, c := range cs { |
|
errs.Add(c.Close()) |
|
} |
|
return errs.Err() |
|
}
|
|
|