feat: Initial
This commit is contained in:
commit
f0abca60db
26 files changed
+1112
No files matched your search
+127
@@ -0,0 +1,127 @@
|
||||
package errors
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func Wrap(err error, message string) error {
|
||||
return &UniverseErrorImpl{
|
||||
msg: message,
|
||||
cause: err,
|
||||
stack: CaptureStackIfEnabled(),
|
||||
}
|
||||
}
|
||||
|
||||
func Get[T *any](err error, field string) T {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
var uerr UniverseError
|
||||
if As(err, &uerr) {
|
||||
value := uerr.GetAny(field)
|
||||
if value, ok := value.(T); ok {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func Unwrap(err error) error {
|
||||
u, ok := err.(interface {
|
||||
Unwrap() error
|
||||
})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return u.Unwrap()
|
||||
}
|
||||
|
||||
func Is(err, target error) bool {
|
||||
if err == nil || target == nil {
|
||||
return err == target
|
||||
}
|
||||
|
||||
isComparable := reflect.TypeOf(target).Comparable()
|
||||
return is(err, target, isComparable)
|
||||
}
|
||||
|
||||
func is(err, target error, targetComparable bool) bool {
|
||||
for {
|
||||
if targetComparable && err == target {
|
||||
return true
|
||||
}
|
||||
if x, ok := err.(interface{ Is(error) bool }); ok && x.Is(target) {
|
||||
return true
|
||||
}
|
||||
switch x := err.(type) {
|
||||
case interface{ Unwrap() error }:
|
||||
err = x.Unwrap()
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, err := range x.Unwrap() {
|
||||
if is(err, target, targetComparable) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func As(err error, target any) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if target == nil {
|
||||
panic("errors: target cannot be nil")
|
||||
}
|
||||
val := reflect.ValueOf(target)
|
||||
typ := val.Type()
|
||||
if typ.Kind() != reflect.Ptr || val.IsNil() {
|
||||
panic("errors: target must be a non-nil pointer")
|
||||
}
|
||||
targetType := typ.Elem()
|
||||
if targetType.Kind() != reflect.Interface && !targetType.Implements(errorType) {
|
||||
panic("errors: *target must be interface or implement error")
|
||||
}
|
||||
return as(err, target, val, targetType)
|
||||
}
|
||||
|
||||
func as(err error, target any, targetVal reflect.Value, targetType reflect.Type) bool {
|
||||
for {
|
||||
if reflect.TypeOf(err).AssignableTo(targetType) {
|
||||
targetVal.Elem().Set(reflect.ValueOf(err))
|
||||
return true
|
||||
}
|
||||
if x, ok := err.(interface{ As(any) bool }); ok && x.As(target) {
|
||||
return true
|
||||
}
|
||||
switch x := err.(type) {
|
||||
case interface{ Unwrap() error }:
|
||||
err = x.Unwrap()
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, err := range x.Unwrap() {
|
||||
if err == nil {
|
||||
continue
|
||||
}
|
||||
if as(err, target, targetVal, targetType) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var errorType = reflect.TypeOf((*error)(nil)).Elem()
|
||||
Reference in new issue
Block a user