Compare commits
	
		
			4 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 87a004e577 | |||
| 376c6cab50 | |||
| 4a3f25baa0 | |||
| aa33bc8df3 | 
| @@ -7,6 +7,9 @@ type SyncSet[TData comparable] struct { | ||||
| 	lock sync.Mutex | ||||
| } | ||||
|  | ||||
| // Add adds `value` to the set | ||||
| // returns true  if the value was actually inserted | ||||
| // returns false if the value already existed | ||||
| func (s *SyncSet[TData]) Add(value TData) bool { | ||||
| 	s.lock.Lock() | ||||
| 	defer s.lock.Unlock() | ||||
| @@ -15,10 +18,10 @@ func (s *SyncSet[TData]) Add(value TData) bool { | ||||
| 		s.data = make(map[TData]bool) | ||||
| 	} | ||||
|  | ||||
| 	_, ok := s.data[value] | ||||
| 	_, existsInPreState := s.data[value] | ||||
| 	s.data[value] = true | ||||
|  | ||||
| 	return !ok | ||||
| 	return !existsInPreState | ||||
| } | ||||
|  | ||||
| func (s *SyncSet[TData]) AddAll(values []TData) { | ||||
|   | ||||
| @@ -270,8 +270,12 @@ func (b *Builder) Any(key string, val any) *Builder { | ||||
| } | ||||
|  | ||||
| func (b *Builder) Stringer(key string, val fmt.Stringer) *Builder { | ||||
| 	if val == nil { | ||||
| 		return b.addMeta(key, MDTString, "(!nil)") | ||||
| 	} else { | ||||
| 		return b.addMeta(key, MDTString, val.String()) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (b *Builder) Stack() *Builder { | ||||
| 	return b.addMeta("@Stack", MDTString, string(debug.Stack())) | ||||
|   | ||||
| @@ -27,6 +27,7 @@ func FromError(err error) *ExErr { | ||||
| 		StatusCode:     nil, | ||||
| 		Message:        err.Error(), | ||||
| 		WrappedErrType: fmt.Sprintf("%T", err), | ||||
| 		WrappedErr:     err, | ||||
| 		Caller:         "", | ||||
| 		OriginalError:  nil, | ||||
| 		Meta:           getForeignMeta(err), | ||||
| @@ -43,6 +44,7 @@ func newExErr(cat ErrorCategory, errtype ErrorType, msg string) *ExErr { | ||||
| 		StatusCode:     nil, | ||||
| 		Message:        msg, | ||||
| 		WrappedErrType: "", | ||||
| 		WrappedErr:     nil, | ||||
| 		Caller:         callername(2), | ||||
| 		OriginalError:  nil, | ||||
| 		Meta:           make(map[string]MetaValue), | ||||
| @@ -59,6 +61,7 @@ func wrapExErr(e *ExErr, msg string, cat ErrorCategory, stacktraceskip int) *ExE | ||||
| 		StatusCode:     e.StatusCode, | ||||
| 		Message:        msg, | ||||
| 		WrappedErrType: "", | ||||
| 		WrappedErr:     nil, | ||||
| 		Caller:         callername(1 + stacktraceskip), | ||||
| 		OriginalError:  e, | ||||
| 		Meta:           make(map[string]MetaValue), | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package exerr | ||||
|  | ||||
| import ( | ||||
| 	"gogs.mikescher.com/BlackForestBytes/goext/dataext" | ||||
| 	"gogs.mikescher.com/BlackForestBytes/goext/langext" | ||||
| ) | ||||
|  | ||||
| @@ -37,25 +38,32 @@ type ErrorType struct { | ||||
|  | ||||
| //goland:noinspection GoUnusedGlobalVariable | ||||
| var ( | ||||
| 	TypeInternal       = ErrorType{"INTERNAL_ERROR", langext.Ptr(500)} | ||||
| 	TypePanic          = ErrorType{"PANIC", langext.Ptr(500)} | ||||
| 	TypeNotImplemented = ErrorType{"NOT_IMPLEMENTED", langext.Ptr(500)} | ||||
| 	TypeInternal       = NewType("INTERNAL_ERROR", langext.Ptr(500)) | ||||
| 	TypePanic          = NewType("PANIC", langext.Ptr(500)) | ||||
| 	TypeNotImplemented = NewType("NOT_IMPLEMENTED", langext.Ptr(500)) | ||||
|  | ||||
| 	TypeWrap = ErrorType{"Wrap", nil} | ||||
| 	TypeWrap = NewType("Wrap", nil) | ||||
|  | ||||
| 	TypeBindFailURI      = ErrorType{"BINDFAIL_URI", langext.Ptr(400)} | ||||
| 	TypeBindFailQuery    = ErrorType{"BINDFAIL_QUERY", langext.Ptr(400)} | ||||
| 	TypeBindFailJSON     = ErrorType{"BINDFAIL_JSON", langext.Ptr(400)} | ||||
| 	TypeBindFailFormData = ErrorType{"BINDFAIL_FORMDATA", langext.Ptr(400)} | ||||
| 	TypeBindFailHeader   = ErrorType{"BINDFAIL_HEADER", langext.Ptr(400)} | ||||
| 	TypeBindFailURI      = NewType("BINDFAIL_URI", langext.Ptr(400)) | ||||
| 	TypeBindFailQuery    = NewType("BINDFAIL_QUERY", langext.Ptr(400)) | ||||
| 	TypeBindFailJSON     = NewType("BINDFAIL_JSON", langext.Ptr(400)) | ||||
| 	TypeBindFailFormData = NewType("BINDFAIL_FORMDATA", langext.Ptr(400)) | ||||
| 	TypeBindFailHeader   = NewType("BINDFAIL_HEADER", langext.Ptr(400)) | ||||
|  | ||||
| 	TypeUnauthorized = ErrorType{"UNAUTHORIZED", langext.Ptr(401)} | ||||
| 	TypeAuthFailed   = ErrorType{"AUTH_FAILED", langext.Ptr(401)} | ||||
| 	TypeUnauthorized = NewType("UNAUTHORIZED", langext.Ptr(401)) | ||||
| 	TypeAuthFailed   = NewType("AUTH_FAILED", langext.Ptr(401)) | ||||
|  | ||||
| 	// other values come from pkgconfig | ||||
| ) | ||||
|  | ||||
| var registeredTypes = dataext.SyncSet[string]{} | ||||
|  | ||||
| func NewType(key string, defStatusCode *int) ErrorType { | ||||
| 	insertOkay := registeredTypes.Add(key) | ||||
| 	if !insertOkay { | ||||
| 		panic("Cannot register same ErrType ('" + key + "') more than once") | ||||
| 	} | ||||
|  | ||||
| 	return ErrorType{key, defStatusCode} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import ( | ||||
| 	"github.com/rs/xid" | ||||
| 	"github.com/rs/zerolog" | ||||
| 	"gogs.mikescher.com/BlackForestBytes/goext/langext" | ||||
| 	"reflect" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| ) | ||||
| @@ -20,6 +21,7 @@ type ExErr struct { | ||||
|  | ||||
| 	Message        string `json:"message"` | ||||
| 	WrappedErrType string `json:"wrappedErrType"` | ||||
| 	WrappedErr     any    `json:"-"` | ||||
| 	Caller         string `json:"caller"` | ||||
|  | ||||
| 	OriginalError *ExErr `json:"originalError"` | ||||
| @@ -33,6 +35,9 @@ func (ee *ExErr) Error() string { | ||||
|  | ||||
| // Unwrap must be implemented so that some error.XXX methods work | ||||
| func (ee *ExErr) Unwrap() error { | ||||
| 	if ee.OriginalError == nil { | ||||
| 		return nil // this is neccessary - otherwise we return a wrapped nil and the `x == nil` comparison fails (= panic in errors.Is and other failures) | ||||
| 	} | ||||
| 	return ee.OriginalError | ||||
| } | ||||
|  | ||||
| @@ -44,17 +49,29 @@ func (ee *ExErr) Is(e error) bool { | ||||
| // As must be implemented so that error.As(x) works | ||||
| // | ||||
| //goland:noinspection GoTypeAssertionOnErrors | ||||
| func (ee *ExErr) As(e any) bool { | ||||
| 	if dstErr, ok := e.(*ExErr); ok { | ||||
| func (ee *ExErr) As(target any) bool { | ||||
| 	if dstErr, ok := target.(*ExErr); ok { | ||||
|  | ||||
| 		if dst0, ok := ee.contains(dstErr); ok { | ||||
| 			dstErr = dst0 | ||||
| 			return true | ||||
| 		} else { | ||||
| 			return false | ||||
| 		} | ||||
| 	} else if dstErr, ok := e.(error); ok { | ||||
| 		return IsFrom(ee, dstErr) | ||||
|  | ||||
| 	} else { | ||||
|  | ||||
| 		val := reflect.ValueOf(target) | ||||
|  | ||||
| 		typStr := val.Type().Elem().String() | ||||
|  | ||||
| 		for curr := ee; curr != nil; curr = curr.OriginalError { | ||||
| 			if curr.Category == CatForeign && curr.WrappedErrType == typStr && curr.WrappedErr != nil { | ||||
| 				val.Elem().Set(reflect.ValueOf(curr.WrappedErr)) | ||||
| 				return true | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										93
									
								
								exerr/exerr_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								exerr/exerr_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,93 @@ | ||||
| package exerr | ||||
|  | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"gogs.mikescher.com/BlackForestBytes/goext/tst" | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
| type golangErr struct { | ||||
| 	Message string | ||||
| } | ||||
|  | ||||
| func (g golangErr) Error() string { | ||||
| 	return g.Message | ||||
| } | ||||
|  | ||||
| type golangErr2 struct { | ||||
| 	Message string | ||||
| } | ||||
|  | ||||
| func (g golangErr2) Error() string { | ||||
| 	return g.Message | ||||
| } | ||||
|  | ||||
| type simpleError struct { | ||||
| } | ||||
|  | ||||
| func (g simpleError) Error() string { | ||||
| 	return "Something simple went wroong" | ||||
| } | ||||
|  | ||||
| type simpleError2 struct { | ||||
| } | ||||
|  | ||||
| func (g simpleError2) Error() string { | ||||
| 	return "Something simple went wroong" | ||||
| } | ||||
|  | ||||
| func TestExErrIs1(t *testing.T) { | ||||
| 	e0 := simpleError{} | ||||
|  | ||||
| 	wrap := Wrap(e0, "something went wrong").Str("test", "123").Build() | ||||
|  | ||||
| 	tst.AssertTrue(t, errors.Is(wrap, simpleError{})) | ||||
| 	tst.AssertFalse(t, errors.Is(wrap, golangErr{})) | ||||
| 	tst.AssertFalse(t, errors.Is(wrap, golangErr{"error1"})) | ||||
| } | ||||
|  | ||||
| func TestExErrIs2(t *testing.T) { | ||||
| 	e0 := golangErr{"error1"} | ||||
|  | ||||
| 	wrap := Wrap(e0, "something went wrong").Str("test", "123").Build() | ||||
|  | ||||
| 	tst.AssertTrue(t, errors.Is(wrap, e0)) | ||||
| 	tst.AssertTrue(t, errors.Is(wrap, golangErr{"error1"})) | ||||
| 	tst.AssertFalse(t, errors.Is(wrap, golangErr{"error2"})) | ||||
| 	tst.AssertFalse(t, errors.Is(wrap, simpleError{})) | ||||
| } | ||||
|  | ||||
| func TestExErrAs(t *testing.T) { | ||||
|  | ||||
| 	e0 := golangErr{"error1"} | ||||
|  | ||||
| 	w0 := Wrap(e0, "something went wrong").Str("test", "123").Build() | ||||
|  | ||||
| 	{ | ||||
| 		out := golangErr{} | ||||
| 		ok := errors.As(w0, &out) | ||||
| 		tst.AssertTrue(t, ok) | ||||
| 		tst.AssertEqual(t, out.Message, "error1") | ||||
| 	} | ||||
|  | ||||
| 	w1 := Wrap(w0, "outher error").Build() | ||||
|  | ||||
| 	{ | ||||
| 		out := golangErr{} | ||||
| 		ok := errors.As(w1, &out) | ||||
| 		tst.AssertTrue(t, ok) | ||||
| 		tst.AssertEqual(t, out.Message, "error1") | ||||
| 	} | ||||
|  | ||||
| 	{ | ||||
| 		out := golangErr2{} | ||||
| 		ok := errors.As(w1, &out) | ||||
| 		tst.AssertFalse(t, ok) | ||||
| 	} | ||||
|  | ||||
| 	{ | ||||
| 		out := simpleError2{} | ||||
| 		ok := errors.As(w1, &out) | ||||
| 		tst.AssertFalse(t, ok) | ||||
| 	} | ||||
| } | ||||
| @@ -112,7 +112,7 @@ func (w *GinRouteBuilder) Use(middleware ...gin.HandlerFunc) *GinRouteBuilder { | ||||
| func (w *GinRouteBuilder) Handle(handler WHandlerFunc) { | ||||
|  | ||||
| 	if w.routes.wrapper.bufferBody { | ||||
| 		arr := make([]gin.HandlerFunc, len(w.handlers)+1) | ||||
| 		arr := make([]gin.HandlerFunc, 0, len(w.handlers)+1) | ||||
| 		arr = append(arr, BodyBuffer()) | ||||
| 		arr = append(arr, w.handlers...) | ||||
| 		w.handlers = arr | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| package goext | ||||
|  | ||||
| const GoextVersion = "0.0.224" | ||||
| const GoextVersion = "0.0.228" | ||||
|  | ||||
| const GoextVersionTimestamp = "2023-08-08T12:38:22+0200" | ||||
| const GoextVersionTimestamp = "2023-08-08T15:33:52+0200" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user