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-27 17:08:52 +07:00
|
|
|
type Sequence interface {
|
|
|
|
// WrapBy prepends the next Sequence to the current Sequence.
|
|
|
|
WrapBy(parent Sequence)
|
|
|
|
|
|
|
|
// Parent returns the parent Sequence.
|
|
|
|
// Return nil if this Sequence is Root.
|
|
|
|
Parent() Sequence
|
|
|
|
|
|
|
|
// Root returns the outermost Sequence in the sequence.
|
|
|
|
//
|
|
|
|
// Returns self if current Sequence is the outermost.
|
|
|
|
Root() Sequence
|
|
|
|
|
|
|
|
// IsRoot checks if the Sequence is the outermost Sequence in the sequence.
|
|
|
|
IsRoot() bool
|
|
|
|
|
|
|
|
// Error returns the Error in the sequence.
|
|
|
|
Error() Error
|
|
|
|
|
|
|
|
// Iter returns an iterator to traverse Errors in the sequence.
|
|
|
|
Iter() iter.Seq[Error]
|
|
|
|
|
|
|
|
// AppendChild appends a child Sequence to the current Sequence.
|
|
|
|
AppendChild(child Sequence)
|
|
|
|
}
|
|
|
|
|
|
|
|
type sequence struct {
|
|
|
|
parent Sequence
|
|
|
|
children []Sequence
|
2024-08-26 16:24:41 +07:00
|
|
|
err Error
|
2024-08-22 17:26:53 +07:00
|
|
|
}
|
|
|
|
|
2024-08-27 17:08:52 +07:00
|
|
|
func (se *sequence) WrapBy(parent Sequence) {
|
|
|
|
parent.AppendChild(se)
|
2024-08-26 16:24:41 +07:00
|
|
|
se.parent = parent
|
2024-08-22 17:26:53 +07:00
|
|
|
}
|
|
|
|
|
2024-08-27 17:08:52 +07:00
|
|
|
func (se *sequence) AppendChild(child Sequence) {
|
|
|
|
se.children = append(se.children, child)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (se *sequence) Parent() Sequence {
|
2024-08-26 16:24:41 +07:00
|
|
|
if se.parent != nil {
|
2024-08-27 17:08:52 +07:00
|
|
|
return se.parent
|
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.
|
2024-08-27 17:08:52 +07:00
|
|
|
func (se *sequence) Root() Sequence {
|
|
|
|
var root Sequence = se
|
|
|
|
for {
|
|
|
|
if root.Parent() == nil {
|
|
|
|
return root
|
|
|
|
}
|
|
|
|
root = root.Parent()
|
2024-08-22 17:26:53 +07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-26 16:24:41 +07:00
|
|
|
// IsRoot checks if the Error is the outermost Error in the sequence.
|
2024-08-27 17:08:52 +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.
|
2024-08-27 17:08:52 +07:00
|
|
|
func (se *sequence) Error() Error {
|
2024-08-26 16:24:41 +07:00
|
|
|
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
|
|
|
|
// }
|
2024-08-27 17:08:52 +07:00
|
|
|
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
|
|
|
}
|