package errors import ( "fmt" "reflect" ) func Wrap(err error, message string) error { return &UniverseErrorImpl{ msg: message, cause: err, stack: CaptureStackIfEnabled(), } } func Wrapf(err error, format string, args ...interface{}) error { return Wrap(err, fmt.Sprintf(format, args...)) } 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()