102 lines
2.3 KiB
Go
102 lines
2.3 KiB
Go
// Package x provides common utility functions for error handling and assertions.
|
|
package x
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"runtime"
|
|
)
|
|
|
|
// Assert evaluates a condition and if it fails, panics with the given message.
|
|
func Assert(cond bool, msg string) {
|
|
if !cond {
|
|
panic(errors.New(msg))
|
|
}
|
|
}
|
|
|
|
// Check evaluates a condition, adds an error to its list and continues.
|
|
// Returns an I interface that can be used to chain multiple checks.
|
|
func Check(cond bool, err error) I {
|
|
return new(invariants).Check(cond, err)
|
|
}
|
|
|
|
// I is an interface for chaining multiple condition checks and collecting errors.
|
|
type I interface {
|
|
// Check evaluates a condition and adds an error to the list if false
|
|
Check(cond bool, err error) I
|
|
// Join returns a single error wrapping all collected errors
|
|
Join() error
|
|
// First returns the first error encountered
|
|
First() error
|
|
// All returns all collected errors as a slice
|
|
All() []error
|
|
}
|
|
|
|
type invariants struct {
|
|
errs []error
|
|
}
|
|
|
|
// Check evaluates a condition, adds an error to its list and continues
|
|
func (i *invariants) Check(cond bool, err error) I {
|
|
if !cond {
|
|
i.errs = append(i.errs, err)
|
|
}
|
|
return i
|
|
}
|
|
|
|
// Join returns a single error wrapping all errors that have been collected by the checks.
|
|
func (i *invariants) Join() error {
|
|
return errors.Join(i.errs...)
|
|
}
|
|
|
|
// First returns the first error found by the checks, or nil if no errors were found.
|
|
func (i *invariants) First() error {
|
|
if len(i.errs) > 0 {
|
|
return i.errs[0]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// All returns all errors found by the checks as a slice.
|
|
func (i *invariants) All() []error {
|
|
return i.errs
|
|
}
|
|
|
|
type xError struct {
|
|
LineNo int
|
|
File string
|
|
E error
|
|
Debug bool
|
|
}
|
|
|
|
func (e *xError) Error() string {
|
|
if e.Debug {
|
|
return fmt.Sprintf(
|
|
"%s\n\t%s:%d", e.E, e.File, e.LineNo,
|
|
)
|
|
}
|
|
return e.E.Error()
|
|
}
|
|
|
|
func (e *xError) Unwrap() error {
|
|
return e.E
|
|
}
|
|
|
|
// NewError returns an error that wraps an error and optionally provides the file and line number where the error occurred.
|
|
// If debug is true, the error message will include file and line information.
|
|
func NewError(unwrapped error, debug bool) error {
|
|
_, file, line, ok := runtime.Caller(1)
|
|
|
|
if !ok {
|
|
file = "unknown"
|
|
line = 0
|
|
}
|
|
|
|
return &xError{
|
|
LineNo: line,
|
|
File: file,
|
|
E: unwrapped,
|
|
Debug: debug,
|
|
}
|
|
}
|