Skip to content

Commit

Permalink
WIP [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Oct 15, 2024
1 parent 6f4cd23 commit 184932d
Show file tree
Hide file tree
Showing 4 changed files with 220 additions and 78 deletions.
35 changes: 0 additions & 35 deletions config/handlertype.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,41 +46,6 @@ func (t HandlerType) String() string {
}
}

// SwitchByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h.
func SwitchByHandlerTypeOf(
h Handler,
aggregate func(*Aggregate),
process func(*Process),
integration func(*Integration),
projection func(*Projection),
) {
switch h := h.(type) {
case *Aggregate:
if aggregate == nil {
panic("no case function was provided for aggregate handlers")
}
aggregate(h)
case *Process:
if process == nil {
panic("no case function was provided for process handlers")
}
process(h)
case *Integration:
if integration == nil {
panic("no case function was provided for integration handlers")
}
integration(h)
case *Projection:
if projection == nil {
panic("no case function was provided for projection handlers")
}
projection(h)
default:
panic("invalid handler type")
}
}

// RouteCapabilities returns a value that describes the routing capabilities of
// the handler type.
func (t HandlerType) RouteCapabilities() RouteCapabilities {
Expand Down
43 changes: 0 additions & 43 deletions config/handlertype_test.go

This file was deleted.

118 changes: 118 additions & 0 deletions config/handlertypeswitch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package config

import (
"github.com/dogmatiq/enginekit/internal/enum"
)

// SwitchByHandlerType invokes one of the provided functions based on t.
//
// It provides a compile-time guarantee that all possible values are handled,
// even if new [HandlerType] values are added in the future.
//
// It panics if the function associated with t is nil, or if t is not a valid
// [HandlerType].
func SwitchByHandlerType(
t HandlerType,
aggregate func(),
process func(),
integration func(),
projection func(),
) {
enum.Switch(t, aggregate, process, integration, projection)
}

// MapByHandlerType maps t to a value of type T.
//
// It provides a compile-time guarantee that all possible values are handled,
// even if new [HandlerType] values are added in the future.
//
// It panics if t is not a valid [HandlerType].
func MapByHandlerType[T any](t HandlerType, aggregate, process, integration, projection T) T {
return enum.Map(t, aggregate, process, integration, projection)
}

// SwitchByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func SwitchByHandlerTypeOf(
h Handler,
aggregate func(*Aggregate),
process func(*Process),
integration func(*Integration),
projection func(*Projection),
) {
switch h := h.(type) {
case *Aggregate:
if aggregate != nil {
aggregate(h)
}
case *Process:
if process != nil {
process(h)
}
case *Integration:
if integration != nil {
integration(h)
}
case *Projection:
if projection != nil {
projection(h)
}
default:
panic("invalid handler type")
}
}

// MapByHandlerTypeOf invokes one of the provided functions based on the
// [HandlerType] of h, and returns the result.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func MapByHandlerTypeOf[T any](
h Handler,
aggregate func(*Aggregate) T,
process func(*Process) T,
integration func(*Integration) T,
projection func(*Projection) T,
) (result T) {
SwitchByHandlerTypeOf(
h,
enum.AssignResult(aggregate, &result),
enum.AssignResult(process, &result),
enum.AssignResult(integration, &result),
enum.AssignResult(projection, &result),
)

return result
}

// MapByHandlerTypeOfWithErr invokes one of the provided functions based on the
// [HandlerType] of h, and returns the result and error value.
//
// It provides a compile-time guarantee that all types are handled, even if new
// [HandlerType] values are added in the future.
//
// It panics if the function associated with h's type is nil.
func MapByHandlerTypeOfWithErr[T any](
h Handler,
aggregate func(*Aggregate) (T, error),
process func(*Process) (T, error),
integration func(*Integration) (T, error),
projection func(*Projection) (T, error),
) (result T, err error) {
SwitchByHandlerTypeOf(
h,
enum.AssignResultErr(aggregate, &result, &err),
enum.AssignResultErr(process, &result, &err),
enum.AssignResultErr(integration, &result, &err),
enum.AssignResultErr(projection, &result, &err),
)

return result, err
}
102 changes: 102 additions & 0 deletions config/handlertypeswitch_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package config

import "testing"

func TestSwitchByHandlerType(t *testing.T) {
cases := []struct {
Type HandlerType
Want string
}{
{CommandKind, "command"},
{EventKind, "event"},
{TimeoutKind, "timeout"},
}

for _, c := range cases {
var result string

SwitchByKind(
c.Kind,
func() { result = "command" },
func() { result = "event" },
func() { result = "timeout" },
)

if result != c.Want {
t.Fatalf("unexpected result: got %q, want %q", result, c.Want)
}
}

t.Run("it panics when the associated function is nil", func(t *testing.T) {
cases := []struct {
Kind Kind
Want string
}{
{CommandKind, `no case function was provided for "command"`},
{EventKind, `no case function was provided for "event"`},
{TimeoutKind, `no case function was provided for "timeout"`},
}

for _, c := range cases {
func() {
defer func() {
if got := recover(); got != c.Want {
t.Fatalf("unexpected panic: got %q, want %q", got, c.Want)
}
}()

SwitchByKind(c.Kind, nil, nil, nil)
}()
}
})

t.Run("it panics when the kind is invalid", func(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Fatal("expected a panic")
}
}()

SwitchByKind(Kind(-1), nil, nil, nil)
})
}

func TestSwitchByHandlerTypeOf(t *testing.T) {
cases := []struct {
Handler Handler
Want string
}{
{
&Aggregate{},
"aggregate",
},
{
&Process{},
"process",
},
{
&Integration{},
"integration",
},
{
&Projection{},
"projection",
},
}

for _, c := range cases {
var got string

SwitchByHandlerTypeOf(
c.Handler,
func(*Aggregate) { got = "aggregate" },
func(*Process) { got = "process" },
func(*Integration) { got = "integration" },
func(*Projection) { got = "projection" },
)

if got != c.Want {
t.Errorf("unexpected value: got %q, want %q", got, c.Want)
}
}
}

0 comments on commit 184932d

Please sign in to comment.