1 //go:build !go1.20 2 // +build !go1.20 3 4 package jwt 5 6 import ( 7 "errors" 8 "fmt" 9 ) 10 11 // Is implements checking for multiple errors using [errors.Is], since multiple 12 // error unwrapping is not possible in versions less than Go 1.20. 13 func (je joinedError) Is(err error) bool { 14 for _, e := range je.errs { 15 if errors.Is(e, err) { 16 return true 17 } 18 } 19 20 return false 21 } 22 23 // wrappedErrors is a workaround for wrapping multiple errors in environments 24 // where Go 1.20 is not available. It basically uses the already implemented 25 // functionality of joinedError to handle multiple errors with supplies a 26 // custom error message that is identical to the one we produce in Go 1.20 using 27 // multiple %w directives. 28 type wrappedErrors struct { 29 msg string 30 joinedError 31 } 32 33 // Error returns the stored error string 34 func (we wrappedErrors) Error() string { 35 return we.msg 36 } 37 38 // newError creates a new error message with a detailed error message. The 39 // message will be prefixed with the contents of the supplied error type. 40 // Additionally, more errors, that provide more context can be supplied which 41 // will be appended to the message. Since we cannot use of Go 1.20's possibility 42 // to include more than one %w formatting directive in [fmt.Errorf], we have to 43 // emulate that. 44 // 45 // For example, 46 // 47 // newError("no keyfunc was provided", ErrTokenUnverifiable) 48 // 49 // will produce the error string 50 // 51 // "token is unverifiable: no keyfunc was provided" 52 func newError(message string, err error, more ...error) error { 53 // We cannot wrap multiple errors here with %w, so we have to be a little 54 // bit creative. Basically, we are using %s instead of %w to produce the 55 // same error message and then throw the result into a custom error struct. 56 var format string 57 var args []any 58 if message != "" { 59 format = "%s: %s" 60 args = []any{err, message} 61 } else { 62 format = "%s" 63 args = []any{err} 64 } 65 errs := []error{err} 66 67 for _, e := range more { 68 format += ": %s" 69 args = append(args, e) 70 errs = append(errs, e) 71 } 72 73 err = &wrappedErrors{ 74 msg: fmt.Sprintf(format, args...), 75 joinedError: joinedError{errs: errs}, 76 } 77 return err 78 } 79