You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
4.6 KiB
193 lines
4.6 KiB
package errs
|
|
|
|
import (
|
|
"core/errs/stack"
|
|
"fmt"
|
|
"regexp"
|
|
)
|
|
|
|
const (
|
|
// errCodePattern is the regular expression that defines a valid error code format.
|
|
// The error code can optionally have a module, which is separated by "::".
|
|
// The valid characters are alphanumeric characters and the symbols ":-_".
|
|
errCodePattern string = "^[a-zA-Z0-9._-]+(::[a-zA-Z0-9._-]+)?$"
|
|
)
|
|
|
|
const (
|
|
// ModuleSeparator is the separator used between the module and value parts of the error code.
|
|
ModuleSeparator string = "::"
|
|
)
|
|
|
|
// Module configuration
|
|
const moduleName = "core.errs" + ModuleSeparator
|
|
|
|
// Error messages for internal use
|
|
const (
|
|
errNilWrapMsg string = "error trying to wrap % into a nil error"
|
|
errNilCauseMsg string = "error trying to wrap % into a nil cause"
|
|
)
|
|
|
|
// Standard error codes for common error scenarios
|
|
const (
|
|
CodePanicError string = "panic"
|
|
CodeMultiError string = "multiple-errors"
|
|
CodeParamError string = "Param"
|
|
CodeParamNilError string = "Param-nil"
|
|
CodeParamOutOfRangeError string = "Param-out-of-range"
|
|
)
|
|
|
|
// G provides a global access point for common errors and information
|
|
// This struct combines documentation links and pre-initialized error instances
|
|
var (
|
|
G = struct {
|
|
InfoHelp,
|
|
InfoLink string
|
|
|
|
ErrParam,
|
|
ErrParamNil,
|
|
ErrParamOutOfRange,
|
|
ErrInvalidError,
|
|
ErrInvalidNilError,
|
|
ErrUnknownPanicError,
|
|
ErrInvalidErrCode ErrCode
|
|
}{
|
|
InfoLink: "https://git.activething.com/go/active",
|
|
InfoHelp: "https://doc.activething.com/go/active",
|
|
|
|
ErrParam: ErrCode(CodeParamError),
|
|
ErrParamNil: ErrCode(CodeParamNilError),
|
|
ErrParamOutOfRange: ErrCode(CodeParamOutOfRangeError),
|
|
ErrUnknownPanicError: ErrCode(moduleName + "unknown-panic-error"),
|
|
ErrInvalidNilError: ErrCode(moduleName + "invalid-nil-error"),
|
|
ErrInvalidError: ErrCode(moduleName + "invalid-error"),
|
|
ErrInvalidErrCode: ErrCode(moduleName + "invalid-err-code"),
|
|
}
|
|
|
|
// g contains private package-level variables
|
|
g = struct {
|
|
panicErrNil *ErrPanic
|
|
|
|
codeValidator *regexp.Regexp
|
|
}{
|
|
|
|
panicErrNil: NewErrPanic(G.ErrInvalidNilError),
|
|
|
|
codeValidator: regexp.MustCompile(errCodePattern),
|
|
}
|
|
)
|
|
|
|
// ToError converts any value to an error type
|
|
// Returns nil if the input is nil
|
|
// Converts []error to ErrMulti
|
|
// Uses fmt.Errorf for other types
|
|
func ToError(err any) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
switch e := err.(type) {
|
|
case error:
|
|
return e
|
|
case []error:
|
|
if len(e) == 0 {
|
|
return nil
|
|
}
|
|
return NewErrMulti(e...)
|
|
default:
|
|
return fmt.Errorf("%v", err)
|
|
}
|
|
}
|
|
|
|
// PanicRecoveredError creates an error from a recovered panic value
|
|
// Returns nil if the recovered value is nil
|
|
func PanicRecoveredError(rec any) error {
|
|
if rec == nil {
|
|
return nil
|
|
}
|
|
return *NewErrPanic(ToError(rec))
|
|
}
|
|
|
|
// Unwrap provides standard error unwrapping functionality
|
|
// Implements the unwrap interface for error chains
|
|
func Unwrap(err error) error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if cs, is := err.(Unwrapper); is {
|
|
return cs.Unwrap()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UnwrapCause retrieves the root cause of an error chain
|
|
// Traverses the error chain looking for Causer implementation
|
|
func UnwrapCause(err error) error {
|
|
e := err
|
|
for e != nil {
|
|
cs, is := e.(Causer)
|
|
if is {
|
|
return cs.Cause()
|
|
}
|
|
e = Unwrap(e)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UnwrapCauses retrieves all causes in an error chain
|
|
// Returns a slice of errors representing the cause chain
|
|
func UnwrapCauses(err error) []error {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if al, is := err.(Causers); is {
|
|
return al.Causes()
|
|
}
|
|
var l ErrorList
|
|
e := err
|
|
for e != nil {
|
|
l = append(l, e)
|
|
e = Unwrap(e)
|
|
}
|
|
return l
|
|
}
|
|
|
|
// UnwrapList retrieves all errors in an error chain as an ErrorList
|
|
// Handles both UnwrapperList implementations and standard error chains
|
|
func UnwrapList(err error) ErrorList {
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if al, is := err.(UnwrapperList); is {
|
|
return al.Unwrap()
|
|
}
|
|
var l ErrorList
|
|
e := err
|
|
for e != nil {
|
|
l = append(l, e)
|
|
e = Unwrap(e)
|
|
}
|
|
return l
|
|
}
|
|
|
|
// UnwrapTrace retrieves the stack trace from an error
|
|
func UnwrapTrace(err error) stack.Stack {
|
|
return stack.UnwrapStack(err, false)
|
|
}
|
|
|
|
// WrapError combines two errors into a single error, establishing a cause relationship.
|
|
// If either error is nil, the non-nil error is returned.
|
|
// Otherwise, a new error is returned that has the first error as the cause.
|
|
func WrapError(err, cause error) error {
|
|
if err == nil {
|
|
return cause
|
|
}
|
|
if cause == nil {
|
|
return err
|
|
}
|
|
return *NewErrWithCause(err, cause)
|
|
}
|
|
|
|
// ValidateCode check if un err code is valid
|
|
func ValidateCode(code string) bool {
|
|
return g.codeValidator.MatchString(code)
|
|
}
|