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