mirror of
https://github.com/jimeh/go-render.git
synced 2026-02-19 03:16:39 +00:00
83 lines
2.2 KiB
Go
83 lines
2.2 KiB
Go
package render
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
)
|
|
|
|
// ErrUnsupportedFormat is returned when a format is not supported by a
|
|
// renderer. Any method that accepts a format string may return this error.
|
|
var ErrUnsupportedFormat = fmt.Errorf("%w: unsupported format", Err)
|
|
|
|
// Renderer is a renderer that delegates rendering to another renderer
|
|
// based on a format value.
|
|
type Renderer struct {
|
|
// Renderers is a map of format names to renderers. When Render is called,
|
|
// the format is used to look up the renderer to use.
|
|
Renderers map[string]FormatRenderer
|
|
}
|
|
|
|
// New returns a new Renderer that delegates rendering to the specified
|
|
// renderers.
|
|
//
|
|
// Any renderers which implement the Formats interface, will also be set as the
|
|
// renderer for all format strings returned by Format() on the renderer.
|
|
func New(renderers map[string]FormatRenderer) *Renderer {
|
|
newRenderers := make(map[string]FormatRenderer, len(renderers))
|
|
|
|
for format, r := range renderers {
|
|
newRenderers[format] = r
|
|
|
|
if x, ok := r.(Formats); ok {
|
|
for _, f := range x.Formats() {
|
|
if f != format {
|
|
newRenderers[f] = r
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return &Renderer{Renderers: newRenderers}
|
|
}
|
|
|
|
// Render renders a value to an io.Writer using the specified format. If the
|
|
// format is not supported, ErrUnsupportedFormat is returned.
|
|
//
|
|
// If the format is supported, but the value cannot be rendered to the format,
|
|
// the error returned by the renderer is returned. In most cases this will be
|
|
// ErrCannotRender, but it could be a different error if the renderer returns
|
|
// one.
|
|
func (r *Renderer) Render(w io.Writer, format string, v any) error {
|
|
renderer, ok := r.Renderers[format]
|
|
if !ok {
|
|
return fmt.Errorf("%w: %s", ErrUnsupportedFormat, format)
|
|
}
|
|
|
|
err := renderer.Render(w, v)
|
|
if err != nil {
|
|
if errors.Is(err, ErrCannotRender) {
|
|
return fmt.Errorf("%w: %s", ErrUnsupportedFormat, format)
|
|
}
|
|
if !errors.Is(err, ErrFailed) {
|
|
return fmt.Errorf("%w: %w", ErrFailed, err)
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *Renderer) OnlyWith(formats ...string) *Renderer {
|
|
renderers := make(map[string]FormatRenderer, len(formats))
|
|
|
|
for _, format := range formats {
|
|
if r, ok := r.Renderers[format]; ok {
|
|
renderers[format] = r
|
|
}
|
|
}
|
|
|
|
return New(renderers)
|
|
}
|