errors_go_other.go

 1//go:build !go1.20
 2// +build !go1.20
 3
 4package jwt
 5
 6import (
 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.
13func (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.
28type wrappedErrors struct {
29	msg string
30	joinedError
31}
32
33// Error returns the stored error string
34func (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"
52func 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}