| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package errors | 5 package errors |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "fmt" | 8 "fmt" |
| 9 "reflect" | 9 "reflect" |
| 10 "sync" | |
| 11 ) | 10 ) |
| 12 | 11 |
| 13 var ( | 12 var ( |
| 14 multiErrorType = reflect.TypeOf(MultiError(nil)) | 13 multiErrorType = reflect.TypeOf(MultiError(nil)) |
| 15 ) | 14 ) |
| 16 | 15 |
| 17 // MultiError is a simple `error` implementation which represents multiple | 16 // MultiError is a simple `error` implementation which represents multiple |
| 18 // `error` objects in one. | 17 // `error` objects in one. |
| 19 type MultiError []error | 18 type MultiError []error |
| 20 | 19 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 continue | 65 continue |
| 67 } | 66 } |
| 68 ret = append(ret, e) | 67 ret = append(ret, e) |
| 69 } | 68 } |
| 70 if len(ret) == 0 { | 69 if len(ret) == 0 { |
| 71 return nil | 70 return nil |
| 72 } | 71 } |
| 73 return ret | 72 return ret |
| 74 } | 73 } |
| 75 | 74 |
| 76 // LazyMultiError is a lazily-constructed MultiError. You specify the target | |
| 77 // MultiError size up front (as Size), and then you call Assign for each error | |
| 78 // encountered, and it's potential index. The MultiError will only be allocated | |
| 79 // if one of the Assign'd errors is non-nil. Similarly, Get will retrieve either | |
| 80 // the allocated MultiError, or nil if no error was encountered. | |
| 81 type LazyMultiError struct { | |
| 82 sync.Mutex | |
| 83 | |
| 84 Size int | |
| 85 me MultiError | |
| 86 } | |
| 87 | |
| 88 // Assign semantically assigns the error to the given index in the MultiError. | |
| 89 // If the error is nil, no action is taken. Otherwise the MultiError is | |
| 90 // allocated to its full size (if not already), and the error assigned into it. | |
| 91 // | |
| 92 // It returns true iff err != nil. | |
| 93 func (e *LazyMultiError) Assign(i int, err error) bool { | |
| 94 if err == nil { | |
| 95 return false | |
| 96 } | |
| 97 e.Lock() | |
| 98 defer e.Unlock() | |
| 99 if e.me == nil { | |
| 100 e.me = make(MultiError, e.Size) | |
| 101 } | |
| 102 e.me[i] = err | |
| 103 return true | |
| 104 } | |
| 105 | |
| 106 // GetOne returns the error at the given index, or nil, if no non-nil error | |
| 107 // was Assign'd. | |
| 108 func (e *LazyMultiError) GetOne(i int) error { | |
| 109 e.Lock() | |
| 110 defer e.Unlock() | |
| 111 if e.me == nil { | |
| 112 return nil | |
| 113 } | |
| 114 return e.me[i] | |
| 115 } | |
| 116 | |
| 117 // Get returns the MultiError, or nil, if no non-nil error was Assign'd. | |
| 118 func (e *LazyMultiError) Get() error { | |
| 119 e.Lock() | |
| 120 defer e.Unlock() | |
| 121 if e.me == nil { | |
| 122 return nil | |
| 123 } | |
| 124 return e.me | |
| 125 } | |
| 126 | |
| 127 // Fix will convert a MultiError compatible type (e.g. []error) to this | 75 // Fix will convert a MultiError compatible type (e.g. []error) to this |
| 128 // version of MultiError. | 76 // version of MultiError. |
| 129 func Fix(err error) error { | 77 func Fix(err error) error { |
| 130 if err != nil { | 78 if err != nil { |
| 131 // we know that err already conforms to the error interface (or
the caller's | 79 // we know that err already conforms to the error interface (or
the caller's |
| 132 // method wouldn't compile), so check to see if the error's unde
rlying type | 80 // method wouldn't compile), so check to see if the error's unde
rlying type |
| 133 // looks like one of the special error types we implement. | 81 // looks like one of the special error types we implement. |
| 134 v := reflect.ValueOf(err) | 82 v := reflect.ValueOf(err) |
| 135 if v.Type().ConvertibleTo(multiErrorType) { | 83 if v.Type().ConvertibleTo(multiErrorType) { |
| 136 err = v.Convert(multiErrorType).Interface().(error) | 84 err = v.Convert(multiErrorType).Interface().(error) |
| 137 } | 85 } |
| 138 } | 86 } |
| 139 return err | 87 return err |
| 140 } | 88 } |
| OLD | NEW |