package errutil import "encoding/json" // WalkFunc is a callback for WalkErrors type WalkFunc func(errcomp ErrorObject) (stop bool, err error) // WalkErrors walk from base error through all parents // return ErrorWalkLoop if detected loop func WalkErrors(base ErrorObject, walkFunc WalkFunc) (err error) { if base == nil { return } loopCheckMap := map[ErrorObject]bool{} for base != nil { if _, exist := loopCheckMap[base]; exist { return ErrorWalkLoop.New(nil) } loopCheckMap[base] = true stop, walkerr := walkFunc(base) if walkerr != nil { return walkerr } if stop { return } base = base.Parent() } return } // Length count number of ErrorObject and all parents, return -1 if error func Length(base ErrorObject) int { length := 0 if err := WalkErrors(base, func(errcomp ErrorObject) (stop bool, walkerr error) { length++ return false, nil }); err != nil { return -1 } return length } // AddParent add parent to errobj func AddParent(errobj ErrorObject, parent ErrorObject) error { if errobj == nil || parent == nil { return nil } // set parent if not exist if errobj.Parent() == nil { errobj.SetParent(parent) return nil } // find oldest parent to set base := errobj if err := WalkErrors(base.Parent(), func(errcomp ErrorObject) (stop bool, walkerr error) { // already in parent tree if errcomp == parent { base = nil return true, nil } base = errcomp return false, nil }); err != nil { return err } if base != nil { base.SetParent(parent) } return nil } // MarshalJSON marshal error to json func MarshalJSON(errobj error) ([]byte, error) { errjson, err := newJSON(1, errobj) if errjson == nil || err != nil { return []byte(""), err } return json.Marshal(errjson) }