go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/common/errors/filter.go (about)

     1  // Copyright 2016 The LUCI Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package errors
    16  
    17  // Filter examines a supplied error and removes instances of excluded errors
    18  // from it. If the entire supplied error is excluded, Filter will return nil.
    19  //
    20  // If a MultiError is supplied to Filter, it will be recursively traversed, and
    21  // its child errors will be turned into nil if they match the supplied filter.
    22  // If a MultiError has all of its children converted to nil as a result of the
    23  // filter, it will itself be reduced to nil.
    24  func Filter(err error, exclude error, others ...error) error {
    25  	return FilterFunc(err, func(e error) bool {
    26  		if e == exclude {
    27  			return true
    28  		}
    29  		for _, v := range others {
    30  			if e == v {
    31  				return true
    32  			}
    33  		}
    34  		return false
    35  	})
    36  }
    37  
    38  // FilterFunc examines a supplied error and removes instances of errors that
    39  // match the supplied filter function. If the entire supplied error is removed,
    40  // FilterFunc will return nil.
    41  //
    42  // If a MultiError is supplied to FilterFunc, it will be recursively traversed,
    43  // and its child errors will be turned into nil if they match the supplied
    44  // filter function. If a MultiError has all of its children converted to nil as
    45  // a result of the filter, it will itself be reduced to nil.
    46  //
    47  // Consqeuently, if err is a MultiError, shouldFilter will be called once with
    48  // err as its value and once for every non-nil error that it contains.
    49  func FilterFunc(err error, shouldFilter func(error) bool) error {
    50  	switch {
    51  	case shouldFilter == nil:
    52  		return err
    53  	case err == nil:
    54  		return nil
    55  	case shouldFilter(err):
    56  		return nil
    57  	}
    58  
    59  	if merr, ok := err.(MultiError); ok {
    60  		var lme MultiError
    61  		for i, e := range merr {
    62  			if e != nil {
    63  				e = FilterFunc(e, shouldFilter)
    64  				if e != nil {
    65  					if lme == nil {
    66  						lme = make(MultiError, len(merr))
    67  					}
    68  					lme[i] = e
    69  				}
    70  			}
    71  		}
    72  		if lme == nil {
    73  			return nil
    74  		}
    75  		return lme
    76  	}
    77  
    78  	return err
    79  }