diff --git a/exceptions/Exception.go b/exceptions/Exception.go index d4aeb3e..889cc45 100644 --- a/exceptions/Exception.go +++ b/exceptions/Exception.go @@ -11,6 +11,8 @@ import ( "io" "os" "strings" + + "github.com/tursom/GoCollections/lang" ) type Exception interface { @@ -18,13 +20,13 @@ type Exception interface { Error() string Name() string Message() string - StackTrace() []StackTrace + StackTrace() []lang.StackTrace PrintStackTrace() PrintStackTraceTo(writer io.Writer) BuildPrintStackTrace(builder *strings.Builder) } -func PrintStackTraceByArray(writer io.Writer, trace []StackTrace) { +func PrintStackTraceByArray(writer io.Writer, trace []lang.StackTrace) { if trace == nil { return } @@ -44,7 +46,7 @@ func PrintStackTraceByArray(writer io.Writer, trace []StackTrace) { } } -func BuildStackTraceByArray(builder *strings.Builder, trace []StackTrace) { +func BuildStackTraceByArray(builder *strings.Builder, trace []lang.StackTrace) { if trace == nil { return } @@ -95,7 +97,7 @@ func Print(err error) { err.(Exception).PrintStackTrace() default: _, _ = fmt.Fprintln(os.Stderr, err) - PrintStackTraceByArray(os.Stderr, GetStackTrace()) + PrintStackTraceByArray(os.Stderr, lang.GetStackTrace()) } } diff --git a/exceptions/RuntimeException.go b/exceptions/RuntimeException.go index e395bc3..6976744 100644 --- a/exceptions/RuntimeException.go +++ b/exceptions/RuntimeException.go @@ -19,7 +19,7 @@ type RuntimeException struct { lang.BaseObject message string exceptionName string - stackTrace []StackTrace + stackTrace []lang.StackTrace cause Exception } @@ -28,9 +28,9 @@ func NewRuntimeException(message string, config *ExceptionConfig) RuntimeExcepti config = DefaultExceptionConfig() } - var stackTrace []StackTrace = nil + var stackTrace []lang.StackTrace = nil if config.GetStackTrace { - stackTrace = GetStackTraceSkipDeep(config.SkipStack + 1) + stackTrace = lang.GetStackTraceSkipDeep(config.SkipStack + 1) } var causeException Exception = nil @@ -84,7 +84,7 @@ func (o RuntimeException) Name() string { return o.exceptionName } -func (o RuntimeException) StackTrace() []StackTrace { +func (o RuntimeException) StackTrace() []lang.StackTrace { return o.stackTrace } diff --git a/lang/Lang.go b/lang/Lang.go index 9699869..08865a8 100644 --- a/lang/Lang.go +++ b/lang/Lang.go @@ -6,7 +6,22 @@ package lang -import "unsafe" +import ( + "fmt" + "io" + "os" + "strings" + "unsafe" + + "github.com/tursom/GoCollections/exceptions" +) + +type TypeCastException struct { + BaseObject + message string + stackTrace []StackTrace + cause any +} func Nil[T any]() T { var n T @@ -31,6 +46,17 @@ func TryCast[T any](v any) (T, bool) { } func Cast[T any](v any) T { + defer func() { + r := recover() + if r != nil { + panic(&TypeCastException{ + message: "cast failed", + stackTrace: GetStackTraceSkipDeep(1), + cause: r, + }) + } + }() + if v == nil { return Nil[T]() } else { @@ -39,9 +65,63 @@ func Cast[T any](v any) T { } func ForceCast[T any](v unsafe.Pointer) *T { + defer func() { + r := recover() + if r != nil { + panic(&TypeCastException{ + message: "cast failed", + stackTrace: GetStackTraceSkipDeep(1), + cause: r, + }) + } + }() + if v == nil { return nil } else { return (*T)(v) } } + +func (t *TypeCastException) Cause() exceptions.Exception { + return nil +} + +func (t *TypeCastException) Error() string { + return fmt.Sprintf("TypeCastException: %s\ncause by: %s", t.message, t.cause) +} + +func (t *TypeCastException) Name() string { + return "github.com.tursom.GoCollections.lang.TypeCastException" +} + +func (t *TypeCastException) Message() string { + return t.message +} + +func (t *TypeCastException) StackTrace() []StackTrace { + return t.stackTrace +} + +func (t *TypeCastException) PrintStackTrace() { + t.PrintStackTraceTo(os.Stderr) +} + +func (t *TypeCastException) PrintStackTraceTo(writer io.Writer) { + builder := strings.Builder{} + t.BuildPrintStackTrace(&builder) + bytes := []byte(builder.String()) + writeBytes := 0 + _, _ = writer.Write(bytes[writeBytes:]) +} + +func (t *TypeCastException) BuildPrintStackTrace(builder *strings.Builder) { + builder.WriteString(t.Error()) + builder.WriteString("\n") + if t.StackTrace() == nil { + return + } + for _, stackTrace := range t.StackTrace() { + stackTrace.WriteTo(builder) + } +} diff --git a/exceptions/StackTrace.go b/lang/StackTrace.go similarity index 98% rename from exceptions/StackTrace.go rename to lang/StackTrace.go index 7e6006e..5b22665 100644 --- a/exceptions/StackTrace.go +++ b/lang/StackTrace.go @@ -4,7 +4,7 @@ * license that can be found in the LICENSE file. */ -package exceptions +package lang import ( "fmt" diff --git a/exceptions/StackTrace_test.go b/lang/StackTrace_test.go similarity index 95% rename from exceptions/StackTrace_test.go rename to lang/StackTrace_test.go index dc9b697..9060673 100644 --- a/exceptions/StackTrace_test.go +++ b/lang/StackTrace_test.go @@ -4,7 +4,7 @@ * license that can be found in the LICENSE file. */ -package exceptions +package lang import ( "fmt"