import (
"errors"
+ "fmt"
)
type Action string
return Action(string(t) + child)
}
+func (t Action) New(reason ...string) (e Error) {
+ e = Error{
+ action: t,
+ Reason: string(t),
+ }
+ if len(reason) > 0 {
+ e.Reason = reason[0]
+ }
+ return
+}
+
type Error struct {
son error
Reason string
action Action
}
+func (t Error) Is(e error) bool {
+ fmt.Println(t, e)
+ return t.Error() == e.Error()
+}
+
func (t Error) Error() string {
return t.Reason
}
+func (t Error) Unwrap() error {
+ return nil
+}
+
func (t Error) WithReason(reason string) Error {
t.Reason = reason
return t
if v, ok := e.(Error); ok {
if v.action == action {
return true
- } else if v.son != nil {
- return Catch((v.son).(Error), action)
}
}
- return false
-}
-
-// Grow will append e to fe
-func Append(fe Error, e error) Error {
- if v, ok := e.(Error); ok {
- fe.son = v
- } else {
- fe.son = Error{
- Reason: e.Error(),
+ for _, err := range Unwrap(e) {
+ if v, ok := err.(Error); ok {
+ if v.action == action {
+ return true
+ }
}
}
- return fe
+ return false
}
func New(reason string, action ...Action) (e Error) {
var errs []error
for _, v := range e {
- if e, ok := v.(interface {
- Unwrap() []error
- }); ok {
- errs = append(errs, e.Unwrap()...)
- } else {
+ switch x := v.(type) {
+ case interface{ Unwrap() []error }:
+ errs = append(errs, x.Unwrap()...)
+ default:
errs = append(errs, v)
}
}
return []error{}
}
- if e, ok := e.(interface {
- Unwrap() []error
- }); ok {
- return e.Unwrap()
+ switch x := e.(type) {
+ case interface{ Unwrap() error }:
+ return []error{x.Unwrap()}
+ case interface{ Unwrap() []error }:
+ return x.Unwrap()
+ default:
}
return []error{errors.Unwrap(e)}
return e.Error() + "\n"
}
ErrActionSimplifyFunc ErrFormat = func(e error) string {
- if err, ok := e.(Error); ok {
+ if err, ok := e.(Error); ok && string(err.action) != err.Reason {
return string(err.action) + ":" + e.Error() + "\n"
} else {
return e.Error() + "\n"
return "> " + e.Error() + " "
}
ErrActionInLineFunc ErrFormat = func(e error) string {
- if err, ok := e.(Error); ok {
+ if err, ok := e.(Error); ok && string(err.action) != err.Reason {
return "> " + string(err.action) + ":" + e.Error() + " "
} else {
return "> " + e.Error() + " "
import (
"errors"
"io"
+ "os"
"testing"
)
t.Fail()
}
- err = Append(New("r1", a11), err)
+ err = Join(New("r1", a11), err)
if !Catch(err, a11) {
t.Fail()
}
func TestXxx2(t *testing.T) {
- err := Append(New("r1", a1), io.EOF)
+ err := Join(New("r1", a1), io.EOF)
if !Catch(err, a1) {
t.Fatal()
}
t.Fatal()
}
}
+
+func Test4(t *testing.T) {
+ var Action1 Action = `Action1`
+ e := Join(os.ErrClosed, Action1.New(), os.ErrDeadlineExceeded)
+ for _, v := range Unwrap(e) {
+ t.Log(v)
+ }
+ if !Catch(e, Action1) {
+ t.Fatal()
+ }
+ if Catch(e, a1) {
+ t.Fatal()
+ }
+ if !errors.Is(e, Action1.New()) {
+ t.Fatal()
+ }
+ if !errors.Is(e, os.ErrClosed) {
+ t.Fatal()
+ }
+ if errors.Is(e, io.EOF) {
+ t.Fatal()
+ }
+ t.Log(ErrorFormat(e, ErrActionInLineFunc))
+}
gzip "compress/gzip"
br "github.com/qydysky/brotli"
+ pe "github.com/qydysky/part/errors"
pio "github.com/qydysky/part/io"
s "github.com/qydysky/part/strings"
// "encoding/binary"
)
var (
- ErrEmptyUrl = errors.New("ErrEmptyUrl")
- ErrCantRetry = errors.New("ErrCantRetry")
- ErrNewRequest = errors.New("ErrNewRequest")
- ErrClientDo = errors.New("ErrClientDo")
- ErrResponFileCreate = errors.New("ErrResponFileCreate")
- ErrWriteRes = errors.New("ErrWriteRes")
- ErrReadRes = errors.New("ErrReadRes")
- ErrPostStrOrRawPipe = errors.New("ErrPostStrOrRawPipe")
- ErrNoDate = errors.New("ErrNoDate")
+ ErrEmptyUrl = pe.Action("ErrEmptyUrl")
+ ErrCantRetry = pe.Action("ErrCantRetry")
+ ErrNewRequest = pe.Action("ErrNewRequest")
+ ErrClientDo = pe.Action("ErrClientDo")
+ ErrResponFileCreate = pe.Action("ErrResponFileCreate")
+ ErrWriteRes = pe.Action("ErrWriteRes")
+ ErrReadRes = pe.Action("ErrReadRes")
+ ErrPostStrOrRawPipe = pe.Action("ErrPostStrOrRawPipe")
+ ErrNoDate = pe.Action("ErrNoDate")
)
type Req struct {
}
if val.Url == "" {
- return ErrEmptyUrl
+ return ErrEmptyUrl.New()
}
var body io.Reader
if len(val.PostStr) > 0 && val.RawPipe != nil {
- return ErrPostStrOrRawPipe
+ return ErrPostStrOrRawPipe.New()
}
if val.Retry != 0 && val.RawPipe != nil {
- return ErrCantRetry
+ return ErrCantRetry.New()
}
if val.RawPipe != nil {
body = val.RawPipe
req, e := http.NewRequestWithContext(ctx, val.Method, val.Url, body)
if e != nil {
- return errors.Join(ErrNewRequest, e)
+ return pe.Join(ErrNewRequest.New(), e)
}
for _, v := range val.Cookies {
resp, e := client.Do(req)
if e != nil {
- return errors.Join(ErrClientDo, e)
+ return pe.Join(ErrClientDo.New(), e)
}
if v, ok := Header["Connection"]; ok && strings.ToLower(v) != "keep-alive" {
t.responFile, e = os.Create(val.SaveToPath)
if e != nil {
t.responFile.Close()
- return errors.Join(err, ErrResponFileCreate, e)
+ return pe.Join(err, ErrResponFileCreate.New(), e)
}
ws = append(ws, t.responFile)
}
t.copyResBuf[:],
time.Duration(int(time.Millisecond)*writeLoopTO), io.MultiWriter(ws...),
resReadCloser,
- func(s string) { errChan <- errors.New(s) },
+ func(s string) { errChan <- pe.New(s) },
)
for len(errChan) > 0 {
- err = errors.Join(err, <-errChan)
+ err = pe.Join(err, <-errChan)
}
if t.responBuf != nil {
if date := res.Header.Get("date"); date != `` {
return time.Parse(time.RFC1123, date)
} else {
- return time.Time{}, ErrNoDate
+ return time.Time{}, ErrNoDate.New()
}
}