Select Git revision
template_executor.go

Semyon Krestyaninov authored
template_executor.go 1.74 KiB
package executor
import (
"bytes"
"context"
"sync"
"text/template"
"git.perx.ru/perxis/perxis-go/pkg/errors"
)
type TemplateExecutor struct {
data map[string]any
funcMap template.FuncMap
}
func NewTemplateExecutor(data map[string]any) *TemplateExecutor {
te := &TemplateExecutor{
data: data,
}
te.init()
return te
}
func (exec *TemplateExecutor) init() {
if exec.data == nil {
exec.data = make(map[string]any)
}
delete(exec.data, "Error")
exec.funcMap = template.FuncMap{
"error": exec.errorFunc,
}
}
func (exec *TemplateExecutor) Execute(_ context.Context, input string) (string, error) {
templ, err := template.New("template_executor").Funcs(exec.funcMap).Parse(input)
if err != nil {
return "", err
}
buf := getBuffer()
defer releaseBuffer(buf)
err = templ.Execute(buf, exec.data)
if err != nil {
return "", err
}
output := buf.String()
if output == "<no value>" {
return "", nil
}
return output, nil
}
// IsCanceled возвращает true, если в процессе выполнения шаблона была вызвана
// шаблонная функция error.
func (exec *TemplateExecutor) IsCanceled() bool {
_, ok := exec.data["Error"]
return ok
}
func (exec *TemplateExecutor) errorFunc(text string) (string, error) {
exec.data["Error"] = text
return "", errors.New(text)
}
//nolint:gochecknoglobals // Доступ к пулу необходим на глобальном уровне.
var bufferPool = &sync.Pool{
New: func() any {
return new(bytes.Buffer)
},
}
func getBuffer() *bytes.Buffer {
buf, _ := bufferPool.Get().(*bytes.Buffer)
return buf
}
func releaseBuffer(buf *bytes.Buffer) {
const maxBufCap = 1024
if buf.Cap() > maxBufCap {
return
}
buf.Reset()
bufferPool.Put(buf)
}