mirror of
https://github.com/jimeh/go-render.git
synced 2026-02-18 19:06:39 +00:00
This is yet another drastic refactor of public API and concepts. Hopefully the last one, as I'm now fairly happy with things.
81 lines
1.8 KiB
Go
81 lines
1.8 KiB
Go
package render
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// Multi is a Handler that tries multiple handlers until one succeeds.
|
|
type Multi struct {
|
|
Handlers []Handler
|
|
}
|
|
|
|
var (
|
|
_ Handler = (*Multi)(nil)
|
|
_ PrettyHandler = (*Multi)(nil)
|
|
_ FormatsHandler = (*Multi)(nil)
|
|
)
|
|
|
|
// Render tries each handler in order until one succeeds. If none succeed,
|
|
// ErrCannotRender is returned. If a handler returns an error that is not
|
|
// ErrCannotRender, that error is returned.
|
|
func (mr *Multi) Render(w io.Writer, v any) error {
|
|
for _, r := range mr.Handlers {
|
|
err := r.Render(w, v)
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if !errors.Is(err, ErrCannotRender) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("%w: %T", ErrCannotRender, v)
|
|
}
|
|
|
|
// RenderPretty tries each handler in order until one succeeds. If none
|
|
// succeed, ErrCannotRender is returned. If a handler returns an error that is
|
|
// not ErrCannotRender, that error is returned.
|
|
//
|
|
// If a handler implements PrettyHandler, then the RenderPretty method is used
|
|
// instead of Render. Otherwise, the Render method is used.
|
|
func (mr *Multi) RenderPretty(w io.Writer, v any) error {
|
|
for _, r := range mr.Handlers {
|
|
var err error
|
|
if x, ok := r.(PrettyHandler); ok {
|
|
err = x.RenderPretty(w, v)
|
|
} else {
|
|
err = r.Render(w, v)
|
|
}
|
|
if err == nil {
|
|
return nil
|
|
}
|
|
if !errors.Is(err, ErrCannotRender) {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return fmt.Errorf("%w: %T", ErrCannotRender, v)
|
|
}
|
|
|
|
// Formats returns a list of format strings that this Handler supports.
|
|
func (mr *Multi) Formats() []string {
|
|
formats := make(map[string]struct{})
|
|
|
|
for _, r := range mr.Handlers {
|
|
if x, ok := r.(FormatsHandler); ok {
|
|
for _, f := range x.Formats() {
|
|
formats[f] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
result := make([]string, 0, len(formats))
|
|
for f := range formats {
|
|
result = append(result, f)
|
|
}
|
|
|
|
return result
|
|
}
|