summaryrefslogtreecommitdiff
path: root/vendor/github.com/zeebo
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/zeebo')
-rw-r--r--vendor/github.com/zeebo/errs/.gitignore1
-rw-r--r--vendor/github.com/zeebo/errs/AUTHORS5
-rw-r--r--vendor/github.com/zeebo/errs/LICENSE21
-rw-r--r--vendor/github.com/zeebo/errs/README.md235
-rw-r--r--vendor/github.com/zeebo/errs/errs.go298
-rw-r--r--vendor/github.com/zeebo/errs/group.go85
-rw-r--r--vendor/github.com/zeebo/errs/is_go1.20.go8
-rw-r--r--vendor/github.com/zeebo/errs/is_go_other.go17
8 files changed, 670 insertions, 0 deletions
diff --git a/vendor/github.com/zeebo/errs/.gitignore b/vendor/github.com/zeebo/errs/.gitignore
new file mode 100644
index 0000000..722d5e7
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/.gitignore
@@ -0,0 +1 @@
+.vscode
diff --git a/vendor/github.com/zeebo/errs/AUTHORS b/vendor/github.com/zeebo/errs/AUTHORS
new file mode 100644
index 0000000..6246e74
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/AUTHORS
@@ -0,0 +1,5 @@
+Egon Elbre <github.com/egonelbre>
+Jeff Wendling <leterip@gmail.com>
+JT Olio <github.com/jtolds>
+Kaloyan Raev <github.com/kaloyan-raev>
+paul cannon <github.com/thepaul>
diff --git a/vendor/github.com/zeebo/errs/LICENSE b/vendor/github.com/zeebo/errs/LICENSE
new file mode 100644
index 0000000..3ba9193
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 The Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/github.com/zeebo/errs/README.md b/vendor/github.com/zeebo/errs/README.md
new file mode 100644
index 0000000..0f72bf7
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/README.md
@@ -0,0 +1,235 @@
+# errs
+
+[![GoDoc](https://godoc.org/github.com/zeebo/errs?status.svg)](https://godoc.org/github.com/zeebo/errs)
+[![Sourcegraph](https://sourcegraph.com/github.com/zeebo/errs/-/badge.svg)](https://sourcegraph.com/github.com/zeebo/errs?badge)
+[![Go Report Card](https://goreportcard.com/badge/github.com/zeebo/errs)](https://goreportcard.com/report/github.com/zeebo/errs)
+
+errs is a package for making errors friendly and easy.
+
+### Creating Errors
+
+The easiest way to use it, is to use the package level [New][New] function.
+It's much like `fmt.Errorf`, but better. For example:
+
+```go
+func checkThing() error {
+ return errs.New("what's up with %q?", "zeebo")
+}
+```
+
+Why is it better? Errors come with a stack trace that is only printed
+when a `"+"` character is used in the format string. This should retain the
+benefits of being able to diagnose where and why errors happen, without all of
+the noise of printing a stack trace in every situation. For example:
+
+```go
+func doSomeRealWork() {
+ err := checkThing()
+ if err != nil {
+ fmt.Printf("%+v\n", err) // contains stack trace if it's a errs error.
+ fmt.Printf("%v\n", err) // does not contain a stack trace
+ return
+ }
+}
+```
+
+### Error Classes
+
+You can create a [Class][Class] of errors and check if any error was created by
+that class. The class name is prefixed to all of the errors it creates. For example:
+
+```go
+var Unauthorized = errs.Class("unauthorized")
+
+func checkUser(username, password string) error {
+ if username != "zeebo" {
+ return Unauthorized.New("who is %q?", username)
+ }
+ if password != "hunter2" {
+ return Unauthorized.New("that's not a good password, jerkmo!")
+ }
+ return nil
+}
+
+func handleRequest() {
+ if err := checkUser("zeebo", "hunter3"); Unauthorized.Has(err) {
+ fmt.Println(err)
+ }
+
+ // output:
+ // unauthorized: that's not a good password, jerkmo!
+}
+```
+
+Classes can also [Wrap][ClassWrap] other errors, and errors may be wrapped
+multiple times. For example:
+
+```go
+var (
+ Error = errs.Class("mypackage")
+ Unauthorized = errs.Class("unauthorized")
+)
+
+func deep3() error {
+ return fmt.Errorf("ouch")
+}
+
+func deep2() error {
+ return Unauthorized.Wrap(deep3())
+}
+
+func deep1() error {
+ return Error.Wrap(deep2())
+}
+
+func deep() {
+ fmt.Println(deep1())
+
+ // output:
+ // mypackage: unauthorized: ouch
+}
+```
+
+In the above example, both `Error.Has(deep1())` and `Unauthorized.Has(deep1())`
+would return `true`, and the stack trace would only be recorded once at the
+`deep2` call.
+
+In addition, when an error has been wrapped, wrapping it again with the same class will
+not do anything. For example:
+
+```go
+func doubleWrap() {
+ fmt.Println(Error.Wrap(Error.New("foo")))
+
+ // output:
+ // mypackage: foo
+}
+```
+
+This is to make it an easier decision if you should wrap or not (you should).
+
+### Utilities
+
+[Classes][Classes] is a helper function to get a slice of classes that an error
+has. The latest wrap is first in the slice. For example:
+
+```go
+func getClasses() {
+ classes := errs.Classes(deep1())
+ fmt.Println(classes[0] == &Error)
+ fmt.Println(classes[1] == &Unauthorized)
+
+ // output:
+ // true
+ // true
+}
+```
+
+Finally, a helper function, [Unwrap][Unwrap] is provided to get the
+wrapped error in cases where you might want to inspect details. For
+example:
+
+```go
+var Error = errs.Class("mypackage")
+
+func getHandle() (*os.File, error) {
+ fh, err := os.Open("neat_things")
+ if err != nil {
+ return nil, Error.Wrap(err)
+ }
+ return fh, nil
+}
+
+func checkForNeatThings() {
+ fh, err := getHandle()
+ if os.IsNotExist(errs.Unwrap(err)) {
+ panic("no neat things?!")
+ }
+ if err != nil {
+ panic("phew, at least there are neat things, even if i can't see them")
+ }
+ fh.Close()
+}
+```
+
+It knows about both the `Unwrap() error` and `Unwrap() []error` methods that are
+often used in the community, and will call them as many times as possible.
+
+### Defer
+
+The package also provides [WrapP][WrapP] versions of [Wrap][Wrap] that are useful
+in defer contexts. For example:
+
+```go
+func checkDefer() (err error) {
+ defer Error.WrapP(&err)
+
+ fh, err := os.Open("secret_stash")
+ if err != nil {
+ return nil, err
+ }
+ return fh.Close()
+}
+```
+
+### Groups
+
+[Groups][Group] allow one to collect a set of errors. For example:
+
+```go
+func tonsOfErrors() error {
+ var group errs.Group
+ for _, work := range someWork {
+ group.Add(maybeErrors(work))
+ }
+ return group.Err()
+}
+```
+
+Some things to note:
+
+- The [Add][GroupAdd] method only adds to the group if the passed in error is non-nil.
+- The [Err][GroupErr] method returns an error only if non-nil errors have been added, and
+ additionally returns just the error if only one error was added. Thus, we always
+ have that if you only call `group.Add(err)`, then `group.Err() == err`.
+
+The returned error will format itself similarly:
+
+```go
+func groupFormat() {
+ var group errs.Group
+ group.Add(errs.New("first"))
+ group.Add(errs.New("second"))
+ err := group.Err()
+
+ fmt.Printf("%v\n", err)
+ fmt.Println()
+ fmt.Printf("%+v\n", err)
+
+ // output:
+ // first; second
+ //
+ // group:
+ // --- first
+ // ... stack trace
+ // --- second
+ // ... stack trace
+}
+```
+
+### Contributing
+
+errs is released under an MIT License. If you want to contribute, be sure to
+add yourself to the list in AUTHORS.
+
+[New]: https://godoc.org/github.com/zeebo/errs#New
+[Wrap]: https://godoc.org/github.com/zeebo/errs#Wrap
+[WrapP]: https://godoc.org/github.com/zeebo/errs#WrapP
+[Class]: https://godoc.org/github.com/zeebo/errs#Class
+[ClassNew]: https://godoc.org/github.com/zeebo/errs#Class.New
+[ClassWrap]: https://godoc.org/github.com/zeebo/errs#Class.Wrap
+[Unwrap]: https://godoc.org/github.com/zeebo/errs#Unwrap
+[Classes]: https://godoc.org/github.com/zeebo/errs#Classes
+[Group]: https://godoc.org/github.com/zeebo/errs#Group
+[GroupAdd]: https://godoc.org/github.com/zeebo/errs#Group.Add
+[GroupErr]: https://godoc.org/github.com/zeebo/errs#Group.Err
diff --git a/vendor/github.com/zeebo/errs/errs.go b/vendor/github.com/zeebo/errs/errs.go
new file mode 100644
index 0000000..9a42e3d
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/errs.go
@@ -0,0 +1,298 @@
+// Package errs provides a simple error package with stack traces.
+package errs
+
+import (
+ "fmt"
+ "io"
+ "runtime"
+)
+
+// Namer is implemented by all errors returned in this package. It returns a
+// name for the class of error it is, and a boolean indicating if the name is
+// valid.
+type Namer interface{ Name() (string, bool) }
+
+// Causer is implemented by all errors returned in this package. It returns
+// the underlying cause of the error, or nil if there is no underlying cause.
+//
+// Deprecated: check for the 'Unwrap()' interface from the stdlib errors package
+// instead.
+type Causer interface{ Cause() error }
+
+// New returns an error not contained in any class. This is the same as calling
+// fmt.Errorf(...) except it captures a stack trace on creation.
+func New(format string, args ...interface{}) error {
+ return (*Class).create(nil, 3, fmt.Errorf(format, args...))
+}
+
+// Wrap returns an error not contained in any class. It just associates a stack
+// trace with the error. Wrap returns nil if err is nil.
+func Wrap(err error) error {
+ return (*Class).create(nil, 3, err)
+}
+
+// WrapP stores into the error pointer if it contains a non-nil error an error not
+// contained in any class. It just associates a stack trace with the error. WrapP
+// does nothing if the pointer or pointed at error is nil.
+func WrapP(err *error) {
+ if err != nil && *err != nil {
+ *err = (*Class).create(nil, 3, *err)
+ }
+}
+
+// Often, we call Unwrap as much as possible. Since comparing arbitrary
+// interfaces with equality isn't panic safe, we only loop up to 100
+// times to ensure that a poor implementation that causes a cycle does
+// not run forever.
+const maxUnwrap = 100
+
+// Unwrap returns the final, most underlying error, if any, or just the error.
+//
+// Deprecated: Prefer errors.Is() and errors.As().
+func Unwrap(err error) error {
+ for i := 0; err != nil && i < maxUnwrap; i++ {
+ var nerr error
+
+ switch e := err.(type) {
+ case Causer:
+ nerr = e.Cause()
+
+ case interface{ Unwrap() error }:
+ nerr = e.Unwrap()
+
+ case interface{ Ungroup() []error }:
+ // consider the first error to be the "main" error.
+ errs := e.Ungroup()
+ if len(errs) > 0 {
+ nerr = errs[0]
+ }
+ case interface{ Unwrap() []error }:
+ // consider the first error to be the "main" error.
+ errs := e.Unwrap()
+ if len(errs) > 0 {
+ nerr = errs[0]
+ }
+ }
+
+ if nerr == nil {
+ return err
+ }
+ err = nerr
+ }
+
+ return err
+}
+
+// Classes returns all the classes that have wrapped the error.
+func Classes(err error) (classes []*Class) {
+ IsFunc(err, func(err error) bool {
+ if e, ok := err.(*errorT); ok {
+ classes = append(classes, e.class)
+ }
+ return false
+ })
+ return classes
+}
+
+// IsFunc checks if any of the underlying errors matches the func
+func IsFunc(err error, is func(err error) bool) bool {
+ for {
+ if is(err) {
+ return true
+ }
+
+ switch u := err.(type) {
+ case interface{ Unwrap() error }:
+ err = u.Unwrap()
+ case Causer:
+ err = u.Cause()
+
+ case interface{ Ungroup() []error }:
+ for _, err := range u.Ungroup() {
+ if IsFunc(err, is) {
+ return true
+ }
+ }
+ return false
+ case interface{ Unwrap() []error }:
+ for _, err := range u.Unwrap() {
+ if IsFunc(err, is) {
+ return true
+ }
+ }
+ return false
+
+ default:
+ return false
+ }
+ }
+}
+
+//
+// error classes
+//
+
+// Class represents a class of errors. You can construct errors, and check if
+// errors are part of the class.
+type Class string
+
+// Has returns true if the passed in error (or any error wrapped by it) has
+// this class.
+func (c *Class) Has(err error) bool {
+ return IsFunc(err, func(err error) bool {
+ errt, ok := err.(*errorT)
+ return ok && errt.class == c
+ })
+}
+
+// New constructs an error with the format string that will be contained by
+// this class. This is the same as calling Wrap(fmt.Errorf(...)).
+func (c *Class) New(format string, args ...interface{}) error {
+ return c.create(3, fmt.Errorf(format, args...))
+}
+
+// Wrap returns a new error based on the passed in error that is contained in
+// this class. Wrap returns nil if err is nil.
+func (c *Class) Wrap(err error) error {
+ return c.create(3, err)
+}
+
+// WrapP stores into the error pointer if it contains a non-nil error an error contained
+// in this class. WrapP does nothing if the pointer or pointed at error is nil.
+func (c *Class) WrapP(err *error) {
+ if err != nil && *err != nil {
+ *err = c.create(3, *err)
+ }
+}
+
+// Instance creates a class membership object which implements the error
+// interface and allows errors.Is() to check whether given errors are
+// (or contain) an instance of this class.
+//
+// This makes possible a construct like the following:
+//
+// if errors.Is(err, MyClass.Instance()) {
+// fmt.Printf("err is an instance of MyClass")
+// }
+//
+// ..without requiring the Class type to implement the error interface itself,
+// as that would open the door to sundry misunderstandings and misusage.
+func (c *Class) Instance() error {
+ return (*classMembershipChecker)(c)
+}
+
+// create constructs the error, or just adds the class to the error, keeping
+// track of the stack if it needs to construct it.
+func (c *Class) create(depth int, err error) error {
+ if err == nil {
+ return nil
+ }
+
+ var pcs []uintptr
+ if err, ok := err.(*errorT); ok {
+ if c == nil || err.class == c {
+ return err
+ }
+ pcs = err.pcs
+ }
+
+ errt := &errorT{
+ class: c,
+ err: err,
+ pcs: pcs,
+ }
+
+ if errt.pcs == nil {
+ errt.pcs = make([]uintptr, 64)
+ n := runtime.Callers(depth, errt.pcs)
+ errt.pcs = errt.pcs[:n:n]
+ }
+
+ return errt
+}
+
+type classMembershipChecker Class
+
+func (cmc *classMembershipChecker) Error() string {
+ panic("classMembershipChecker used as concrete error! don't do that")
+}
+
+//
+// errors
+//
+
+// errorT is the type of errors returned from this package.
+type errorT struct {
+ class *Class
+ err error
+ pcs []uintptr
+}
+
+var ( // ensure *errorT implements the helper interfaces.
+ _ Namer = (*errorT)(nil)
+ _ Causer = (*errorT)(nil)
+ _ error = (*errorT)(nil)
+)
+
+// Stack returns the pcs for the stack trace associated with the error.
+func (e *errorT) Stack() []uintptr { return e.pcs }
+
+// errorT implements the error interface.
+func (e *errorT) Error() string {
+ return fmt.Sprintf("%v", e)
+}
+
+// Format handles the formatting of the error. Using a "+" on the format string
+// specifier will also write the stack trace.
+func (e *errorT) Format(f fmt.State, c rune) {
+ sep := ""
+ if e.class != nil && *e.class != "" {
+ fmt.Fprintf(f, "%s", string(*e.class))
+ sep = ": "
+ }
+ if text := e.err.Error(); len(text) > 0 {
+ fmt.Fprintf(f, "%s%v", sep, text)
+ }
+ if f.Flag(int('+')) {
+ summarizeStack(f, e.pcs)
+ }
+}
+
+// Cause implements the interface wrapping errors were previously
+// expected to implement to allow getting at underlying causes.
+func (e *errorT) Cause() error {
+ return e.err
+}
+
+// Unwrap returns the immediate underlying error.
+func (e *errorT) Unwrap() error {
+ return e.err
+}
+
+// Name returns the name for the error, which is the first wrapping class.
+func (e *errorT) Name() (string, bool) {
+ if e.class == nil {
+ return "", false
+ }
+ return string(*e.class), true
+}
+
+// Is determines whether an error is an instance of the given error class.
+//
+// Use with (*Class).Instance().
+func (e *errorT) Is(err error) bool {
+ cmc, ok := err.(*classMembershipChecker)
+ return ok && e.class == (*Class)(cmc)
+}
+
+// summarizeStack writes stack line entries to the writer.
+func summarizeStack(w io.Writer, pcs []uintptr) {
+ frames := runtime.CallersFrames(pcs)
+ for {
+ frame, more := frames.Next()
+ if !more {
+ return
+ }
+ fmt.Fprintf(w, "\n\t%s:%d", frame.Function, frame.Line)
+ }
+}
diff --git a/vendor/github.com/zeebo/errs/group.go b/vendor/github.com/zeebo/errs/group.go
new file mode 100644
index 0000000..22b824a
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/group.go
@@ -0,0 +1,85 @@
+package errs
+
+import (
+ "fmt"
+ "io"
+)
+
+// Group is a list of errors.
+type Group []error
+
+// Combine combines multiple non-empty errors into a single error.
+func Combine(errs ...error) error {
+ var group Group
+ group.Add(errs...)
+ return group.Err()
+}
+
+// Add adds non-empty errors to the Group.
+func (group *Group) Add(errs ...error) {
+ for _, err := range errs {
+ if err != nil {
+ *group = append(*group, err)
+ }
+ }
+}
+
+// Err returns an error containing all of the non-nil errors.
+// If there was only one error, it will return it.
+// If there were none, it returns nil.
+func (group Group) Err() error {
+ sanitized := group.sanitize()
+ if len(sanitized) == 0 {
+ return nil
+ }
+ if len(sanitized) == 1 {
+ return sanitized[0]
+ }
+ return combinedError(sanitized)
+}
+
+// sanitize returns group that doesn't contain nil-s
+func (group Group) sanitize() Group {
+ // sanity check for non-nil errors
+ for i, err := range group {
+ if err == nil {
+ sanitized := make(Group, 0, len(group)-1)
+ sanitized = append(sanitized, group[:i]...)
+ sanitized.Add(group[i+1:]...)
+ return sanitized
+ }
+ }
+
+ return group
+}
+
+// combinedError is a list of non-empty errors
+type combinedError []error
+
+// Unwrap returns the first error.
+func (group combinedError) Unwrap() []error { return group }
+
+// Error returns error string delimited by semicolons.
+func (group combinedError) Error() string { return fmt.Sprintf("%v", group) }
+
+// Format handles the formatting of the error. Using a "+" on the format
+// string specifier will cause the errors to be formatted with "+" and
+// delimited by newlines. They are delimited by semicolons otherwise.
+func (group combinedError) Format(f fmt.State, c rune) {
+ delim := "; "
+ if f.Flag(int('+')) {
+ io.WriteString(f, "group:\n--- ")
+ delim = "\n--- "
+ }
+
+ for i, err := range group {
+ if i != 0 {
+ io.WriteString(f, delim)
+ }
+ if formatter, ok := err.(fmt.Formatter); ok {
+ formatter.Format(f, c)
+ } else {
+ fmt.Fprintf(f, "%v", err)
+ }
+ }
+}
diff --git a/vendor/github.com/zeebo/errs/is_go1.20.go b/vendor/github.com/zeebo/errs/is_go1.20.go
new file mode 100644
index 0000000..6f8799a
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/is_go1.20.go
@@ -0,0 +1,8 @@
+//go:build go1.20
+
+package errs
+
+import "errors"
+
+// Is checks if any of the underlying errors matches target
+func Is(err, target error) bool { return errors.Is(err, target) }
diff --git a/vendor/github.com/zeebo/errs/is_go_other.go b/vendor/github.com/zeebo/errs/is_go_other.go
new file mode 100644
index 0000000..92f3b5b
--- /dev/null
+++ b/vendor/github.com/zeebo/errs/is_go_other.go
@@ -0,0 +1,17 @@
+//go:build !go1.20
+// +build !go1.20
+
+package errs
+
+// Is checks if any of the underlying errors matches target
+func Is(err, target error) bool {
+ return IsFunc(err, func(err error) bool {
+ if err == target {
+ return true
+ }
+ if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
+ return true
+ }
+ return false
+ })
+}