Skip to content

Commit

Permalink
Merge pull request #31 from waschik/master
Browse files Browse the repository at this point in the history
Add "As" of standard errors module
  • Loading branch information
ConradIrwin authored May 5, 2021
2 parents 7c02372 + 725b1a2 commit 5c4c70f
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 4 deletions.
6 changes: 5 additions & 1 deletion error.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ func WrapPrefix(e interface{}, prefix string, skip int) *Error {

}


// Errorf creates a new error with the given message. You can use it
// as a drop-in replacement for fmt.Errorf() to provide descriptive
// errors in return values.
Expand Down Expand Up @@ -203,3 +202,8 @@ func (err *Error) TypeName() string {
}
return reflect.TypeOf(err.Err).String()
}

// Return the wrapped error (implements api for As function).
func (err *Error) Unwrap() error {
return err.Err
}
5 changes: 5 additions & 0 deletions error_1_13.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ import (
baseErrors "errors"
)

// find error in any wrapped error
func As(err error, target interface{}) bool {
return baseErrors.As(err, target)
}

// Is detects whether the error is equal to a given error. Errors
// are considered equal by this function if they are matched by errors.Is
// or if their contained errors are matched through errors.Is
Expand Down
4 changes: 2 additions & 2 deletions error_1_13_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,10 @@ type errorWithCustomIs struct {
}

func (ewci errorWithCustomIs) Error() string {
return "["+ewci.Key+"]: " + ewci.Err.Error()
return "[" + ewci.Key + "]: " + ewci.Err.Error()
}

func (ewci errorWithCustomIs) Is(target error) bool {
matched, ok := target.(errorWithCustomIs)
return ok && matched.Key == ewci.Key
}
}
37 changes: 36 additions & 1 deletion error_backward.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,41 @@

package errors

import (
"reflect"
)

type unwrapper interface {
Unwrap() error
}

// As assigns error or any wrapped error to the value target points
// to. If there is no value of the target type of target As returns
// false.
func As(err error, target interface{}) bool {
targetType := reflect.TypeOf(target)

for {
errType := reflect.TypeOf(err)

if errType == nil {
return false
}

if reflect.PtrTo(errType) == targetType {
reflect.ValueOf(target).Elem().Set(reflect.ValueOf(err))
return true
}

wrapped, ok := err.(unwrapper)
if ok {
err = wrapped.Unwrap()
} else {
return false
}
}
}

// Is detects whether the error is equal to a given error. Errors
// are considered equal by this function if they are the same object,
// or if they both contain the same error inside an errors.Error.
Expand All @@ -19,4 +54,4 @@ func Is(e error, original error) bool {
}

return false
}
}
29 changes: 29 additions & 0 deletions error_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,29 @@ func BenchmarkStackFormat(b *testing.B) {
}
}

func TestAs(t *testing.T) {
var errStrIn errorString = "TestForFun"

var errStrOut errorString
if As(errStrIn, &errStrOut) {
if errStrOut != "TestForFun" {
t.Errorf("direct errStr value is not returned")
}
} else {
t.Errorf("direct errStr is not returned")
}

errStrOut = ""
err := Wrap(errStrIn, 0)
if As(err, &errStrOut) {
if errStrOut != "TestForFun" {
t.Errorf("wrapped errStr value is not returned")
}
} else {
t.Errorf("wrapped errStr is not returned")
}
}

func TestStackFormat(t *testing.T) {

defer func() {
Expand Down Expand Up @@ -316,3 +339,9 @@ func callersToFrames(callers []uintptr) []runtime.Frame {
}
}
}

type errorString string

func (e errorString) Error() string {
return string(e)
}

0 comments on commit 5c4c70f

Please sign in to comment.