Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

errs.gno

2.66 Kb · 111 lines
  1// Package errs provides utilities for combining multiple errors.
  2// This is a simplified version of https://github.com/uber-go/multierr (MIT License),
  3// adapted for the Gno programming language with a focus on core functionality
  4// and idiomatic usage patterns.
  5//
  6// Example usage:
  7//
  8//	err1 := doSomething()
  9//	err2 := doSomethingElse()
 10//	if err := errs.Combine(err1, err2); err != nil {
 11//	    return err // Returns combined errors or single error
 12//	}
 13package errs
 14
 15import (
 16	"strings"
 17)
 18
 19// multiError represents multiple errors combined into one.
 20type multiError struct {
 21	errors []error
 22}
 23
 24// Error implements the error interface by returning a single-line representation
 25// of all contained errors, separated by semicolons.
 26func (m *multiError) Error() string {
 27	if m == nil || len(m.errors) == 0 {
 28		return ""
 29	}
 30
 31	var b strings.Builder
 32	first := true
 33	for _, err := range m.errors {
 34		if first {
 35			first = false
 36		} else {
 37			b.WriteString("; ")
 38		}
 39		b.WriteString(err.Error())
 40	}
 41	return b.String()
 42}
 43
 44// String returns a multi-line representation of the error.
 45func (m *multiError) String() string {
 46	if m == nil || len(m.errors) == 0 {
 47		return ""
 48	}
 49
 50	var b strings.Builder
 51	b.WriteString("the following errors occurred:")
 52	for _, err := range m.errors {
 53		b.WriteString("\n -  ")
 54		b.WriteString(err.Error())
 55	}
 56	return b.String()
 57}
 58
 59// Unwrap returns the slice of underlying errors contained in this multiError.
 60// Returns nil if the receiver is nil.
 61func (m *multiError) Unwrap() []error {
 62	if m == nil {
 63		return nil
 64	}
 65	return m.errors
 66}
 67
 68// Errors extracts the underlying errors from an error interface.
 69// If the error is a multiError, it returns its contained errors.
 70// If the error is nil, returns nil.
 71// If the error is a regular error, returns a slice containing just that error.
 72func Errors(err error) []error {
 73	if err == nil {
 74		return nil
 75	}
 76
 77	if merr, ok := err.(*multiError); ok {
 78		return merr.Unwrap()
 79	}
 80
 81	return []error{err}
 82}
 83
 84// Combine merges multiple errors into a single error efficiently.
 85// It handles several cases:
 86//   - If all input errors are nil, returns nil
 87//   - If there's exactly one non-nil error, returns that error directly
 88//   - If there are multiple non-nil errors, returns a multiError containing them
 89//   - Flattens any *multiError in the input
 90func Combine(errs ...error) error {
 91	nonNil := make([]error, 0, len(errs))
 92	for _, err := range errs {
 93		if err == nil {
 94			continue
 95		}
 96		if m, ok := err.(*multiError); ok && m != nil {
 97			nonNil = append(nonNil, m.Unwrap()...)
 98		} else {
 99			nonNil = append(nonNil, err)
100		}
101	}
102
103	switch len(nonNil) {
104	case 0:
105		return nil
106	case 1:
107		return nonNil[0]
108	default:
109		return &multiError{errors: nonNil}
110	}
111}