Files
x/pkg.go
Colin Henry 54aae5f242
All checks were successful
Go / build (1.23) (push) Successful in 3m51s
big updates: tests, bug fixed, documentation. oh my
2026-01-03 15:53:50 -08:00

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,
}
}