mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-04 12:10:21 -05:00
82 lines
1.9 KiB
Go
82 lines
1.9 KiB
Go
package wait
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
)
|
|
|
|
var (
|
|
// ErrVisitStop is used as a return value from [VisitFunc] to stop the walk.
|
|
// It is not returned as an error by any function.
|
|
ErrVisitStop = errors.New("stop the walk")
|
|
|
|
// Deprecated: use [ErrVisitStop] instead.
|
|
VisitStop = ErrVisitStop
|
|
|
|
// ErrVisitRemove is used as a return value from [VisitFunc] to have the current node removed.
|
|
// It is not returned as an error by any function.
|
|
ErrVisitRemove = errors.New("remove this strategy")
|
|
|
|
// Deprecated: use [ErrVisitRemove] instead.
|
|
VisitRemove = ErrVisitRemove
|
|
)
|
|
|
|
// VisitFunc is a function that visits a strategy node.
|
|
// If it returns [ErrVisitStop], the walk stops.
|
|
// If it returns [ErrVisitRemove], the current node is removed.
|
|
type VisitFunc func(root Strategy) error
|
|
|
|
// Walk walks the strategies tree and calls the visit function for each node.
|
|
func Walk(root *Strategy, visit VisitFunc) error {
|
|
if root == nil {
|
|
return errors.New("root strategy is nil")
|
|
}
|
|
|
|
if err := walk(root, visit); err != nil {
|
|
if errors.Is(err, ErrVisitRemove) || errors.Is(err, ErrVisitStop) {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// walk walks the strategies tree and calls the visit function for each node.
|
|
// It returns an error if the visit function returns an error.
|
|
func walk(root *Strategy, visit VisitFunc) error {
|
|
if *root == nil {
|
|
// No strategy.
|
|
return nil
|
|
}
|
|
|
|
// Allow the visit function to customize the behaviour of the walk before visiting the children.
|
|
if err := visit(*root); err != nil {
|
|
if errors.Is(err, ErrVisitRemove) {
|
|
*root = nil
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
if s, ok := (*root).(*MultiStrategy); ok {
|
|
var i int
|
|
for range s.Strategies {
|
|
if err := walk(&s.Strategies[i], visit); err != nil {
|
|
if errors.Is(err, ErrVisitRemove) {
|
|
s.Strategies = slices.Delete(s.Strategies, i, i+1)
|
|
if errors.Is(err, VisitStop) {
|
|
return VisitStop
|
|
}
|
|
continue
|
|
}
|
|
|
|
return err
|
|
}
|
|
i++
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|