mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
143 lines
3.2 KiB
Go
143 lines
3.2 KiB
Go
// Package errors wraps pkg/errors and includes some custom features such as
|
|
// error codes.
|
|
package errors
|
|
|
|
import (
|
|
"encoding/json"
|
|
"io"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
// Code is an error code which can be used to check against a given error. For
|
|
// example, see the Is() method.
|
|
type Code string
|
|
|
|
var CodeTODO Code = "TODOError"
|
|
|
|
func New(code Code, message string) error {
|
|
return errors.WithStack(codedError{
|
|
Code: code,
|
|
Message: message,
|
|
})
|
|
}
|
|
|
|
func As(err error, target interface{}) bool {
|
|
return errors.As(err, target)
|
|
}
|
|
|
|
func Cause(err error) error {
|
|
return errors.Cause(err)
|
|
}
|
|
|
|
func Errorf(format string, args ...interface{}) error {
|
|
return errors.Errorf(format, args...)
|
|
}
|
|
|
|
// Is is a fork of the Is() method from `pkg/errors` which takes as its target
|
|
// an error Code instead of an error.
|
|
func Is(err error, target Code) bool {
|
|
match := codedError{
|
|
Code: target,
|
|
}
|
|
return errors.Is(err, match)
|
|
}
|
|
|
|
func Unwrap(err error) error {
|
|
return errors.Unwrap(err)
|
|
}
|
|
|
|
func WithMessage(err error, message string) error {
|
|
return errors.WithMessage(err, message)
|
|
}
|
|
|
|
func WithMessagef(err error, format string, args ...interface{}) error {
|
|
return errors.WithMessagef(err, format, args...)
|
|
}
|
|
|
|
func WithStack(err error) error {
|
|
return errors.WithStack(err)
|
|
}
|
|
|
|
func Wrap(err error, message string) error {
|
|
return errors.Wrap(err, message)
|
|
}
|
|
|
|
func Wrapf(err error, fmt string, args ...interface{}) error {
|
|
return errors.Wrapf(err, fmt, args...)
|
|
}
|
|
|
|
// codedError is the fundamental type used by this package to provide coded
|
|
// errors.
|
|
type codedError struct {
|
|
Code Code `json:"code"`
|
|
Message string `json:"message"`
|
|
Wrapped string `json:"wrapped,omitempty"`
|
|
}
|
|
|
|
func (ce codedError) Error() string {
|
|
if ce.Wrapped != "" {
|
|
return ce.Wrapped
|
|
}
|
|
return ce.Message
|
|
}
|
|
|
|
// func (ce codedError) As(target interface{}) bool {
|
|
// return false
|
|
// }
|
|
|
|
func (ce codedError) Is(err error) bool {
|
|
if e, ok := err.(codedError); ok && ce.Code == e.Code {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
const (
|
|
ErrUncoded Code = "Uncoded"
|
|
)
|
|
|
|
// MarshalJSON returns the provided error as a json object (as a string)
|
|
// representing a codedError. If err is not already a codedError, the json
|
|
// object will still represent a codedError but its `code` value will be empty.
|
|
// Note: an empty code here is intentional and is different from code
|
|
// `errors.Uncoded` which is a valid code; it just means the developer returned
|
|
// a codedError but didn't bother to choose (or create) a useful error code.
|
|
func MarshalJSON(err error) string {
|
|
cause := Cause(err)
|
|
|
|
var out *codedError
|
|
|
|
switch v := cause.(type) {
|
|
case codedError:
|
|
v.Wrapped = err.Error()
|
|
out = &v
|
|
default:
|
|
out = &codedError{
|
|
Message: cause.Error(),
|
|
Wrapped: err.Error(),
|
|
}
|
|
}
|
|
|
|
// Marshal the codedError to json as output.
|
|
j, jerr := json.Marshal(out)
|
|
if jerr != nil {
|
|
return out.Error()
|
|
}
|
|
|
|
return string(j)
|
|
|
|
}
|
|
|
|
// UnmarshalJSON converts the byte slice into a codedError. If the bytes can't
|
|
// unmarshal to a codedError, a normal error will be returned containing the
|
|
// string value of the byte slice.
|
|
func UnmarshalJSON(r io.Reader) error {
|
|
b, _ := io.ReadAll(r)
|
|
|
|
out := &codedError{}
|
|
if err := json.Unmarshal(b, out); err != nil {
|
|
return errors.New(string(b))
|
|
}
|
|
return out
|
|
}
|