zen/core/zerr/sequence.go

81 lines
1.7 KiB
Go
Raw Normal View History

2024-08-22 17:26:53 +07:00
package zerr
import "iter"
2024-08-26 16:24:41 +07:00
// Sequence keeps track of the sequence of errors.
2024-08-22 17:26:53 +07:00
//
// The implementation is reversed linked list.
//
2024-08-26 16:24:41 +07:00
// When wrapping errors, the wrapping error
// will be the parent of the wrapped Error
// if the wrapped Error is a zerr.Error.
2024-08-22 17:26:53 +07:00
type Sequence struct {
2024-08-26 16:24:41 +07:00
parent *Sequence
children []*Sequence
err Error
2024-08-22 17:26:53 +07:00
}
2024-08-26 16:24:41 +07:00
// WrapBy prepends the next Sequence to the current Sequence.
func (se *Sequence) WrapBy(parent *Sequence) {
parent.children = append(parent.children, se)
se.parent = parent
2024-08-22 17:26:53 +07:00
}
// Outer returns the error that wraps this Error.
// Return nil if this Error is not wrapped
// or wrapping outer is not a zerr.Error.
func (se *Sequence) Outer() Error {
2024-08-26 16:24:41 +07:00
if se.parent != nil {
return se.parent.err
2024-08-22 17:26:53 +07:00
}
return nil
}
// Root returns the outermost Error in the sequence.
//
// Returns self if there is no outermost.
func (se *Sequence) Root() *Sequence {
root := se
2024-08-26 16:24:41 +07:00
for root.parent != nil {
root = root.parent
2024-08-22 17:26:53 +07:00
}
return root
}
2024-08-26 16:24:41 +07:00
// IsRoot checks if the Error is the outermost Error in the sequence.
2024-08-22 17:26:53 +07:00
func (se *Sequence) IsRoot() bool {
2024-08-26 16:24:41 +07:00
return se.parent == nil
}
// Error returns the Error in the sequence.
func (se *Sequence) Error() Error {
return se.err
2024-08-22 17:26:53 +07:00
}
// Iter returns an iterator to traverse the sequence.
//
// Iterator will skip any nil values in the sequence.
//
2024-08-26 16:24:41 +07:00
// Iteration is traversed depth first.
2024-08-22 17:26:53 +07:00
//
// Example:
//
2024-08-26 16:24:41 +07:00
// for e := range err.Sequence().Iter() {
2024-08-22 17:26:53 +07:00
// // e is zerr.Error
// // do something with e
// }
func (se *Sequence) Iter() iter.Seq[Error] {
2024-08-26 16:24:41 +07:00
return func(yield func(Error) bool) {
if se.err != nil && !yield(se.err) {
return
}
for _, child := range se.children {
for e := range child.Iter() {
if !yield(e) {
2024-08-22 17:26:53 +07:00
return
}
}
}
2024-08-26 16:24:41 +07:00
}
2024-08-22 17:26:53 +07:00
}