99 lines
2.1 KiB
Go
99 lines
2.1 KiB
Go
package zerr
|
|
|
|
import "iter"
|
|
|
|
// Sequence is the implementation of zerr.Sequence.
|
|
//
|
|
// The implementation is reversed linked list.
|
|
//
|
|
// New Sequence value will be added to the start of the list.
|
|
type Sequence struct {
|
|
prev *Sequence
|
|
next *Sequence
|
|
err Error
|
|
index int
|
|
}
|
|
|
|
// Set prepends the next Sequence to the current Sequence.
|
|
func (se *Sequence) Set(next *Sequence) {
|
|
next.next = se
|
|
se.prev = next
|
|
se.index = next.index + 1
|
|
if next.next != nil {
|
|
next.next.Set(se)
|
|
}
|
|
}
|
|
|
|
// 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 {
|
|
if se.prev != nil {
|
|
return se.prev.err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Inner returns the inner zerr.Error in the sequence.
|
|
//
|
|
// if there is no inner zerr.Error, it returns nil.
|
|
//
|
|
// if the inner error is not a zerr.Error, this returns nil.
|
|
func (se *Sequence) Inner() Error {
|
|
if se.next != nil {
|
|
return se.next.err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Index returns the index of this Error in the sequence.
|
|
func (se *Sequence) Index() int {
|
|
return se.index
|
|
}
|
|
|
|
// Root returns the outermost Error in the sequence.
|
|
//
|
|
// Returns self if there is no outermost.
|
|
func (se *Sequence) Root() *Sequence {
|
|
root := se
|
|
for root.prev != nil {
|
|
root = root.prev
|
|
}
|
|
return root
|
|
}
|
|
|
|
func (se *Sequence) IsRoot() bool {
|
|
return se.prev == nil
|
|
}
|
|
|
|
// Iter returns an iterator to traverse the sequence.
|
|
//
|
|
// The iterator will start from outermost zerr.Error (root) to the last zerr.Error
|
|
// in depth-first order.
|
|
//
|
|
// Iterator will skip any nil values in the sequence.
|
|
//
|
|
// Iterator does not guarantee idempotent behavior.
|
|
// Next call to iterator may start from different root
|
|
// because the parent in the tree may be wrapped
|
|
// by another zerr.Error.
|
|
//
|
|
// Example:
|
|
//
|
|
// for _, e := range err.Sequence().Iter() {
|
|
// // e is zerr.Error
|
|
// // do something with e
|
|
// }
|
|
func (se *Sequence) Iter() iter.Seq[Error] {
|
|
root := se.Root()
|
|
return iter.Seq[Error](func(yield func(V Error) bool) {
|
|
for next := root; next != nil; next = next.next {
|
|
if next.err != nil {
|
|
if !yield(next.err) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|