Skip to content

Commit

Permalink
Add ExtendableFactory[T any] type
Browse files Browse the repository at this point in the history
  • Loading branch information
a20r committed Feb 28, 2024
1 parent b43d7bd commit a4a5784
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 11 deletions.
44 changes: 35 additions & 9 deletions factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ type Factory[T any] interface {
New(vs ...T) Falta
}

// ExtendableFactory is an error factory that can be extended.
type ExtendableFactory[T any] interface {
Factory[T]
Extend(f Factory[T]) ExtendableFactory[T]
}

// Falta is an error returned by the Factory
type Falta struct {
errFmt string
Expand Down Expand Up @@ -103,20 +109,20 @@ func New[T any](errFmt string) Factory[T] {
return newTmplFalta[T](errFmt)
}

// NewM returns a new Falta instance using a template that expects a falta.M (i.e., map[string]any). This is a
// convenience function for calling falta.New[falta.M](...)
func NewM(errFmt string) Factory[M] {
return New[M](errFmt)
// M is a convenience type for using Falta instances with maps.
type M map[string]any

// NewM returns a new ExtendableFactory instance using a template that expects a falta.M (i.e., map[string]any).
// This is a convenience function for calling falta.New[falta.M](...)
func NewM(errFmt string) ExtendableFactory[M] {
return newTmplFalta[M](errFmt)
}

// Newf creates a new Falta instance that will construct errors using the printf format string provided.
func Newf(errFmt string) Factory[any] {
func Newf(errFmt string) ExtendableFactory[any] {
return newFmtFactory(errFmt)
}

// M is a convenience type for using Falta instances with maps.
type M map[string]any

type tmplFalta[T any] struct {
errFmt string
tmpl *template.Template
Expand All @@ -139,12 +145,22 @@ func (f tmplFalta[T]) New(vs ...T) Falta {
builder := new(strings.Builder)

if err := f.tmpl.Execute(builder, vs[0]); err != nil {
panic(err)
panic(fmt.Errorf("falta: cannot execute template: %w", err))
}

return Falta{errFmt: f.errFmt, error: fmt.Errorf(builder.String())}
}

func (f tmplFalta[T]) Extend(other Factory[T]) ExtendableFactory[T] {
v, ok := other.(tmplFalta[T])

if !ok {
panic(fmt.Errorf("falta: tmpl factories can only be extended by other tmpl factories with the same type"))
}

return newTmplFalta[T](f.errFmt + " " + v.errFmt)
}

func (f tmplFalta[T]) Error() string {
return f.errFmt
}
Expand Down Expand Up @@ -175,6 +191,16 @@ func (f fmtFalta) New(vs ...any) Falta {
return Falta{errFmt: f.errFmt, error: fmt.Errorf(f.errFmt, vs...)}
}

func (f fmtFalta) Extend(other Factory[any]) ExtendableFactory[any] {
v, ok := other.(fmtFalta)

if !ok {
panic(fmt.Errorf("falta: fmt factories can only be extended by other fmt factories"))
}

return newFmtFactory(f.errFmt + " " + v.errFmt)
}

func (f fmtFalta) Error() string {
return f.errFmt
}
Expand Down
33 changes: 31 additions & 2 deletions factory_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,12 +123,41 @@ func TestNewError(t *testing.T) {
}

func TestNewM(t *testing.T) {
f := falta.NewM("falta test: [code={{.code}}] test error with message: {{.message}}")
f := falta.NewM("falta test: [code={{.code}}] test error with message '{{.message}}'")

err := f.New(falta.M{
"code": 503,
"message": "Bad Gateway",
})

expectedErr := fmt.Errorf("falta test: [code=503] test error with message: Bad Gateway")
expectedErr := fmt.Errorf("falta test: [code=503] test error with message 'Bad Gateway'")
assert.ErrorIs(t, err, expectedErr)
}

func TestExtendableFactory(t *testing.T) {
ErrCallFailed := falta.NewM("falta test: [code={{.code}}] test error with message '{{.message}}'")
ErrCallFailedWithReason := ErrCallFailed.Extend(falta.NewM("because {{.reason}}"))

as := assert.New(t)

{
err := ErrCallFailed.New(falta.M{
"code": 503,
"message": "Bad Gateway",
})

expectedErr := fmt.Errorf("falta test: [code=503] test error with message 'Bad Gateway'")
as.ErrorIs(err, expectedErr)
}

{
err := ErrCallFailedWithReason.New(falta.M{
"code": 503,
"message": "Bad Gateway",
"reason": "server is down",
})

expectedErr := fmt.Errorf("falta test: [code=503] test error with message 'Bad Gateway' because server is down")
as.ErrorIs(err, expectedErr)
}
}

0 comments on commit a4a5784

Please sign in to comment.